› Foros › PC › Software libre
#include <stdio.h>
#include <stdlib.h>
#include <jpeglib.h>
#include <errno.h>
#include <string.h>
#include <locale.h>
#include <math.h>
#include <stdint.h>
/* Grafica el espectro de la imagen. Reinoso G. 15/06/2010
* Toma la línea central y devuelve el histograma en escala de grises.
* Basado en el ejemplo de la libjpeg en http://www.cim.mcgill.ca/~junaed/libjpeg.php
* Compilar con: gcc espectro.c -g -ljpeg -o espectro -Wall -lm
* */
typedef struct {
int colores;
int ancho;
int alto;
int leida;
double *buffer;
} t_linea;
t_linea read_jpeg_line(char *filename, unsigned int num_linea, unsigned int ancho)
{
t_linea central;
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
unsigned char* filas[1];
double* media_filas[1];
FILE *infile = fopen( filename, "rb" );
if ( !infile )
{
printf("Error al abrir %s: %s.\n", filename, strerror(errno) );
exit(1);
}
/* JPEG */
cinfo.err = jpeg_std_error( &jerr );
jpeg_create_decompress( &cinfo );
jpeg_stdio_src( &cinfo, infile );
jpeg_read_header( &cinfo, TRUE );
/*
printf( "JPEG File Information: \n" );
printf( "Image width and height: %d pixels and %d pixels.\n", cinfo.image_width, cinfo.image_height );
printf( "Color components per pixel: %d.\n", cinfo.num_components );
printf( "Color space: %d.\n", cinfo.jpeg_color_space );
*/
if (num_linea > cinfo.image_height) {
printf("Imposible obtener la línea %d, el alto de la imagen es de sólo %d.\n",
num_linea,
cinfo.image_height);
exit(1);
}
else if (num_linea == 0) {
num_linea = cinfo.image_height/2;
}
/* reservamos espacio ahora que ya sabemos cuánto */
filas[0] = (unsigned char *)malloc( cinfo.image_width*cinfo.num_components );
media_filas[0] = (double *)malloc( cinfo.image_width*cinfo.num_components*sizeof(double) );
/* Comenzar la descompresión */
jpeg_start_decompress( &cinfo );
/* Leemos hasta la mitad del archivo */
while( cinfo.output_scanline <= num_linea+ancho && cinfo.output_scanline < cinfo.image_height)
{
jpeg_read_scanlines( &cinfo, filas, 1 );
//printf("Leída la línea %d de %d.\n", cinfo.output_scanline, cinfo.image_height);
if (cinfo.output_scanline >= num_linea-ancho && cinfo.output_scanline <= num_linea+ancho)
{
int i;
for (i=1; i <= cinfo.image_width*cinfo.num_components; i++) {
media_filas[0][i-1] = media_filas[0][i-1] + filas[0][i-1]*1.0/(1+2*ancho);
}
printf("Incorporada la línea %d de %d.\n", cinfo.output_scanline, cinfo.image_height);
}
}
central.colores = cinfo.num_components;
central.alto = cinfo.image_height;
central.ancho = cinfo.image_width;
central.leida = num_linea;
central.buffer = media_filas[0];
jpeg_destroy_decompress( &cinfo );
fclose(infile);
free(filas[0]);
return central;
}
/* Escribe un breve fichero AVS con los valores de la linea o lineas analizados */
/* Para eso transforma t_linea.buffer a unsiged char */
void writeimage (char *outfilename, t_linea linea) {
uint32_t width;
uint32_t height;
uint8_t *avsbuffer;
FILE *outfile;
/* Esto porque el formato AVS no le gusta el endian de los intel */
#define SWAP(x) ( ((x) << 24) | \
(((x) << 8) & 0x00ff0000) | \
(((x) >> 8) & 0x0000ff00) | \
((x) >> 24) )
#define FIX(x) (*(unsigned *)&(x) = \
SWAP(*(unsigned *)&(x)))
width = linea.ancho;
width = FIX(width);
height = 10;
height = FIX(height);
int i;
outfile = fopen(outfilename, "wb");
if ( !outfile ) {
printf("Error al abrir %s: %s.\n", outfilename, strerror(errno));
exit(1);
}
avsbuffer = (uint8_t*) malloc(linea.ancho * 4); /* Header + ancho x ARGB */
if (linea.colores == 1) {
int i,j;
for (i = 0, j=0; i < (linea.ancho); i++, j+=4) {
avsbuffer[j] = 0; /* Alpha */
avsbuffer[j+1] = linea.buffer[i]; /* Red */
avsbuffer[j+2] = linea.buffer[i]; /* Green */
avsbuffer[j+3] = linea.buffer[i]; /* Blue */
}
}
else {
int i,j;
for (i = 0, j=0; i < (linea.ancho*3); i+=3, j+=4) {
avsbuffer[j] = 255; /* Alpha */
avsbuffer[j+1] = linea.buffer[i]; /* Red */
avsbuffer[j+2] = linea.buffer[i+1]; /* Green */
avsbuffer[j+3] = linea.buffer[i+2]; /* Blue */
}
}
fwrite(&width, 4, 1, outfile);
fwrite(&height, 4, 1, outfile);
for (i=0; i < 10; i++) {
fwrite(avsbuffer, 1, linea.ancho * 4, outfile);
}
free(avsbuffer);
fclose(outfile);
}
/* Genera el archivo de órdenes para gnuplot y lanza el programa (debe estar en el path) */
void do_gnuplot (char *textfilename, char *graphfilename, t_linea linea) {
FILE *outfile;
outfile = fopen(textfilename, "w");
if ( !outfile ) {
printf("Error al abrir %s: %s.\n", textfilename, strerror(errno));
exit(1);
}
fprintf(outfile,
"set terminal pngcairo nocrop enhanced size 1000,300 truecolor font 'Arial,10'\n"
"#set terminal png nocrop enhanced size 1000,300 # para gnuplot <= 4.2\n"
"se output '%s'\n"
"se xrange [0:%d]\n"
"se yrange [0:1.05]\n"
"se grid front lc rgb '#999999'\n"
"unset key\n"
"plot 'resul_espectro.x' binary filetype=avs with rgbimage, \\\n"
" 'resul_espectro.dat' w l lw 4 lc rgb 'white', \\\n"
" 'resul_espectro.dat' w l lw 2 lc rgb 'red'\n"
, graphfilename, linea.ancho - 1
);
fclose(outfile);
system("gnuplot resul_espectro.plot"); /* sí, está mal, TODO usar textfilename */
}
int main(int argc, char **argv)
{
t_linea linea;
char *infilename;
char *outfilename = "resul_espectro.dat";
int num_linea = 0;
unsigned int ancho = 0;
setlocale (LC_MESSAGES, "");
if (argc < 2 || argc > 4) {
puts("Uso: espectro <fichero.jpg> [linea] [+-lineas]");
exit(1);
}
else if (argc == 3) {
num_linea = atoi(argv[2]);
}
else if (argc == 4) {
num_linea = atoi(argv[2]);
ancho = atoi(argv[3]);
}
infilename = argv[1];
linea = read_jpeg_line(infilename, num_linea, ancho);
if (linea.ancho < 2) {
puts("Imagen no válida.");
exit(1);
}
printf("\nSe ha leído la línea %d de %d (+-%d).\nEl ancho de la linea es %d.\n",
linea.leida,
linea.alto, /* de la imagen, no de la linea */
ancho,
linea.ancho); /* no confundir el ancho de la linea con el ancho vertical de la ponderación */
/* Dibujar la imagen en formato AVS. */
writeimage("resul_espectro.x", linea);
/* Calcular el archivo de salida */
if (linea.colores == 3) {
int i;
int lum = 0;
unsigned char x,y,z;
int max = 0;
FILE *outfile;
/* Evaluar el máximo */
for (i = 0; i < (linea.ancho*3); i+=3) {
long acc;
x = linea.buffer[i];
y = linea.buffer[i+1];
z = linea.buffer[i+2];
/* lum = x+3*y+z; */
acc = x*x;
acc += y*y;
acc += z*z;
lum = sqrt(acc);
if (max < lum) max = lum;
}
printf("Imagen en color, valor máximo %d.\n", max);
printf("Escribiendo el archivo %s...\n", outfilename);
outfile = fopen(outfilename, "w");
if ( !outfile ) {
printf("Error al abrir %s: %s.\n", outfilename, strerror(errno));
exit(1);
}
/* Escribir los valores normalizados */
for (i = 0; i < (linea.ancho*3); i+=3) {
long acc;
x = linea.buffer[i];
y = linea.buffer[i+1];
z = linea.buffer[i+2];
/* lum = x+3*y+z; */
acc = x*x;
acc += y*y;
acc += z*z;
lum = sqrt(acc);
fprintf(outfile, "%i\t%f\n", i/3, lum/(float)max);
//printf("%i\t%x %x %x %d\t%f\n", i/3, x,y,z,lum,lum/(float)max);
}
fclose(outfile);
}
else if (linea.colores == 1) {
int i;
int max = 0;
FILE *outfile;
/* Evaluar el máximo */
for (i = 0; i < linea.ancho; i++) {
if (max < linea.buffer[i]) max = linea.buffer[i];
}
printf("Imagen en escala de grises, valor máximo %d.\n", max);
printf("Escribiendo el archivo %s...\n", outfilename);
outfile = fopen(outfilename, "w");
if ( !outfile ) {
printf("Error al abrir %s: %s.\n", outfilename, strerror(errno));
exit(1);
}
/* Escribir los valores normalizados */
for (i = 0; i < linea.ancho; i++) {
fprintf(outfile, "%i\t%f\n", i, linea.buffer[i]/(float)max);
}
fclose(outfile);
}
else {
puts("Tipo de imagen no reconocida.");
exit(1);
}
/* Dibujar el gráfico con gnuplot */
puts("Llamando a Gnuplot...");
do_gnuplot("resul_espectro.plot", "resul_espectro.png", linea);
puts("Hecho.");
return 0;
}
coyote@Miyuki ~$ gcc espectro.c -g -ljpeg -o espectro -Wall -lm
coyote@Miyuki ~$ ls -lh espectro*
-rwxr-xr-x 1 coyote users 27K oct 12 18:01 espectro
-rw-r--r-- 1 coyote users 9,0K oct 12 18:00 espectro.c
$ gcc main.c -g -ljpeg -o espectro -Wall -lm
$ ll
total 44K
-rwxr-xr-x 1 jose jose 29K 2010-10-12 18:09 espectro
-rw-r--r-- 1 jose jose 9,0K 2010-10-12 18:03 main.c
coyote escribió:Obviamente, también tendrías que instalar el paquete -dev de jpeg (o libjpeg)
sudo apt-get install libjpeg-dev
AzagraMac escribió:compilado, que curioso... a ti te deja el ejecutable con 27k a mi con 29k, por cierto compilado en Ubuntu 10.10 64Bits
CFLAGS="-march=native -mtune=native -O2 -pipe"
CXXFLAGS="-march=native -mtune=native -O2 -pipe"
MAKEFLAGS="-j3"
AzagraMac escribió:coyote escribió:Obviamente, también tendrías que instalar el paquete -dev de jpeg (o libjpeg)
listo, era lo que me faltabasudo apt-get install libjpeg-dev
compilado, que curioso... a ti te deja el ejecutable con 27k a mi con 29k, por cierto compilado en Ubuntu 10.10 64Bits
coyote@Miyuki ~$ ./espectro 2010-10-12-333547.jpeg
Incorporada la línea 312 de 624.
Se ha leído la línea 312 de 624 (+-0).
El ancho de la linea es 515.
Imagen en color, valor máximo 441.
Escribiendo el archivo resul_espectro.dat...
Llamando a Gnuplot...
sh: gnuplot: no se encontró la orden
Hecho.
AzagraMac escribió:a mi si me lanza gnuplot, de echo me ha dejado varios archivos donde tengo el .jpeg
Storz escribió:Muchas gracias a ambos, por cierto coyote:
Elije el color!
coyote escribió:Storz escribió:Muchas gracias a ambos, por cierto coyote:
Elije el color!
Me pillo el blanco (o azulao claro, según se mire)
try$ ./espectro test.jpg 1 2
Se ha le�do la l�nea 1 de 640 (+-2).
El ancho de la linea es 480.
Imagen en color, valor m�ximo 0.
Escribiendo el archivo resul_espectro.dat...
Llamando a Gnuplot...
set terminal pngcairo nocrop enhanced size 1000,300 truecolor font 'Arial,10'
^
"resul_espectro.plot", line 1: unknown or ambiguous terminal type; type just 'set terminal' for a list
Hecho.
set terminal pngcairo nocrop enhanced size 1000,300 truecolor font 'Arial,10'
#set terminal png nocrop enhanced size 1000,300 # para gnuplot <= 4.2
se output 'resul_espectro.png'
se xrange [0:479]
se yrange [0:1.05]
se grid front lc rgb '#999999'
unset key
plot 'resul_espectro.x' binary filetype=avs with rgbimage, \
'resul_espectro.dat' w l lw 4 lc rgb 'white', \
'resul_espectro.dat' w l lw 2 lc rgb 'red'
Storz escribió:Muchas gracias a ambos, por cierto coyote:
Elije el color!
$ ll
total 364K
-rwxr-xr-x 1 jose jose 29K 2010-10-12 19:33 espectro
-rw-r--r-- 1 jose jose 9,0K 2010-10-12 18:03 main.c
-rw-r--r-- 1 jose jose 222K 2010-09-27 23:26 prueba.jpg
-rw-r--r-- 1 jose jose 11K 2010-10-12 19:33 resul_espectro.dat
-rw-r--r-- 1 jose jose 418 2010-10-12 19:33 resul_espectro.plot
-rw-r--r-- 1 jose jose 48K 2010-10-12 19:33 resul_espectro.png
-rw-r--r-- 1 jose jose 32K 2010-10-12 19:33 resul_espectro.x
o$ ./espectro prueba.jpg
Incorporada la línea 366 de 732.
Se ha leído la línea 366 de 732 (+-0).
El ancho de la linea es 800.
Imagen en color, valor máximo 418.
Escribiendo el archivo resul_espectro.dat...
Llamando a Gnuplot...
Hecho.
G N U P L O T
Version 4.4 patchlevel 0
last modified March 2010
System: Linux 2.6.35-22-generic
Copyright (C) 1986-1993, 1998, 2004, 2007-2010
Thomas Williams, Colin Kelley and many others
gnuplot home: http://www.gnuplot.info
faq, bugs, etc: type "help seeking-assistance"
immediate help: type "help"
plot window: hit 'h'
Terminal type set to 'wxt'
gnuplot>
AzagraMac escribió:No es un poco diferente tu .png del mio?
y el tuyo