Ich habe eine Anwendung, die ein Bild mit einem transparenten Hintergrund lädt, dann benutze ich StretchBlt
, um es auf die gewünschte Größe zu ändern, mit set mit SetStretchBltMode
(Ich versuchte mit anderen Modi, während die Transparenz intakt, machte auch das skalierte Bild 'hässlich').
Allerdings ersetzt StretchBlt
den transparenten Hintergrund durch eine Farbe (schwarz), die nicht zum Hintergrund des Fensters passt, auf dem das Bild angezeigt wird. So
Ich habe zwei Möglichkeiten:
1) Ersetzen Sie den transparenten Hintergrund des Bildes mit der Hintergrundfarbe des Fensters, dann StretchBlt
2 mit Größe ändern) Resize es, während die Transparenz Hintergrund hält (bevorzugte Option)
Ich habe versucht, nach WinAPI-Funktion zu suchen, die beide Funktionen bieten würde, aber ich habe keine gefunden.
Wie mache ich eine dieser Optionen (ersetzen Sie die Transparenz oder ändern Sie die Größe, während Sie es beibehalten) mit einfachen WinAPI?Größe ändern HBITMAP bei transparentem Hintergrund
Antwort
Zuerst BitBlt
, StretchBlt
und TransparentBlt
unterstützen nicht die Alpha-Kanal ..
TransparentBlt
Werke, indem sie alles, was Farbe angegeben Sie wollen, transparent.
Wenn Sie Alpha-Kanal und Blending-Unterstützung möchten, benötigen Sie: AlphaBlend
.
Sie können folgendes tun:
BLENDFUNCTION fnc;
fnc.BlendOp = AC_SRC_OVER;
fnc.BlendFlags = 0;
fnc.SourceConstantAlpha = 0xFF;
fnc.AlphaFormat = AC_SRC_ALPHA;
//You need to create a memDC.. and an HBITMAP..
//Select the hBitmap into the memDC.
HGDIOBJ obj = SelectObject(memDC, hBmp);
//Render with alpha blending..
AlphaBlend(DC, rect.X, rect.Y, rect.Width, rect.Height, memDC, 0, 0, Width, Height, fnc);
//Restore the memDC to original state..
SelectObject(memDC, obj);
OR tun Sie Ihre eigenen Pre-multiplizierten alpha-Wiedergabe durch den Kanal Farben selbst Berechnung ..
Alternativ können Sie GDI + versuchen und sehen, wie das klappt :
ULONG_PTR GdiImage::GDIToken = 0;
Gdiplus::GdiplusStartupInput GdiImage::GDIStartInput = NULL;
Gdiplus::GdiplusStartup(&GdiImage::GDIToken, &GdiImage::GDIStartInput, NULL);
Gdiplus::Image* Img = Gdiplus::Image::FromFile(L"PathToImage.ext"); //where ext can be png, bmp, etc..
Gdiplus::Graphics graphics(DC);
//graphics.SetSmoothingMode(SmoothingModeHighSpeed);
graphics.SetInterpolationMode(Gdiplus:: InterpolationModeBilinear); //InterpolationModeNearestNeighbor
//graphics.SetPixelOffsetMode(Gdiplus::PixelOffsetModeHalf);
graphics.DrawImage(Img, x, y, w, h);
delete Img;
Gdiplus::GdiplusShutdown(GdiImage::GDIToken);
GdiImage::GDIStartInput = NULL;
GdiImage::GDIToken = 0;
Das funktioniert, aber das resultierende Bild ist hässlich wie bei 'StretchBlt', ohne' HALTFONE' zu verwenden, wie in meiner Frage beschrieben. –
Nun ich bin mir nicht sicher, was Sie mit "sieht hässlich" meinen. Sie möchten nicht "HALFTONE" verwenden, aber Sie möchten skalieren. Haben Sie vorher und nachher Bilder? (vor Skalierung, Skalierung mit Halbton, Skalierung ohne Halbton). – Brandon
@ あ ぶ ら こ こ; Ich habe "GDIPlus" hinzugefügt, nur für den Fall, dass Sie das versuchen wollen. 'GDIPlus' kann Transparente Bitmaps, PNG, etc. unterstützen. Es hat auch Interpolation, Glättung, Halbton und andere Effekte und Transformationen. – Brandon
ich für WinAPI Funktion versucht suchen, bieten würde entweder Funktionalität, aber ich habe keine gefunden.
Obwohl andere haben bereits ein paar Vorschläge, meines Wissens keine der zur Zeit (12/2017) verfügbar native OS APIs bieten hochwertige Bild Resampling.
Es gibt viele Bibliotheken von Drittanbietern für das Resampling. Viele (die meisten?) Von ihnen sind ziemlich kompliziert und wahrscheinlich zu viel, wenn die Bildverarbeitung nicht die Hauptaufgabe Ihrer Anwendung ist.
Im folgenden Beispiel verwende ich die Public-Domain, Single-Header-Datei, keine externe Abhängigkeiten "stb_image_resize.h" Bibliothek. Just #include
es in Ihrem Projekt und damit fertig sein. Die Bibliothek ist nicht die schnellste, aber ich würde sie nicht besonders langsam nennen. Wo es glänzt, ist Benutzerfreundlichkeit und Vielseitigkeit. Es ist auch einfach zu erweitern, wenn Sie zusätzliche Filter wie Lanczos haben möchten (für die ich Code bereitstellen kann, wenn es Interesse gibt). Obwohl die eingebauten Filter bereits viel besser sind als die der OS APIs.
Das folgende Beispielprogramm erwartet in der Datei "flower.bmp" des aktuellen Verzeichnisses eine 32-Bit-Bitmap mit einem Alpha-Kanal (nicht vorgemischt). Das Image wird mit der OS-API LoadImageW()
geladen, unter Verwendung von stbir_resize_uint8()
auf ein Drittel der ursprünglichen Abmessungen neu abgetastet und unter Verwendung von GDI + im aktuellen Verzeichnis als "flower_resized.bmp" gespeichert.
#include <Windows.h>
#include <iostream>
#include <gdiplus.h>
#pragma comment(lib, "gdiplus")
namespace gp = Gdiplus;
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "stb_image_resize.h"
int main()
{
// Using LR_CREATEDIBSECTION flag to get direct access to the bitmap's pixel data.
HBITMAP hBmpIn = reinterpret_cast<HBITMAP>(
LoadImageW(NULL, L"flower.bmp", IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE | LR_CREATEDIBSECTION));
if(!hBmpIn)
{
std::cout << "Failed to load bitmap.\n";
return 1;
}
// Getting bitmap information including a pointer to the bitmap's pixel data
// in infoIn.dsBm.bmBits.
// This will fail if hBmpIn is not a DIB. In this case you may call GetDIBits()
// to get a copy of the bitmap's pixel data instead.
DIBSECTION infoIn{};
if(!GetObject(hBmpIn, sizeof(infoIn), &infoIn))
{
std::cout << "Bitmap is not a DIB.\n";
return 1;
}
// Some sanity checks of the input image.
if(infoIn.dsBm.bmBitsPixel != 32 || infoIn.dsBm.bmPlanes != 1 ||
infoIn.dsBmih.biCompression != BI_RGB)
{
std::cout << "Bitmap is not 32 bpp uncompressed.\n";
return 1;
}
// Create a DIB for the output. We receive a HBITMAP aswell as a writable
// pointer to the bitmap pixel data.
int out_w = infoIn.dsBm.bmWidth/3, out_h = infoIn.dsBm.bmHeight/3;
BITMAPINFO infoOut{};
auto& hdr = infoOut.bmiHeader;
hdr.biSize = sizeof(hdr);
hdr.biBitCount = 32;
hdr.biCompression = BI_RGB;
hdr.biWidth = out_w;
hdr.biHeight = out_h; // negate the value to create top-down bitmap
hdr.biPlanes = 1;
unsigned char* pOutPixels = nullptr;
HBITMAP hBmpOut = CreateDIBSection(NULL, &infoOut, DIB_RGB_COLORS,
reinterpret_cast<void**>(&pOutPixels), NULL, 0);
if(!hBmpOut)
{
std::cout << "Could not create output bitmap.\n";
return 1;
}
// Resample the input bitmap using the simplest API.
// These functions use a "default" resampling filter defined at compile time
// (currently "Mitchell" for downsampling and "Catmull-Rom" for upsampling).
// To change the filter, you can change the compile-time defaults
// by #defining STBIR_DEFAULT_FILTER_UPSAMPLE and STBIR_DEFAULT_FILTER_DOWNSAMPLE,
// or you can use the medium-complexity API.
// Consult "stb_image_resize.h" which contains the documentation.
stbir_resize_uint8(
reinterpret_cast< unsigned char const* >(infoIn.dsBm.bmBits),
infoIn.dsBm.bmWidth,
infoIn.dsBm.bmHeight,
0, // input_stride_in_bytes, 0 = packed continously in memory
pOutPixels,
out_w,
out_h,
0, // output_stride_in_bytes, 0 = packed continously in memory
4 // num_channels
);
// Use GDI+ for saving the resized image to disk.
gp::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdipToken = 0;
gp::GdiplusStartup(&gdipToken, &gdiplusStartupInput, nullptr);
{
gp::Bitmap bmpOut(hBmpOut, nullptr);
// I'm taking a shortcut here by hardcoding the encoder CLSID. Check MSDN to do it by-the-book:
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms533843(v=vs.85).aspx
class __declspec(uuid("{557cf400-1a04-11d3-9a73-0000f81ef32e}")) BmpEncoderId;
bmpOut.Save(L"flower_resized.bmp", &__uuidof(BmpEncoderId));
}
// Cleanup
gp::GdiplusShutdown(gdipToken);
DeleteObject(hBmpIn);
DeleteObject(hBmpOut);
std::cout << "All done.\n";
return 0;
}
Hinweise:
Wenn transparente Bilder Resampling, es ist in der Regel ratsam, eine premultiplied alpha channel zu verwenden. Andernfalls kann das neu abgetastete Bild Artefakte aufweisen, die im Allgemeinen entlang der Kanten von Formen erkennbar sind. STBIR verwendet "Alpha-Weighted Resampling" (effektives Premultipling, Resampling und dann Premultipling), es sei denn, Sie geben das STBIR_FLAG_ALPHA_PREMULTIPLIED
Flag an. So erhalten Sie Leistungsvorteile, wenn Sie nach dem Laden eines Bildes manuell einmal multiplizieren. Die meisten Windows-APIs (z. B. AlphaBlend
), die transparente Bilder anzeigen können, erwarten, dass der Alphakanal ohnehin vorgemultipliziert wird.
- 1. Bildfarbe mit transparentem Hintergrund ändern
- 2. DialogFragment mit transparentem Hintergrund
- 3. PreferenceFragment mit transparentem Hintergrund?
- 4. Aktivität mit transparentem Hintergrund
- 5. BottomSheetDialog mit transparentem Hintergrund
- 6. WideImage - Canvas mit transparentem Hintergrund
- 7. HBITMAP Bitmap-
- 8. Android AlertDialog mit transparentem Hintergrund
- 9. MPMoviePlayerViewController mit transparentem Hintergrund laden?
- 10. Imagemagick Text mit transparentem Hintergrund
- 11. Schwarzer Hintergrund auf transparentem UITabBar
- 12. Transparente Schrift auf transparentem Hintergrund
- 13. Recolor Bild mit transparentem Hintergrund
- 14. Hintergrund von transparentem Text transformieren?
- 15. R-Plot-Legende mit transparentem Hintergrund
- 16. Größe ändern bei speichern
- 17. Clear JFrame Hintergrund auf transparentem Fenster
- 18. Animation auf transparentem Hintergrund JFrame Linux
- 19. So erstellen Sie einen Film mit transparentem Hintergrund im Handumdrehen mit transparentem Hintergrund
- 20. Hintergrund bei ID load ändern
- 21. HTML/CSS gibt Bild mit transparentem Hintergrund einen weißen Hintergrund
- 22. Export Grundstück in .png mit transparentem Hintergrund
- 23. Button Border mit transparentem Hintergrund in Swift
- 24. WPF Datagrid abgerundete Ecke mit transparentem Hintergrund
- 25. OpenGL ES 2.0 GLKit mit transparentem Hintergrund
- 26. Hintergrund mit transparentem Bild in PIL verschmelzen
- 27. QTJambi und Webkit, Probleme mit transparentem Hintergrund
- 28. SVG-Pfad mit Bildfilter aber transparentem Hintergrund
- 29. JavaScript abgerundete Ecken mit transparentem Hintergrund
- 30. Augmented Reality Videospiel mit transparentem Hintergrund
"transparenter Hintergrund" ist sehr unspezifisch - bitte teilen Sie uns das genaue Bildformat mit, z. G. "32 bpp ARGB mit vormultiplexiertem Alpha". Auch das Anzeigen Ihres aktuellen Codes wäre hilfreich. – zett42
Es ist eine GDI-Funktion, GDI hängt bei 24bpp fest und unterstützt keine 32bpp-Bildformate. Betrachten Sie GDI +, gdiplus.h Header-Datei. –
Werfen Sie einen Blick auf die [WIC API] (https://msdn.microsoft.com/en-us/library/windows/desktop/ee719655 (v = vs.85) .aspx). GDI ist in diesen Tagen nicht viel (und GDI + ist eher langsam). –