This one is to put at the end of Tools.h until there is a better place in mobj.h
LONG_PTR zCreateAlphaMask (IN WCHAR* zInputName, IN WCHAR* zInputMask, IN BOOL ReturnBitmap) {
LONG_PTR nResult = 0;
LONG_PTR img1 = 0, img2 = 0, graphics1 = 0, graphics2 = 0;
long imgW1 = 0, imgH1 = 0, imgW2 = 0, imgH2 = 0;
long S1 = INWSTR(-1, zInputName, (WCHAR*) $DOT);
if (!FileExist(zInputName)) S1 = 0;
if (S1) {
// Make sure that a full path is being used.
zCheckName(zInputMask);
long S2 = INWSTR(-1, zInputMask, (WCHAR*) $DOT);
if (!FileExist(zInputMask)) S2 = 0;
if (S2 == 0) S1 = 0;
}
if (S1) {
long ImageType = TextureCheckExtension(zInputMask);
long nRet = -1, nSwapRB = -1;
if (ImageType == MEDIA_TGA) {
nRet = ZI_LoadTGA(zInputMask, &img2);
} else if (ImageType == MEDIA_DDS) {
nRet = ZI_LoadDDS(zInputMask, &img2, &nSwapRB);
} else { // all GDI+
nRet = GdipLoadImageFromFile(zInputMask, img2);
}
if (nRet == 0) {
GetImageSize(img2, imgW2, imgH2);
nRet = -1, nSwapRB = -1;
ImageType = TextureCheckExtension(zInputName);
if (ImageType == MEDIA_TGA) {
nRet = ZI_LoadTGA(zInputName, &img1);
} else if (ImageType == MEDIA_DDS) {
nRet = ZI_LoadDDS(zInputName, &img1, &nSwapRB);
} else { // all GDI+
nRet = GdipLoadImageFromFile(zInputName, img1);
}
if (nRet == 0) {
GetImageSize(img1, imgW1, imgH1);
if ((imgW1 == imgW2) && (imgH1 == imgH2)) {
HDC hDC = zDisplayDC();
HDC ImgHDC = CreateCompatibleDC(hDC);
HBITMAP hbmReturn = zCreateDIBSection(hDC, imgW1, imgH1, 32);
SelectObject(ImgHDC, hbmReturn);
HDC MaskHDC = CreateCompatibleDC(hDC);
HBITMAP hbmMask = zCreateDIBSection(hDC, imgW2, imgH2, 32);
SelectObject(MaskHDC, hbmMask);
DeleteDC(hDC);
if (GdipCreateFromHDC(MaskHDC, graphics2) == 0) {
if (GdipDrawImageRectI(graphics2, img2, 0, 0, imgW2, imgH2) == 0) {
// Draw image
if (GdipCreateFromHDC(ImgHDC, graphics1) == 0) {
if (GdipDrawImageRectI(graphics1, img1, 0, 0, imgW1, imgH1) == 0) {
long AlphaRGB1 = 0, AlphaRGB2 = 0;
GdipBitmapGetPixel(img2, 0, 0, AlphaRGB2);
BITMAP bm2 = { 0 };
GetObject(hbmMask, sizeof(bm2), &bm2);
BYTE* pBits2 = (BYTE*) bm2.bmBits;
GdipBitmapGetPixel(img1, 0, 0, AlphaRGB1);
BITMAP bm1 = { 0 };
GetObject(hbmReturn, sizeof(bm1), &bm1);
BYTE* pBits1 = (BYTE*) bm1.bmBits;
for (long y = 0; y < bm1.bmHeight; ++y) {
for (long x = 0; x < bm1.bmWidth; ++x) {
pBits1[3] = (BYTE) ((pBits2[2] * 0.2989f) + (pBits2[1] * 0.5870f) + (pBits2[0] * 0.114f));
pBits2 += 4;
pBits1 += 4;
}
}
}
// Cleanup
GdipDeleteGraphics(graphics1);
}
if (img1) { GdipDisposeImage(img1); img1 = 0; }
img1 = zBitmapToImage(ImgHDC);
if (ImgHDC) DeleteDC(ImgHDC);
DeleteObject(hbmReturn);
}
if (img2) { GdipDisposeImage(img2); img2 = 0; }
if (graphics2) GdipDeleteGraphics(graphics2);
}
if (MaskHDC) DeleteDC(MaskHDC);
DeleteObject(hbmMask);
}
}
}
}
if (img1) {
HDC hDC = zDisplayDC();
HDC ImgHDC = CreateCompatibleDC(hDC);
HBITMAP hbmReturn = zCreateDIBSection(hDC, imgW1, imgH1, 32);
SelectObject(ImgHDC, hbmReturn);
DeleteDC(hDC);
// Draw image
if (GdipCreateFromHDC(ImgHDC, graphics1) == 0) {
for (long K = 0; K < 4; K++) { // Increase opacity
GdipDrawImageRectI(graphics1, img1, 0, 0, imgW1, imgH1);
}
// Cleanup
GdipDeleteGraphics(graphics1);
}
GdipDisposeImage(img1);
if (ReturnBitmap) {
DeleteDC(ImgHDC);
nResult = (LONG_PTR) hbmReturn;
} else {
nResult = zBitmapToImage(ImgHDC);
DeleteDC(ImgHDC);
DeleteObject(hbmReturn);
}
}
return nResult;
}
and the missing GdipDrawImageRectI API to add into Tools.h after GdipDeleteGraphics.
long GdipDrawImageRectI(IN LONG_PTR graphics, IN LONG_PTR lpImg, IN long x, IN long y, IN long W, IN long H) {
long nRet = -1; // Error
HMODULE hModule = gdiplib();
if (hModule) {
long_proc (LONG_PTR, LONG_PTR, long, long, long, long);
static zProc hProc;
if (hProc == 0) { hProc = (zProc) GetProcAddress(hModule, "GdipDrawImageRectI"); }
if (hProc) { nRet = hProc(graphics, lpImg, x, y, W, H); }
}
return nRet;
}
Warning, the
zCreateAlphaMask code has not been tested yet.
The function returns either a gdiplus LONG_PTR or a HBITMAP handle if ReturnBitmap is TRUE.
It is up to you to cleanup the bitmap handle or the gdiplus LONG_PTR once done.
Look at the "Increase opacity" loop, 4 seems the good value to me, this is what i am using in my standalone utility.
why wouldn't you also add alpha mask GDI+ AA resizing to fit the diffuse texture size if necessary?
I do not understand what you mean.