mirror of
https://github.com/holub/mame
synced 2025-07-01 16:19:38 +03:00
png: support 16-bit samples
This commit is contained in:
parent
90593ab006
commit
44bc3ffa43
@ -647,14 +647,6 @@ bool render_load_png(bitmap_argb32 &bitmap, emu_file &file, const char *dirname,
|
|||||||
if (result != PNGERR_NONE)
|
if (result != PNGERR_NONE)
|
||||||
return false;
|
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 less than 8 bits, upsample
|
// if less than 8 bits, upsample
|
||||||
if (PNGERR_NONE != png_expand_buffer_8bit(&png))
|
if (PNGERR_NONE != png_expand_buffer_8bit(&png))
|
||||||
{
|
{
|
||||||
@ -674,6 +666,14 @@ bool render_load_png(bitmap_argb32 &bitmap, emu_file &file, const char *dirname,
|
|||||||
}
|
}
|
||||||
else if (png.width == bitmap.width() && png.height == bitmap.height())
|
else if (png.width == bitmap.width() && png.height == bitmap.height())
|
||||||
{
|
{
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
// alpha case
|
// alpha case
|
||||||
hasalpha = copy_png_alpha_to_bitmap(bitmap, &png);
|
hasalpha = copy_png_alpha_to_bitmap(bitmap, &png);
|
||||||
}
|
}
|
||||||
|
@ -145,16 +145,20 @@ public:
|
|||||||
png_error copy_to_bitmap(bitmap_argb32 &bitmap, bool &hasalpha) const
|
png_error copy_to_bitmap(bitmap_argb32 &bitmap, bool &hasalpha) const
|
||||||
{
|
{
|
||||||
// do some basic checks for unsupported images
|
// do some basic checks for unsupported images
|
||||||
|
if ((8 > pnginfo.bit_depth) || (pnginfo.bit_depth % 8))
|
||||||
|
return PNGERR_UNSUPPORTED_FORMAT; // only do multiples of 8bps here - expand lower bit depth first
|
||||||
if ((ARRAY_LENGTH(samples) <= pnginfo.color_type) || !samples[pnginfo.color_type])
|
if ((ARRAY_LENGTH(samples) <= pnginfo.color_type) || !samples[pnginfo.color_type])
|
||||||
return PNGERR_UNSUPPORTED_FORMAT; // unknown colour sample format
|
return PNGERR_UNSUPPORTED_FORMAT; // unknown colour sample format
|
||||||
if ((0 != pnginfo.interlace_method) && (1 != pnginfo.interlace_method))
|
if ((0 != pnginfo.interlace_method) && (1 != pnginfo.interlace_method))
|
||||||
return PNGERR_UNSUPPORTED_FORMAT; // unknown interlace method
|
return PNGERR_UNSUPPORTED_FORMAT; // unknown interlace method
|
||||||
if (8 != pnginfo.bit_depth)
|
if ((3 == pnginfo.color_type) && (8 != pnginfo.bit_depth))
|
||||||
return PNGERR_UNSUPPORTED_FORMAT; // only do 8bpp here - expand lower bit depth first
|
return PNGERR_UNSUPPORTED_FORMAT; // indexed colour must be exactly 8bpp
|
||||||
|
|
||||||
// everything looks sane, allocate the bitmap and deinterlace into it
|
// everything looks sane, allocate the bitmap and deinterlace into it
|
||||||
bitmap.allocate(pnginfo.width, pnginfo.height);
|
bitmap.allocate(pnginfo.width, pnginfo.height);
|
||||||
std::uint8_t accumalpha(0xff);
|
std::uint8_t accumalpha(0xff);
|
||||||
|
uint32_t const bps(pnginfo.bit_depth >> 3);
|
||||||
|
uint32_t const bpp(bps * samples[pnginfo.color_type]);
|
||||||
unsigned const pass_count(get_pass_count());
|
unsigned const pass_count(get_pass_count());
|
||||||
std::uint32_t pass_offset[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
std::uint32_t pass_offset[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
for (unsigned pass = 0; pass_count > pass; ++pass)
|
for (unsigned pass = 0; pass_count > pass; ++pass)
|
||||||
@ -173,7 +177,7 @@ public:
|
|||||||
// handle 8bpp palettized case
|
// handle 8bpp palettized case
|
||||||
for (std::uint32_t y = 0; dimensions.second > y; ++y)
|
for (std::uint32_t y = 0; dimensions.second > y; ++y)
|
||||||
{
|
{
|
||||||
for (std::uint32_t x = 0; dimensions.first > x; ++x, ++src)
|
for (std::uint32_t x = 0; dimensions.first > x; ++x, src += bpp)
|
||||||
{
|
{
|
||||||
// determine alpha and expand to 32bpp
|
// determine alpha and expand to 32bpp
|
||||||
std::uint8_t const alpha((*src < pnginfo.num_trans) ? pnginfo.trans[*src] : 0xff);
|
std::uint8_t const alpha((*src < pnginfo.num_trans) ? pnginfo.trans[*src] : 0xff);
|
||||||
@ -186,10 +190,11 @@ public:
|
|||||||
}
|
}
|
||||||
else if (0 == pnginfo.color_type)
|
else if (0 == pnginfo.color_type)
|
||||||
{
|
{
|
||||||
// handle 8bpp grayscale non-alpha case
|
// handle grayscale non-alpha case
|
||||||
|
uint32_t const bpp(pnginfo.bit_depth >> 3);
|
||||||
for (std::uint32_t y = 0; dimensions.second > y; ++y)
|
for (std::uint32_t y = 0; dimensions.second > y; ++y)
|
||||||
{
|
{
|
||||||
for (std::uint32_t x = 0; dimensions.first > x; ++x, ++src)
|
for (std::uint32_t x = 0; dimensions.first > x; ++x, src += bpp)
|
||||||
{
|
{
|
||||||
rgb_t const pix(0xff, src[0], src[0], src[0]);
|
rgb_t const pix(0xff, src[0], src[0], src[0]);
|
||||||
bitmap.pix32((y << y_shift) + y_offs, (x << x_shift) + x_offs) = pix;
|
bitmap.pix32((y << y_shift) + y_offs, (x << x_shift) + x_offs) = pix;
|
||||||
@ -198,38 +203,47 @@ public:
|
|||||||
}
|
}
|
||||||
else if (4 == pnginfo.color_type)
|
else if (4 == pnginfo.color_type)
|
||||||
{
|
{
|
||||||
// handle 8bpp grayscale alpha case
|
// handle grayscale alpha case
|
||||||
|
uint32_t const i(0 * bps);
|
||||||
|
uint32_t const a(1 * bps);
|
||||||
for (std::uint32_t y = 0; dimensions.second > y; ++y)
|
for (std::uint32_t y = 0; dimensions.second > y; ++y)
|
||||||
{
|
{
|
||||||
for (std::uint32_t x = 0; dimensions.first > x; ++x, src += 2)
|
for (std::uint32_t x = 0; dimensions.first > x; ++x, src += bpp)
|
||||||
{
|
{
|
||||||
accumalpha &= src[1];
|
accumalpha &= src[a];
|
||||||
rgb_t const pix(src[1], src[0], src[0], src[0]);
|
rgb_t const pix(src[a], src[i], src[i], src[i]);
|
||||||
bitmap.pix32((y << y_shift) + y_offs, (x << x_shift) + x_offs) = pix;
|
bitmap.pix32((y << y_shift) + y_offs, (x << x_shift) + x_offs) = pix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (2 == pnginfo.color_type)
|
else if (2 == pnginfo.color_type)
|
||||||
{
|
{
|
||||||
// handle 32bpp non-alpha case
|
// handle RGB non-alpha case
|
||||||
|
uint32_t const r(0 * bps);
|
||||||
|
uint32_t const g(1 * bps);
|
||||||
|
uint32_t const b(2 * bps);
|
||||||
for (std::uint32_t y = 0; dimensions.second > y; ++y)
|
for (std::uint32_t y = 0; dimensions.second > y; ++y)
|
||||||
{
|
{
|
||||||
for (std::uint32_t x = 0; dimensions.first > x; ++x, src += 3)
|
for (std::uint32_t x = 0; dimensions.first > x; ++x, src += bpp)
|
||||||
{
|
{
|
||||||
rgb_t const pix(0xff, src[0], src[1], src[2]);
|
rgb_t const pix(0xff, src[r], src[g], src[b]);
|
||||||
bitmap.pix32((y << y_shift) + y_offs, (x << x_shift) + x_offs) = pix;
|
bitmap.pix32((y << y_shift) + y_offs, (x << x_shift) + x_offs) = pix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// handle 32bpp alpha case
|
// handle RGB alpha case
|
||||||
|
uint32_t const r(0 * bps);
|
||||||
|
uint32_t const g(1 * bps);
|
||||||
|
uint32_t const b(2 * bps);
|
||||||
|
uint32_t const a(3 * bps);
|
||||||
for (std::uint32_t y = 0; dimensions.second > y; ++y)
|
for (std::uint32_t y = 0; dimensions.second > y; ++y)
|
||||||
{
|
{
|
||||||
for (std::uint32_t x = 0; dimensions.first > x; ++x, src += 4)
|
for (std::uint32_t x = 0; dimensions.first > x; ++x, src += bpp)
|
||||||
{
|
{
|
||||||
accumalpha &= src[3];
|
accumalpha &= src[a];
|
||||||
rgb_t const pix(src[3], src[0], src[1], src[2]);
|
rgb_t const pix(src[a], src[r], src[g], src[b]);
|
||||||
bitmap.pix32((y << y_shift) + y_offs, (x << x_shift) + x_offs) = pix;
|
bitmap.pix32((y << y_shift) + y_offs, (x << x_shift) + x_offs) = pix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -248,12 +262,12 @@ public:
|
|||||||
return PNGERR_NONE;
|
return PNGERR_NONE;
|
||||||
|
|
||||||
// do some basic checks for unsupported images
|
// do some basic checks for unsupported images
|
||||||
if ((0 != pnginfo.color_type) && (3 != pnginfo.color_type))
|
|
||||||
return PNGERR_UNSUPPORTED_FORMAT; // unknown colour sample format
|
|
||||||
if ((0 != pnginfo.interlace_method) && (1 != pnginfo.interlace_method))
|
|
||||||
return PNGERR_UNSUPPORTED_FORMAT; // unknown interlace method
|
|
||||||
if (!pnginfo.bit_depth || (8 % pnginfo.bit_depth))
|
if (!pnginfo.bit_depth || (8 % pnginfo.bit_depth))
|
||||||
return PNGERR_UNSUPPORTED_FORMAT; // bit depth must be a factor of eight
|
return PNGERR_UNSUPPORTED_FORMAT; // bit depth must be a factor of eight
|
||||||
|
if ((0 != pnginfo.color_type) && (3 != pnginfo.color_type))
|
||||||
|
return PNGERR_UNSUPPORTED_FORMAT; // only upsample monochrome and indexed colour
|
||||||
|
if ((0 != pnginfo.interlace_method) && (1 != pnginfo.interlace_method))
|
||||||
|
return PNGERR_UNSUPPORTED_FORMAT; // unknown interlace method
|
||||||
|
|
||||||
// calculate the offset for each pass of the interlace on the input and output
|
// calculate the offset for each pass of the interlace on the input and output
|
||||||
unsigned const pass_count(get_pass_count());
|
unsigned const pass_count(get_pass_count());
|
||||||
@ -368,8 +382,8 @@ private:
|
|||||||
png_error process(std::list<image_data_chunk> const &idata)
|
png_error process(std::list<image_data_chunk> const &idata)
|
||||||
{
|
{
|
||||||
// do some basic checks for unsupported images
|
// do some basic checks for unsupported images
|
||||||
if ((ARRAY_LENGTH(samples) <= pnginfo.color_type) || !samples[pnginfo.color_type])
|
if (!pnginfo.bit_depth || (ARRAY_LENGTH(samples) <= pnginfo.color_type) || !samples[pnginfo.color_type])
|
||||||
return PNGERR_UNSUPPORTED_FORMAT; // unknown colour sample format
|
return PNGERR_UNSUPPORTED_FORMAT; // unknown colour format
|
||||||
if ((0 != pnginfo.interlace_method) && (1 != pnginfo.interlace_method))
|
if ((0 != pnginfo.interlace_method) && (1 != pnginfo.interlace_method))
|
||||||
return PNGERR_UNSUPPORTED_FORMAT; // unknown interlace method
|
return PNGERR_UNSUPPORTED_FORMAT; // unknown interlace method
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user