added a new tool : fimgfx

This commit is contained in:
Tonton Th 2019-11-29 17:06:40 +01:00
parent 59bcdf30d4
commit 9ae7e4d85f
5 changed files with 241 additions and 15 deletions

1
.gitignore vendored
View File

@ -43,3 +43,4 @@ tools/addtga2fimg
tools/addpnm2fimg tools/addpnm2fimg
tools/cumulfimgs tools/cumulfimgs
tools/fimgops tools/fimgops
tools/fimgfx

View File

@ -51,9 +51,10 @@ chaque pixel en virgule flottante sur 32bits, le type
Attention, tout le code que nous allons voir ensemble est en Attention, tout le code que nous allons voir ensemble est en
perpétuelle évolution\footnote{voir page \pageref{TODO}}, perpétuelle évolution\footnote{voir page \pageref{TODO}},
et sa fiablité reste à démontrer\index{valgrind}. et sa fiablité (surtout sur certains aspects mathématiques)
reste à démontrer\index{valgrind}.
Mais le service après-vente est assez réactif. Du moins Mais le service après-vente est assez réactif. Du moins
pour ceux qui suivent \texttt{\#tetalab} sur le réseau pour ceux qui suivent le canal \texttt{\#tetalab} sur le réseau
IRC de Freenode. IRC de Freenode.
% ------------------------------------------------------------------- % -------------------------------------------------------------------
@ -79,6 +80,8 @@ puis l'enregistrer dans un fichier \texttt{.fimg}\index{.fimg},
un format complètement inconnu, puisque je viens de l'inventer un format complètement inconnu, puisque je viens de l'inventer
à l'instant même. à l'instant même.
\vspace{1em}
Tout d'abord, nous devons déclarer et garnir quelques variables Tout d'abord, nous devons déclarer et garnir quelques variables
pour gérer la machinerie interne. pour gérer la machinerie interne.
@ -89,8 +92,9 @@ FloatImg fimg;
\end{verbatim} \end{verbatim}
Ensuite, nous enchainerons trois étapes : création de l'image Ensuite, nous enchainerons trois étapes : création de l'image
en mémoire centrale, initialisations des valeurs de pixel à 0.0, en mémoire centrale, initialisation des valeurs de chaque pixel à 0.0,
et pour conclure, enregistrement dans un fichier. et pour conclure, enregistrement dans un fichier\footnote{Au format
ésotérique, mais très véloce.} binaire.
\begin{verbatim} \begin{verbatim}
foo = fimg_create(&fimg, width, height, FIMG_TYPE_RGB); foo = fimg_create(&fimg, width, height, FIMG_TYPE_RGB);
@ -139,6 +143,9 @@ lesquels sont décrits en page \pageref{outils}.
% ------------------------------------------------------------------- % -------------------------------------------------------------------
\section{Installation} \section{Installation}
\textit{Attention, ça devient un peu gore.}
\subsection{Prérequis} \subsection{Prérequis}
Vous devez, en dehors des outils classiques (bash, gcc, make\dots), Vous devez, en dehors des outils classiques (bash, gcc, make\dots),
@ -255,8 +262,9 @@ int fimg_destroy(FloatImg *fimg);
\end{verbatim} \end{verbatim}
Les types d'images actuellement gérés sont les trois grands Les types d'images actuellement gérés sont les trois grands
classiques : gray, rgb et rgba. Il y a les constantes adéquates classiques : gray, rgb et rgba. Les constantes adéquates sont
dans \texttt{floatimg.h}. Les codes d'erreur sont disparates dans \texttt{floatimg.h} et expliquées quelques lignes plus haut.
Les codes d'erreur sont disparates
et non documentés. et non documentés.
\vspace{1em} \vspace{1em}
@ -272,7 +280,44 @@ int fimg_plot_rgb (FloatImg *head, int x, int y,
Les paramètres sont explicites, mais leur validité doit être Les paramètres sont explicites, mais leur validité doit être
sévèrement controlée par l'appelant. Il y a une fonction sévèrement controlée par l'appelant. Il y a une fonction
soeur, \texttt{fimg\_add\_rgb}\index{fimg\_add\_rgb}, soeur, \texttt{fimg\_add\_rgb}\index{fimg\_add\_rgb},
qui ajoute du rgb à un pixel. qui ajoute du rgb à un pixel, laquelle a d'ailleur été
la base de la seconde génération de la
photographie\index{photographie} en cumul\index{cumul}.
\subsubsection{Contraste}\index{contraste}
Certaines opérations d'ajustement du contraste d'une image
semblent cohérents avec la notion d'image flottante.
Certains d'entre eux, les plus simples, sont disponibles.
Ils prennent chacun trois paramètres, d'abord les images
source et destination (\texttt{* FloatImg}), et le troisième
est un nombre en double précision donnant la valeur
maximale \textsl{supposée} de l'image source.
\begin{verbatim}
/* source in lib/contrast.c */
int fimg_square_root(FloatImg *s, FloatImg *d, double maxval);
int fimg_power_2(FloatImg *s, FloatImg *d, double maxval);
int fimg_cos_01(FloatImg *s, FloatImg *d, double maxval);
\end{verbatim}
Rappelons qu'il est possible pour un logiciel applicatif
comme \texttt{grabvidseq} (Cf page \pageref{grabvidseq})
de renseigner deux champs du descripteur d'image avec des
données pertinentes.
Ces deux champs sont \textit{fval} et \textit{count}.
Dans ce cas particulier, le premier indique la valeur
maximale du capteur, et le second sert à compter le
nombre de capture\footnote{Et c'est bien géré aussi
dans l'upscaling.} effectuées.
\vspace{1em}
La prochaine étape consistera à trouver une façon de faire
une égalisation\index{égalisation} par histogramme\index{histogramme}
qui respecte, dans toute sa futilité, le concept\index{concept}
de pixel flottant.
\subsection{funcs/}\index{funcs/}\label{funcs} \subsection{funcs/}\index{funcs/}\label{funcs}
@ -386,9 +431,15 @@ les valeurs moyennes de chaque composante.
Puis nous rajouterons\footnote{Les patchs sont les bienvenus} Puis nous rajouterons\footnote{Les patchs sont les bienvenus}
le calcul de la variance\index{variance}. le calcul de la variance\index{variance}.
\subsection{fimgfx}\index{fimgfx}\label{fimgfx}
\textit{En cours de création\index{XXX}.
Attention, je vais expérimenter un parsing un peu étrange
sur les arguments de la ligne de commande. coredump expected.}
\subsection{fimgops}\index{fimgops}\label{fimgops} \subsection{fimgops}\index{fimgops}\label{fimgops}
Quelques opérations diverses entre deeux images, qui doivent être Quelques opérations diverses entre deux images, qui doivent être
de la même taille, et du même type \textsl{pour le moment, de la même taille, et du même type \textsl{pour le moment,
uniquement RGB}. uniquement RGB}.
@ -448,14 +499,15 @@ Il reste plein de choses à faire pour que ce soit vraiment utilisable.
\textsl{[en cours]}. \textsl{[en cours]}.
\item Compléter les traitements mathémathiques (eg le gamma\index{gamma}). \item Compléter les traitements mathémathiques (eg le gamma\index{gamma}).
\item Formaliser les codes d'erreur. \item Formaliser les codes d'erreur.
\
\end{itemize} \end{itemize}
% ------------------------------------------------------------------- % -------------------------------------------------------------------
\section{Exemples pour yusers}\index{example} \section{Exemples pour yusers}\index{example}
Nous allons \textsl{essayer d'improviser} un exemple presque réel, Nous allons \textsl{essayer d'improviser} un exemple presque réel,
avec un peu de rache\index{rache} dedans. avec un peu de rache\index{rache} dedans. Ce qui est autorisé dans
les exemples.
\vspace{1em} \vspace{1em}
@ -485,7 +537,7 @@ convert -delay 10 xx*.pnm foo.gif
\end{verbatim} \end{verbatim}
Voilà, si les choses se passent mal, vous allez découvrir Voilà, si les choses se passent mal, vous allez découvrir
que votre drand n'est pas si drand que ça. que votre drand n'est pas si drand que ça. Séquence angoisse.
% ------------------------------------------------------------------- % -------------------------------------------------------------------
@ -546,7 +598,9 @@ de l'image, en profitant du fait que l'on est capable
de prendre $N$ images en rafale. de prendre $N$ images en rafale.
Pour être rigoureux dans la prise de vue, ce $N$ doit Pour être rigoureux dans la prise de vue, ce $N$ doit
être un multiple de 4, surtout si le nombre de capture est faible.. être un multiple de 4, surtout si le nombre de capture est faible.
N'hésitez pas à faire des essais, le résultat est parfois
aléatoire, surtout avec une caméra qui bouge.
\vspace{1em} \vspace{1em}
@ -590,7 +644,7 @@ en mode portnawak\dots
L'idée est donc de construire un appareil autonome, basé sur un Raspi et L'idée est donc de construire un appareil autonome, basé sur un Raspi et
une webcam \textsc{usb}\index{USB}, alimenté par batterie et permettant d'aller une webcam \textsc{usb}\index{USB}, alimenté par batterie et permettant d'aller
faire des images au bord d'un lac. faire des images au bord d'un lac ou dans la campagne de l'Ariège.
% ------------------------------------------------------------------- % -------------------------------------------------------------------

View File

@ -2,7 +2,7 @@
* floatimg.h * floatimg.h
*/ */
#define FIMG_VERSION 77 #define FIMG_VERSION 78
/* /*
* in memory descriptor * in memory descriptor

View File

@ -9,7 +9,7 @@ DEPS = ../floatimg.h ../libfloatimg.a Makefile
# ---------- # ----------
all: fimg2pnm mkfimg png2fimg fimgstats fimg2png \ all: fimg2pnm mkfimg png2fimg fimgstats fimg2png \
addpnm2fimg cumulfimgs fimgops addpnm2fimg cumulfimgs fimgops fimgfx
fimgstats: fimgstats.c $(DEPS) fimgstats: fimgstats.c $(DEPS)
gcc $(COPT) $< ../libfloatimg.a -o $@ gcc $(COPT) $< ../libfloatimg.a -o $@
@ -23,6 +23,9 @@ mkfimg: mkfimg.c $(DEPS)
fimgops: fimgops.c $(DEPS) fimgops: fimgops.c $(DEPS)
gcc $(COPT) $< ../libfloatimg.a -o $@ gcc $(COPT) $< ../libfloatimg.a -o $@
fimgfx: fimgfx.c $(DEPS)
gcc $(COPT) $< ../libfloatimg.a -o $@
fimg2pnm: fimg2pnm.c $(DEPS) fimg2pnm: fimg2pnm.c $(DEPS)
gcc $(COPT) $< ../libfloatimg.a -o $@ gcc $(COPT) $< ../libfloatimg.a -o $@

168
tools/fimgfx.c Normal file
View File

@ -0,0 +1,168 @@
/*
FIMGFX
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "../floatimg.h"
/* --------------------------------------------------------------------- */
int verbosity;
float global_fvalue;
typedef struct {
char *name;
int id;
int nbarg;
} Fx;
enum fxid { Fx_cos01, Fx_pow2, Fx_sqrt };
Fx fx_list[] = {
{ "cos01", Fx_cos01, 0 },
{ "pow2", Fx_pow2, 0 },
{ "sqrt", Fx_sqrt, 0 },
{ NULL, 0, 0 }
};
/* --------------------------------------------------------------------- */
int lookup_fx(char *txt)
{
Fx *fx;
int n;
#if DEBUG_LEVEL
fprintf(stderr, ">>> %s ( '%s' )\n", __func__, txt);
#endif
for (n=0, fx=fx_list; fx->name; fx++, n++) {
#if DEBUG_LEVEL
fprintf(stderr, "-> %3d %s\n", n, fx->name);
#endif
if (!strcmp(fx->name, txt)) {
return n;
}
}
return -1;
}
/* --------------------------------------------------------------------- */
static void help(int lvl)
{
printf("fimg special effects (%d)\n", lvl);
exit(0);
}
/* --------------------------------------------------------------------- */
int do_an_effect(char *sf, int act, char *df)
{
FloatImg src, dest;
int foo;
double maxval;
#if 1
fprintf(stderr, ">>> %s ( '%s' %d '%s' )\n", __func__,
sf, act, df);
#endif
foo = fimg_create_from_dump(sf, &src);
if (foo) {
fprintf(stderr, "err load '%s' : %d\n", sf, foo);
return foo;
}
maxval = (double)fimg_get_maxvalue(&src);
foo = fimg_clone(&src, &dest, 0);
if (foo) {
fprintf(stderr, "err clone %p : %d\n", &src, foo);
return foo;
}
switch (act) {
case Fx_cos01:
fimg_cos_01(&src, &dest, maxval); break;
case Fx_pow2:
fimg_power_2(&src, &dest, maxval); break;
case Fx_sqrt:
fimg_square_root(&src, &dest, maxval); break;
default:
fprintf(stderr, "*** %s : %d is bad action\n", __func__, act);
break;
}
foo = fimg_dump_to_file(&dest, df, 0);
if (foo) {
fprintf(stderr, "dumping datas to file give us a %d\n", foo);
return foo;
}
return 0;
}
/* --------------------------------------------------------------------- */
int main(int argc, char *argv[])
{
int foo, opt, action;
int nba;
char *operator;
char *srcname = "";
char *dstname = "out.fimg";
while ((opt = getopt(argc, argv, "hk:v")) != -1) {
switch(opt) {
case 'h': help(0); break;
case 'k': global_fvalue = atof(optarg); break;
case 'v': verbosity++; break;
}
}
#if 1
fprintf(stderr, "argc %d optind %d\n", argc, optind);
for (foo=0; foo<argc; foo++)
fprintf(stderr, "%3d %c %s\n", foo, foo==optind?'*':' ', argv[foo]);
#endif
if (3 > argc-optind) {
fprintf(stderr, "%s need some arguments...\n", argv[0]);
exit(1);
}
operator = argv[optind];
action = lookup_fx(operator);
if (action < 0) {
fprintf(stderr, "garbage found in opcode field : %s\n", operator);
exit(1);
}
if (verbosity) {
fprintf(stderr, "global fvalue %f\n", global_fvalue);
fprintf(stderr, "action %d\n", action);
fprintf(stderr, "verbosity %d\n", verbosity);
}
if ((nba=fx_list[action].nbarg)) {
fprintf(stderr, "action '%s' need %d arg\n", operator, nba);
}
srcname = argv[optind+1];
dstname = argv[optind+2];
fprintf(stderr, "%s ==> %s\n", srcname, dstname);
foo = do_an_effect(srcname, action, dstname);
fprintf(stderr, "do an effect -> %d\n", foo);
fprintf(stderr, "\n%s [done]\n", argv[0]);
return 0;
}
/* --------------------------------------------------------------------- */