From b90fd355150a0f56e368bb33619459b19ec92bee Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Thu, 8 Oct 2020 02:04:31 +1100 Subject: Various improvements to image file handling: Moved MS DIB parser out of ICO file reader and made it available for artwork and layout images. Added more efficient I/O and better error checking for JPEG file loading (MAME will no longer exit immediately on a bad JPEG file). Made caller responsible for opening files for loading images, to avoid decompressing images used in ZIP/7z artwork multiple times. Added support for JPEG and Windows DIB to picture_image_device. Added support for SVG image files in external artwork. Added support for using I/O port value for animation state and masking animation state values. Made bounds elements more flexible in layouts. Reworked headers to reduce dependencies. Updated layout file format documentation. --- src/lib/util/png.cpp | 253 +++++++++++++++++++++++++-------------------------- 1 file changed, 123 insertions(+), 130 deletions(-) (limited to 'src/lib/util/png.cpp') diff --git a/src/lib/util/png.cpp b/src/lib/util/png.cpp index 69835e54051..50aeb28c5fe 100644 --- a/src/lib/util/png.cpp +++ b/src/lib/util/png.cpp @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles, Vas Crabb /********************************************************************* - png.c + png.cpp PNG reading functions. @@ -16,34 +16,13 @@ #include #include -#include -#include -#include -#include - #include #include +#include +#include - -/*************************************************************************** - GLOBAL VARIABLES -***************************************************************************/ - -static const int samples[] = { 1, 0, 3, 1, 2, 0, 4 }; - - - -/*************************************************************************** - INLINE FUNCTIONS -***************************************************************************/ - -static inline int compute_rowbytes(const png_info &pnginfo) -{ - return (pnginfo.width * samples[pnginfo.color_type] * pnginfo.bit_depth + 7) / 8; -} - - +namespace util { /*************************************************************************** GENERAL FUNCTIONS @@ -66,6 +45,12 @@ void png_info::free_data() namespace { +/*************************************************************************** + GLOBAL VARIABLES +***************************************************************************/ + +constexpr int samples[] = { 1, 0, 3, 1, 2, 0, 4 }; + constexpr std::uint8_t PNG_SIGNATURE[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a }; #define MNG_Signature "\x8A\x4D\x4E\x47\x0D\x0A\x1A\x0A" @@ -101,6 +86,12 @@ constexpr std::uint8_t PNG_PF_Average = 3; constexpr std::uint8_t PNG_PF_Paeth = 4; +/*************************************************************************** + INLINE FUNCTIONS +***************************************************************************/ + +inline int compute_rowbytes(const png_info &pnginfo) { return (pnginfo.width * samples[pnginfo.color_type] * pnginfo.bit_depth + 7) / 8; } + inline uint8_t fetch_8bit(uint8_t const *v) { return *v; } inline uint16_t fetch_16bit(uint8_t const *v) { return big_endianize_int16(*reinterpret_cast(v)); } inline uint32_t fetch_32bit(uint8_t const *v) { return big_endianize_int32(*reinterpret_cast(v)); } @@ -132,11 +123,11 @@ private: { // do some basic checks for unsupported images if (!pnginfo.bit_depth || (ARRAY_LENGTH(samples) <= pnginfo.color_type) || !samples[pnginfo.color_type]) - return PNGERR_UNSUPPORTED_FORMAT; // unknown colour format + return png_error::UNSUPPORTED_FORMAT; // unknown colour format if ((0 != pnginfo.interlace_method) && (1 != pnginfo.interlace_method)) - return PNGERR_UNSUPPORTED_FORMAT; // unknown interlace method + return png_error::UNSUPPORTED_FORMAT; // unknown interlace method if ((3 == pnginfo.color_type) && (!pnginfo.num_palette || !pnginfo.palette)) - return PNGERR_FILE_CORRUPT; // indexed colour with no palette + return png_error::FILE_CORRUPT; // indexed colour with no palette // calculate the offset for each pass of the interlace unsigned const pass_count(get_pass_count()); @@ -146,13 +137,13 @@ private: // allocate memory for the filtered image try { pnginfo.image.reset(new std::uint8_t [pass_offset[pass_count]]); } - catch (std::bad_alloc const &) { return PNGERR_OUT_OF_MEMORY; } + catch (std::bad_alloc const &) { return png_error::OUT_OF_MEMORY; } // decompress image data - png_error error = PNGERR_NONE; + png_error error = png_error::NONE; error = decompress(idata, pass_offset[pass_count]); std::uint32_t const bpp(get_bytes_per_pixel()); - for (unsigned pass = 0; (pass_count > pass) && (PNGERR_NONE == error); ++pass) + for (unsigned pass = 0; (pass_count > pass) && (png_error::NONE == error); ++pass) { // compute some basic parameters std::pair const dimensions(get_pass_dimensions(pass)); @@ -161,7 +152,7 @@ private: // we de-filter in place, stripping the filter bytes off the rows uint8_t *dst(&pnginfo.image[pass_offset[pass]]); uint8_t const *src(dst); - for (std::uint32_t y = 0; (dimensions.second > y) && (PNGERR_NONE == error); ++y) + for (std::uint32_t y = 0; (dimensions.second > y) && (png_error::NONE == error); ++y) { // first byte of each row is the filter type uint8_t const filter(*src++); @@ -172,7 +163,7 @@ private: } // if we errored, free the image data - if (error != PNGERR_NONE) + if (error != png_error::NONE) pnginfo.image.reset(); return error; @@ -182,7 +173,7 @@ private: { // only deflate is permitted if (0 != pnginfo.compression_method) - return PNGERR_DECOMPRESS_ERROR; + return png_error::DECOMPRESS_ERROR; // allocate zlib stream z_stream stream; @@ -195,7 +186,7 @@ private: stream.next_in = Z_NULL; zerr = inflateInit(&stream); if (Z_OK != zerr) - return PNGERR_DECOMPRESS_ERROR; + return png_error::DECOMPRESS_ERROR; // decompress IDAT blocks stream.next_out = pnginfo.image.get(); @@ -217,28 +208,28 @@ private: // it's all good if we got end-of-stream or we have with no data remaining if ((Z_OK == inflateEnd(&stream)) && ((Z_STREAM_END == zerr) || ((Z_OK == zerr) && (idata.end() == it) && !stream.avail_in))) - return PNGERR_NONE; + return png_error::NONE; else - return PNGERR_DECOMPRESS_ERROR; + return png_error::DECOMPRESS_ERROR; } png_error unfilter_row(std::uint8_t type, uint8_t const *src, uint8_t *dst, uint8_t const *dstprev, int bpp, std::uint32_t rowbytes) { if (0 != pnginfo.filter_method) - return PNGERR_UNKNOWN_FILTER; + return png_error::UNKNOWN_FILTER; switch (type) { case PNG_PF_None: // no filter, just copy std::copy_n(src, rowbytes, dst); - return PNGERR_NONE; + return png_error::NONE; case PNG_PF_Sub: // SUB = previous pixel dst = std::copy_n(src, bpp, dst); src += bpp; for (std::uint32_t x = bpp; rowbytes > x; ++x, ++src, ++dst) *dst = *src + dst[-bpp]; - return PNGERR_NONE; + return png_error::NONE; case PNG_PF_Up: // UP = pixel above if (dstprev) @@ -250,7 +241,7 @@ private: { std::copy_n(src, rowbytes, dst); } - return PNGERR_NONE; + return png_error::NONE; case PNG_PF_Average: // AVERAGE = average of pixel above and previous pixel if (dstprev) @@ -267,7 +258,7 @@ private: for (std::uint32_t x = bpp; rowbytes > x; ++x, ++src, ++dst) *dst = *src + (dst[-bpp] >> 1); } - return PNGERR_NONE; + return png_error::NONE; case PNG_PF_Paeth: // PAETH = special filter for (std::uint32_t x = 0; rowbytes > x; ++x, ++src, ++dst) @@ -281,10 +272,10 @@ private: int32_t const dc(std::abs(prediction - pc)); *dst = ((da <= db) && (da <= dc)) ? (*src + pa) : (db <= dc) ? (*src + pb) : (*src + pc); } - return PNGERR_NONE; + return png_error::NONE; default: // unknown filter type - return PNGERR_UNKNOWN_FILTER; + return png_error::UNKNOWN_FILTER; } } @@ -294,7 +285,7 @@ private: { case PNG_CN_IHDR: // image header if (13 > length) - return PNGERR_FILE_CORRUPT; + return png_error::FILE_CORRUPT; pnginfo.width = fetch_32bit(&data[0]); pnginfo.height = fetch_32bit(&data[4]); pnginfo.bit_depth = fetch_8bit(&data[8]); @@ -307,31 +298,31 @@ private: case PNG_CN_PLTE: // palette pnginfo.num_palette = length / 3; if ((length % 3) || ((3 == pnginfo.color_type) && ((1 << pnginfo.bit_depth) < pnginfo.num_palette))) - return PNGERR_FILE_CORRUPT; + return png_error::FILE_CORRUPT; pnginfo.palette = std::move(data); break; case PNG_CN_tRNS: // transparency information if (((0 == pnginfo.color_type) && (2 > length)) || ((2 == pnginfo.color_type) && (6 > length))) - return PNGERR_FILE_CORRUPT; + return png_error::FILE_CORRUPT; pnginfo.num_trans = length; pnginfo.trans = std::move(data); break; case PNG_CN_IDAT: // image data try { idata.emplace_back(length, std::move(data)); } - catch (std::bad_alloc const &) { return PNGERR_OUT_OF_MEMORY; } + catch (std::bad_alloc const &) { return png_error::OUT_OF_MEMORY; } break; case PNG_CN_gAMA: // gamma if (4 > length) - return PNGERR_FILE_CORRUPT; + return png_error::FILE_CORRUPT; pnginfo.source_gamma = fetch_32bit(data.get()) / 100000.0; break; case PNG_CN_pHYs: // physical information if (9 > length) - return PNGERR_FILE_CORRUPT; + return png_error::FILE_CORRUPT; pnginfo.xres = fetch_32bit(&data[0]); pnginfo.yres = fetch_32bit(&data[4]); pnginfo.resolution_unit = fetch_8bit(&data[8]); @@ -361,17 +352,17 @@ private: } catch (std::bad_alloc const &) { - return PNGERR_OUT_OF_MEMORY; + return png_error::OUT_OF_MEMORY; } break; /* anything else */ default: if ((type & 0x20000000) == 0) - return PNGERR_UNKNOWN_CHUNK; + return png_error::UNKNOWN_CHUNK; break; } - return PNGERR_NONE; + return png_error::NONE; } unsigned get_pass_count() const @@ -413,23 +404,23 @@ private: return ((samples[pnginfo.color_type] * pnginfo.bit_depth) + 7) >> 3; } - static png_error read_chunk(util::core_file &fp, std::unique_ptr &data, std::uint32_t &type, std::uint32_t &length) + static png_error read_chunk(core_file &fp, std::unique_ptr &data, std::uint32_t &type, std::uint32_t &length) { std::uint8_t tempbuff[4]; /* fetch the length of this chunk */ if (fp.read(tempbuff, 4) != 4) - return PNGERR_FILE_TRUNCATED; + return png_error::FILE_TRUNCATED; length = fetch_32bit(tempbuff); /* fetch the type of this chunk */ if (fp.read(tempbuff, 4) != 4) - return PNGERR_FILE_TRUNCATED; + return png_error::FILE_TRUNCATED; type = fetch_32bit(tempbuff); /* stop when we hit an IEND chunk */ if (type == PNG_CN_IEND) - return PNGERR_NONE; + return png_error::NONE; /* start the CRC with the chunk type (but not the length) */ std::uint32_t crc = crc32(0, tempbuff, 4); @@ -439,13 +430,13 @@ private: { /* allocate memory for this chunk */ try { data.reset(new std::uint8_t [length]); } - catch (std::bad_alloc const &) { return PNGERR_OUT_OF_MEMORY; } + catch (std::bad_alloc const &) { return png_error::OUT_OF_MEMORY; } /* read the data from the file */ if (fp.read(data.get(), length) != length) { data.reset(); - return PNGERR_FILE_TRUNCATED; + return png_error::FILE_TRUNCATED; } /* update the CRC */ @@ -456,7 +447,7 @@ private: if (fp.read(tempbuff, 4) != 4) { data.reset(); - return PNGERR_FILE_TRUNCATED; + return png_error::FILE_TRUNCATED; } std::uint32_t const chunk_crc = fetch_32bit(tempbuff); @@ -464,10 +455,10 @@ private: if (crc != chunk_crc) { data.reset(); - return PNGERR_FILE_CORRUPT; + return png_error::FILE_CORRUPT; } - return PNGERR_NONE; + return png_error::NONE; } png_info & pnginfo; @@ -481,13 +472,13 @@ public: { // 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 + return png_error::UNSUPPORTED_FORMAT; // only do multiples of 8bps here - expand lower bit depth first if ((ARRAY_LENGTH(samples) <= pnginfo.color_type) || !samples[pnginfo.color_type]) - return PNGERR_UNSUPPORTED_FORMAT; // unknown colour sample format + return png_error::UNSUPPORTED_FORMAT; // unknown colour sample format if ((0 != pnginfo.interlace_method) && (1 != pnginfo.interlace_method)) - return PNGERR_UNSUPPORTED_FORMAT; // unknown interlace method + return png_error::UNSUPPORTED_FORMAT; // unknown interlace method if ((3 == pnginfo.color_type) && (8 != pnginfo.bit_depth)) - return PNGERR_UNSUPPORTED_FORMAT; // indexed colour must be exactly 8bpp + return png_error::UNSUPPORTED_FORMAT; // indexed colour must be exactly 8bpp // everything looks sane, allocate the bitmap and deinterlace into it bitmap.allocate(pnginfo.width, pnginfo.height); @@ -603,22 +594,22 @@ public: // set hasalpha flag and return hasalpha = 0xffU != accumalpha; - return PNGERR_NONE; + return png_error::NONE; } png_error expand_buffer_8bit() { // nothing to do if we're at 8 or greater already if (pnginfo.bit_depth >= 8) - return PNGERR_NONE; + return png_error::NONE; // do some basic checks for unsupported images if (!pnginfo.bit_depth || (8 % pnginfo.bit_depth)) - return PNGERR_UNSUPPORTED_FORMAT; // bit depth must be a factor of eight + return png_error::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 + return png_error::UNSUPPORTED_FORMAT; // only upsample monochrome and indexed colour if ((0 != pnginfo.interlace_method) && (1 != pnginfo.interlace_method)) - return PNGERR_UNSUPPORTED_FORMAT; // unknown interlace method + return png_error::UNSUPPORTED_FORMAT; // unknown interlace method // calculate the offset for each pass of the interlace on the input and output unsigned const pass_count(get_pass_count()); @@ -633,7 +624,7 @@ public: // allocate a new buffer at 8-bit std::unique_ptr outbuf; try { outbuf.reset(new std::uint8_t [outp_offset[pass_count]]); } - catch (std::bad_alloc const &) { return PNGERR_OUT_OF_MEMORY; } + catch (std::bad_alloc const &) { return png_error::OUT_OF_MEMORY; } // upsample bitmap std::uint8_t const bytesamples(8 / pnginfo.bit_depth); @@ -687,13 +678,13 @@ public: pnginfo.image = std::move(outbuf); pnginfo.bit_depth = 8; - return PNGERR_NONE; + return png_error::NONE; } - png_error read_file(util::core_file &fp) + png_error read_file(core_file &fp) { // initialize the data structures - png_error error = PNGERR_NONE; + png_error error = png_error::NONE; pnginfo.reset(); std::list idata; @@ -701,13 +692,13 @@ public: error = verify_header(fp); // loop until we hit an IEND chunk - while (PNGERR_NONE == error) + while (png_error::NONE == error) { // read a chunk std::unique_ptr chunk_data; std::uint32_t chunk_type = 0, chunk_length; error = read_chunk(fp, chunk_data, chunk_type, chunk_length); - if (PNGERR_NONE == error) + if (png_error::NONE == error) { if (chunk_type == PNG_CN_IEND) break; // stop when we hit an IEND chunk @@ -717,29 +708,29 @@ public: } // finish processing the image - if (PNGERR_NONE == error) + if (png_error::NONE == error) error = process(idata); // if we have an error, free all the output data - if (error != PNGERR_NONE) + if (error != png_error::NONE) pnginfo.reset(); return error; } - static png_error verify_header(util::core_file &fp) + static png_error verify_header(core_file &fp) { EQUIVALENT_ARRAY(PNG_SIGNATURE, std::uint8_t) signature; // read 8 bytes if (fp.read(signature, sizeof(signature)) != sizeof(signature)) - return PNGERR_FILE_TRUNCATED; + return png_error::FILE_TRUNCATED; // return an error if we don't match if (std::memcmp(signature, PNG_SIGNATURE, sizeof(PNG_SIGNATURE))) - return PNGERR_BAD_SIGNATURE; + return png_error::BAD_SIGNATURE; - return PNGERR_NONE; + return png_error::NONE; } }; @@ -760,7 +751,7 @@ constexpr unsigned png_private::ADAM7_Y_OFFS[7]; core stream -------------------------------------------------*/ -png_error png_info::verify_header(util::core_file &fp) +png_error png_info::verify_header(core_file &fp) { return png_private::verify_header(fp); } @@ -770,7 +761,7 @@ png_error png_info::verify_header(util::core_file &fp) read_file - read a PNG from a core stream -------------------------------------------------*/ -png_error png_info::read_file(util::core_file &fp) +png_error png_info::read_file(core_file &fp) { return png_private(*this).read_file(fp); } @@ -781,7 +772,7 @@ png_error png_info::read_file(util::core_file &fp) bitmap -------------------------------------------------*/ -png_error png_read_bitmap(util::core_file &fp, bitmap_argb32 &bitmap) +png_error png_read_bitmap(core_file &fp, bitmap_argb32 &bitmap) { png_error result; png_info pnginfo; @@ -789,12 +780,12 @@ png_error png_read_bitmap(util::core_file &fp, bitmap_argb32 &bitmap) // read the PNG data result = png.read_file(fp); - if (PNGERR_NONE != result) + if (png_error::NONE != result) return result; // resample to 8bpp if necessary result = png.expand_buffer_8bit(); - if (PNGERR_NONE != result) + if (png_error::NONE != result) { pnginfo.free_data(); return result; @@ -848,13 +839,13 @@ png_error png_info::add_text(const char *keyword, const char *text) char32_t ch; int const len(uchar_from_utf8(&ch, ptr, kwend - ptr)); if ((0 >= len) || (32 > ch) || (255 < ch) || ((126 < ch) && (161 > ch)) || (((32 == prev) || (keyword == ptr)) && (32 == ch))) - return PNGERR_UNSUPPORTED_FORMAT; + return png_error::UNSUPPORTED_FORMAT; prev = ch; ++cnt; ptr += len; } if ((32 == prev) || (1 > cnt) || (79 < cnt)) - return PNGERR_UNSUPPORTED_FORMAT; + return png_error::UNSUPPORTED_FORMAT; // apply rules to text char const *const textend(text + std::strlen(text)); @@ -863,14 +854,14 @@ png_error png_info::add_text(const char *keyword, const char *text) char32_t ch; int const len(uchar_from_utf8(&ch, ptr, textend - ptr)); if ((0 >= len) || (1 > ch) || (255 < ch)) - return PNGERR_UNSUPPORTED_FORMAT; + return png_error::UNSUPPORTED_FORMAT; ptr += len; } // allocate a new text element try { textlist.emplace_back(std::piecewise_construct, std::forward_as_tuple(keyword, kwend), std::forward_as_tuple(text, textend)); } - catch (std::bad_alloc const &) { return PNGERR_OUT_OF_MEMORY; } - return PNGERR_NONE; + catch (std::bad_alloc const &) { return png_error::OUT_OF_MEMORY; } + return png_error::NONE; } @@ -879,7 +870,7 @@ png_error png_info::add_text(const char *keyword, const char *text) the given file -------------------------------------------------*/ -static png_error write_chunk(util::core_file &fp, const uint8_t *data, uint32_t type, uint32_t length) +static png_error write_chunk(core_file &fp, const uint8_t *data, uint32_t type, uint32_t length) { uint8_t tempbuff[8]; uint32_t crc; @@ -891,22 +882,22 @@ static png_error write_chunk(util::core_file &fp, const uint8_t *data, uint32_t /* write that data */ if (fp.write(tempbuff, 8) != 8) - return PNGERR_FILE_ERROR; + return png_error::FILE_ERROR; /* append the actual data */ if (length > 0) { if (fp.write(data, length) != length) - return PNGERR_FILE_ERROR; + return png_error::FILE_ERROR; crc = crc32(crc, data, length); } /* write the CRC */ put_32bit(tempbuff, crc); if (fp.write(tempbuff, 4) != 4) - return PNGERR_FILE_ERROR; + return png_error::FILE_ERROR; - return PNGERR_NONE; + return png_error::NONE; } @@ -915,7 +906,7 @@ static png_error write_chunk(util::core_file &fp, const uint8_t *data, uint32_t chunk to the given file by deflating it -------------------------------------------------*/ -static png_error write_deflated_chunk(util::core_file &fp, uint8_t *data, uint32_t type, uint32_t length) +static png_error write_deflated_chunk(core_file &fp, uint8_t *data, uint32_t type, uint32_t length) { uint64_t lengthpos = fp.tell(); uint8_t tempbuff[8192]; @@ -931,7 +922,7 @@ static png_error write_deflated_chunk(util::core_file &fp, uint8_t *data, uint32 /* write that data */ if (fp.write(tempbuff, 8) != 8) - return PNGERR_FILE_ERROR; + return png_error::FILE_ERROR; /* initialize the stream */ memset(&stream, 0, sizeof(stream)); @@ -939,7 +930,7 @@ static png_error write_deflated_chunk(util::core_file &fp, uint8_t *data, uint32 stream.avail_in = length; zerr = deflateInit(&stream, Z_DEFAULT_COMPRESSION); if (zerr != Z_OK) - return PNGERR_COMPRESS_ERROR; + return png_error::COMPRESS_ERROR; /* now loop until we run out of data */ for ( ; ; ) @@ -956,7 +947,7 @@ static png_error write_deflated_chunk(util::core_file &fp, uint8_t *data, uint32 if (fp.write(tempbuff, bytes) != bytes) { deflateEnd(&stream); - return PNGERR_FILE_ERROR; + return png_error::FILE_ERROR; } crc = crc32(crc, tempbuff, bytes); zlength += bytes; @@ -970,29 +961,29 @@ static png_error write_deflated_chunk(util::core_file &fp, uint8_t *data, uint32 if (zerr != Z_OK) { deflateEnd(&stream); - return PNGERR_COMPRESS_ERROR; + return png_error::COMPRESS_ERROR; } } /* clean up deflater(maus) */ zerr = deflateEnd(&stream); if (zerr != Z_OK) - return PNGERR_COMPRESS_ERROR; + return png_error::COMPRESS_ERROR; /* write the CRC */ put_32bit(tempbuff, crc); if (fp.write(tempbuff, 4) != 4) - return PNGERR_FILE_ERROR; + return png_error::FILE_ERROR; /* seek back and update the length */ fp.seek(lengthpos, SEEK_SET); put_32bit(tempbuff + 0, zlength); if (fp.write(tempbuff, 4) != 4) - return PNGERR_FILE_ERROR; + return png_error::FILE_ERROR; /* return to the end */ fp.seek(lengthpos + 8 + zlength + 4, SEEK_SET); - return PNGERR_NONE; + return png_error::NONE; } @@ -1016,7 +1007,7 @@ static png_error convert_bitmap_to_image_palette(png_info &pnginfo, const bitmap /* allocate memory for the palette */ try { pnginfo.palette.reset(new std::uint8_t [3 * 256]); } - catch (std::bad_alloc const &) { return PNGERR_OUT_OF_MEMORY; } + catch (std::bad_alloc const &) { return png_error::OUT_OF_MEMORY; } /* build the palette */ std::fill_n(pnginfo.palette.get(), 3 * 256, 0); @@ -1036,7 +1027,7 @@ static png_error convert_bitmap_to_image_palette(png_info &pnginfo, const bitmap catch (std::bad_alloc const &) { pnginfo.palette.reset(); - return PNGERR_OUT_OF_MEMORY; + return png_error::OUT_OF_MEMORY; } /* copy in the pixels, specifying a nullptr filter */ @@ -1051,7 +1042,7 @@ static png_error convert_bitmap_to_image_palette(png_info &pnginfo, const bitmap *dst++ = *src++; } - return PNGERR_NONE; + return png_error::NONE; } @@ -1075,7 +1066,7 @@ static png_error convert_bitmap_to_image_rgb(png_info &pnginfo, const bitmap_t & /* allocate memory for the image */ try { pnginfo.image.reset(new std::uint8_t [pnginfo.height * (rowbytes + 1)]); } - catch (std::bad_alloc const &) { return PNGERR_OUT_OF_MEMORY; } + catch (std::bad_alloc const &) { return png_error::OUT_OF_MEMORY; } /* copy in the pixels, specifying a nullptr filter */ for (y = 0; y < pnginfo.height; y++) @@ -1127,10 +1118,10 @@ static png_error convert_bitmap_to_image_rgb(png_info &pnginfo, const bitmap_t & /* unsupported format */ else - return PNGERR_UNSUPPORTED_FORMAT; + return png_error::UNSUPPORTED_FORMAT; } - return PNGERR_NONE; + return png_error::NONE; } @@ -1139,7 +1130,7 @@ static png_error convert_bitmap_to_image_rgb(png_info &pnginfo, const bitmap_t & chunks to the given file -------------------------------------------------*/ -static png_error write_png_stream(util::core_file &fp, png_info &pnginfo, const bitmap_t &bitmap, int palette_length, const rgb_t *palette) +static png_error write_png_stream(core_file &fp, png_info &pnginfo, const bitmap_t &bitmap, int palette_length, const rgb_t *palette) { uint8_t tempbuff[16]; png_error error; @@ -1149,7 +1140,7 @@ static png_error write_png_stream(util::core_file &fp, png_info &pnginfo, const error = convert_bitmap_to_image_palette(pnginfo, bitmap, palette_length, palette); else error = convert_bitmap_to_image_rgb(pnginfo, bitmap, palette_length, palette); - if (error != PNGERR_NONE) + if (error != png_error::NONE) return error; // if we wanted to get clever and do filtering, we would do it here @@ -1163,18 +1154,18 @@ static png_error write_png_stream(util::core_file &fp, png_info &pnginfo, const put_8bit(tempbuff + 11, pnginfo.filter_method); put_8bit(tempbuff + 12, pnginfo.interlace_method); error = write_chunk(fp, tempbuff, PNG_CN_IHDR, 13); - if (error != PNGERR_NONE) + if (error != png_error::NONE) return error; // write the PLTE chunk if (pnginfo.num_palette > 0) error = write_chunk(fp, pnginfo.palette.get(), PNG_CN_PLTE, pnginfo.num_palette * 3); - if (error != PNGERR_NONE) + if (error != png_error::NONE) return error; - // write a single IDAT chunk */ + // write a single IDAT chunk error = write_deflated_chunk(fp, pnginfo.image.get(), PNG_CN_IDAT, pnginfo.height * (compute_rowbytes(pnginfo) + 1)); - if (error != PNGERR_NONE) + if (error != png_error::NONE) return error; // write TEXT chunks @@ -1182,7 +1173,7 @@ static png_error write_png_stream(util::core_file &fp, png_info &pnginfo, const for (png_info::png_text const &text : pnginfo.textlist) { try { textbuf.resize(text.first.length() + 1 + text.second.length()); } - catch (std::bad_alloc const &) { return PNGERR_OUT_OF_MEMORY; } + catch (std::bad_alloc const &) { return png_error::OUT_OF_MEMORY; } std::uint8_t *dst(&textbuf[0]); // convert keyword to ISO-8859-1 @@ -1213,7 +1204,7 @@ static png_error write_png_stream(util::core_file &fp, png_info &pnginfo, const } error = write_chunk(fp, &textbuf[0], PNG_CN_tEXt, dst - &textbuf[0]); - if (error != PNGERR_NONE) + if (error != png_error::NONE) return error; } @@ -1222,7 +1213,7 @@ static png_error write_png_stream(util::core_file &fp, png_info &pnginfo, const } -png_error png_write_bitmap(util::core_file &fp, png_info *info, bitmap_t const &bitmap, int palette_length, const rgb_t *palette) +png_error png_write_bitmap(core_file &fp, png_info *info, bitmap_t const &bitmap, int palette_length, const rgb_t *palette) { // use a dummy pnginfo if none passed to us png_info pnginfo; @@ -1231,7 +1222,7 @@ png_error png_write_bitmap(util::core_file &fp, png_info *info, bitmap_t const & // write the PNG signature if (fp.write(PNG_SIGNATURE, sizeof(PNG_SIGNATURE)) != sizeof(PNG_SIGNATURE)) - return PNGERR_FILE_ERROR; + return png_error::FILE_ERROR; /* write the rest of the PNG data */ return write_png_stream(fp, *info, bitmap, palette_length, palette); @@ -1246,7 +1237,7 @@ png_error png_write_bitmap(util::core_file &fp, png_info *info, bitmap_t const & ********************************************************************************/ /** - * @fn png_error mng_capture_start(util::core_file &fp, bitmap_t &bitmap, unsigned rate) + * @fn png_error mng_capture_start(core_file &fp, bitmap_t &bitmap, unsigned rate) * * @brief Mng capture start. * @@ -1257,12 +1248,12 @@ png_error png_write_bitmap(util::core_file &fp, png_info *info, bitmap_t const & * @return A png_error. */ -png_error mng_capture_start(util::core_file &fp, bitmap_t &bitmap, unsigned rate) +png_error mng_capture_start(core_file &fp, bitmap_t &bitmap, unsigned rate) { uint8_t mhdr[28]; if (fp.write(MNG_Signature, 8) != 8) - return PNGERR_FILE_ERROR; + return png_error::FILE_ERROR; memset(mhdr, 0, 28); put_32bit(mhdr + 0, bitmap.width()); @@ -1273,7 +1264,7 @@ png_error mng_capture_start(util::core_file &fp, bitmap_t &bitmap, unsigned rate } /** - * @fn png_error mng_capture_frame(util::core_file &fp, png_info *info, bitmap_t &bitmap, int palette_length, const rgb_t *palette) + * @fn png_error mng_capture_frame(core_file &fp, png_info *info, bitmap_t &bitmap, int palette_length, const rgb_t *palette) * * @brief Mng capture frame. * @@ -1286,13 +1277,13 @@ png_error mng_capture_start(util::core_file &fp, bitmap_t &bitmap, unsigned rate * @return A png_error. */ -png_error mng_capture_frame(util::core_file &fp, png_info &info, bitmap_t const &bitmap, int palette_length, const rgb_t *palette) +png_error mng_capture_frame(core_file &fp, png_info &info, bitmap_t const &bitmap, int palette_length, const rgb_t *palette) { return write_png_stream(fp, info, bitmap, palette_length, palette); } /** - * @fn png_error mng_capture_stop(util::core_file &fp) + * @fn png_error mng_capture_stop(core_file &fp) * * @brief Mng capture stop. * @@ -1301,7 +1292,9 @@ png_error mng_capture_frame(util::core_file &fp, png_info &info, bitmap_t const * @return A png_error. */ -png_error mng_capture_stop(util::core_file &fp) +png_error mng_capture_stop(core_file &fp) { return write_chunk(fp, nullptr, MNG_CN_MEND, 0); } + +} // namespace util -- cgit v1.2.3-70-g09d2