diff --git a/.gitignore b/.gitignore index c475581..e09e3bf 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,4 @@ tools/addtga2fimg tools/addpnm2fimg tools/cumulfimgs tools/fimgops +tools/fimgfx diff --git a/doc/the_floatimg_hack.tex b/doc/the_floatimg_hack.tex index f818bc4..49c3dfa 100644 --- a/doc/the_floatimg_hack.tex +++ b/doc/the_floatimg_hack.tex @@ -51,9 +51,10 @@ chaque pixel en virgule flottante sur 32bits, le type Attention, tout le code que nous allons voir ensemble est en 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 -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. % ------------------------------------------------------------------- @@ -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 à l'instant même. +\vspace{1em} + Tout d'abord, nous devons déclarer et garnir quelques variables pour gérer la machinerie interne. @@ -89,8 +92,9 @@ FloatImg fimg; \end{verbatim} Ensuite, nous enchainerons trois étapes : création de l'image -en mémoire centrale, initialisations des valeurs de pixel à 0.0, -et pour conclure, enregistrement dans un fichier. +en mémoire centrale, initialisation des valeurs de chaque pixel à 0.0, +et pour conclure, enregistrement dans un fichier\footnote{Au format +ésotérique, mais très véloce.} binaire. \begin{verbatim} foo = fimg_create(&fimg, width, height, FIMG_TYPE_RGB); @@ -139,6 +143,9 @@ lesquels sont décrits en page \pageref{outils}. % ------------------------------------------------------------------- \section{Installation} +\textit{Attention, ça devient un peu gore.} + + \subsection{Prérequis} Vous devez, en dehors des outils classiques (bash, gcc, make\dots), @@ -255,8 +262,9 @@ int fimg_destroy(FloatImg *fimg); \end{verbatim} Les types d'images actuellement gérés sont les trois grands -classiques : gray, rgb et rgba. Il y a les constantes adéquates -dans \texttt{floatimg.h}. Les codes d'erreur sont disparates +classiques : gray, rgb et rgba. Les constantes adéquates sont +dans \texttt{floatimg.h} et expliquées quelques lignes plus haut. +Les codes d'erreur sont disparates et non documentés. \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 sévèrement controlée par l'appelant. Il y a une fonction 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} @@ -386,9 +431,15 @@ les valeurs moyennes de chaque composante. Puis nous rajouterons\footnote{Les patchs sont les bienvenus} 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} -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, uniquement RGB}. @@ -448,14 +499,15 @@ Il reste plein de choses à faire pour que ce soit vraiment utilisable. \textsl{[en cours]}. \item Compléter les traitements mathémathiques (eg le gamma\index{gamma}). \item Formaliser les codes d'erreur. -\ + \end{itemize} % ------------------------------------------------------------------- \section{Exemples pour yusers}\index{example} 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} @@ -485,7 +537,7 @@ convert -delay 10 xx*.pnm foo.gif \end{verbatim} 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. 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} @@ -590,7 +644,7 @@ en mode portnawak\dots 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 -faire des images au bord d'un lac. +faire des images au bord d'un lac ou dans la campagne de l'Ariège. % ------------------------------------------------------------------- diff --git a/floatimg.h b/floatimg.h index 52694d7..cb19982 100644 --- a/floatimg.h +++ b/floatimg.h @@ -2,7 +2,7 @@ * floatimg.h */ -#define FIMG_VERSION 77 +#define FIMG_VERSION 78 /* * in memory descriptor diff --git a/tools/Makefile b/tools/Makefile index 9b624e7..d389817 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -9,7 +9,7 @@ DEPS = ../floatimg.h ../libfloatimg.a Makefile # ---------- all: fimg2pnm mkfimg png2fimg fimgstats fimg2png \ - addpnm2fimg cumulfimgs fimgops + addpnm2fimg cumulfimgs fimgops fimgfx fimgstats: fimgstats.c $(DEPS) gcc $(COPT) $< ../libfloatimg.a -o $@ @@ -23,6 +23,9 @@ mkfimg: mkfimg.c $(DEPS) fimgops: fimgops.c $(DEPS) gcc $(COPT) $< ../libfloatimg.a -o $@ +fimgfx: fimgfx.c $(DEPS) + gcc $(COPT) $< ../libfloatimg.a -o $@ + fimg2pnm: fimg2pnm.c $(DEPS) gcc $(COPT) $< ../libfloatimg.a -o $@ diff --git a/tools/fimgfx.c b/tools/fimgfx.c new file mode 100644 index 0000000..1c4cb66 --- /dev/null +++ b/tools/fimgfx.c @@ -0,0 +1,168 @@ +/* + FIMGFX +*/ +#include +#include +#include +#include + +#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-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; +} +/* --------------------------------------------------------------------- */