Convert PNGLibrary to use vector instead of raw pointers.

This is just as efficient, but also safer.
This commit is contained in:
Stephen Anthony 2019-12-28 17:44:50 -03:30
parent 041af0736c
commit ca1207344c
2 changed files with 29 additions and 41 deletions

View File

@ -107,10 +107,10 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface)
// The PNG read function expects an array of rows, not a single 1-D array // The PNG read function expects an array of rows, not a single 1-D array
for(uInt32 irow = 0, offset = 0; irow < ReadInfo.height; ++irow, offset += ReadInfo.pitch) for(uInt32 irow = 0, offset = 0; irow < ReadInfo.height; ++irow, offset += ReadInfo.pitch)
ReadInfo.row_pointers[irow] = png_bytep(ReadInfo.buffer.get() + offset); ReadInfo.row_pointers[irow] = static_cast<png_bytep>(ReadInfo.buffer.data() + offset);
// Read the entire image in one go // Read the entire image in one go
png_read_image(png_ptr, ReadInfo.row_pointers.get()); png_read_image(png_ptr, ReadInfo.row_pointers.data());
// We're finished reading // We're finished reading
png_read_end(png_ptr, info_ptr); png_read_end(png_ptr, info_ptr);
@ -135,13 +135,13 @@ void PNGLibrary::saveImage(const string& filename, const VariantList& comments)
png_uint_32 width = rect.w(), height = rect.h(); png_uint_32 width = rect.w(), height = rect.h();
// Get framebuffer pixel data (we get ABGR format) // Get framebuffer pixel data (we get ABGR format)
unique_ptr<png_byte[]> buffer = make_unique<png_byte[]>(width * height * 4); vector<png_byte> buffer(width * height * 4);
fb.readPixels(buffer.get(), width*4, rect); fb.readPixels(buffer.data(), width*4, rect);
// Set up pointers into "buffer" byte array // Set up pointers into "buffer" byte array
unique_ptr<png_bytep[]> rows = make_unique<png_bytep[]>(height); vector<png_bytep> rows(height);
for(png_uint_32 k = 0; k < height; ++k) for(png_uint_32 k = 0; k < height; ++k)
rows[k] = png_bytep(buffer.get() + k*width*4); rows[k] = static_cast<png_bytep>(buffer.data() + k*width*4);
// And save the image // And save the image
saveImageToDisk(out, rows, width, height, comments); saveImageToDisk(out, rows, width, height, comments);
@ -164,20 +164,20 @@ void PNGLibrary::saveImage(const string& filename, const FBSurface& surface,
} }
// Get the surface pixel data (we get ABGR format) // Get the surface pixel data (we get ABGR format)
unique_ptr<png_byte[]> buffer = make_unique<png_byte[]>(width * height * 4); vector<png_byte> buffer(width * height * 4);
surface.readPixels(buffer.get(), width, rect); surface.readPixels(buffer.data(), width, rect);
// Set up pointers into "buffer" byte array // Set up pointers into "buffer" byte array
unique_ptr<png_bytep[]> rows = make_unique<png_bytep[]>(height); vector<png_bytep> rows(height);
for(png_uint_32 k = 0; k < height; ++k) for(png_uint_32 k = 0; k < height; ++k)
rows[k] = png_bytep(buffer.get() + k*width*4); rows[k] = static_cast<png_bytep>(buffer.data() + k*width*4);
// And save the image // And save the image
saveImageToDisk(out, rows, width, height, comments); saveImageToDisk(out, rows, width, height, comments);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PNGLibrary::saveImageToDisk(ofstream& out, const unique_ptr<png_bytep[]>& rows, void PNGLibrary::saveImageToDisk(ofstream& out, const vector<png_bytep>& rows,
png_uint_32 width, png_uint_32 height, const VariantList& comments) png_uint_32 width, png_uint_32 height, const VariantList& comments)
{ {
png_structp png_ptr = nullptr; png_structp png_ptr = nullptr;
@ -228,7 +228,7 @@ void PNGLibrary::saveImageToDisk(ofstream& out, const unique_ptr<png_bytep[]>& r
png_set_bgr(png_ptr); png_set_bgr(png_ptr);
// Write the entire image in one go // Write the entire image in one go
png_write_image(png_ptr, rows.get()); png_write_image(png_ptr, const_cast<png_bytep*>(rows.data()));
// We're finished writing // We're finished writing
png_write_end(png_ptr, info_ptr); png_write_end(png_ptr, info_ptr);
@ -385,24 +385,13 @@ void PNGLibrary::takeSnapshot(uInt32 number)
bool PNGLibrary::allocateStorage(png_uint_32 w, png_uint_32 h) bool PNGLibrary::allocateStorage(png_uint_32 w, png_uint_32 h)
{ {
// Create space for the entire image (3 bytes per pixel in RGB format) // Create space for the entire image (3 bytes per pixel in RGB format)
uInt32 req_buffer_size = w * h * 3; size_t req_buffer_size = w * h * 3;
if(req_buffer_size > ReadInfo.buffer_size) if(req_buffer_size > ReadInfo.buffer.size())
{ ReadInfo.buffer.resize(req_buffer_size);
ReadInfo.buffer = make_unique<png_byte[]>(req_buffer_size);
if(ReadInfo.buffer == nullptr)
return false;
ReadInfo.buffer_size = req_buffer_size; size_t req_row_size = h;
} if(req_row_size > ReadInfo.row_pointers.size())
uInt32 req_row_size = h; ReadInfo.row_pointers.resize(req_row_size);
if(req_row_size > ReadInfo.row_size)
{
ReadInfo.row_pointers = make_unique<png_bytep[]>(req_row_size);
if(ReadInfo.row_pointers == nullptr)
return false;
ReadInfo.row_size = req_row_size;
}
ReadInfo.width = w; ReadInfo.width = w;
ReadInfo.height = h; ReadInfo.height = h;
@ -427,13 +416,13 @@ void PNGLibrary::loadImagetoSurface(FBSurface& surface)
// Convert RGB triples into pixels and store in the surface // Convert RGB triples into pixels and store in the surface
uInt32 *s_buf, s_pitch; uInt32 *s_buf, s_pitch;
surface.basePtr(s_buf, s_pitch); surface.basePtr(s_buf, s_pitch);
uInt8* i_buf = ReadInfo.buffer.get(); const uInt8* i_buf = ReadInfo.buffer.data();
uInt32 i_pitch = ReadInfo.pitch; const uInt32 i_pitch = ReadInfo.pitch;
const FrameBuffer& fb = myOSystem.frameBuffer(); const FrameBuffer& fb = myOSystem.frameBuffer();
for(uInt32 irow = 0; irow < ih; ++irow, i_buf += i_pitch, s_buf += s_pitch) for(uInt32 irow = 0; irow < ih; ++irow, i_buf += i_pitch, s_buf += s_pitch)
{ {
uInt8* i_ptr = i_buf; const uInt8* i_ptr = i_buf;
uInt32* s_ptr = s_buf; uInt32* s_ptr = s_buf;
for(uInt32 icol = 0; icol < ReadInfo.width; ++icol, i_ptr += 3) for(uInt32 icol = 0; icol < ReadInfo.width; ++icol, i_ptr += 3)
*s_ptr++ = fb.mapRGB(*i_ptr, *(i_ptr+1), *(i_ptr+2)); *s_ptr++ = fb.mapRGB(*i_ptr, *(i_ptr+1), *(i_ptr+2));
@ -448,7 +437,7 @@ void PNGLibrary::writeComments(png_structp png_ptr, png_infop info_ptr,
if(numComments == 0) if(numComments == 0)
return; return;
unique_ptr<png_text[]> text_ptr = make_unique<png_text[]>(numComments); vector<png_text> text_ptr(numComments);
for(uInt32 i = 0; i < numComments; ++i) for(uInt32 i = 0; i < numComments; ++i)
{ {
text_ptr[i].key = const_cast<char*>(comments[i].first.c_str()); text_ptr[i].key = const_cast<char*>(comments[i].first.c_str());
@ -456,7 +445,7 @@ void PNGLibrary::writeComments(png_structp png_ptr, png_infop info_ptr,
text_ptr[i].compression = PNG_TEXT_COMPRESSION_NONE; text_ptr[i].compression = PNG_TEXT_COMPRESSION_NONE;
text_ptr[i].text_length = 0; text_ptr[i].text_length = 0;
} }
png_set_text(png_ptr, info_ptr, text_ptr.get(), numComments); png_set_text(png_ptr, info_ptr, text_ptr.data(), numComments);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -492,8 +481,6 @@ void PNGLibrary::png_user_error(png_structp ctx, png_const_charp str)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PNGLibrary::ReadInfoType PNGLibrary::ReadInfo = { PNGLibrary::ReadInfoType PNGLibrary::ReadInfo;
nullptr, nullptr, 0, 0, 0, 0, 0
};
#endif // PNG_SUPPORT #endif // PNG_SUPPORT

View File

@ -137,10 +137,11 @@ class PNGLibrary
// The following data remains between invocations of allocateStorage, // The following data remains between invocations of allocateStorage,
// and is only changed when absolutely necessary. // and is only changed when absolutely necessary.
struct ReadInfoType { struct ReadInfoType {
ByteBuffer buffer; vector<png_byte> buffer;
unique_ptr<png_bytep[]> row_pointers; vector<png_bytep> row_pointers;
png_uint_32 width, height, pitch; png_uint_32 width, height, pitch;
uInt32 buffer_size, row_size;
ReadInfoType() : width(0), height(0), pitch(0) { }
}; };
static ReadInfoType ReadInfo; static ReadInfoType ReadInfo;
@ -166,7 +167,7 @@ class PNGLibrary
@param height The height of the PNG image @param height The height of the PNG image
@param comments The text comments to add to the PNG image @param comments The text comments to add to the PNG image
*/ */
void saveImageToDisk(ofstream& out, const unique_ptr<png_bytep[]>& rows, void saveImageToDisk(ofstream& out, const vector<png_bytep>& rows,
png_uint_32 width, png_uint_32 height, png_uint_32 width, png_uint_32 height,
const VariantList& comments); const VariantList& comments);