Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
978
Src/Plugins/Library/ml_devices/image.cpp
Normal file
978
Src/Plugins/Library/ml_devices/image.cpp
Normal file
|
@ -0,0 +1,978 @@
|
|||
#include "main.h"
|
||||
#include "./image.h"
|
||||
|
||||
|
||||
HBITMAP
|
||||
Image_Load(const wchar_t *path, unsigned int type,
|
||||
unsigned int flags, int width, int height)
|
||||
{
|
||||
MLIMAGESOURCE source;
|
||||
HWND libraryWindow = Plugin_GetLibraryWindow();
|
||||
if (NULL == libraryWindow)
|
||||
return NULL;
|
||||
|
||||
source.cbSize = sizeof(source);
|
||||
source.lpszName = path;
|
||||
source.type = type;
|
||||
source.flags = (flags & ~IMAGE_FILTER_MASK);
|
||||
source.cxDst = width;
|
||||
source.cyDst = height;
|
||||
|
||||
if (0 == (ISF_LOADFROMFILE & source.flags))
|
||||
{
|
||||
source.hInst = WASABI_API_LNG_HINST;
|
||||
if (NULL != source.hInst)
|
||||
{
|
||||
HBITMAP bitmap = MLImageLoader_LoadDib(libraryWindow, &source);
|
||||
if (NULL != bitmap)
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
if (WASABI_API_ORIG_HINST == source.hInst)
|
||||
return NULL;
|
||||
|
||||
source.hInst = WASABI_API_ORIG_HINST;
|
||||
return (NULL != source.hInst) ?
|
||||
MLImageLoader_LoadDib(libraryWindow, &source) :
|
||||
NULL;
|
||||
}
|
||||
|
||||
return MLImageLoader_LoadDib(Plugin_GetLibraryWindow(), &source);
|
||||
}
|
||||
|
||||
HBITMAP
|
||||
Image_LoadEx(HINSTANCE instance, const wchar_t *path, unsigned int type,
|
||||
unsigned int flags, int width, int height)
|
||||
{
|
||||
MLIMAGESOURCE source = {0};
|
||||
|
||||
source.cbSize = sizeof(source);
|
||||
source.hInst = instance;
|
||||
source.lpszName = path;
|
||||
source.type = type;
|
||||
source.flags = (flags & ~IMAGE_FILTER_MASK);
|
||||
source.cxDst = width;
|
||||
source.cyDst = height;
|
||||
|
||||
return MLImageLoader_LoadDib(Plugin_GetLibraryWindow(), &source);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_FilterEx(void *pixelData, long width, long height, unsigned short bpp,
|
||||
unsigned int flags, COLORREF backColor, COLORREF frontColor, COLORREF blendColor)
|
||||
{
|
||||
MLIMAGEFILTERAPPLYEX filter;
|
||||
HWND libraryWindow;
|
||||
BOOL result;
|
||||
|
||||
if (NULL == pixelData)
|
||||
return FALSE;
|
||||
|
||||
libraryWindow = Plugin_GetLibraryWindow();
|
||||
if (NULL == libraryWindow)
|
||||
return FALSE;
|
||||
|
||||
filter.cbSize = sizeof(filter);
|
||||
filter.pData = (BYTE*)pixelData;
|
||||
filter.cx = width;
|
||||
filter.cy = height;
|
||||
filter.bpp = bpp;
|
||||
filter.imageTag = NULL;
|
||||
|
||||
result = FALSE;
|
||||
|
||||
if (0 != (IMAGE_FILTER_GRAYSCALE & flags))
|
||||
{
|
||||
filter.filterUID = MLIF_GRAYSCALE_UID;
|
||||
result = MLImageFilter_ApplyEx(libraryWindow, &filter);
|
||||
}
|
||||
|
||||
filter.rgbBk = backColor;
|
||||
filter.rgbFg = frontColor;
|
||||
|
||||
if (32 == bpp)
|
||||
{
|
||||
filter.filterUID = MLIF_FILTER1_PRESERVE_ALPHA_UID;
|
||||
result = MLImageFilter_ApplyEx(libraryWindow, &filter);
|
||||
|
||||
if (0 != (IMAGE_FILTER_BLEND & flags))
|
||||
{
|
||||
filter.filterUID = MLIF_BLENDONBK_UID;
|
||||
filter.rgbBk = blendColor;
|
||||
result = MLImageFilter_ApplyEx(libraryWindow, &filter);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
filter.filterUID = MLIF_FILTER1_UID;
|
||||
result = MLImageFilter_ApplyEx(libraryWindow, &filter);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_Filter(HBITMAP bitmap, unsigned int flags,
|
||||
COLORREF backColor, COLORREF frontColor, COLORREF blendColor)
|
||||
{
|
||||
DIBSECTION bitmapData;
|
||||
BITMAP *bi;
|
||||
|
||||
if (NULL == bitmap)
|
||||
return NULL;
|
||||
|
||||
if (sizeof(bitmapData) != GetObjectW(bitmap, sizeof(bitmapData), &bitmapData))
|
||||
return FALSE;
|
||||
|
||||
bi = &bitmapData.dsBm;
|
||||
|
||||
return Image_FilterEx(bi->bmBits, bi->bmWidth, bi->bmHeight, bi->bmBitsPixel,
|
||||
flags, backColor, frontColor, blendColor);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_BlendEx(void *pixelData, long width, long height, unsigned short bpp, COLORREF blendColor)
|
||||
{
|
||||
MLIMAGEFILTERAPPLYEX filter;
|
||||
HWND libraryWindow;
|
||||
|
||||
if (NULL == pixelData || 32 != bpp)
|
||||
return FALSE;
|
||||
|
||||
libraryWindow = Plugin_GetLibraryWindow();
|
||||
if (NULL == libraryWindow)
|
||||
return FALSE;
|
||||
|
||||
filter.cbSize = sizeof(filter);
|
||||
filter.pData = (BYTE*)pixelData;
|
||||
filter.cx = width;
|
||||
filter.cy = height;
|
||||
filter.bpp = bpp;
|
||||
filter.imageTag = NULL;
|
||||
|
||||
|
||||
filter.filterUID = MLIF_BLENDONBK_UID;
|
||||
filter.rgbBk = blendColor;
|
||||
return MLImageFilter_ApplyEx(libraryWindow, &filter);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_Blend(HBITMAP bitmap, COLORREF blendColor)
|
||||
{
|
||||
DIBSECTION bitmapData;
|
||||
BITMAP *bi;
|
||||
|
||||
if (NULL == bitmap)
|
||||
return NULL;
|
||||
|
||||
if (sizeof(bitmapData) != GetObjectW(bitmap, sizeof(bitmapData), &bitmapData))
|
||||
return FALSE;
|
||||
|
||||
bi = &bitmapData.dsBm;
|
||||
|
||||
return Image_BlendEx(bi->bmBits, bi->bmWidth, bi->bmHeight, bi->bmBitsPixel, blendColor);
|
||||
}
|
||||
|
||||
HBITMAP
|
||||
Image_LoadSkinnedEx(HINSTANCE instance, const wchar_t *path, unsigned int type,
|
||||
unsigned int flags, int width, int height,
|
||||
COLORREF backColor, COLORREF frontColor, COLORREF blendColor)
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
|
||||
bitmap = Image_LoadEx(instance, path, type, flags, width, height);
|
||||
if (NULL == bitmap)
|
||||
return NULL;
|
||||
|
||||
Image_Filter(bitmap, flags, backColor, frontColor, blendColor);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
HBITMAP
|
||||
Image_LoadSkinned(const wchar_t *path, unsigned int type,
|
||||
unsigned int flags, int width, int height,
|
||||
COLORREF backColor, COLORREF frontColor, COLORREF blendColor)
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
|
||||
bitmap = Image_Load(path, type, flags, width, height);
|
||||
if (NULL == bitmap)
|
||||
return NULL;
|
||||
|
||||
Image_Filter(bitmap, flags, backColor, frontColor, blendColor);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
HBITMAP
|
||||
Image_DuplicateDib(HBITMAP source)
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
DIBSECTION sourceDib;
|
||||
HDC windowDC;
|
||||
void *pixelData;
|
||||
|
||||
if (NULL == source)
|
||||
return NULL;
|
||||
|
||||
if (sizeof(sourceDib) != GetObjectW(source, sizeof(sourceDib), &sourceDib))
|
||||
return FALSE;
|
||||
|
||||
|
||||
sourceDib.dsBmih.biSize = sizeof(BITMAPINFOHEADER);
|
||||
if (sourceDib.dsBmih.biHeight > 0)
|
||||
sourceDib.dsBmih.biHeight = -sourceDib.dsBmih.biHeight;
|
||||
|
||||
windowDC = GetDCEx(NULL, NULL, DCX_WINDOW | DCX_CACHE);
|
||||
|
||||
bitmap = CreateDIBSection(windowDC, (BITMAPINFO*)&sourceDib.dsBmih, DIB_RGB_COLORS, &pixelData, NULL, 0);
|
||||
|
||||
if (NULL != windowDC)
|
||||
ReleaseDC(NULL, windowDC);
|
||||
|
||||
if (NULL == bitmap)
|
||||
return NULL;
|
||||
|
||||
CopyMemory(pixelData, sourceDib.dsBm.bmBits, sourceDib.dsBm.bmWidthBytes * sourceDib.dsBm.bmHeight);
|
||||
|
||||
return bitmap;
|
||||
|
||||
}
|
||||
BOOL
|
||||
Image_ColorOver(HBITMAP bitmap, const RECT *prcPart, BOOL premult, COLORREF rgb)
|
||||
{
|
||||
DIBSECTION bitmapData;
|
||||
BITMAP *bi;
|
||||
|
||||
if (NULL == bitmap)
|
||||
return NULL;
|
||||
|
||||
if (sizeof(bitmapData) != GetObjectW(bitmap, sizeof(bitmapData), &bitmapData))
|
||||
return FALSE;
|
||||
|
||||
if (BI_RGB != bitmapData.dsBmih.biCompression ||
|
||||
1 != bitmapData.dsBmih.biPlanes ||
|
||||
32 != bitmapData.dsBm.bmBitsPixel)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bi = &bitmapData.dsBm;
|
||||
|
||||
return (NULL == prcPart) ?
|
||||
Image_ColorOverEx((BYTE*)bi->bmBits, bi->bmWidth, bi->bmHeight,
|
||||
0, 0, bi->bmWidth, bi->bmHeight,
|
||||
bi->bmBitsPixel, premult, rgb) :
|
||||
Image_ColorOverEx((BYTE*)bi->bmBits, bi->bmWidth, bi->bmHeight,
|
||||
prcPart->left, prcPart->top,
|
||||
prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
|
||||
bi->bmBitsPixel, premult, rgb);
|
||||
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_ColorOverEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
|
||||
long x, long y, long cx, long cy, unsigned short bpp,
|
||||
BOOL premult, COLORREF rgb)
|
||||
{
|
||||
LONG pitch;
|
||||
UINT a, r, g, b, ma, mr, mg, mb;
|
||||
INT step = (bpp>>3);
|
||||
LPBYTE line, cursor;
|
||||
pitch = bitmapCX * step;
|
||||
while (pitch%4) pitch++;
|
||||
|
||||
if (step < 3)
|
||||
return TRUE;
|
||||
|
||||
if (cy < 0) cy -= cy;
|
||||
|
||||
a = (LOBYTE((rgb)>>24)); r = GetRValue(rgb); g = GetGValue(rgb); b = GetBValue(rgb);
|
||||
ma = 255 - a; mr = r * 255; mg = g * 255; mb = b * 255;
|
||||
|
||||
if (0 == a)
|
||||
return TRUE;
|
||||
|
||||
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
|
||||
line = pPixels + pitch * ofs + x*step;
|
||||
|
||||
if (0xFF == a)
|
||||
{
|
||||
for (; cy-- != 0; line += pitch)
|
||||
{
|
||||
for (x = cx, cursor = line; x-- != 0; cursor += step)
|
||||
{
|
||||
cursor[0] = (BYTE)b;
|
||||
cursor[1] = (BYTE)g;
|
||||
cursor[2] = (BYTE)r;
|
||||
// cursor[3] = 0xFF;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
if (premult)
|
||||
{
|
||||
for (; cy-- != 0; line += pitch)
|
||||
{
|
||||
for (x = cx, cursor = line; x-- != 0; cursor += step)
|
||||
{
|
||||
int t = (mb + ma * cursor[0] + 127) / 255;
|
||||
cursor[0] = (t > 0xFF) ? 0xFF : t;
|
||||
t = (mg + ma * cursor[1] + 127) / 255;
|
||||
cursor[1] = (t > 0xFF) ? 0xFF : t;
|
||||
t = (mr+ ma * cursor[2] + 127) / 255;
|
||||
cursor[2] = (t > 0xFF) ? 0xFF : t;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WORD k = (((255 - a)*255 + 127)/255);
|
||||
for (; cy-- != 0; line += pitch)
|
||||
{
|
||||
for (x = cx, cursor = line; x-- != 0; cursor += step)
|
||||
{
|
||||
cursor[0] = (b*a + k*cursor[0] + 127)/255;
|
||||
cursor[1] = (g*a + k*cursor[1] + 127)/255;
|
||||
cursor[2] = (r*a + k*cursor[2] + 127)/255;
|
||||
// cursor[3] = (a*a + k*cursor[3] + 127)/255;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_Premultiply(HBITMAP hbmp, const RECT *prcPart)
|
||||
{
|
||||
DIBSECTION dibsec;
|
||||
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
|
||||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
|
||||
return FALSE;
|
||||
|
||||
return (NULL == prcPart) ?
|
||||
Image_PremultiplyEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
0, 0, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
dibsec.dsBm.bmBitsPixel) :
|
||||
Image_PremultiplyEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
prcPart->left, prcPart->top, RECTWIDTH(*prcPart), RECTHEIGHT(*prcPart),
|
||||
dibsec.dsBm.bmBitsPixel);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_PremultiplyEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
|
||||
long x, long y, long cx, long cy, unsigned short bpp)
|
||||
{
|
||||
if (32 != bpp)
|
||||
return FALSE;
|
||||
|
||||
LONG pitch;
|
||||
INT step = (bpp>>3);
|
||||
LPBYTE line, cursor;
|
||||
pitch = bitmapCX * step;
|
||||
while (pitch%4) pitch++;
|
||||
|
||||
if (cy < 0)
|
||||
cy = -cy;
|
||||
|
||||
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
|
||||
line = pPixels + pitch * ofs + x*step;
|
||||
|
||||
UINT a;
|
||||
for (; cy-- != 0; line += pitch)
|
||||
{
|
||||
for (x = cx, cursor = line; x-- != 0; cursor += step)
|
||||
{
|
||||
a = cursor[3];
|
||||
if (0 == a)
|
||||
{
|
||||
cursor[0] = 0;
|
||||
cursor[1] = 0;
|
||||
cursor[2] = 0;
|
||||
}
|
||||
else if (255 != a)
|
||||
{
|
||||
cursor[0] = (BYTE)MulDiv(cursor[0], a, 255);
|
||||
cursor[1] = (BYTE)MulDiv(cursor[1], a, 255);
|
||||
cursor[2] = (BYTE)MulDiv(cursor[2], a, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_Demultiply(HBITMAP hbmp, const RECT *prcPart)
|
||||
{
|
||||
DIBSECTION dibsec;
|
||||
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
|
||||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
|
||||
return FALSE;
|
||||
|
||||
return (NULL == prcPart) ?
|
||||
Image_DemultiplyEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
0, 0, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
dibsec.dsBm.bmBitsPixel) :
|
||||
Image_DemultiplyEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
prcPart->left, prcPart->top, RECTWIDTH(*prcPart), RECTHEIGHT(*prcPart),
|
||||
dibsec.dsBm.bmBitsPixel);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_DemultiplyEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
|
||||
long x, long y, long cx, long cy, unsigned short bpp)
|
||||
{
|
||||
if (32 != bpp)
|
||||
return FALSE;
|
||||
|
||||
LONG pitch;
|
||||
INT step = (bpp>>3);
|
||||
LPBYTE line, cursor;
|
||||
pitch = bitmapCX * step;
|
||||
while (pitch%4) pitch++;
|
||||
|
||||
if (cy < 0)
|
||||
cy = -cy;
|
||||
|
||||
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
|
||||
line = pPixels + pitch * ofs + x*step;
|
||||
|
||||
UINT a;
|
||||
for (; cy-- != 0; line += pitch)
|
||||
{
|
||||
for (x = cx, cursor = line; x-- != 0; cursor += step)
|
||||
{
|
||||
a = cursor[3];
|
||||
if (0 == a)
|
||||
{
|
||||
cursor[0] = 0;
|
||||
cursor[1] = 0;
|
||||
cursor[2] = 0;
|
||||
}
|
||||
else if (255 != a)
|
||||
{
|
||||
cursor[0] = (BYTE)MulDiv(cursor[0], 255, a);
|
||||
cursor[1] = (BYTE)MulDiv(cursor[1], 255, a);
|
||||
cursor[2] = (BYTE)MulDiv(cursor[2], 255, a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
BOOL
|
||||
Image_Saturate(HBITMAP hbmp, const RECT *prcPart, int n, BOOL fScale)
|
||||
{
|
||||
DIBSECTION dibsec;
|
||||
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
|
||||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
|
||||
return FALSE;
|
||||
|
||||
return Image_SaturateEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
prcPart->left, prcPart->top,
|
||||
prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
|
||||
dibsec.dsBm.bmBitsPixel, n, fScale);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_SaturateEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
|
||||
long x, long y, long cx, long cy, unsigned short bpp,
|
||||
int n, BOOL fScale)
|
||||
{
|
||||
if (32 != bpp)
|
||||
return FALSE;
|
||||
|
||||
LONG pitch;
|
||||
INT step = (bpp>>3);
|
||||
LPBYTE line, cursor;
|
||||
pitch = bitmapCX * step;
|
||||
while (pitch%4) pitch++;
|
||||
|
||||
if (FALSE == fScale)
|
||||
{
|
||||
if (n < 0) n = 0;
|
||||
else if (n > 1000) n = 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n < -1000) n = -1000;
|
||||
else if (n > 1000) n = 1000;
|
||||
}
|
||||
|
||||
if (cy < 0)
|
||||
cy = -cy;
|
||||
|
||||
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
|
||||
line = pPixels + pitch * ofs + x*step;
|
||||
|
||||
COLORREF rgb;
|
||||
INT k;
|
||||
WORD h, l, s;
|
||||
|
||||
for (; cy-- != 0; line += pitch)
|
||||
{
|
||||
for (x = cx, cursor = line; x-- != 0; cursor += step)
|
||||
{
|
||||
rgb = RGB(cursor[2], cursor[1], cursor[0]);
|
||||
ColorRGBToHLS(rgb, &h, &l, &s);
|
||||
if(FALSE == fScale)
|
||||
s = ((WORD)((240 * n)/1000));
|
||||
else
|
||||
{
|
||||
k = s;
|
||||
s = (WORD)(k + (k * n) /1000);
|
||||
}
|
||||
|
||||
rgb = ColorHLSToRGB(h, l, s);
|
||||
|
||||
cursor[0] = GetBValue(rgb);
|
||||
cursor[1] = GetGValue(rgb);
|
||||
cursor[2] = GetRValue(rgb);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_AdjustAlpha(HBITMAP hbmp, const RECT *prcPart, int n, BOOL fScale)
|
||||
{
|
||||
DIBSECTION dibsec;
|
||||
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
|
||||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
|
||||
return FALSE;
|
||||
|
||||
return Image_AdjustAlphaEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
prcPart->left, prcPart->top,
|
||||
prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
|
||||
dibsec.dsBm.bmBitsPixel, n, fScale);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_AdjustAlphaEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
|
||||
long x, long y, long cx, long cy, unsigned short bpp,
|
||||
int n, BOOL fScale)
|
||||
{
|
||||
if (32 != bpp)
|
||||
return FALSE;
|
||||
|
||||
LONG pitch;
|
||||
INT step = (bpp>>3);
|
||||
LPBYTE line, cursor;
|
||||
pitch = bitmapCX * step;
|
||||
while (pitch%4) pitch++;
|
||||
|
||||
if (FALSE == fScale)
|
||||
{
|
||||
if (n < 0) n = 0;
|
||||
else if (n > 1000) n = 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (n < -1000) n = -1000;
|
||||
else if (n > 1000) n = 1000;
|
||||
}
|
||||
|
||||
if (cy < 0)
|
||||
cy = -cy;
|
||||
|
||||
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
|
||||
line = pPixels + pitch * ofs + x*step;
|
||||
|
||||
INT k;
|
||||
|
||||
for (; cy-- != 0; line += pitch)
|
||||
{
|
||||
for (x = cx, cursor = line; x-- != 0; cursor += step)
|
||||
{
|
||||
if(FALSE == fScale)
|
||||
cursor[3] = ((BYTE)((255 * n)/1000));
|
||||
else
|
||||
{
|
||||
k = cursor[3];
|
||||
k = k + MulDiv(k, n, 1000);
|
||||
if (k > 255) k = 255;
|
||||
cursor[3] = (BYTE)k;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_AdjustSaturationAlpha(HBITMAP hbmp, const RECT *prcPart, int nSaturation, int nAlpha)
|
||||
{
|
||||
DIBSECTION dibsec;
|
||||
if (!hbmp || sizeof(DIBSECTION) != GetObject(hbmp, sizeof(DIBSECTION), &dibsec) ||
|
||||
BI_RGB != dibsec.dsBmih.biCompression || 1 != dibsec.dsBmih.biPlanes || dibsec.dsBm.bmBitsPixel != 32)
|
||||
return FALSE;
|
||||
|
||||
return Image_AdjustSaturationAlphaEx((BYTE*)dibsec.dsBm.bmBits, dibsec.dsBm.bmWidth, dibsec.dsBm.bmHeight,
|
||||
prcPart->left, prcPart->top,
|
||||
prcPart->right - prcPart->left, prcPart->bottom - prcPart->top,
|
||||
dibsec.dsBm.bmBitsPixel, nSaturation, nAlpha);
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_AdjustSaturationAlphaEx(unsigned char *pPixels, int bitmapCX, int bitmapCY,
|
||||
long x, long y, long cx, long cy,
|
||||
unsigned short bpp, int nSaturation, int nAlpha)
|
||||
{
|
||||
if (32 != bpp)
|
||||
return FALSE;
|
||||
|
||||
LONG pitch;
|
||||
INT step = (bpp>>3);
|
||||
LPBYTE line, cursor;
|
||||
pitch = bitmapCX * step;
|
||||
while (pitch%4) pitch++;
|
||||
|
||||
if (nSaturation < -1000) nSaturation = -1000;
|
||||
else if (nSaturation > 1000) nSaturation = 1000;
|
||||
|
||||
if (nAlpha < -1000) nAlpha = -1000;
|
||||
else if (nAlpha > 1000) nAlpha = 1000;
|
||||
|
||||
if (cy < 0)
|
||||
cy = -cy;
|
||||
|
||||
INT ofs = (bitmapCY > 0) ? (bitmapCY - (y + cy)) : y;
|
||||
line = pPixels + pitch * ofs + x*step;
|
||||
|
||||
INT k;
|
||||
COLORREF rgb;
|
||||
WORD h, l, s;
|
||||
|
||||
for (; cy-- != 0; line += pitch)
|
||||
{
|
||||
for (x = cx, cursor = line; x-- != 0; cursor += step)
|
||||
{
|
||||
k = cursor[3];
|
||||
k = k + MulDiv(k, nAlpha, 1000);
|
||||
if (k > 255) k = 255;
|
||||
cursor[3] = (BYTE)k;
|
||||
|
||||
rgb = RGB(cursor[2], cursor[1], cursor[0]);
|
||||
ColorRGBToHLS(rgb, &h, &l, &s);
|
||||
|
||||
k = s;
|
||||
k = k + MulDiv(k, nSaturation, 1000);
|
||||
if (k > 240) k = 240;
|
||||
s = (WORD)k;
|
||||
|
||||
rgb = ColorHLSToRGB(h, l, s);
|
||||
cursor[0] = GetBValue(rgb);
|
||||
cursor[1] = GetGValue(rgb);
|
||||
cursor[2] = GetRValue(rgb);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_FillBorder(HDC targetDC, const RECT *targetRect,
|
||||
HDC sourceDC, const RECT *sourceRect,
|
||||
BOOL fillCenter, BYTE alphaConstant)
|
||||
{
|
||||
INT prevStretchMode;
|
||||
long centerWidth, centerHeight;
|
||||
long sliceWidth, sliceHeight;
|
||||
|
||||
const BLENDFUNCTION blendFunction = { AC_SRC_OVER, 0, alphaConstant, AC_SRC_ALPHA };
|
||||
const long targetWidth = RECTWIDTH(*targetRect);
|
||||
const long targetHeight = RECTHEIGHT(*targetRect);
|
||||
const long sourceWidth = RECTWIDTH(*sourceRect);
|
||||
const long sourceHeight = RECTHEIGHT(*sourceRect);
|
||||
|
||||
if (NULL == targetDC || NULL == sourceDC)
|
||||
return FALSE;
|
||||
|
||||
sliceWidth = sourceWidth/2;
|
||||
sliceHeight = sourceHeight/2;
|
||||
|
||||
if (sliceWidth*2 > targetWidth)
|
||||
sliceWidth = targetWidth/2;
|
||||
|
||||
if (sliceHeight*2 > targetHeight)
|
||||
sliceHeight = targetHeight/2;
|
||||
|
||||
if (0 == sliceWidth || 0 == sliceHeight)
|
||||
return FALSE;
|
||||
|
||||
prevStretchMode = SetStretchBltMode(targetDC, COLORONCOLOR);
|
||||
SetViewportOrgEx(sourceDC, 0, 0, NULL);
|
||||
|
||||
GdiAlphaBlend(targetDC, targetRect->left, targetRect->top, sliceWidth, sliceHeight,
|
||||
sourceDC, sourceRect->left, sourceRect->top, sliceWidth, sliceHeight, blendFunction);
|
||||
GdiAlphaBlend(targetDC, targetRect->right - sliceWidth, targetRect->top, sliceWidth, sliceHeight,
|
||||
sourceDC, sourceRect->right - sliceWidth, sourceRect->top, sliceWidth, sliceHeight, blendFunction);
|
||||
GdiAlphaBlend(targetDC, targetRect->left, targetRect->bottom - sliceHeight, sliceWidth, sliceHeight,
|
||||
sourceDC, sourceRect->left, sourceRect->bottom - sliceHeight, sliceWidth, sliceHeight, blendFunction);
|
||||
GdiAlphaBlend(targetDC, targetRect->right - sliceWidth, targetRect->bottom - sliceHeight, sliceWidth, sliceHeight,
|
||||
sourceDC, sourceRect->right - sliceWidth, sourceRect->bottom - sliceHeight, sliceWidth, sliceHeight, blendFunction);
|
||||
|
||||
if (targetWidth > 2*sliceWidth)
|
||||
{
|
||||
centerWidth = sourceWidth - 2*sliceWidth;
|
||||
if(centerWidth < 1)
|
||||
centerWidth = 1;
|
||||
|
||||
GdiAlphaBlend(targetDC, targetRect->left + sliceWidth, targetRect->top, targetWidth - (sliceWidth * 2), sliceHeight,
|
||||
sourceDC, sourceRect->left + sliceWidth, sourceRect->top, centerWidth, sliceHeight, blendFunction);
|
||||
|
||||
GdiAlphaBlend(targetDC, targetRect->left + sliceWidth, targetRect->bottom - sliceHeight, targetWidth - (sliceWidth * 2), sliceHeight,
|
||||
sourceDC, sourceRect->left + sliceWidth, sourceRect->bottom - sliceHeight, centerWidth, sliceHeight, blendFunction);
|
||||
}
|
||||
else
|
||||
centerWidth = 0;
|
||||
|
||||
if (targetHeight > 2*sliceHeight)
|
||||
{
|
||||
centerHeight = sourceHeight - 2*sliceHeight;
|
||||
if(centerHeight < 1)
|
||||
centerHeight = 1;
|
||||
|
||||
GdiAlphaBlend(targetDC, targetRect->left, targetRect->top + sliceHeight, sliceWidth, targetHeight - (sliceHeight* 2),
|
||||
sourceDC, sourceRect->left, sourceRect->top + sliceHeight, sliceWidth, centerHeight, blendFunction);
|
||||
|
||||
GdiAlphaBlend(targetDC, targetRect->right - sliceWidth, targetRect->top + sliceHeight, sliceWidth, targetHeight - (sliceHeight* 2),
|
||||
sourceDC, sourceRect->right - sliceWidth, sourceRect->top + sliceHeight, sliceWidth, centerHeight, blendFunction);
|
||||
}
|
||||
else
|
||||
centerHeight = 0;
|
||||
|
||||
if (FALSE != fillCenter &&
|
||||
0 != centerWidth && 0 != centerHeight)
|
||||
{
|
||||
GdiAlphaBlend(targetDC, targetRect->left + sliceWidth, targetRect->top + sliceHeight, targetWidth - (sliceWidth * 2), targetHeight - (sliceHeight* 2),
|
||||
sourceDC, sourceRect->left + sliceWidth, sourceRect->top + sliceHeight, centerWidth, centerHeight, blendFunction);
|
||||
|
||||
}
|
||||
|
||||
SetStretchBltMode(targetDC, prevStretchMode);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const ImageInfo *
|
||||
Image_GetBestFit(const ImageInfo *images, size_t count, unsigned int width, unsigned int height)
|
||||
{
|
||||
const ImageInfo *image, *bestFit;
|
||||
double widthDbl, heightDbl;
|
||||
double scaleMin, scaleHorz, scaleVert;
|
||||
|
||||
if (NULL == images || count < 1)
|
||||
return NULL;
|
||||
|
||||
if (width < 1)
|
||||
width = 1;
|
||||
|
||||
if (height < 1)
|
||||
height = 1;
|
||||
|
||||
widthDbl = width;
|
||||
heightDbl = height;
|
||||
|
||||
image = &images[--count];
|
||||
scaleHorz = widthDbl/image->width;
|
||||
scaleVert = heightDbl/image->height;
|
||||
scaleMin = (scaleHorz < scaleVert) ? scaleHorz : scaleVert;
|
||||
bestFit = image;
|
||||
|
||||
if (1.0 != scaleMin)
|
||||
{
|
||||
scaleMin = fabs(1.0 - scaleMin);
|
||||
while(count--)
|
||||
{
|
||||
image = &images[count];
|
||||
scaleHorz = widthDbl/image->width;
|
||||
scaleVert = heightDbl/image->height;
|
||||
if (scaleHorz > scaleVert)
|
||||
scaleHorz = scaleVert;
|
||||
|
||||
if (1.0 == scaleHorz)
|
||||
{
|
||||
bestFit = image;
|
||||
break;
|
||||
}
|
||||
|
||||
scaleHorz = fabs(1.0 - scaleHorz);
|
||||
if (scaleHorz < scaleMin)
|
||||
{
|
||||
scaleMin = scaleHorz;
|
||||
bestFit = image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bestFit;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Image_AlphaBlend(HDC targetDC, const RECT *targetRect,
|
||||
HDC sourceDC, const RECT *sourceRect, BYTE sourceAlpha,
|
||||
HBITMAP sourceBitmap, const RECT *paintRect, AlphaBlendFlags flags,
|
||||
RECT *rectOut)
|
||||
{
|
||||
BOOL result, clipSource;
|
||||
RECT fillRect;
|
||||
int sourceX, sourceY, sourceWidth, sourceHeight;
|
||||
const BLENDFUNCTION blendFunction =
|
||||
{
|
||||
AC_SRC_OVER,
|
||||
0,
|
||||
sourceAlpha,
|
||||
AC_SRC_ALPHA
|
||||
};
|
||||
|
||||
if (NULL != paintRect)
|
||||
{
|
||||
if (FALSE == IntersectRect(&fillRect, targetRect, paintRect))
|
||||
return TRUE;
|
||||
|
||||
clipSource = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyRect(&fillRect, targetRect);
|
||||
clipSource = FALSE;
|
||||
}
|
||||
|
||||
if (NULL != sourceRect)
|
||||
{
|
||||
sourceX = sourceRect->left;
|
||||
sourceY = sourceRect->top;
|
||||
sourceWidth = RECTWIDTH(*sourceRect);
|
||||
sourceHeight = RECTHEIGHT(*sourceRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
BITMAP bitmapInfo;
|
||||
if (sizeof(bitmapInfo) != GetObject(sourceBitmap, sizeof(bitmapInfo), &bitmapInfo))
|
||||
return FALSE;
|
||||
|
||||
sourceX = 0;
|
||||
sourceY = 0;
|
||||
sourceWidth = bitmapInfo.bmWidth;
|
||||
sourceHeight = bitmapInfo.bmHeight;
|
||||
if (sourceHeight < 0)
|
||||
sourceHeight = -sourceHeight;
|
||||
}
|
||||
|
||||
if (0 != (AlphaBlend_ScaleSource & flags))
|
||||
{
|
||||
RECT rect;
|
||||
double scaleHorz, scaleVert;
|
||||
|
||||
scaleHorz = (double)RECTWIDTH(*targetRect) / sourceWidth;
|
||||
scaleVert = (double)RECTHEIGHT(*targetRect) / sourceHeight;
|
||||
if (scaleHorz > scaleVert)
|
||||
scaleHorz = scaleVert;
|
||||
|
||||
SetRect(&rect, 0, 0, (int)(sourceWidth * scaleHorz), (int)(sourceHeight * scaleHorz));
|
||||
|
||||
if (0 != (AlphaBlend_AlignLeft & flags))
|
||||
rect.left = targetRect->left;
|
||||
else if (0 != (AlphaBlend_AlignRight & flags))
|
||||
rect.left = targetRect->right - rect.right;
|
||||
else
|
||||
rect.left = targetRect->left + (RECTWIDTH(*targetRect) - rect.right)/2;
|
||||
|
||||
if (0 != (AlphaBlend_AlignTop & flags))
|
||||
rect.top = targetRect->top;
|
||||
else if (0 != (AlphaBlend_AlignBottom & flags))
|
||||
rect.top = targetRect->bottom - rect.bottom;
|
||||
else
|
||||
rect.top = targetRect->top + (RECTHEIGHT(*targetRect) - rect.bottom)/2;
|
||||
|
||||
rect.right += rect.left;
|
||||
rect.bottom += rect.top;
|
||||
|
||||
if (NULL != rectOut)
|
||||
CopyRect(rectOut, &rect);
|
||||
|
||||
if (NULL != paintRect)
|
||||
{
|
||||
if (FALSE == IntersectRect(&fillRect, &rect, paintRect))
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
CopyRect(&fillRect, &rect);
|
||||
|
||||
sourceX += (int)((fillRect.left - rect.left)/scaleHorz);
|
||||
sourceY += (int)((fillRect.top - rect.top)/ scaleHorz);
|
||||
sourceWidth -= (int)((RECTWIDTH(rect) - RECTWIDTH(fillRect))/scaleHorz);
|
||||
sourceHeight -= (int)((RECTHEIGHT(rect) - RECTHEIGHT(fillRect))/scaleHorz);
|
||||
clipSource = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sourceWidth < RECTWIDTH(*targetRect) ||
|
||||
sourceHeight < RECTHEIGHT(*targetRect))
|
||||
{
|
||||
RECT rect;
|
||||
|
||||
if (0 != (AlphaBlend_AlignLeft & flags))
|
||||
rect.left = targetRect->left;
|
||||
else if (0 != (AlphaBlend_AlignRight & flags))
|
||||
rect.left = targetRect->right - sourceWidth;
|
||||
else
|
||||
rect.left = targetRect->left + (RECTWIDTH(*targetRect) - sourceWidth)/2;
|
||||
|
||||
if (0 != (AlphaBlend_AlignTop & flags))
|
||||
rect.top = targetRect->top;
|
||||
else if (0 != (AlphaBlend_AlignBottom & flags))
|
||||
rect.top = targetRect->bottom - sourceHeight;
|
||||
else
|
||||
rect.top = targetRect->top + (RECTHEIGHT(*targetRect) - sourceHeight)/2;
|
||||
|
||||
rect.right = rect.left + sourceWidth;
|
||||
rect.bottom = rect.top + sourceHeight;
|
||||
|
||||
if (NULL != paintRect)
|
||||
{
|
||||
if (FALSE == IntersectRect(&fillRect, &rect, paintRect))
|
||||
return TRUE;
|
||||
|
||||
sourceX += (fillRect.left - rect.left);
|
||||
sourceY += (fillRect.top - rect.top);
|
||||
sourceWidth -= (RECTWIDTH(rect) - RECTWIDTH(fillRect));
|
||||
sourceHeight -= (RECTHEIGHT(rect) - RECTHEIGHT(fillRect));
|
||||
}
|
||||
else
|
||||
CopyRect(&fillRect, &rect);
|
||||
|
||||
if (NULL != rectOut)
|
||||
CopyRect(rectOut, &rect);
|
||||
|
||||
clipSource = FALSE;
|
||||
}
|
||||
else if (NULL != rectOut)
|
||||
CopyRect(rectOut, targetRect);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (FALSE != clipSource)
|
||||
{
|
||||
sourceX += (fillRect.left - targetRect->left);
|
||||
sourceY += (fillRect.top - targetRect->top);
|
||||
sourceWidth -= (RECTWIDTH(*targetRect) - RECTWIDTH(fillRect));
|
||||
sourceHeight -= (RECTHEIGHT(*targetRect) - RECTHEIGHT(fillRect));
|
||||
}
|
||||
|
||||
if (NULL != sourceBitmap)
|
||||
SelectBitmap(sourceDC, sourceBitmap);
|
||||
|
||||
result = GdiAlphaBlend(targetDC, fillRect.left, fillRect.top, RECTWIDTH(fillRect), RECTHEIGHT(fillRect),
|
||||
sourceDC, sourceX, sourceY, sourceWidth, sourceHeight, blendFunction);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue