summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/rendutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/rendutil.cpp')
-rw-r--r--src/emu/rendutil.cpp132
1 files changed, 25 insertions, 107 deletions
diff --git a/src/emu/rendutil.cpp b/src/emu/rendutil.cpp
index f35332436fb..01691af4374 100644
--- a/src/emu/rendutil.cpp
+++ b/src/emu/rendutil.cpp
@@ -21,7 +21,6 @@
/* utilities */
static void resample_argb_bitmap_average(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 dy);
static void resample_argb_bitmap_bilinear(u32 *dest, u32 drowpixels, u32 dwidth, u32 dheight, const u32 *source, u32 srowpixels, u32 swidth, u32 sheight, const render_color &color, u32 dx, u32 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);
@@ -655,33 +654,29 @@ bool render_load_png(bitmap_argb32 &bitmap, emu_file &file, const char *dirname,
png_free(&png);
return false;
}
- if (png.interlace_method != 0 && png.interlace_method != 1)
- {
- 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)
+
+ // if less than 8 bits, upsample
+ if (PNGERR_NONE != png_expand_buffer_8bit(&png))
{
- 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);
+ // non-alpha case
+ if (PNGERR_NONE != png_copy_to_bitmap(&png, bitmap, hasalpha))
+ {
+ png_free(&png);
+ return false;
+ }
}
-
- // alpha case
else if (png.width == bitmap.width() && png.height == bitmap.height())
+ {
+ // alpha case
hasalpha = copy_png_alpha_to_bitmap(bitmap, &png);
+ }
// free PNG data
png_free(&png);
@@ -690,11 +685,11 @@ bool render_load_png(bitmap_argb32 &bitmap, emu_file &file, const char *dirname,
/*-------------------------------------------------
- copy_png_to_bitmap - copy the PNG data to a
- bitmap
+ copy_png_alpha_to_bitmap - copy the PNG data
+ to the alpha channel of a bitmap
-------------------------------------------------*/
-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)
{
// FIXME: this function is basically copy/pasted from the PNG code in util, and should be unified with it
u8 accumalpha = 0xff;
@@ -728,111 +723,34 @@ static bool copy_png_to_bitmap(bitmap_argb32 &bitmap, const png_info *png)
{
for (u32 x = 0; width > x; ++x, ++src)
{
- // determine alpha and expand to 32bpp
- u8 alpha = (*src < png->num_trans) ? png->trans[*src] : 0xff;
+ bitmap_argb32::pixel_t &dest(png->interlace_method ? bitmap.pix32(y_trans(y), x_trans(x)) : bitmap.pix32(y, x));
+ rgb_t const pixel(dest);
+ u8 const alpha(rgb_t(png->palette[*src * 3], png->palette[*src * 3 + 1], png->palette[*src * 3 + 2]).brightness());
accumalpha &= alpha;
- rgb_t const pix(alpha, png->palette[*src * 3], png->palette[*src * 3 + 1], png->palette[*src * 3 + 2]);
- (png->interlace_method ? bitmap.pix32(y_trans(y), x_trans(x)) : bitmap.pix32(y, x)) = pix;
+ dest = rgb_t(alpha, pixel.r(), pixel.g(), pixel.b());
}
}
}
else if (png->color_type == 0)
{
- // handle 8bpp grayscale case
- for (u32 y = 0; height > y; ++y)
- {
- for (u32 x = 0; width > x; ++x, ++src)
- {
- rgb_t const pix(0xff, *src, *src, *src);
- (png->interlace_method ? bitmap.pix32(y_trans(y), x_trans(x)) : bitmap.pix32(y, x)) = pix;
- }
- }
- }
- else if (png->color_type == 2)
- {
- // handle 32bpp non-alpha case
- for (u32 y = 0; height > y; ++y)
- {
- for (u32 x = 0; width > x; ++x, src += 3)
- {
- rgb_t const pix(0xff, src[0], src[1], src[2]);
- (png->interlace_method ? bitmap.pix32(y_trans(y), x_trans(x)) : bitmap.pix32(y, x)) = pix;
- }
- }
- }
- else
- {
- // handle 32bpp alpha case
- for (u32 y = 0; height > y; ++y)
- {
- for (u32 x = 0; width > x; ++x, src += 4)
- {
- accumalpha &= src[3];
- rgb_t const pix(src[3], src[0], src[1], src[2]);
- (png->interlace_method ? bitmap.pix32(y_trans(y), x_trans(x)) : bitmap.pix32(y, x)) = pix;
- }
- }
- }
- }
-
- // 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)
-{
- // FIXME: this function is basically copy/pasted from the PNG code in util, and should be unified with it
- u8 accumalpha = 0xff;
-
- // colour format table
- static constexpr unsigned samples[] = { 1, 0, 3, 1, 2, 0, 4 };
-
- // adam7 interlace tables
- static constexpr unsigned x_bias[7] = { 7, 3, 3, 1, 1, 0, 0 };
- static constexpr unsigned y_bias[7] = { 7, 7, 3, 3, 1, 1, 0 };
- static constexpr unsigned x_shift[7] = { 3, 3, 2, 2, 1, 1, 0 };
- static constexpr unsigned y_shift[7] = { 3, 3, 3, 2, 2, 1, 1 };
-
- unsigned const pass_count(png->interlace_method ? 7 : 1);
- u32 pass_offset[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- for (unsigned pass = 0; pass_count > pass; ++pass)
- {
- // calculate offset for next interlace pass
- u32 const width(png->interlace_method ? ((png->width + x_bias[pass]) >> x_shift[pass]) : png->width);
- u32 const height(png->interlace_method ? ((png->height + y_bias[pass]) >> y_shift[pass]) : png->height);
- u32 const rowbytes(((width * samples[png->color_type] * png->bit_depth) + 7) >> 3);
- pass_offset[pass + 1] = pass_offset[pass] + (height * (rowbytes + 1));
- u8 const *src(png->image + pass_offset[pass]);
- auto const x_trans = [offs = (1 << x_shift[pass]) - x_bias[pass] - 1, shift = x_shift[pass]] (u32 x) { return (x << shift) + offs; };
- auto const y_trans = [offs = (1 << y_shift[pass]) - y_bias[pass] - 1, shift = y_shift[pass]] (u32 y) { return (y << shift) + offs; };
-
- if (png->color_type == 3)
- {
- // handle 8bpp palettized case
+ // handle 8bpp grayscale non-alpha case
for (u32 y = 0; height > y; ++y)
{
for (u32 x = 0; width > x; ++x, ++src)
{
bitmap_argb32::pixel_t &dest(png->interlace_method ? bitmap.pix32(y_trans(y), x_trans(x)) : bitmap.pix32(y, x));
rgb_t const pixel(dest);
- u8 const alpha(rgb_t(png->palette[*src * 3], png->palette[*src * 3 + 1], png->palette[*src * 3 + 2]).brightness());
- accumalpha &= alpha;
- dest = rgb_t(alpha, pixel.r(), pixel.g(), pixel.b());
+ accumalpha &= *src;
+ dest = rgb_t(*src, pixel.r(), pixel.g(), pixel.b());
}
}
}
- else if (png->color_type == 0)
+ else if (png->color_type == 4)
{
- // handle 8bpp grayscale case
+ // handle 8bpp grayscale alpha case
for (u32 y = 0; height > y; ++y)
{
- for (u32 x = 0; width > x; ++x, ++src)
+ for (u32 x = 0; width > x; ++x, src += 2)
{
bitmap_argb32::pixel_t &dest(png->interlace_method ? bitmap.pix32(y_trans(y), x_trans(x)) : bitmap.pix32(y, x));
rgb_t const pixel(dest);