forked from tTh/FloatImg
added a new tool : fimgfx
This commit is contained in:
parent
59bcdf30d4
commit
9ae7e4d85f
|
@ -43,3 +43,4 @@ tools/addtga2fimg
|
|||
tools/addpnm2fimg
|
||||
tools/cumulfimgs
|
||||
tools/fimgops
|
||||
tools/fimgfx
|
||||
|
|
|
@ -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.
|
||||
|
||||
% -------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* floatimg.h
|
||||
*/
|
||||
|
||||
#define FIMG_VERSION 77
|
||||
#define FIMG_VERSION 78
|
||||
|
||||
/*
|
||||
* in memory descriptor
|
||||
|
|
|
@ -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 $@
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
/* --------------------------------------------------------------------- */
|
Loading…
Reference in New Issue