Gdiplus::Bitmap
-
Wie ist es möglich die Transparenz eines bitmaps, das aus dem Speicher geladen wird beizubehalten?
Ich benutze 32bit bitmaps und habe eine struct, die einen BITMAPV5HEADER und einen unterschiedlich großen array von DWORDs enthält.
Ich speichere das Bitmap so ab:
// Bitmap aus icon(transparent) Gdiplus::Bitmap* pBmp = Gdiplus::Bitmap::FromHICON(hIc); DeleteObject(hIc); // Struct + array für daten DWORD siz = pBmp->GetWidth() * pBmp->GetHeight() * sizeof(DWORD); PreviewTag* pPt = (PreviewTag*)new BYTE[siz + sizeof(PreviewTag)]; pPt->FourCharacterCode = 'PREV'; pPt->CachedBitmap = NULL; pPt->FrameNumber = dwFrame; pPt->SizeOfData = siz; // Den header füllen ZERO_VAR1(pPt->BitmapHeader); pPt->BitmapHeader.bV5Size = sizeof(BITMAPV5HEADER); pPt->BitmapHeader.bV5Width = pBmp->GetWidth(); pPt->BitmapHeader.bV5Height = pBmp->GetHeight(); pPt->BitmapHeader.bV5Planes = 1; pPt->BitmapHeader.bV5BitCount = 32; pPt->BitmapHeader.bV5Compression = BI_RGB; pPt->BitmapHeader.bV5SizeImage = 0; pPt->BitmapHeader.bV5XPelsPerMeter = (LONG)pBmp->GetHorizontalResolution(); pPt->BitmapHeader.bV5YPelsPerMeter = (LONG)pBmp->GetVerticalResolution(); pPt->BitmapHeader.bV5ClrUsed = 0; pPt->BitmapHeader.bV5ClrImportant = 0; pPt->BitmapHeader.bV5RedMask = 0x000000ff; pPt->BitmapHeader.bV5GreenMask = 0x0000ff00; pPt->BitmapHeader.bV5BlueMask = 0x00ff0000; pPt->BitmapHeader.bV5AlphaMask = 0xff000000; Gdiplus::BitmapData bmpD; pBmp->LockBits(NULL, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &bmpD); if(bmpD.Stride > 0) // Höhe ist negativ bei top-down bitmap pPt->BitmapHeader.bV5Height *= -1; BYTE* pCur = (BYTE*)bmpD.Scan0; // Bei top down zu beginn des arrays, bei normalen am ende + stride(negativ) BYTE* pCurT = (BYTE*)(pPt + 1) + (bmpD.Stride < 0 ? siz + bmpD.Stride : 0); for(DWORD i = 0; i < bmpD.Height; i++) { for(DWORD j = 0; j < bmpD.Width; j++) *(DWORD*)pCurT = *(DWORD*)pCur, pCur += sizeof(DWORD), pCurT += sizeof(DWORD); if(bmpD.Stride < 0) { // Wenn bottom-up vom ende der reihe an den anfang der oberen reihe pCur += bmpD.Stride * 2; pCurT += bmpD.Stride * 2; } } pBmp->UnlockBits(&bmpD);Und lade es später so:
CachedBitmap = new Gdiplus::Bitmap((BITMAPINFO*)&BitmapHeader, this + 1);
-
...............
-
Also wenn ich beim geladenen Bitmap LockBits ausführe, dann haben alle stellen als alpha 255, beim speichern nicht.
-
Das speicher passiert natürlich zuvor.
Es muss irgendwo beim bitmap constructor liegen,
aber der andere mit (INT,INT,INT,Pixelformat,void*) zeigt später überhaupt nichts an.
-
Der Bitmap-Konstruktor ignoriert leider den Alpha-Channel immer

Außer manuell z.B. über LockBits() kriegt man den vermutl. nicht von GDI+ selbst gesetzt.(Das Problem ist das das Bitmap-Format ursprünglich keinen Alpha-Channel vorgesehen hatte und einige Software da wirklich 32Bit Farbtiefe mit meint, andere eben 24Bit+Alpha oder gar einfach irgendwas darein gepappt haben - Microsoft dachte sich daher wohl: Ignorieren wir den besser einfach ;D)
...oder aber falls möglich z.B. auf PNG ausweichen - Da gibt es diese Probleme mit dem Alpha-Channel nicht

-
Also an PNG hab ich auch schon gedacht, nur ist es ein bischen ein problem, dass ich die größe der in-den-speicher-zu-speichernden datei nicht direkt bestimmen kann und ich in GDI+ dafür ein IStram brauche. Dazu habe ich dann auch schon mal ein Memory stream gecodet, das problem ist aber, dass ich in der zieldatei, das bild als eine art tag abspeichere, der eine bestimmte größe hat, deswegen wollte ich es halt zuerst mit dem bitmap versuchen, aber wenn einem eben kein anderer ausweg bleibt, dann werd ich mich einmal daran machen das zu implementieren - trotzdem danke für die antwort.