2012-07-30 31 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; 
} 

मैं उपरोक्त कोड का उपयोग 24-बिट प्रति पिक्सल बीएमपी छवि के आरजीबी डेटा को सरणी में पढ़ने के लिए कर रहा हूं। फ़ाइल की शुरुआत से ऑफसेट जहां छवि डेटा शुरू होता है (बीएमपी हेडर के बाद) बीएमपी विनिर्देश के अनुसार ऑफ़सेट 10 पर दिया जाता है। उपर्युक्त कोड निष्पादित करते समय मुझे निम्न आउटपुट मिलता है।फ़्रेड से अप्रत्याशित वापसी मूल्य()

Offset = 54 
698400 bytes requested! 
33018 bytes read! 

ऑफ़सेट आउटपुट सही लगता है क्योंकि फ़ाइल का आकार 698454 बाइट्स (= 698400 + 54) है। हालांकि, fread() द्वारा लौटाया गया मान इंगित करता है कि पूरे छवि डेटा को पढ़ा नहीं जा सकता है। हालांकि, मैं बाद में temp सरणी में डेटा का उपयोग कर आरजीबी डेटा को ग्रेस्केल में परिवर्तित करने और इस डेटा को फिर से बीएमपी फ़ाइल में लिखने के लिए उपयोग कर रहा हूं। आउटपुट छवि की दृष्टि से जांच करने से कोई त्रुटि नहीं आती है, यानी ऐसा लगता है जैसे मैं वास्तव में पहली इनपुट छवि को पहले स्थान पर पढ़ता हूं हालांकि fread() अलग-अलग संकेत मिलता है।

क्या कोई इस व्यवहार को समझा सकता है?

+0

दो प्रश्न: 1) क्या आप 'fread' पर कॉल के बाद' temp' की सामग्री जांच सकते हैं, यह देखने के लिए कि क्या यह वास्तव में 33018 बाइट्स के बाद पढ़ना बंद कर दिया गया है? 2) मैं '% IU' प्रारूप विनिर्देशक से अपरिचित हूं - क्या आप डीबगर में 'read' के वास्तविक मान को देख सकते हैं? – Treb

+0

मुझे नहीं लगता कि यह आपके द्वारा देखे जा रहे लक्षणों का कारण बन रहा है, लेकिन आपको सही 'printf' प्रारूप तारों का उपयोग करना चाहिए। 'Size_t' के लिए प्रारूप' "% zu" 'है। '"% Iu "' गैर-मानक है। यदि आपका कार्यान्वयन '% zu" का समर्थन नहीं करता है, तो आप 'printf ("% lu बाइट्स पढ़ सकते हैं! \ N", (हस्ताक्षरित लंबे) पढ़ सकते हैं); ' –

+0

मैं संकलन करने के लिए मिनीजीडब्ल्यू के साथ जीसीसी का उपयोग कर रहा हूं और कंपाइलर '% zu' विनिर्देशक को पहचान नहीं करता है (मैंने पहले उस का उपयोग करने की कोशिश की थी)। मैंने पढ़ा है कि विंडोज़ में '% Iu' का उपयोग करना है। – simon

उत्तर

20

(मुझे यकीन है हूँ आप Windows पर हैं)

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

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

होना चाहिए फ़ाइल Windows पर पाठ मोड में खोला जाता है, क्रम पढ़ने जब ऐसा होता है बंद हो जाएगा 0x1a (Ctrl-Z) बाइट हिट करने के लिए, जो विंडोज़ टेक्स्ट फ़ाइलों के लिए एक ईओएफ मार्कर मानता है। यहां तक ​​कि यदि यह Ctrl-Z नहीं दबाता है, तो भी जब आप सीआर/एलएफ अनुक्रमों को एक एलएफ चरित्र में परिवर्तित करते हैं तो आपको दूषित डेटा मिल जाएगा।

हालांकि, मैं समझा नहीं सकता कि आप आंशिक फ़ाइल पढ़ने (बस भाग्यशाली?) से एक अच्छी छवि क्यों प्राप्त कर सकते हैं।

आप क्योंकि fread() कार्यान्वयन बाइट्स आपके द्वारा अनुरोध की संख्या पढ़ा करता बफर से एक छवि प्रस्तुत करना करने में सक्षम हैं (या लगभग इतनी - संख्या कुछ ब्लॉक आकार की एक बहु के लिए नीचे गोल हो जाता है) बफर में है, तो यह कनवर्ट करने के लिए सीआर/एलएफ अनुक्रमों और Ctrl-Z EOF झंडे की तलाश करने वाले बफर को स्कैन करता है।

तो fread()33018 लौटाता है, बफर वास्तव में फ़ाइल से डेटा के साथ लगभग पूरी तरह से लिखा गया है। डेटा 100% सही नहीं है (उदाहरण के लिए, कुछ सीआर अक्षरों को शायद हटा दिया गया था) या पूरा हो गया है, लेकिन इस मामले में यह एक ऐसी छवि प्रस्तुत करने के लिए पर्याप्त है जो आपके जैसा अपेक्षित दिखता है।

बेशक, यह केवल एक अवलोकन है कि यह विशेष रनटाइम वर्तमान में कैसे व्यवहार करता है - यह भविष्य में हमेशा इस तरह से व्यवहार नहीं कर सकता है (या आज भी सभी प्रणालियों पर)।

+0

वास्तव में मैं ओपी में उल्लेख करना भूल गया हूं। उस बिंदु को इंगित करने के लिए धन्यवाद, समस्या हल हो गई! क्या आप वाकई पढ़ना बंद कर देते हैं? जैसा कि बताया गया है, मैं अभी भी पूरी बीएमपी छवि की एक सही ग्रेस्केल छवि देने में सक्षम था हालांकि 'डेटा' के अनुसार ~ डेटा डेटा का केवल ~ 5% वास्तव में पढ़ा गया था। – simon

+0

@simon: यह संभव है कि रनटाइम आपके द्वारा बफर में अनुरोध किए गए बाइट्स की संख्या को पढ़ता है, फिर इसके माध्यम से जाता है और लाइन एंडिंग और ईओएफ अनुवादों को 'फिक्स-अप' करता है। लेकिन मैं बस अनुमान लगा रहा हूँ। –

+0

मैंने उत्पन्न दो आउटपुट छवियों की तुलना की है (एक '' आर '' के साथ फ़ाइल खोलकर और दूसरा '' आरबी "' के साथ) और वे समान नहीं हैं। छवियों को देखकर, केवल अंतर यह प्रतीत होता है कि 'आर' छवि में अंतिम कुछ पिक्सेल काले हैं जबकि उन्हें वास्तव में सफेद होना चाहिए। तो मुझे लगता है कि 'फ्रेड' वास्तव में वापसी मूल्य द्वारा इंगित की तुलना में अधिक बाइट्स पढ़ता है, लेकिन जरूरी नहीं कि बाइट्स की वास्तविक संख्या अनुरोध की गई हो। – simon