gdiplus: Implement GdipBitmapGetHistogram().
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Vincent Povirk <vincent@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
8de0275e48
commit
509ba80bcb
|
@ -618,7 +618,7 @@
|
|||
618 stub GdipInitializePalette
|
||||
619 stdcall GdipBitmapCreateApplyEffect(ptr long ptr ptr ptr ptr long ptr ptr)
|
||||
620 stdcall GdipBitmapApplyEffect(ptr ptr ptr long ptr ptr)
|
||||
621 stub GdipBitmapGetHistogram
|
||||
621 stdcall GdipBitmapGetHistogram(ptr long long ptr ptr ptr ptr)
|
||||
622 stdcall GdipBitmapGetHistogramSize(long ptr)
|
||||
623 stdcall GdipBitmapConvertFormat(ptr long long long ptr float)
|
||||
624 stdcall GdipImageSetAbort(ptr ptr)
|
||||
|
|
|
@ -5387,6 +5387,129 @@ GpStatus WINGDIPAPI GdipBitmapConvertFormat(GpBitmap *bitmap, PixelFormat format
|
|||
return NotImplemented;
|
||||
}
|
||||
|
||||
static void set_histogram_point_argb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
|
||||
{
|
||||
ch0[ color >> 24 ]++;
|
||||
ch1[(color >> 16) & 0xff]++;
|
||||
ch2[(color >> 8) & 0xff]++;
|
||||
ch3[ color & 0xff]++;
|
||||
}
|
||||
|
||||
static void set_histogram_point_pargb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
|
||||
{
|
||||
BYTE alpha = color >> 24;
|
||||
|
||||
ch0[alpha]++;
|
||||
ch1[(((color >> 16) & 0xff) * alpha) / 0xff]++;
|
||||
ch2[(((color >> 8) & 0xff) * alpha) / 0xff]++;
|
||||
ch3[(( color & 0xff) * alpha) / 0xff]++;
|
||||
}
|
||||
|
||||
static void set_histogram_point_rgb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
|
||||
{
|
||||
ch0[(color >> 16) & 0xff]++;
|
||||
ch1[(color >> 8) & 0xff]++;
|
||||
ch2[ color & 0xff]++;
|
||||
}
|
||||
|
||||
static void set_histogram_point_gray(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
|
||||
{
|
||||
ch0[(76 * ((color >> 16) & 0xff) + 150 * ((color >> 8) & 0xff) + 29 * (color & 0xff)) / 0xff]++;
|
||||
}
|
||||
|
||||
static void set_histogram_point_b(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
|
||||
{
|
||||
ch0[color & 0xff]++;
|
||||
}
|
||||
|
||||
static void set_histogram_point_g(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
|
||||
{
|
||||
ch0[(color >> 8) & 0xff]++;
|
||||
}
|
||||
|
||||
static void set_histogram_point_r(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
|
||||
{
|
||||
ch0[(color >> 16) & 0xff]++;
|
||||
}
|
||||
|
||||
static void set_histogram_point_a(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
|
||||
{
|
||||
ch0[(color >> 24) & 0xff]++;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* GdipBitmapGetHistogram [GDIPLUS.@]
|
||||
*/
|
||||
GpStatus WINGDIPAPI GdipBitmapGetHistogram(GpBitmap *bitmap, HistogramFormat format, UINT num_of_entries,
|
||||
UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
|
||||
{
|
||||
static void (* const set_histogram_point[])(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3) =
|
||||
{
|
||||
set_histogram_point_argb,
|
||||
set_histogram_point_pargb,
|
||||
set_histogram_point_rgb,
|
||||
set_histogram_point_gray,
|
||||
set_histogram_point_b,
|
||||
set_histogram_point_g,
|
||||
set_histogram_point_r,
|
||||
set_histogram_point_a,
|
||||
};
|
||||
UINT width, height, x, y;
|
||||
|
||||
TRACE("(%p, %d, %u, %p, %p, %p, %p)\n", bitmap, format, num_of_entries,
|
||||
ch0, ch1, ch2, ch3);
|
||||
|
||||
if (!bitmap || num_of_entries != 256)
|
||||
return InvalidParameter;
|
||||
|
||||
/* Make sure passed channel pointers match requested format */
|
||||
switch (format)
|
||||
{
|
||||
case HistogramFormatARGB:
|
||||
case HistogramFormatPARGB:
|
||||
if (!ch0 || !ch1 || !ch2 || !ch3)
|
||||
return InvalidParameter;
|
||||
memset(ch0, 0, num_of_entries * sizeof(UINT));
|
||||
memset(ch1, 0, num_of_entries * sizeof(UINT));
|
||||
memset(ch2, 0, num_of_entries * sizeof(UINT));
|
||||
memset(ch3, 0, num_of_entries * sizeof(UINT));
|
||||
break;
|
||||
case HistogramFormatRGB:
|
||||
if (!ch0 || !ch1 || !ch2 || ch3)
|
||||
return InvalidParameter;
|
||||
memset(ch0, 0, num_of_entries * sizeof(UINT));
|
||||
memset(ch1, 0, num_of_entries * sizeof(UINT));
|
||||
memset(ch2, 0, num_of_entries * sizeof(UINT));
|
||||
break;
|
||||
case HistogramFormatGray:
|
||||
case HistogramFormatB:
|
||||
case HistogramFormatG:
|
||||
case HistogramFormatR:
|
||||
case HistogramFormatA:
|
||||
if (!ch0 || ch1 || ch2 || ch3)
|
||||
return InvalidParameter;
|
||||
memset(ch0, 0, num_of_entries * sizeof(UINT));
|
||||
break;
|
||||
default:
|
||||
WARN("Invalid histogram format requested, %d\n", format);
|
||||
return InvalidParameter;
|
||||
}
|
||||
|
||||
GdipGetImageWidth(&bitmap->image, &width);
|
||||
GdipGetImageHeight(&bitmap->image, &height);
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
ARGB color;
|
||||
|
||||
GdipBitmapGetPixel(bitmap, x, y, &color);
|
||||
set_histogram_point[format](color, ch0, ch1, ch2, ch3);
|
||||
}
|
||||
|
||||
return Ok;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* GdipBitmapGetHistogramSize [GDIPLUS.@]
|
||||
*/
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "wine/test.h"
|
||||
|
||||
static GpStatus (WINAPI *pGdipBitmapGetHistogramSize)(HistogramFormat,UINT*);
|
||||
static GpStatus (WINAPI *pGdipBitmapGetHistogram)(GpBitmap*,HistogramFormat,UINT,UINT*,UINT*,UINT*,UINT*);
|
||||
|
||||
#define expect(expected, got) ok((got) == (expected), "Expected %d, got %d\n", (UINT)(expected), (UINT)(got))
|
||||
#define expectf(expected, got) ok(fabs((expected) - (got)) < 0.0001, "Expected %f, got %f\n", (expected), (got))
|
||||
|
@ -4787,8 +4788,9 @@ static void test_getadjustedpalette(void)
|
|||
GdipDisposeImageAttributes(imageattributes);
|
||||
}
|
||||
|
||||
static void test_histogramsize(void)
|
||||
static void test_histogram(void)
|
||||
{
|
||||
UINT ch0[256], ch1[256], ch2[256], ch3[256];
|
||||
HistogramFormat test_formats[] =
|
||||
{
|
||||
HistogramFormatARGB,
|
||||
|
@ -4800,8 +4802,10 @@ static void test_histogramsize(void)
|
|||
HistogramFormatR,
|
||||
HistogramFormatA,
|
||||
};
|
||||
const UINT WIDTH = 8, HEIGHT = 16;
|
||||
UINT num, i, x;
|
||||
GpStatus stat;
|
||||
UINT num, i;
|
||||
GpBitmap *bm;
|
||||
|
||||
if (!pGdipBitmapGetHistogramSize)
|
||||
{
|
||||
|
@ -4827,6 +4831,89 @@ static void test_histogramsize(void)
|
|||
expect(Ok, stat);
|
||||
expect(256, num);
|
||||
}
|
||||
|
||||
bm = NULL;
|
||||
stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
|
||||
expect(Ok, stat);
|
||||
|
||||
/* Three solid rgb rows, next three rows are rgb shades. */
|
||||
for (x = 0; x < WIDTH; x++)
|
||||
{
|
||||
GdipBitmapSetPixel(bm, x, 0, 0xffff0000);
|
||||
GdipBitmapSetPixel(bm, x, 1, 0xff00ff00);
|
||||
GdipBitmapSetPixel(bm, x, 2, 0xff0000ff);
|
||||
|
||||
GdipBitmapSetPixel(bm, x, 3, 0xff010000);
|
||||
GdipBitmapSetPixel(bm, x, 4, 0xff003f00);
|
||||
GdipBitmapSetPixel(bm, x, 5, 0xff000020);
|
||||
}
|
||||
|
||||
stat = pGdipBitmapGetHistogram(NULL, HistogramFormatRGB, 256, ch0, ch1, ch2, ch3);
|
||||
expect(InvalidParameter, stat);
|
||||
|
||||
stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, ch2, ch3);
|
||||
expect(InvalidParameter, stat);
|
||||
|
||||
stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, ch2, NULL);
|
||||
expect(InvalidParameter, stat);
|
||||
|
||||
stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, NULL, NULL);
|
||||
expect(InvalidParameter, stat);
|
||||
|
||||
stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, NULL, NULL, NULL);
|
||||
expect(InvalidParameter, stat);
|
||||
|
||||
/* Requested format matches bitmap format */
|
||||
stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 256, ch0, ch1, ch2, ch3);
|
||||
expect(InvalidParameter, stat);
|
||||
|
||||
stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 100, ch0, ch1, ch2, NULL);
|
||||
expect(InvalidParameter, stat);
|
||||
|
||||
stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 257, ch0, ch1, ch2, NULL);
|
||||
expect(InvalidParameter, stat);
|
||||
|
||||
/* Channel 3 is not used, must be NULL */
|
||||
stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 256, ch0, ch1, ch2, NULL);
|
||||
expect(Ok, stat);
|
||||
|
||||
ok(ch0[0xff] == WIDTH, "Got red (0xff) %u\n", ch0[0xff]);
|
||||
ok(ch1[0xff] == WIDTH, "Got green (0xff) %u\n", ch1[0xff]);
|
||||
ok(ch2[0xff] == WIDTH, "Got blue (0xff) %u\n", ch1[0xff]);
|
||||
ok(ch0[0x01] == WIDTH, "Got red (0x01) %u\n", ch0[0x01]);
|
||||
ok(ch1[0x3f] == WIDTH, "Got green (0x3f) %u\n", ch1[0x3f]);
|
||||
ok(ch2[0x20] == WIDTH, "Got blue (0x20) %u\n", ch1[0x20]);
|
||||
|
||||
/* ARGB histogram from RGB data. */
|
||||
stat = pGdipBitmapGetHistogram(bm, HistogramFormatARGB, 256, ch0, ch1, ch2, NULL);
|
||||
expect(InvalidParameter, stat);
|
||||
|
||||
stat = pGdipBitmapGetHistogram(bm, HistogramFormatARGB, 256, ch0, ch1, ch2, ch3);
|
||||
expect(Ok, stat);
|
||||
|
||||
ok(ch1[0xff] == WIDTH, "Got red (0xff) %u\n", ch1[0xff]);
|
||||
ok(ch2[0xff] == WIDTH, "Got green (0xff) %u\n", ch2[0xff]);
|
||||
ok(ch3[0xff] == WIDTH, "Got blue (0xff) %u\n", ch3[0xff]);
|
||||
ok(ch1[0x01] == WIDTH, "Got red (0x01) %u\n", ch1[0x01]);
|
||||
ok(ch2[0x3f] == WIDTH, "Got green (0x3f) %u\n", ch2[0x3f]);
|
||||
ok(ch3[0x20] == WIDTH, "Got blue (0x20) %u\n", ch3[0x20]);
|
||||
|
||||
ok(ch0[0xff] == WIDTH * HEIGHT, "Got alpha (0xff) %u\n", ch0[0xff]);
|
||||
|
||||
/* Request grayscale histogram from RGB bitmap. */
|
||||
stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, ch2, ch3);
|
||||
expect(InvalidParameter, stat);
|
||||
|
||||
stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, ch2, NULL);
|
||||
expect(InvalidParameter, stat);
|
||||
|
||||
stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, NULL, NULL);
|
||||
expect(InvalidParameter, stat);
|
||||
|
||||
stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, NULL, NULL, NULL);
|
||||
expect(Ok, stat);
|
||||
|
||||
GdipDisposeImage((GpImage*)bm);
|
||||
}
|
||||
|
||||
START_TEST(image)
|
||||
|
@ -4843,6 +4930,7 @@ START_TEST(image)
|
|||
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
|
||||
|
||||
pGdipBitmapGetHistogramSize = (void*)GetProcAddress(mod, "GdipBitmapGetHistogramSize");
|
||||
pGdipBitmapGetHistogram = (void*)GetProcAddress(mod, "GdipBitmapGetHistogram");
|
||||
|
||||
test_supported_encoders();
|
||||
test_CloneBitmapArea();
|
||||
|
@ -4890,7 +4978,7 @@ START_TEST(image)
|
|||
test_dispose();
|
||||
test_createeffect();
|
||||
test_getadjustedpalette();
|
||||
test_histogramsize();
|
||||
test_histogram();
|
||||
|
||||
GdiplusShutdown(gdiplusToken);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ GpStatus WINGDIPAPI GdipSetAdjustableArrowCapWidth(GpAdjustableArrowCap*,REAL);
|
|||
/* Bitmap */
|
||||
GpStatus WINGDIPAPI GdipBitmapApplyEffect(GpBitmap*,CGpEffect*,RECT*,BOOL,VOID**,INT*);
|
||||
GpStatus WINGDIPAPI GdipBitmapCreateApplyEffect(GpBitmap**,INT,CGpEffect*,RECT*,RECT*,GpBitmap**,BOOL,VOID**,INT*);
|
||||
GpStatus WINGDIPAPI GdipBitmapGetHistogram(GpBitmap*,HistogramFormat,UINT,UINT*,UINT*,UINT*,UINT*);
|
||||
GpStatus WINGDIPAPI GdipBitmapGetHistogramSize(HistogramFormat,UINT*);
|
||||
GpStatus WINGDIPAPI GdipBitmapGetPixel(GpBitmap*,INT,INT,ARGB*);
|
||||
GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap*,GDIPCONST GpRect*,UINT,
|
||||
|
|
Loading…
Reference in New Issue