Commit 00de9c2b authored by Dmitry Timoshkov's avatar Dmitry Timoshkov Committed by Vitaly Lipatov

gdiplus: Prefer using pre-multiplied ARGB data in the scaler.

This further improves performance by about 20%.
parent 6ada6367
......@@ -600,6 +600,17 @@ static GpStatus alpha_blend_pixels(GpGraphics *graphics, INT dst_x, INT dst_y,
return alpha_blend_pixels_hrgn(graphics, dst_x, dst_y, src, src_width, src_height, src_stride, NULL, fmt);
}
/* NOTE: start and end pixels must be in pre-multiplied ARGB format */
static FORCEINLINE ARGB blend_colors_premult(ARGB start, ARGB end, REAL position)
{
UINT pos = position * 255.0f + 0.5f;
return
(((((start >> 24) ) << 8) + (((end >> 24) ) - ((start >> 24) )) * pos) >> 8) << 24 |
(((((start >> 16) & 0xff) << 8) + (((end >> 16) & 0xff) - ((start >> 16) & 0xff)) * pos) >> 8) << 16 |
(((((start >> 8) & 0xff) << 8) + (((end >> 8) & 0xff) - ((start >> 8) & 0xff)) * pos) >> 8) << 8 |
(((((start ) & 0xff) << 8) + (((end ) & 0xff) - ((start ) & 0xff)) * pos) >> 8);
}
static ARGB blend_colors(ARGB start, ARGB end, REAL position)
{
INT start_a, end_a, final_a;
......@@ -1085,6 +1096,75 @@ static ARGB resample_bitmap_pixel(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT
}
}
static ARGB resample_bitmap_pixel_premult(GDIPCONST GpRect *src_rect, LPBYTE bits, UINT width,
UINT height, GpPointF *point, GDIPCONST GpImageAttributes *attributes,
InterpolationMode interpolation, PixelOffsetMode offset_mode)
{
static int fixme;
switch (interpolation)
{
default:
if (!fixme++)
FIXME("Unimplemented interpolation %i\n", interpolation);
/* fall-through */
case InterpolationModeBilinear:
{
REAL leftxf, topyf;
INT leftx, rightx, topy, bottomy;
ARGB topleft, topright, bottomleft, bottomright;
ARGB top, bottom;
float x_offset;
leftx = (INT)point->X;
leftxf = (REAL)leftx;
rightx = positive_ceilf(point->X);
topy = (INT)point->Y;
topyf = (REAL)topy;
bottomy = positive_ceilf(point->Y);
if (leftx == rightx && topy == bottomy)
return sample_bitmap_pixel(src_rect, bits, width, height,
leftx, topy, attributes);
topleft = sample_bitmap_pixel(src_rect, bits, width, height,
leftx, topy, attributes);
topright = sample_bitmap_pixel(src_rect, bits, width, height,
rightx, topy, attributes);
bottomleft = sample_bitmap_pixel(src_rect, bits, width, height,
leftx, bottomy, attributes);
bottomright = sample_bitmap_pixel(src_rect, bits, width, height,
rightx, bottomy, attributes);
x_offset = point->X - leftxf;
top = blend_colors_premult(topleft, topright, x_offset);
bottom = blend_colors_premult(bottomleft, bottomright, x_offset);
return blend_colors_premult(top, bottom, point->Y - topyf);
}
case InterpolationModeNearestNeighbor:
{
FLOAT pixel_offset;
switch (offset_mode)
{
default:
case PixelOffsetModeNone:
case PixelOffsetModeHighSpeed:
pixel_offset = 0.5;
break;
case PixelOffsetModeHalf:
case PixelOffsetModeHighQuality:
pixel_offset = 0.0;
break;
}
return sample_bitmap_pixel(src_rect, bits, width, height,
floorf(point->X + pixel_offset), point->Y + pixel_offset, attributes);
}
}
}
static REAL intersect_line_scanline(const GpPointF *p1, const GpPointF *p2, REAL y)
{
return (p1->X - p2->X) * (p2->Y - y) / (p2->Y - p1->Y) + p2->X;
......@@ -3234,8 +3314,10 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
lockeddata.Scan0 = src_data;
if (!do_resampling && bitmap->format == PixelFormat32bppPARGB)
lockeddata.PixelFormat = apply_image_attributes(imageAttributes, NULL, 0, 0, 0, ColorAdjustTypeBitmap, bitmap->format);
else
else if (imageAttributes != &defaultImageAttributes)
lockeddata.PixelFormat = PixelFormat32bppARGB;
else
lockeddata.PixelFormat = PixelFormat32bppPARGB;
stat = GdipBitmapLockBits(bitmap, &src_area, ImageLockModeRead|ImageLockModeUserInputBuf,
lockeddata.PixelFormat, &lockeddata);
......@@ -3293,8 +3375,14 @@ GpStatus WINGDIPAPI GdipDrawImagePointsRect(GpGraphics *graphics, GpImage *image
dst_color = (ARGB*)(dst_data + dst_stride * (y - dst_area.top) + sizeof(ARGB) * (x - dst_area.left));
if (src_pointf.X >= srcx && src_pointf.X < srcx + srcwidth && src_pointf.Y >= srcy && src_pointf.Y < srcy+srcheight)
*dst_color = resample_bitmap_pixel(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf,
imageAttributes, interpolation, offset_mode);
{
if (lockeddata.PixelFormat != PixelFormat32bppPARGB)
*dst_color = resample_bitmap_pixel(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf,
imageAttributes, interpolation, offset_mode);
else
*dst_color = resample_bitmap_pixel_premult(&src_area, src_data, bitmap->width, bitmap->height, &src_pointf,
imageAttributes, interpolation, offset_mode);
}
else
*dst_color = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment