2008-12-02 11 views
7

Khi tôi tạo một Gdiplus :: Bitmap mới bằng cách sử dụng chức năng Bitmap :: FromHBITMAP, kết quả Bitmap bị mờ - không có sự minh bạch một phần nào từ HBITMAP ban đầu được giữ nguyên.Làm thế nào để tạo một Gdiplus :: Bitmap từ một HBITMAP, giữ lại thông tin kênh alpha?

Có cách nào để tạo ra một Gdiplus :: Bitmap từ HBITMAP mang lại dữ liệu kênh alpha không?

+0

Bạn có biết chắc chắn rằng HBITMAP có một kênh alpha để bắt đầu với? Ví dụ, bạn đã tạo nó như một DIB với BI_RGB và 32bpp hay một số cách khác? –

+0

Có, nó có độ trong suốt. Nó thu hút độc đáo bằng cách sử dụng hàm :: AlphaBlend(). – mackenir

+0

(Tôi đã tạo nó trong C# bằng cách sử dụng Bitmap mới (tên tệp chuỗi) và gọi GetHBitmap() trên đối tượng bitmap .NET) – mackenir

Trả lời

4

Nó chỉ ra rằng GDI + không bao giờ mang qua kênh alpha khi tạo Bitmap từ HBITMAP.

Câu trả lời là:

  • Sử dụng GetObject đi qua trong một BITMAP và HBITMAP, để có được chiều rộng và chiều cao (và nếu bitmap đầu vào là một DIB, dữ liệu pixel) của HBITMAP đầu vào.
  • Tạo bitmap có kích thước chính xác với định dạng pixel 32 bit PARGB.
  • Sử dụng LockBits để lưu giữ bộ nhớ pixelData của Bitmap mới của bạn.
  • Nếu bạn có pixel từ GetObject, hãy sao chép giá trị ARGB qua sử dụng memcpy.
  • Mở khóa cuộc gọiThanh toán trên Bitmap mới.

Trong trường hợp của tôi, định dạng của đầu vào HBITMAP là chính xác để thực hiện ghi nhớ thẳng từ dữ liệu pixel bitmap đầu vào tới dữ liệu pixel bitmap mới.

Nếu bạn không nhận dữ liệu pixel đầu vào từ GetObject, hãy sử dụng GetDIBits để nhận bản sao ở định dạng chính xác. đang

9

Tôi nghĩ rằng làm việc là có ích hơn hướng dẫn, vì vậy:

#include <GdiPlus.h> 
#include <memory> 

Gdiplus::Status HBitmapToBitmap(HBITMAP source, Gdiplus::PixelFormat pixel_format, Gdiplus::Bitmap** result_out) 
{ 
    BITMAP source_info = { 0 }; 
    if(!::GetObject(source, sizeof(source_info), &source_info)) 
    return Gdiplus::GenericError; 

    Gdiplus::Status s; 

    std::auto_ptr<Gdiplus::Bitmap> target(new Gdiplus::Bitmap(source_info.bmWidth, source_info.bmHeight, pixel_format)); 
    if(!target.get()) 
    return Gdiplus::OutOfMemory; 
    if((s = target->GetLastStatus()) != Gdiplus::Ok) 
    return s; 

    Gdiplus::BitmapData target_info; 
    Gdiplus::Rect rect(0, 0, source_info.bmWidth, source_info.bmHeight); 

    s = target->LockBits(&rect, Gdiplus::ImageLockModeWrite, pixel_format, &target_info); 
    if(s != Gdiplus::Ok) 
    return s; 

    if(target_info.Stride != source_info.bmWidthBytes) 
    return Gdiplus::InvalidParameter; // pixel_format is wrong! 

    CopyMemory(target_info.Scan0, source_info.bmBits, source_info.bmWidthBytes * source_info.bmHeight); 

    s = target->UnlockBits(&target_info); 
    if(s != Gdiplus::Ok) 
    return s; 

    *result_out = target.release(); 

    return Gdiplus::Ok; 
} 
+0

Tôi đã gặp sự cố tương tự với 'CBitmap', từ đó tôi đã truy xuất' HBITMAP'. Trong trường hợp đó ':: GetObject()' left 'source_info.bmBits' được đặt thành NULL. Tôi có thể giải quyết điều này bằng cách gọi 'myCBitmapPtr-> GetBitmapBits (source_info.bmWidthBytes * source_info.bmHeight, target_info.Scan0)' – foraidt

+0

BTW, các giá trị trả về được kiểm tra độc đáo trong ví dụ của bạn, nhưng nếu 'source_info.bmBits' là NULL, có một truy cập vi phạm trong cuộc gọi đến 'CopyMemory()'. – foraidt