2011-09-19 10 views
6

डेल्फी & सी ++ बिल्डर के पास एक स्कैनलाइन संपत्ति वाला एक टीबीटमैप क्लास है जो बिटमैप के पिक्सल की स्मृति देता है। जब मैं बीएमपी फ़ाइल के हेक्स संपादक में देखता हूं तो यह अलग दिखता है।टीबीआईटीएमएपी को समझना। डेल्फी और सी ++ बिल्डर में स्कैनलाइन

मैं जावा में एक सी ++ बिल्डर ऐप पोर्ट करने की कोशिश कर रहा हूं, और स्कैनलाइन में एल्गोरिदम को समझना चाहता हूं। अगर मेरे पास फ़ाइल है, तो मैं स्कैनलाइन की तरह मेमोरी सरणी कैसे उत्पन्न करूं? स्कैनलाइन के पीछे सटीक कल्पना क्या है?

क्लारिफ़िकेशन: बीएमपी एक विंडोज 24 बिट डीआईबी है। मैं कोड में कोई अन्य जानकारी प्रदान नहीं करता; सी ++ बिल्डर इसे किसी प्रकार की मेमोरी स्ट्रक्चर में लोड करने लगता है, लेकिन यह बाइट-फॉर-बाइट नहीं है। जानना चाहते हैं कि उस संरचना का नमूना क्या है।

+0

नाम "TBitmap" जरूरी माइक्रोसॉफ्ट "बिटमैप" फ़ाइल स्वरूप से कोई लेना देना नहीं है, क्या आप जानते हैं ! डेल्फी "टीबीटमैप" में "स्कैनलाइन" संपत्ति केवल एक रास्टर लाइन है - कुछ भी नहीं, कुछ भी कम नहीं। – paulsm4

+1

बिटमैप फ़ाइल का पिक्सेल प्रारूप क्या है और आप इसे TBitmap में कैसे लोड करते हैं? क्या आपका बिटमैप ऊपर या नीचे नीचे संग्रहीत है? –

+0

संरचना का कौन सा हिस्सा आप समझना चाहते हैं? TBitmap फ़ील्ड, या पिक्सेल डेटा? –

उत्तर

8

एक बिटमैप फ़ाइल BITMAPFILEHEADER के साथ शुरू होती है, bfOffBits सदस्य छवि डेटा का प्रारंभिक पता निर्दिष्ट करता है। यह ध (11-14 वें बाइट्स) में एक ड्वॉर्ड है। डेल्फी वीसीएल में 'windows.pas' में TBitmapFileHeader के रूप में परिभाषित संरचना है।

ScanLine की अंतिम पंक्ति इस छवि डेटा (नीचे-अप) पर इंगित करती है। वीसीएल में यह मूल्य bmBitsdsBm (BITMAP) सदस्य या DIBSECTION छवि का सदस्य है। जब एक स्कैन लाइन का अनुरोध किया जाता है, तो वीसीएल अनुरोधित पंक्ति के आधार पर ऑफ़सेट की गणना करता है, पंक्ति में पिक्सल की संख्या (छवि की चौड़ाई) और कितने बिट्स पिक्सेल बनाते हैं, और इस ऑफसेट को जोड़ने वाले पते पर पॉइंटर लौटाते हैं bmBits। यह वास्तव में बाइट-बाय-बाइट छवि डेटा है।

नीचे डेल्फी नमूना कोड एक फ़ाइल स्ट्रीम में एक 24bit बिटमैप पढ़ता है और Bitmap.ScanLine समकक्ष की पिक्सेल डेटा के साथ प्रत्येक पढ़ने पिक्सेल तुलना:

procedure TForm1.Button1Click(Sender: TObject); 
var 
    BmpFile: string; 
    Bmp: TBitmap; 

    fs: TFileStream; 
    FileHeader: TBitmapFileHeader; 
    InfoHeader: TBitmapInfoHeader; 
    iHeight, iWidth, Padding: Longint; 

    ScanLine: Pointer; 
    RGBFile, RGBBitmap: TRGBTriple; 
begin 
    BmpFile := ExtractFilePath(Application.ExeName) + 'Attention_128_24.bmp'; 

    // laod bitmap to TBitmap 
    Bmp := TBitmap.Create; 
    Bmp.LoadFromFile(BmpFile); 
    Assert(Bmp.PixelFormat = pf24bit); 

    // read bitmap file with stream 
    fs := TFileStream.Create(BmpFile, fmOpenRead or fmShareDenyWrite); 
    // need to get the start of pixel array 
    fs.Read(FileHeader, SizeOf(FileHeader)); 
    // need to get width and height of bitmap 
    fs.Read(InfoHeader, SizeOf(InfoHeader)); 
    // just a general demo - no top-down image allowed 
    Assert(InfoHeader.biHeight > 0); 
    // size of each row is a multiple of the size of a DWORD 
    Padding := SizeOf(DWORD) - 
     (InfoHeader.biWidth * 3) mod SizeOf(DWORD); // pf24bit -> 3 bytes 

    // start of pixel array 
    fs.Seek(FileHeader.bfOffBits, soFromBeginning); 


    // compare reading from file stream with the value from scanline 
    for iHeight := InfoHeader.biHeight - 1 downto 0 do begin 

    // get the scanline, bottom first 
    ScanLine := Bmp.ScanLine[iHeight]; 

    for iWidth := 0 to InfoHeader.biWidth - 1 do begin 

     // read RGB from file stream 
     fs.Read(RGBFile, SizeOf(RGBFile)); 

     // read RGB from scan line 
     RGBBitmap := TRGBTriple(Pointer(
         Longint(ScanLine) + (iWidth * SizeOf(TRGBTriple)))^); 

     // assert the two values are the same 
     Assert((RGBBitmap.rgbtBlue = RGBFile.rgbtBlue) and 
      (RGBBitmap.rgbtGreen = RGBFile.rgbtGreen) and 
      (RGBBitmap.rgbtRed = RGBFile.rgbtRed)); 
    end; 
    // skip row padding 
    fs.Seek(Padding, soCurrent); 
    end; 
end; 



की पिक्सेल डेटा की शुरुआत खोजने के बारे में एक तस्वीर एक हेक्स संपादक में एक बिटमैप फ़ाइल:

enter image description here

+3

सुपर उत्तर! क्या मैं समझने में सही हूं कि केवल अंतर यह है कि TBitmap.ScanLine नीचे-पंक्ति-प्रथम है, जबकि फ़ाइल शीर्ष-पंक्ति-प्रथम है, लेकिन प्रत्येक पंक्ति को बाइट्स के समान अनुक्रम के रूप में प्रस्तुत करेगा? (कम से कम 24 बिट डीआईबी के लिए, जो मैं कर रहा हूं।) – SRobertJames

+0

अधिकांश विंडोज़ बिटमैप्स नीचे-नीचे हैं इसलिए बिटमैप फ़ाइल में पहले पंक्ति है। 'बीएमबीट्स 'एक ही डेटा के लिए सिर्फ एक सूचक है जो स्मृति में है (पंक्तियों के संरेखण को छोड़कर स्मृति लेआउट के लिए थोड़ा अलग है)। जब स्कैनलाइन से अनुरोध किया जाता है कि वीसीएल खातों को ग्राफिक्स.pas में 'TBitmap.GetScanLine' में 'तल-अप' के लिए खाते हैं। यदि आप, फाई, अंतिम पंक्ति का अनुरोध करें ('Bmp.ScanLine [Bmp.Height - 1]') और बिटमैप नीचे-नीचे है, वीसीएल पिक्सेल सरणी की पहली पंक्ति में एक पॉइंटर देता है (जैसा कि अंतिम पंक्ति scanline)। –

+0

अभी भी समझ में परेशानी है। मैं अपने हेक्स संपादक में स्पष्ट रूप से देखता हूं कि बाइट काफी अलग हैं। क्या एकमात्र अंतर पंक्ति क्रम उलटा हुआ है? – SRobertJames

संबंधित मुद्दे