2012-07-30 15 views
6
#include <stdio.h> 
#include <stdint.h> 
#include <stdlib.h> 

int main() 
{ 
    FILE* bmp = NULL; 
    uint32_t offset; 
    uint8_t* temp = NULL; 
    size_t read; 
    unsigned int x_dim = 600, y_dim = 388; 

    bmp = fopen("test_colour.bmp", "r"); 

    if (!bmp) 
     return -1; 

    /* Get the image data offset */ 
    fseek(bmp, 10, SEEK_SET); 
    fgets((char*)&offset, 4, bmp); 

    printf("Offset = %u\n", offset); 

    temp = malloc(3*x_dim*y_dim*sizeof(uint8_t)); 

    if (!temp) 
     return -1; 

    /* Go the the position where the image data is stored */ 
    fseek(bmp, offset, SEEK_SET); 

    /* Copy image data to array */ 
    printf("%u bytes requested!\n", 3*x_dim*y_dim); 
    read = fread((void*)temp, sizeof(uint8_t), 3*x_dim*y_dim, bmp); 
    printf("%Iu bytes read!\n", read); 

    fclose(bmp); 
    free(temp); 

    return 0; 
} 

Sto utilizzando il codice precedente per leggere i dati RGB di un'immagine BMP a 24 bit per pixel su un array. L'offset dall'inizio del file in cui i dati dell'immagine iniziano (dopo l'intestazione BMP) viene fornito all'offset 10 in base alle specifiche BMP. Ottengo il seguente risultato quando si esegue il codice sopra.Valore di ritorno imprevisto da fread()

Offset = 54 
698400 bytes requested! 
33018 bytes read! 

L'output di offset sembra essere corretto perché la dimensione del file è 698454 byte (= 698400 + 54). Tuttavia, il valore restituito da fread() sembra indicare che non è possibile leggere l'intero dato dell'immagine. Tuttavia, sto successivamente utilizzando i dati nell'array temp per convertire i dati RGB in scala di grigi e scrivere nuovamente questi dati in un file BMP. Il controllo visivo dell'immagine di output non indica alcun errore, ad esempio sembra che in realtà io legga l'intera immagine di input in primo luogo sebbene fread() sembra indicare diversamente.

Qualcuno può spiegare questo comportamento?

+0

Due domande: 1) Puoi controllare il contenuto di 'temp' dopo la chiamata a' fread', per vedere se in realtà ha smesso di leggere dopo 33018 byte? 2) Non ho familiarità con l'identificatore di formato '% Iu' - puoi verificare il valore attuale di' read' nel debugger? – Treb

+0

Non penso che questo stia causando i sintomi che stai vedendo, ma dovresti usare le stringhe di formato 'printf' corrette. Il formato per 'size_t' è' "% zu" '. '"% Iu "' non è standard. Se la tua implementazione non supporta '"% zu "', puoi usare 'printf ("% lu byte letti! \ N ", (unsigned long) read);' –

+0

Sto usando gcc con MinGW per compilare e il il compilatore non riconosce l'identificatore '% zu' (ho provato ad usarlo prima). Ho letto che bisogna usare '% Iu' in Windows. – simon

risposta

20

(Scommetto che siete su Windows)

bmp = fopen("test_colour.bmp", "r"); 

dovrebbe essere

bmp = fopen("test_colour.bmp", "rb"); 

Se il file viene aperto in modalità testo su Windows, il runtime smettere di leggere quando succede per colpire un byte 0x1a (Ctrl-Z), che Windows considera un indicatore EOF per i file di testo. Anche se non colpisce Ctrl-Z, i dati corruttibili vengono visualizzati quando Windows converte sequenze CR/LF in un singolo carattere LF.

Tuttavia, non riesco a spiegare perché sei in grado di ottenere una buona immagine dal file parziale letto (solo fortunato?).

Sei in grado di rendere un'immagine dal buffer perché l'implementazione fread() fa leggere il numero di byte richiesti (o quasi - il numero viene arrotondato ad un multiplo di una certa dimensione di blocco) nel buffer, allora esegue la scansione del buffer alla ricerca di sequenze CR/LF da convertire e di flag EOF Ctrl-Z.

Quindi, anche se fread() restituisce 33018, il buffer è stato quasi completamente scritto con i dati del file. I dati non sono corretti al 100% (ad esempio, alcuni caratteri CR sono stati probabilmente scartati) o completi, ma in questo caso è abbastanza vicino da rendere un'immagine che assomiglia a quella che ti aspettavi.

Naturalmente, questa è semplicemente un'osservazione di come questo particolare runtime si comporta attualmente - potrebbe non comportarsi sempre in questo modo in futuro (o anche su tutti i sistemi oggi).

+0

Infatti, sono dimenticato di menzionare in OP. Grazie per averlo indicato, risolto il problema! Sei sicuro che in realtà smetta di leggere? Come accennato, ero ancora in grado di fornire un'immagine in scala di grigi corretta dell'intera immagine di BMP, anche se secondo 'fread' solo il ~ 5% dei dati del file è stato effettivamente letto. – simon

+0

@simon: è possibile che il runtime legge il numero di byte richiesto nel buffer, quindi lo attraversa e "aggiusta" le terminazioni di linea e le conversioni EOF. Ma sto solo supponendo. –

+0

Ho confrontato le due immagini di output generate (una aprendo il file con '" r "' e l'altra con '" rb "') con diff e non sono la stessa cosa. Guardando visivamente le immagini, l'unica differenza sembra essere che gli ultimi pixel dell'immagine "" r "sono neri mentre dovrebbero essere effettivamente bianchi. Quindi suppongo che 'fread' in realtà legge più byte di quanto indicato dal valore restituito, ma non necessariamente il numero effettivo di byte richiesti. – simon

Problemi correlati