Cara menggambar BMP transparan dengan GDI+

Saat ini saya sedang mengedit beberapa kode GDI lama untuk menggunakan GDI+ dan mengalami masalah saat menggambar file BMP dengan latar belakang transparan. Kode GDI lama tidak menggunakan kode tambahan apa pun untuk menggambar latar belakang transparan, jadi saya bertanya-tanya bagaimana cara mencapainya menggunakan GDI+.

Kode saya saat ini terlihat seperti ini

HINSTANCE hinstance = GetModuleHandle(NULL);
bmp = Gdiplus::Bitmap::FromResource(hinstance, MAKEINTRESOURCEW(IDB_BMP));
Gdiplus::Graphics graphics(pDC->m_hDC);
graphics.DrawImage(&bmp, posX, posY);

Saya juga mencoba membuat bitmap baru dari sumber daya dengan menggunakan metode klon dan menggambar bitmap ke yang baru dibuat tetapi tidak ada yang membantu. Kedua kali saya menggunakan PixelFormat32bppPARGB.

Lalu saya mencoba menggunakan alpha blending tetapi dengan cara ini seluruh gambar menjadi transparan dan tidak hanya latar belakangnya:

Gdiplus::ColorMatrix clrMatrix = { 
    1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.5f, 0.0f,
    0.0f, 0.0f, 0.0f, 0.0f, 1.0f
};

Gdiplus::ImageAttributes imgAttr;
imgAttr.SetColorMatrix(&clrMatrix);

graphics.DrawImage(&bmp, destRect, 0, 0, width(), height(), Gdiplus::UnitPixel, &imgAttr);

Informasi transparansi sudah terdapat pada gambar tetapi saya tidak tahu bagaimana menerapkannya saat menggambar gambar. Bagaimana cara mencapai hal ini?


person sigy    schedule 27.07.2012    source sumber


Jawaban (3)


Solusi paling sederhana adalah dengan menggunakan beberapa format selain BMP.

Anda memerlukan bit untuk memuat data alfa, dan Anda memerlukan Bitmap dalam format yang memiliki data alfa. Saat Anda memuat BMP dengan GDI+, format tersebut akan selalu menggunakan format tanpa alfa, meskipun BMP tersebut memiliki saluran alfa. Saya yakin datanya ada di bit gambar, tapi tidak digunakan.

Masalah saat Anda mengkloning atau menggambar ke Bitmap PixelFormat32bppPARGB adalah GDI+ akan mengonversi data gambar ke format baru, yang berarti membuang data alfa.

Dengan asumsi itu memuat bit dengan benar, yang perlu Anda lakukan adalah menyalin bit tersebut langsung ke bitmap lain dengan format yang benar. Anda dapat melakukannya dengan Bitmap::LockBits dan Bitmap::UnlockBits . (Pastikan Anda mengunci setiap bitmap dengan format piksel aslinya sehingga tidak ada konversi yang dilakukan.)

person Esme Povirk    schedule 28.07.2012
comment
Oke, tampaknya GDI lama mampu menggambar gambar seperti itu tanpa baris kode tambahan dan GDI+ baru tidak dapat melakukan hal yang sama tanpa kerja ekstra yang berat....sedih tapi nyata - person sigy; 30.07.2012
comment
Seperti yang ditunjukkan oleh jawabannya, GDI+ dapat juga melakukannya, Anda hanya perlu menggunakan format gambar yang mendukung saluran alfa (seperti PNG). [Saya yakin Anda dapat menyimpan data alfa dalam file BMP, namun Anda tidak seharusnya melakukannya. Itu tidak normal. Jika berhasil, itu berhasil karena ada bug di GDI, dan Anda tidak boleh mengandalkannya.] - person BrainSlugs83; 13.01.2015

Jawaban yang terlambat tetapi:

ImageAttributes imAtt;    
imAtt.SetColorKey(Color(255,255,255), Color(255,255,255), ColorAdjustTypeBitmap);  

Akan membuat white (255,255,255) transparan pada bitmap apa pun yang Anda gunakan dengan atribut gambar ini.

person Evan Carslake    schedule 09.06.2015
comment
Bagaimana cara menggunakan ini pada bitmap? - person Paul; 25.01.2019
comment
Teruskan objek ImageAttributes tersebut ke salah satu versi Graphics.DrawImage yang kelebihan beban - person Gautam Jain; 22.02.2021

Saya memiliki masalah yang sama. BMP transparan belum ditampilkan dengan benar dan sayangnya, PNG tidak dapat dimuat langsung dari sumber daya (kecuali dengan menambahkan sedikit kode yang menyalinnya ke dalam aliran dan memuatnya dari aliran). Saya ingin menghindari kode ini.
Bitmap yang saya gunakan juga hanya menggunakan dua warna (latar belakang dan logo). Memiliki saluran alfa berarti saya harus menyimpannya dengan kedalaman warna yang jauh lebih tinggi daripada kedalaman warna hanya 2 bit.

Jawaban Evan persis seperti yang saya cari :-)

Daripada putih, saya menggunakan warna piksel kiri atas sebagai warna transparan:

Gdiplus::Color ColourOfTopLeftPixel;
Gdiplus::Status eStatus = m_pBitmap->GetPixel(0, 0, &ColourOfTopLeftPixel);
_ASSERTE(eStatus == Gdiplus::Ok);

// The following makes every pixel with the same colour as the top left pixel (ColourOfTopLeftPixel) transparent.
Gdiplus::ImageAttributes ImgAtt;
ImgAtt.SetColorKey(ColourOfTopLeftPixel, ColourOfTopLeftPixel, Gdiplus::ColorAdjustTypeBitmap);
person Dirksche    schedule 08.10.2015