2011-10-11 14 views
8

एक नव निर्मित बिटमैप डिफ़ॉल्ट रूप से एक (सफेद) पृष्ठभूमि प्रतीत होता है। कम से कम, पिक्सेल संपत्ति पर एक प्रश्न पुष्टि करता है। लेकिन Transparent पर सेट होने पर पृष्ठभूमि रंग को पारदर्शी रंग के रूप में क्यों उपयोग नहीं किया जाता है?पहले पेंट करने की आवश्यकता के बिना बिटमैप ट्रांसपरेंसी कैसे प्राप्त करें?

यह साधारण परीक्षण कोड पर विचार करें:

procedure TForm1.Button1Click(Sender: TObject); 
var 
    Bmp: TBitmap; 
begin 
    Bmp := TBitmap.Create; 
    try 
    Bmp.Width := 100; 
    Bmp.Height := 100; 
    Bmp.Transparent := True; 
    Canvas.Draw(0, 0, Bmp);        // A white block is drawn 
    Bmp.Canvas.Brush.Color := Bmp.Canvas.Pixels[0, 99]; // = 'clWhite' 
    Bmp.Canvas.FillRect(Rect(0, 0, 100, 100)); 
    Canvas.Draw(0, 100, Bmp);       // "Nothing" is drawn 
    finally 
    Bmp.Free; 
    end; 
end; 

किसी कारण से, पूरे बिटमैप सतह से पहले यह पारदर्शी, अजीब की तरह लगता है जो प्रदर्शित कर सकते हैं चित्रित किया जाना है।

निम्नलिखित रूपों FillRect करने के लिए कॉल समाप्त करने के लिए, एक ही परिणाम (कोई पारदर्शिता) के साथ सभी की कोशिश की जाती हैं:

  • केवल Brush.Color की स्थापना,
  • Brush.Handle := CreateSolidBrush(clWhite),
  • PixelFormat := pf32Bit,
  • IgnorePalette := True ,
  • TransparantColor := clWhite,
  • TransparantMode := tmFixed,
  • Canvas.Pixels[0, 99] := clWhite जो केवल कि पिक्सेल पारदर्शी बनाता है,
  • Modified := True

तो, इच्छा केवल नव निर्मित बिटमैप के केवल एक हिस्से को पेंट करना और शेष सतह पारदर्शी प्राप्त करना है।

का उपयोग करना: डेल्फी 7, ​​विन 7/64।

+1

अगर आप का पालन करें तो क्या होता है [इस] (http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Graphics_TBitmap_TransparentMode.html) उदाहरण ? –

+0

क्या आप बस कुछ भी आकर्षित नहीं करना चाहते हैं? क्या आप एक पूर्ण पारदर्शी बिटमैप तैयार करना चाहते हैं? – Shambhala

+0

@ शमबाला नहीं, मैं सिर्फ एक (छोटा) हिस्सा आकर्षित करना चाहता हूं। – NGLN

उत्तर

8

बस TransparentColor और बिटमैप के आयाम निर्धारित करने से पहले Canvas.Brush.Color निर्धारित किया है।

+0

हां! और TransparentColor सेट करने की कोई ज़रूरत नहीं है। कैनवास सेट करना। ब्रश। रंग देने के आयाम आयाम चाल करता है। धन्यवाद। – NGLN

+3

कोई भी जानता है कि ऐसा क्यों है? क्या आपको ब्रश रंग सेट करने की भी आवश्यकता है? क्या ब्रश हैंडल को अस्तित्व में रखने के लिए पर्याप्त है? –

+0

@ डेविड अच्छा बिंदु। 'कैनवास। ब्रश। हैंडल: = 0' भी काम करता है, आश्चर्यजनक रूप से पर्याप्त है। – NGLN

1

यह एक लाल वर्ग खींच जाएगा और बाकी पारदर्शी होगा।

procedure TForm1.btnDrawClick(Sender: TObject); 
var 
    Bmp: TBitmap; 
begin 
    Bmp := TBitmap.Create; 
    try 
    Bmp.Width := 100; 
    Bmp.Height := 100; 
    Bmp.Transparent := TRUE; 
    Bmp.TransparentColor := clWhite; 

    Bmp.Canvas.Brush.Color := clWhite; 
    Bmp.Canvas.FillRect(Rect(0, 0, Bmp.Width, Bmp.Height)); 
    Bmp.Canvas.Brush.Color := clRed; 
    Bmp.Canvas.FillRect(Rect(42, 42, 20, 20)); 
    Canvas.Draw(12, 12, Bmp); 
    finally 
    Bmp.Free; 
    end; 
end; 
+0

इच्छा है कि इस परिणाम को पहले FillRect के बिना प्राप्त करना है, जैसा कि प्रश्न में स्पष्ट रूप से बताया गया है। -1 – NGLN

3

मुझे वास्तव में 32 बिट आरजीबीए प्रारूप में मनमानी आकार के टीबीटमैप को पूरी तरह से पारदर्शी (और अन्यथा खाली/खाली) बनाने में सक्षम होने की आवश्यकता है। कई बार। लाज़र टीबीटमैप में इस तरह के बिटमैप को लोड करने में सक्षम है और इसे लोड करने के बाद, आप स्कैनलाइन के साथ इसका उपयोग कर सकते हैं और आरजीबीए प्रारूप का उपयोग नहीं कर रहे हैं। लेकिन जब आप टीबीटमैप स्वयं बनाते हैं तो यह काम नहीं करता है। पिक्सेल प्रारूप पूरी तरह से अनदेखा प्रतीत होता है। तो मैंने जो किया वह बॉक्स से बाहर है, और सरल है, कि यह लगभग आश्चर्यजनक (!) है। लेकिन यह व्यावहारिक है, बहुत अच्छा काम करता है, और एलसीएल और किसी तीसरे पक्ष के पुस्तकालयों से पूरी तरह से स्वतंत्र है। ग्राफिक्स यूनिट पर भी निर्भर नहीं है, क्योंकि यह वास्तविक 32 बिट आरजीबीए बीएमपी फ़ाइल उत्पन्न करता है (मैं इसे टीएममोरीस्ट्रीम में उत्पन्न करता हूं, आप अलग-अलग उत्पन्न कर सकते हैं)। फिर एक बार आपके पास यह हो जाने के बाद, आपके कोड में कहीं और आप इसे TBitmap.LoadFrom स्रोत या TPicture.LoadFrom स्रोत का उपयोग करके लोड कर सकते हैं।

पृष्ठभूमि कहानी मैं शुरू में यहां बताए अनुसार ठीक से प्रारूपित बीएमपी फ़ाइल स्वरूप निम्नलिखित उत्पन्न करने के लिए चाहता था: http://www.fileformat.info/format/bmp/egff.htm लेकिन वहाँ बीएमपी प्रारूप के कुछ वेरिएंट थे, और मैं स्पष्ट नहीं था जो एक पर मैं पालन करने वाला था । तो मैंने एक रिवर्स इंजीनियरिंग दृष्टिकोण के साथ जाने का फैसला किया, लेकिन स्वरूप विवरण ने मुझे बाद में मदद की। मैंने एक खाली 1x1 पिक्सेल 32 आरजीबीए बीएमपी फ़ाइल बनाने के लिए एक ग्राफिकल संपादक (मैंने जीआईएमपी का उपयोग किया) का उपयोग किया, और इसे अल्फा 1 पी.बीएमपी कहा, इसमें केवल पारदर्शिता नहीं थी। फिर मैंने कैनवास को 10x10 पिक्सेल में बदल दिया, और अल्फा 10 पी के रूप में सहेजा।बीएमपी फ़ाइल। फिर मैंने दो फाइलों की तुलना की: compating two bmp files in vbindiff on Ubuntu तो मुझे पता चला कि केवल अंतर ही जोड़े गए पिक्सल थे (प्रत्येक एक 4 बाइट्स सभी शून्यों आरजीबीए था), और हेडर में कुछ अन्य बाइट्स थे। मैंने साझा किए गए लिंक पर प्रारूप प्रलेखन के कारण, मुझे पता चला कि ये थे: FileSize (बाइट्स में), BitmapWidth (पिक्सल में), BitmapHeight (पिक्सल में) और BitmapDataSize (बाइट्स में)। अंतिम एक BitmapWidth*BitmapHeight*4 था, क्योंकि आरजीबीए में प्रत्येक पिक्सेल 4 बाइट्स है। तो अब, मैं अल्फा 1p.bmp फ़ाइलों के अंदर देखे गए बाइट्स के पूरे अनुक्रम को उत्पन्न कर सकता हूं, अंत से 4 बाइट घटाएं (BitmapData का पहला), फिर प्रत्येक पिक्सेल के लिए आरजीबीए डेटा के 4 बाइट्स (सभी शून्य) जोड़ें बीएमपी मैं उत्पन्न करना चाहता हूं, फिर प्रारंभिक अनुक्रम पर वापस आएं और परिवर्तनीय भागों को अद्यतन करें: फ़ाइल आकार, चौड़ाई, ऊंचाई और बीएमपी डेटा आकार। और यह बेकार ढंग से काम करता है! मुझे बस बिगइंडियन के लिए परीक्षण जोड़ना पड़ा और लिखने से पहले शब्द और शब्द संख्या को स्वैप करना होगा। बिगएंडियन में काम कर रहे एआरएम मंचों पर यह मुद्दा बन जाएगा।

कोड

const 
    C_BLANK_ALPHA_BMP32_PREFIX : array[0..137]of byte 
    = ($42, $4D, $00, $00, $00, $00, $00, $00, $00, $00, $8A, $00, $00, $00, $7C, $00, 
    $00, $00, $0A, $00, $00, $00, $0A, $00, $00, $00, $01, $00, $20, $00, $03, $00, 
    $00, $00, $90, $01, $00, $00, $13, $0B, $00, $00, $13, $0B, $00, $00, $00, $00, 
    $00, $00, $00, $00, $00, $00, $00, $00, $00, $FF, $00, $00, $FF, $00, $00, $FF, 
    $00, $00, $FF, $00, $00, $00, $42, $47, $52, $73, $00, $00, $00, $00, $00, $00, 
    $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, 
    $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, 
    $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $02, $00, $00, $00, $00, $00, 
    $00, $00, $00, $00, $00, $00, $00, $00, $00, $00); 

(...) 

    Function RenderEmptyAlphaBitmap(AWidth,AHeight: integer): TMemoryStream; 
    var 
    buf : array[1..4096]of byte; 
    i,p : int64; 
    w : word; 
    dw : dword; 
    BE : Boolean; 
    begin 
    buf[low(buf)] := $00; //this is jyst to prevent compiler warning about not initializing buf variable 
    Result := TMemoryStream.Create; 
    if(AWidth <1)then AWidth := 1; 
    if(AHeight<1)then AHeight := 1; 
    //Write File Header: 
    Result.Write(C_BLANK_ALPHA_BMP32_PREFIX, SizeOf(C_BLANK_ALPHA_BMP32_PREFIX)); 
    //Now start writing the pixels: 
    FillChar(buf[Low(buf)],Length(buf),$00); 
    p := Result.Position; 
    Result.Size := Result.Size+int64(AWidth)*int64(AHeight)*4; 
    Result.Position := p; 
    i := int64(AWidth)*int64(AHeight)*4; //4 because RGBA has 4 bytes 
    while(i>0)do 
     begin 
     if(i>Length(buf)) 
      then w := Length(buf) 
      else w := i; 
     Result.Write(buf[Low(buf)], w); 
     dec(i,w); 
     end; 
    //Go back to the original header and update FileSize, Width, Height, and offset fields: 
    BE := IsBigEndian; 
    Result.Position := 2; dw := Result.Size; 
    if BE then SwapEndian(dw); Result.Write(dw, SizeOf(dw)); 
    Result.Position := 18; dw := AWidth; 
    if BE then SwapEndian(dw); Result.Write(dw, SizeOf(dw)); 
    Result.Position := 22; dw := AHeight; 
    if BE then SwapEndian(dw); Result.Write(dw, SizeOf(dw)); 
    Result.Position := 34; dw := AWidth*AHeight*4; 
    if BE then SwapEndian(dw); Result.Write(dw, SizeOf(dw)); 
    //Done: 
    Result.Position := 0; 
    end; 

सूचना कैसे C_BLANK_ALPHA_BMP32_PREFIX निरंतर मूल रूप से मेरी नमूना alpha1p.bmp फ़ाइल से बाइट क्रम की प्रति, शून्य से पिछले 4 बाइट्स, जो RGBA पिक्सेल थे। : डी

इसके अलावा, मैं IsBigEndian समारोह जो इस प्रकार है उपयोग कर रहा हूँ:

Function IsBigEndian: Boolean; 
    type 
    Q = record case Boolean of 
      True : (i: Integer); 
      False : (p: array[1..4] of Byte); 
     end; 
    var 
    x : ^Q; 
    begin 
    New(x); 
    x^.i := 5; 
    Result := (x^.p[4]=5); 
    Dispose(x); 
    end; 

यह लाजर विकी से नकल है: http://wiki.freepascal.org/Writing_portable_code_regarding_the_processor_architecture आप इस भाग को छोड़ सकते हैं अगर आप BigEndian प्लेटफार्मों के साथ सौदा नहीं है, या आप एक कंपाइलर IFDEF निर्देश का उपयोग कर सकते हैं। बात यह है कि यदि आप {$IFDEF ENDIAN_BIG} का उपयोग करते हैं तो यह संकलक चीजें होती है, जबकि फ़ंक्शन वास्तव में सिस्टम का परीक्षण करता है। यह लिंक विकी में समझाया गया है।

नमूना उपयोग

Procedure TForm1.Button1Click(Sender: TObject); 
var 
    MS : TMemoryStream; 
begin 
    MS := RenderEmptyAlphaBitmap(Image1.Width, Image1.Height); 
    try 
    if Assigned(MS)then Image1.Picture.LoadFromStream(MS); 
    //you can also MS.SaveToFile('my_file.bmp'); if you want 
    finally 
    FreeAndNil(MS); 
    end; 
end; 
+0

मैंने एसडीएल के साथ इस विधि को अपनाने का सुझाव दिया: https://www.quora.com/A-simple-way-to-create-a-transparent-surface-with-SDL-Pascal/answer/Krzysztof-Kamil-Jacewicz –

+0

मुझे नहीं लगता कि प्रश्न 32 बिट * अल्फा * पारदर्शी बिटमैप्स के बारे में है। किसी भी मामले में, अच्छा विचार। लेकिन यह काम अपेक्षित नहीं है ?: https://pastebin.com/EXDRu3zG – kobik

+0

@ कोबिक: कुछ तरीकों से आपकी विधि मेरे लिए काम नहीं करती है। मुझे लगता है कि यह काम नहीं करता था gtk विजेटसेट का उपयोग कर लिनक्स पर था। –

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