كيفية إنشاء Gdiplus::Bitmap من HBITMAP، مع الاحتفاظ بمعلومات قناة ألفا؟

StackOverflow https://stackoverflow.com/questions/335273

  •  22-07-2019
  •  | 
  •  

سؤال

عندما أقوم بإنشاء gdiplus :: صورة نقطية جديدة باستخدام وظيفة bitmap :: fromhbitmap ، فإن النقطة الناتجة غير شفافة - لا يتم الحفاظ على أي من الشفافية الجزئية من hbitmap الأصلي.

هل هناك طريقة لإنشاء Gdiplus::Bitmap من HBITMAP الذي يجمع بيانات قناة ألفا؟

هل كانت مفيدة؟

المحلول 2

اتضح أن GDI+ لا يقوم أبدًا بجلب قناة ألفا عند إنشاء صورة نقطية من HBITMAP.

الجواب هو:

  • استخدم GetObject لتمرير الصورة النقطية وHBITMAP للحصول على العرض والارتفاع (وإذا كانت الصورة النقطية للإدخال عبارة عن DIB، فستكون بيانات البكسل) لإدخال HBITMAP.
  • قم بإنشاء صورة نقطية بالحجم الصحيح بتنسيق 32 بت PARGB بكسل.
  • استخدم LockBits للحصول على ذاكرة PixelData الخاصة بالصورة النقطية الجديدة.
  • إذا حصلت على وحدات البكسل من GetObject، فانسخ قيم ARGB عبر استخدام memcpy.
  • قم باستدعاء UnlockBits على الصورة النقطية الجديدة.

في حالتي، يكون تنسيق الإدخال HBITMAP صحيحًا لإجراء عملية memcpy مباشرة من بيانات بكسل الصورة النقطية المدخلة إلى بيانات بكسل الصورة النقطية الجديدة.

إذا لم تحصل على بيانات البكسل المدخلة من GetObject، فاستخدم GetDIBits للحصول على نسخة بالتنسيق الصحيح.

نصائح أخرى

وأعتقد كود العمل هو أكثر فائدة من تعليمات، لذلك:

#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;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top