diff options
Diffstat (limited to 'src/emu/rendutil.cpp')
| -rw-r--r-- | src/emu/rendutil.cpp | 132 |
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); |
