PDA

View Full Version : Una domanda sul formato JPEG


misterx
18-04-2002, 15:09
Ho scritto questo semplice programma il cui scopo è di prelevare da un file JPEG le dimensioni, in pixel, dell'immagine in esso
contenuta.

Ha però i seguenti problemi:
a) non mi è possibile conoscere a priori il numero di chunck presenti nel file
b) non so se sto agendo in modo pulito e corretto

Fate delle prove con differenti JPEG e noterete subito le differenze

Quando il chunck è uno solo, le dimensioni delle immagini vengono riportate nel modo corretto: no se si è in presenza di due o addirittura più chunck.

La morale è che desidererei ottenere del codice più pulito; potrei inserire un piccolo loop in modo da scansare i chunk superflui ma
sono sicuro che esiste un'altra strada più pulita.

Magari tra di voi c'è chi conosce la struttura dei file JPEG.

Spero di essere stato chiaro, altrimenti; chiedete pure.


ecco il codice:


#include<stdio.h>

main() // qui potete mettere i consueti: main(int argc, char *argv[])
{

FILE *fp;
int c, oldc = 0, JpegHeight, JpegWidth, test = 0;


fp = fopen("miojpeg.jpg","rb");
if(!fp) exit(20);

// test per conoscere quante sequenze 0xFF e 0x0C esistono nel file
// l'ultima sequenza, dopo 3 BYTE contiene le dimensioni H/W dell'immagine
while ( (c = fgetc(fp) ) != EOF)
{
if(oldc == 0xFF && c == 0xC0) test++;
oldc = c;
}
printf("Chunck Trovati: %d\n",test);
fclose(fp);

// riapro nuovamente il file
fp = fopen("miojpeg.jpg","rb");
if(!fp) exit(20);

// ricerco la sequenza di byte 0xFF e 0x0C
while ( (c = fgetc(fp) ) != EOF)
{
if(oldc == 0xFF && c == 0xC0) break;
oldc = c;
}
// salto tre BYTE
c = fgetc(fp); c = fgetc(fp); c = fgetc(fp);

// leggo 2 byte in una word
JpegHeight = (fgetc(fp) << 8) | (fgetc(fp) << 0);
JpegWidth = (fgetc(fp) << 8) | (fgetc(fp) << 0);

// mando in display il risultato
printf("Larghezza: %d\n",JpegWidth);
printf("Altezza: %d\n", JpegHeight);


fclose(fp);

Another
19-04-2002, 17:59
Io ho fatto proprio qsta settimana qcosa del genere in ColdFusion, e ho dovuto trigare parecchio per trovare qche dritta, alla fine per trovare i byte con le dimensioni ho cercato la stringa {FF C0 00 11 08} (che è più o meno la stessa cosa che fai tu) e fino ad ora nn ho avuto problemi ma nn ho provato con tanti file.

Ciao

misterx
19-04-2002, 20:25
Originariamente inviato da Another
[B]Io ho fatto proprio qsta settimana qcosa del genere in ColdFusion, e ho dovuto trigare parecchio per trovare qche dritta, alla fine per trovare i byte con le dimensioni ho cercato la stringa {FF C0 00 11 08} (che è più o meno la stessa cosa che fai tu) e fino ad ora nn ho avuto problemi ma nn ho provato con tanti file.

Ciao


provo anche questa, grazie infinite;)

misterx
20-04-2002, 14:23
cionci

dici che si riesce a semplificare il codice seguente?

a mio parere ho messo troppe if(....)

Ciao

if(c == 0xFF )
{
c = fgetc(fp);

if(c == 0xC0)
{
c = fgetc(fp);
if(c == 0x0)
{
c = fgetc(fp);
if(c == 0x11)
{
c = fgetc(fp);
if(c == 0x08) break;
}
}
}
}

MickMacello
20-04-2002, 15:30
fai uno switch... case


arh arh arh ;)

cionci
20-04-2002, 17:22
Ho fatto un po' di prove...e ho visto che tutti i file fatti in Photoshop vengono suddivisi in + chunk...prova un po' con quelli...

Concordo con MickMacello...

misterx
20-04-2002, 19:55
Originariamente inviato da MickMacello
[B]fai uno switch... case


arh arh arh ;)


ma non è ancora una sorta di if(......)?

misterx
21-04-2002, 10:44
Originariamente inviato da cionci
[b]Ho fatto un po' di prove...e ho visto che tutti i file fatti in Photoshop vengono suddivisi in + chunk...prova un po' con quelli...



quando salvi un file jpeg in Photoshop, hai 3 possibilità:

a) Linea base (Standard)
b) Linea base (Ottimizzata)
c) Progressione Ottimizzata

per tutti i file che rispondono alla (a/b) è possibile col codice da me postato ricavarne le dimensioni (H/L) in modo corretto

quelli che rispondono al punto (c) depistano il mio codice in quanto la sequenza (FF C0 00 11 08) non è più valida; temo che si debba ricercare altro, è quel altro che mi sfugge:)

cionci
21-04-2002, 11:20
Nono...io ho provato con un file di discrete dimensioni ed ho usato la Base Linear e non funziona uguale...

cionci
21-04-2002, 11:27
Mi dice che ci sono 2 chunk e la dimensione è di 97 x 112...invece la dimensione reale è di 502 x 582... Nota che 502/97 = 582/112 (arrotondando un po')...

PS: sto parlando del programma che hai postato...non con il ciclo modificato...

cionci
21-04-2002, 11:30
Come dicevi tu...facendo qualche piccola modifica al programma si riesce ad ottenere la dimensione per i primi 2 metodi...mentre per il terzo non funziona...

misterx
21-04-2002, 13:37
ok, temo che dovrò arrivarci per tentativi......


riguardo alla lunga catena di if(......)


se si usasse un buffer ampio 5 byte che si riempie al contrario?

poi dovrei usare: if(buf[4] == 0x... && buf[3] == 0x...)

sarebbe più efficiente?

lo chiedo in quanto con il codice da me postato ho intenzione di rilevare le dimensioni (H/L) di migliaia di file, e non di uno solo file quindi, più è veloce e meglio è:)

cionci
21-04-2002, 17:14
Puoi tranquillamente leggere un byte alla volta e anche usare una serie di if...stai tranquillo, non avrai problemi di velocità...

Aumentare il buffer non serve niente...visto che fopen, fgetc, fread & company sono già internamente bufferizzate...

misterx
22-04-2002, 20:21
ti riferisci ai fmosi 512 byte?

oggi mi è capitata una cosa alquano misteriosa; usando il codice postato, ho trovato immagini per le quali i valori W/H erano errati.

Copindo il file nella cartella che conteneva l'eseguibile, venivano ritornati i valori corretti.

Ho fatto parecchie prove ottenendo i medesimi risultati.

Mistero della scienza mah......

cionci
22-04-2002, 20:37
Originariamente inviato da misterx
[B]ti riferisci ai fmosi 512 byte?

oggi mi è capitata una cosa alquano misteriosa; usando il codice postato, ho trovato immagini per le quali i valori W/H erano errati.

Copindo il file nella cartella che conteneva l'eseguibile, venivano ritornati i valori corretti.

Ho fatto parecchie prove ottenendo i medesimi risultati.

Mistero della scienza mah......
Non so di preciso quanto sia grosso il buffer della fopen, ma credo intorno ai 4Kb...

Riguardo alla dimensione errata non è che il programma accedeva al file che si trovava nella sua stessa directory e non al file che gli apssavi te ?

misterx
22-04-2002, 20:40
no no, passavo il file corretto.....

saranno mica i soliti buffer che si crea windows; ho già avuto incontri ravvicinati di questo tipo..... mah

Another
23-04-2002, 12:07
Nn avevo provato con il il file salvato in 'progressive' ed in effetti non contiene la sequenza (FF C0 00 11 08) però c'è la (FF C2 00 11 08) :D

Fatemi sapere..

Another
23-04-2002, 14:41
:)

Ho fatto la modifica e sembra funzionare:
cerco l'ultima stringa FF C2 00 11 08, se la trovo è progressive, altrimenti cerco l'ultima FF C0 00 11 08.

cionci
23-04-2002, 20:08
Funziona perfettamente !!! ;)

misterx
23-04-2002, 21:45
Originariamente inviato da Another
[B]:)

Ho fatto la modifica e sembra funzionare:
cerco l'ultima stringa FF C2 00 11 08, se la trovo è progressive, altrimenti cerco l'ultima FF C0 00 11 08.

ok, grazie; allora per le jpeg ribelli farò così:

1) leggo 0xFF
2) per il secondo byte, va bene qualsiasi valore
3) leggo 0x0
4) leggo 0x11
5) leggo 0x08

sperando che non esistano altri chunk depistanti;)

provo, casomai torno sui miei passi:)