diff options
author | 2015-11-08 12:56:12 +0100 | |
---|---|---|
committer | 2015-11-08 12:56:12 +0100 | |
commit | 7c19aac60e12d6f5ea301bdb34d7826a01e0b06f (patch) | |
tree | f310d86aa2c6bfc19d115307dedde4eb0cd52dad /src/emu/rendutil.c | |
parent | a57b46ae933badd7441ce1644711dbb851e2b504 (diff) |
Rename *.c -> *.cpp in our source (nw)
Diffstat (limited to 'src/emu/rendutil.c')
-rw-r--r-- | src/emu/rendutil.c | 731 |
1 files changed, 0 insertions, 731 deletions
diff --git a/src/emu/rendutil.c b/src/emu/rendutil.c deleted file mode 100644 index 872533583b5..00000000000 --- a/src/emu/rendutil.c +++ /dev/null @@ -1,731 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles -/*************************************************************************** - - rendutil.c - - Core rendering utilities. -***************************************************************************/ - -#include "emu.h" -#include "render.h" -#include "rendutil.h" -#include "png.h" - - - -/*************************************************************************** - FUNCTION PROTOTYPES -***************************************************************************/ - -/* utilities */ -static void resample_argb_bitmap_average(UINT32 *dest, UINT32 drowpixels, UINT32 dwidth, UINT32 dheight, const UINT32 *source, UINT32 srowpixels, UINT32 swidth, UINT32 sheight, const render_color &color, UINT32 dx, UINT32 dy); -static void resample_argb_bitmap_bilinear(UINT32 *dest, UINT32 drowpixels, UINT32 dwidth, UINT32 dheight, const UINT32 *source, UINT32 srowpixels, UINT32 swidth, UINT32 sheight, const render_color &color, UINT32 dx, UINT32 dy); -static bool copy_png_to_bitmap(bitmap_argb32 &bitmap, const png_info *png); -static bool copy_png_alpha_to_bitmap(bitmap_argb32 &bitmap, const png_info *png); - - - -/*************************************************************************** - RENDER UTILITIES -***************************************************************************/ - -/*------------------------------------------------- - render_resample_argb_bitmap_hq - perform a high - quality resampling of a texture --------------------------------------------------*/ - -void render_resample_argb_bitmap_hq(bitmap_argb32 &dest, bitmap_argb32 &source, const render_color &color) -{ - if (dest.width() == 0 || dest.height() == 0) - return; - - /* adjust the source base */ - const UINT32 *sbase = &source.pix32(0); - - /* determine the steppings */ - UINT32 swidth = source.width(); - UINT32 sheight = source.height(); - UINT32 dwidth = dest.width(); - UINT32 dheight = dest.height(); - UINT32 dx = (swidth << 12) / dwidth; - UINT32 dy = (sheight << 12) / dheight; - - /* if the source is higher res than the target, use full averaging */ - if (dx > 0x1000 || dy > 0x1000) - resample_argb_bitmap_average(&dest.pix(0), dest.rowpixels(), dwidth, dheight, sbase, source.rowpixels(), swidth, sheight, color, dx, dy); - else - resample_argb_bitmap_bilinear(&dest.pix(0), dest.rowpixels(), dwidth, dheight, sbase, source.rowpixels(), swidth, sheight, color, dx, dy); -} - - -/*------------------------------------------------- - resample_argb_bitmap_average - resample a texture - by performing a true weighted average over - all contributing pixels --------------------------------------------------*/ - -static void resample_argb_bitmap_average(UINT32 *dest, UINT32 drowpixels, UINT32 dwidth, UINT32 dheight, const UINT32 *source, UINT32 srowpixels, UINT32 swidth, UINT32 sheight, const render_color &color, UINT32 dx, UINT32 dy) -{ - UINT64 sumscale = (UINT64)dx * (UINT64)dy; - UINT32 r, g, b, a; - UINT32 x, y; - - /* precompute premultiplied R/G/B/A factors */ - r = color.r * color.a * 256.0f; - g = color.g * color.a * 256.0f; - b = color.b * color.a * 256.0f; - a = color.a * 256.0f; - - /* loop over the target vertically */ - for (y = 0; y < dheight; y++) - { - UINT32 starty = y * dy; - - /* loop over the target horizontally */ - for (x = 0; x < dwidth; x++) - { - UINT64 sumr = 0, sumg = 0, sumb = 0, suma = 0; - UINT32 startx = x * dx; - UINT32 xchunk, ychunk; - UINT32 curx, cury; - - UINT32 yremaining = dy; - - /* accumulate all source pixels that contribute to this pixel */ - for (cury = starty; yremaining; cury += ychunk) - { - UINT32 xremaining = dx; - - /* determine the Y contribution, clamping to the amount remaining */ - ychunk = 0x1000 - (cury & 0xfff); - if (ychunk > yremaining) - ychunk = yremaining; - yremaining -= ychunk; - - /* loop over all source pixels in the X direction */ - for (curx = startx; xremaining; curx += xchunk) - { - UINT32 factor; - - /* determine the X contribution, clamping to the amount remaining */ - xchunk = 0x1000 - (curx & 0xfff); - if (xchunk > xremaining) - xchunk = xremaining; - xremaining -= xchunk; - - /* total contribution = x * y */ - factor = xchunk * ychunk; - - /* fetch the source pixel */ - rgb_t pix = source[(cury >> 12) * srowpixels + (curx >> 12)]; - - /* accumulate the RGBA values */ - sumr += factor * pix.r(); - sumg += factor * pix.g(); - sumb += factor * pix.b(); - suma += factor * pix.a(); - } - } - - /* apply scaling */ - suma = (suma / sumscale) * a / 256; - sumr = (sumr / sumscale) * r / 256; - sumg = (sumg / sumscale) * g / 256; - sumb = (sumb / sumscale) * b / 256; - - /* if we're translucent, add in the destination pixel contribution */ - if (a < 256) - { - rgb_t dpix = dest[y * drowpixels + x]; - suma += dpix.a() * (256 - a); - sumr += dpix.r() * (256 - a); - sumg += dpix.g() * (256 - a); - sumb += dpix.b() * (256 - a); - } - - /* store the target pixel, dividing the RGBA values by the overall scale factor */ - dest[y * drowpixels + x] = rgb_t(suma, sumr, sumg, sumb); - } - } -} - - -/*------------------------------------------------- - resample_argb_bitmap_bilinear - perform texture - sampling via a bilinear filter --------------------------------------------------*/ - -static void resample_argb_bitmap_bilinear(UINT32 *dest, UINT32 drowpixels, UINT32 dwidth, UINT32 dheight, const UINT32 *source, UINT32 srowpixels, UINT32 swidth, UINT32 sheight, const render_color &color, UINT32 dx, UINT32 dy) -{ - UINT32 maxx = swidth << 12, maxy = sheight << 12; - UINT32 r, g, b, a; - UINT32 x, y; - - /* precompute premultiplied R/G/B/A factors */ - r = color.r * color.a * 256.0f; - g = color.g * color.a * 256.0f; - b = color.b * color.a * 256.0f; - a = color.a * 256.0f; - - /* loop over the target vertically */ - for (y = 0; y < dheight; y++) - { - UINT32 starty = y * dy; - - /* loop over the target horizontally */ - for (x = 0; x < dwidth; x++) - { - UINT32 startx = x * dx; - rgb_t pix0, pix1, pix2, pix3; - UINT32 sumr, sumg, sumb, suma; - UINT32 nextx, nexty; - UINT32 curx, cury; - UINT32 factor; - - /* adjust start to the center; note that this math will tend to produce */ - /* negative results on the first pixel, which is why we clamp below */ - curx = startx + dx / 2 - 0x800; - cury = starty + dy / 2 - 0x800; - - /* compute the neighboring pixel */ - nextx = curx + 0x1000; - nexty = cury + 0x1000; - - /* fetch the four relevant pixels */ - pix0 = pix1 = pix2 = pix3 = 0; - if ((INT32)cury >= 0 && cury < maxy && (INT32)curx >= 0 && curx < maxx) - pix0 = source[(cury >> 12) * srowpixels + (curx >> 12)]; - if ((INT32)cury >= 0 && cury < maxy && (INT32)nextx >= 0 && nextx < maxx) - pix1 = source[(cury >> 12) * srowpixels + (nextx >> 12)]; - if ((INT32)nexty >= 0 && nexty < maxy && (INT32)curx >= 0 && curx < maxx) - pix2 = source[(nexty >> 12) * srowpixels + (curx >> 12)]; - if ((INT32)nexty >= 0 && nexty < maxy && (INT32)nextx >= 0 && nextx < maxx) - pix3 = source[(nexty >> 12) * srowpixels + (nextx >> 12)]; - - /* compute the x/y scaling factors */ - curx &= 0xfff; - cury &= 0xfff; - - /* contributions from pixel 0 (top,left) */ - factor = (0x1000 - curx) * (0x1000 - cury); - sumr = factor * pix0.r(); - sumg = factor * pix0.g(); - sumb = factor * pix0.b(); - suma = factor * pix0.a(); - - /* contributions from pixel 1 (top,right) */ - factor = curx * (0x1000 - cury); - sumr += factor * pix1.r(); - sumg += factor * pix1.g(); - sumb += factor * pix1.b(); - suma += factor * pix1.a(); - - /* contributions from pixel 2 (bottom,left) */ - factor = (0x1000 - curx) * cury; - sumr += factor * pix2.r(); - sumg += factor * pix2.g(); - sumb += factor * pix2.b(); - suma += factor * pix2.a(); - - /* contributions from pixel 3 (bottom,right) */ - factor = curx * cury; - sumr += factor * pix3.r(); - sumg += factor * pix3.g(); - sumb += factor * pix3.b(); - suma += factor * pix3.a(); - - /* apply scaling */ - suma = (suma >> 24) * a / 256; - sumr = (sumr >> 24) * r / 256; - sumg = (sumg >> 24) * g / 256; - sumb = (sumb >> 24) * b / 256; - - /* if we're translucent, add in the destination pixel contribution */ - if (a < 256) - { - rgb_t dpix = dest[y * drowpixels + x]; - suma += dpix.a() * (256 - a); - sumr += dpix.r() * (256 - a); - sumg += dpix.g() * (256 - a); - sumb += dpix.b() * (256 - a); - } - - /* store the target pixel, dividing the RGBA values by the overall scale factor */ - dest[y * drowpixels + x] = rgb_t(suma, sumr, sumg, sumb); - } - } -} - - -/*------------------------------------------------- - render_clip_line - clip a line to a rectangle --------------------------------------------------*/ - -int render_clip_line(render_bounds *bounds, const render_bounds *clip) -{ - /* loop until we get a final result */ - while (1) - { - UINT8 code0 = 0, code1 = 0; - UINT8 thiscode; - float x, y; - - /* compute Cohen Sutherland bits for first coordinate */ - if (bounds->y0 > clip->y1) - code0 |= 1; - if (bounds->y0 < clip->y0) - code0 |= 2; - if (bounds->x0 > clip->x1) - code0 |= 4; - if (bounds->x0 < clip->x0) - code0 |= 8; - - /* compute Cohen Sutherland bits for second coordinate */ - if (bounds->y1 > clip->y1) - code1 |= 1; - if (bounds->y1 < clip->y0) - code1 |= 2; - if (bounds->x1 > clip->x1) - code1 |= 4; - if (bounds->x1 < clip->x0) - code1 |= 8; - - /* trivial accept: just return FALSE */ - if ((code0 | code1) == 0) - return FALSE; - - /* trivial reject: just return TRUE */ - if ((code0 & code1) != 0) - return TRUE; - - /* fix one of the OOB cases */ - thiscode = code0 ? code0 : code1; - - /* off the bottom */ - if (thiscode & 1) - { - x = bounds->x0 + (bounds->x1 - bounds->x0) * (clip->y1 - bounds->y0) / (bounds->y1 - bounds->y0); - y = clip->y1; - } - - /* off the top */ - else if (thiscode & 2) - { - x = bounds->x0 + (bounds->x1 - bounds->x0) * (clip->y0 - bounds->y0) / (bounds->y1 - bounds->y0); - y = clip->y0; - } - - /* off the right */ - else if (thiscode & 4) - { - y = bounds->y0 + (bounds->y1 - bounds->y0) * (clip->x1 - bounds->x0) / (bounds->x1 - bounds->x0); - x = clip->x1; - } - - /* off the left */ - else - { - y = bounds->y0 + (bounds->y1 - bounds->y0) * (clip->x0 - bounds->x0) / (bounds->x1 - bounds->x0); - x = clip->x0; - } - - /* fix the appropriate coordinate */ - if (thiscode == code0) - { - bounds->x0 = x; - bounds->y0 = y; - } - else - { - bounds->x1 = x; - bounds->y1 = y; - } - } -} - - -/*------------------------------------------------- - render_clip_quad - clip a quad to a rectangle --------------------------------------------------*/ - -int render_clip_quad(render_bounds *bounds, const render_bounds *clip, render_quad_texuv *texcoords) -{ - /* ensure our assumptions about the bounds are correct */ - assert(bounds->x0 <= bounds->x1); - assert(bounds->y0 <= bounds->y1); - - /* trivial reject */ - if (bounds->y1 < clip->y0) - return TRUE; - if (bounds->y0 > clip->y1) - return TRUE; - if (bounds->x1 < clip->x0) - return TRUE; - if (bounds->x0 > clip->x1) - return TRUE; - - /* clip top (x0,y0)-(x1,y1) */ - if (bounds->y0 < clip->y0) - { - float frac = (clip->y0 - bounds->y0) / (bounds->y1 - bounds->y0); - bounds->y0 = clip->y0; - if (texcoords != NULL) - { - texcoords->tl.u += (texcoords->bl.u - texcoords->tl.u) * frac; - texcoords->tl.v += (texcoords->bl.v - texcoords->tl.v) * frac; - texcoords->tr.u += (texcoords->br.u - texcoords->tr.u) * frac; - texcoords->tr.v += (texcoords->br.v - texcoords->tr.v) * frac; - } - } - - /* clip bottom (x3,y3)-(x2,y2) */ - if (bounds->y1 > clip->y1) - { - float frac = (bounds->y1 - clip->y1) / (bounds->y1 - bounds->y0); - bounds->y1 = clip->y1; - if (texcoords != NULL) - { - texcoords->bl.u -= (texcoords->bl.u - texcoords->tl.u) * frac; - texcoords->bl.v -= (texcoords->bl.v - texcoords->tl.v) * frac; - texcoords->br.u -= (texcoords->br.u - texcoords->tr.u) * frac; - texcoords->br.v -= (texcoords->br.v - texcoords->tr.v) * frac; - } - } - - /* clip left (x0,y0)-(x3,y3) */ - if (bounds->x0 < clip->x0) - { - float frac = (clip->x0 - bounds->x0) / (bounds->x1 - bounds->x0); - bounds->x0 = clip->x0; - if (texcoords != NULL) - { - texcoords->tl.u += (texcoords->tr.u - texcoords->tl.u) * frac; - texcoords->tl.v += (texcoords->tr.v - texcoords->tl.v) * frac; - texcoords->bl.u += (texcoords->br.u - texcoords->bl.u) * frac; - texcoords->bl.v += (texcoords->br.v - texcoords->bl.v) * frac; - } - } - - /* clip right (x1,y1)-(x2,y2) */ - if (bounds->x1 > clip->x1) - { - float frac = (bounds->x1 - clip->x1) / (bounds->x1 - bounds->x0); - bounds->x1 = clip->x1; - if (texcoords != NULL) - { - texcoords->tr.u -= (texcoords->tr.u - texcoords->tl.u) * frac; - texcoords->tr.v -= (texcoords->tr.v - texcoords->tl.v) * frac; - texcoords->br.u -= (texcoords->br.u - texcoords->bl.u) * frac; - texcoords->br.v -= (texcoords->br.v - texcoords->bl.v) * frac; - } - } - return FALSE; -} - - -/*------------------------------------------------- - render_line_to_quad - convert a line and a - width to four points --------------------------------------------------*/ - -void render_line_to_quad(const render_bounds *bounds, float width, render_bounds *bounds0, render_bounds *bounds1) -{ - render_bounds modbounds = *bounds; - float unitx, unity; - - /* - High-level logic -- due to math optimizations, this info is lost below. - - Imagine a thick line of width (w), drawn from (p0) to (p1), with a unit - vector (u) indicating the direction from (p0) to (p1). - - B C - +---------------- ... ------------------+ - | ^ | - | | | - | | | - * (p0) ------------> (w)| * (p1) - | (u) | | - | | | - | v | - +---------------- ... ------------------+ - A D - - To convert this into a quad, we need to compute the four points A, B, C - and D. - - Starting with point A. We first multiply the unit vector by 0.5w and then - rotate the result 90 degrees. Thus, we have: - - A.x = p0.x + 0.5 * w * u.x * cos(90) - 0.5 * w * u.y * sin(90) - A.y = p0.y + 0.5 * w * u.x * sin(90) + 0.5 * w * u.y * cos(90) - - Conveniently, sin(90) = 1, and cos(90) = 0, so this simplifies to: - - A.x = p0.x - 0.5 * w * u.y - A.y = p0.y + 0.5 * w * u.x - - Working clockwise around the polygon, the same fallout happens all around as - we rotate the unit vector by -90 (B), -90 (C), and 90 (D) degrees: - - B.x = p0.x + 0.5 * w * u.y - B.y = p0.y - 0.5 * w * u.x - - C.x = p1.x - 0.5 * w * u.y - C.y = p1.y + 0.5 * w * u.x - - D.x = p1.x + 0.5 * w * u.y - D.y = p1.y - 0.5 * w * u.x - */ - - /* we only care about the half-width */ - width *= 0.5f; - - /* compute a vector from point 0 to point 1 */ - unitx = modbounds.x1 - modbounds.x0; - unity = modbounds.y1 - modbounds.y0; - - /* points just use a +1/+1 unit vector; this gives a nice diamond pattern */ - if (unitx == 0 && unity == 0) - { - unitx = unity = 0.70710678f * width; - modbounds.x0 -= 0.5f * unitx; - modbounds.y0 -= 0.5f * unity; - modbounds.x1 += 0.5f * unitx; - modbounds.y1 += 0.5f * unity; - } - - /* lines need to be divided by their length */ - else - { - /* prescale unitx and unity by the half-width */ - float invlength = width / sqrtf(unitx * unitx + unity * unity); - unitx *= invlength; - unity *= invlength; - } - - /* rotate the unit vector by 90 degrees and add to point 0 */ - bounds0->x0 = modbounds.x0 - unity; - bounds0->y0 = modbounds.y0 + unitx; - - /* rotate the unit vector by -90 degrees and add to point 0 */ - bounds0->x1 = modbounds.x0 + unity; - bounds0->y1 = modbounds.y0 - unitx; - - /* rotate the unit vector by 90 degrees and add to point 1 */ - bounds1->x0 = modbounds.x1 - unity; - bounds1->y0 = modbounds.y1 + unitx; - - /* rotate the unit vector by -09 degrees and add to point 1 */ - bounds1->x1 = modbounds.x1 + unity; - bounds1->y1 = modbounds.y1 - unitx; -} - - -/*------------------------------------------------- - render_load_png - load a PNG file into a - bitmap --------------------------------------------------*/ - -bool render_load_png(bitmap_argb32 &bitmap, emu_file &file, const char *dirname, const char *filename, bool load_as_alpha_to_existing) -{ - // deallocate if we're not overlaying alpha - if (!load_as_alpha_to_existing) - bitmap.reset(); - - // open the file - std::string fname; - if (dirname == NULL) - fname.assign(filename); - else - fname.assign(dirname).append(PATH_SEPARATOR).append(filename); - file_error filerr = file.open(fname.c_str()); - if (filerr != FILERR_NONE) - return false; - - // read the PNG data - png_info png; - png_error result = png_read_file(file, &png); - file.close(); - if (result != PNGERR_NONE) - return false; - - // verify we can handle this PNG - if (png.bit_depth > 8) - { - osd_printf_error("%s: Unsupported bit depth %d (8 bit max)\n", filename, png.bit_depth); - png_free(&png); - return false; - } - if (png.interlace_method != 0) - { - osd_printf_error("%s: Interlace unsupported\n", filename); - png_free(&png); - return false; - } - if (png.color_type != 0 && png.color_type != 3 && png.color_type != 2 && png.color_type != 6) - { - osd_printf_error("%s: Unsupported color type %d\n", filename, png.color_type); - png_free(&png); - return false; - } - - // if less than 8 bits, upsample - png_expand_buffer_8bit(&png); - - // non-alpha case - bool hasalpha = false; - if (!load_as_alpha_to_existing) - { - bitmap.allocate(png.width, png.height); - hasalpha = copy_png_to_bitmap(bitmap, &png); - } - - // alpha case - else if (png.width == bitmap.width() && png.height == bitmap.height()) - hasalpha = copy_png_alpha_to_bitmap(bitmap, &png); - - // free PNG data - png_free(&png); - return hasalpha; -} - - -/*------------------------------------------------- - copy_png_to_bitmap - copy the PNG data to a - bitmap --------------------------------------------------*/ - -static bool copy_png_to_bitmap(bitmap_argb32 &bitmap, const png_info *png) -{ - UINT8 accumalpha = 0xff; - UINT8 *src; - int x, y; - - /* handle 8bpp palettized case */ - if (png->color_type == 3) - { - /* loop over width/height */ - src = png->image; - for (y = 0; y < png->height; y++) - for (x = 0; x < png->width; x++, src++) - { - /* determine alpha and expand to 32bpp */ - UINT8 alpha = (*src < png->num_trans) ? png->trans[*src] : 0xff; - accumalpha &= alpha; - bitmap.pix32(y, x) = rgb_t(alpha, png->palette[*src * 3], png->palette[*src * 3 + 1], png->palette[*src * 3 + 2]); - } - } - - /* handle 8bpp grayscale case */ - else if (png->color_type == 0) - { - /* loop over width/height */ - src = png->image; - for (y = 0; y < png->height; y++) - for (x = 0; x < png->width; x++, src++) - bitmap.pix32(y, x) = rgb_t(0xff, *src, *src, *src); - } - - /* handle 32bpp non-alpha case */ - else if (png->color_type == 2) - { - /* loop over width/height */ - src = png->image; - for (y = 0; y < png->height; y++) - for (x = 0; x < png->width; x++, src += 3) - bitmap.pix32(y, x) = rgb_t(0xff, src[0], src[1], src[2]); - } - - /* handle 32bpp alpha case */ - else - { - /* loop over width/height */ - src = png->image; - for (y = 0; y < png->height; y++) - for (x = 0; x < png->width; x++, src += 4) - { - accumalpha &= src[3]; - bitmap.pix32(y, x) = rgb_t(src[3], src[0], src[1], src[2]); - } - } - - /* set the hasalpha flag */ - return (accumalpha != 0xff); -} - - -/*------------------------------------------------- - copy_png_alpha_to_bitmap - copy the PNG data - to the alpha channel of a bitmap --------------------------------------------------*/ - -static bool copy_png_alpha_to_bitmap(bitmap_argb32 &bitmap, const png_info *png) -{ - UINT8 accumalpha = 0xff; - UINT8 *src; - int x, y; - - /* handle 8bpp palettized case */ - if (png->color_type == 3) - { - /* loop over width/height */ - src = png->image; - for (y = 0; y < png->height; y++) - for (x = 0; x < png->width; x++, src++) - { - rgb_t pixel = bitmap.pix32(y, x); - UINT8 alpha = rgb_t(png->palette[*src * 3], png->palette[*src * 3 + 1], png->palette[*src * 3 + 2]).brightness(); - accumalpha &= alpha; - bitmap.pix32(y, x) = rgb_t(alpha, pixel.r(), pixel.g(), pixel.b()); - } - } - - /* handle 8bpp grayscale case */ - else if (png->color_type == 0) - { - /* loop over width/height */ - src = png->image; - for (y = 0; y < png->height; y++) - for (x = 0; x < png->width; x++, src++) - { - rgb_t pixel = bitmap.pix32(y, x); - accumalpha &= *src; - bitmap.pix32(y, x) = rgb_t(*src, pixel.r(), pixel.g(), pixel.b()); - } - } - - /* handle 32bpp non-alpha case */ - else if (png->color_type == 2) - { - /* loop over width/height */ - src = png->image; - for (y = 0; y < png->height; y++) - for (x = 0; x < png->width; x++, src += 3) - { - rgb_t pixel = bitmap.pix32(y, x); - UINT8 alpha = rgb_t(src[0], src[1], src[2]).brightness(); - accumalpha &= alpha; - bitmap.pix32(y, x) = rgb_t(alpha, pixel.r(), pixel.g(), pixel.b()); - } - } - - /* handle 32bpp alpha case */ - else - { - /* loop over width/height */ - src = png->image; - for (y = 0; y < png->height; y++) - for (x = 0; x < png->width; x++, src += 4) - { - rgb_t pixel = bitmap.pix32(y, x); - UINT8 alpha = rgb_t(src[0], src[1], src[2]).brightness(); - accumalpha &= alpha; - bitmap.pix32(y, x) = rgb_t(alpha, pixel.r(), pixel.g(), pixel.b()); - } - } - - /* set the hasalpha flag */ - return (accumalpha != 0xff); -} |