Browse Source

Fixed loading and saving 16 bit per component PNGs.

--HG--
branch : minor
Alex Szpakowski 8 years ago
parent
commit
c6f8a1535d
1 changed files with 31 additions and 2 deletions
  1. 31 2
      src/modules/image/magpie/PNGHandler.cpp

+ 31 - 2
src/modules/image/magpie/PNGHandler.cpp

@@ -189,7 +189,7 @@ PNGHandler::DecodedImage PNGHandler::decode(love::filesystem::FileData *fdata)
 	if (state.info_raw.bitdepth == 16)
 	if (state.info_raw.bitdepth == 16)
 	{
 	{
 		uint16 *pixeldata = (uint16 *) img.data;
 		uint16 *pixeldata = (uint16 *) img.data;
-		uint16 numpixelcomponents = img.size / sizeof(uint16);
+		size_t numpixelcomponents = img.size / sizeof(uint16);
 
 
 		for (size_t i = 0; i < numpixelcomponents; i++)
 		for (size_t i = 0; i < numpixelcomponents; i++)
 			pixeldata[i] = swapuint16(pixeldata[i]);
 			pixeldata[i] = swapuint16(pixeldata[i]);
@@ -216,8 +216,37 @@ PNGHandler::EncodedImage PNGHandler::encode(const DecodedImage &img, ImageData::
 
 
 	state.encoder.zlibsettings.custom_zlib = zlibCompress;
 	state.encoder.zlibsettings.custom_zlib = zlibCompress;
 
 
+	const uint8 *data = img.data;
+	uint16 *swappeddata = nullptr;
+
+	// LodePNG expects big-endian raw pixel data when encoding a 16 bit image.
+#ifndef LOVE_BIG_ENDIAN
+	if (state.info_raw.bitdepth == 16)
+	{
+		try
+		{
+			swappeddata = new uint16[img.size / sizeof(uint16)];
+		}
+		catch (std::exception &)
+		{
+			throw love::Exception("Out of memory.");
+		}
+
+		const uint16 *rawdata = (const uint16 *) img.data;
+		size_t numpixelcomponents = img.size / sizeof(uint16);
+
+		for (size_t i = 0; i < numpixelcomponents; i++)
+			swappeddata[i] = swapuint16(rawdata[i]);
+
+		data = (const uint8 *) swappeddata;
+	}
+#endif
+
 	unsigned status = lodepng_encode(&encimg.data, &encimg.size,
 	unsigned status = lodepng_encode(&encimg.data, &encimg.size,
-	                                 img.data, img.width, img.height, &state);
+	                                 data, img.width, img.height, &state);
+
+	if (swappeddata != nullptr)
+		delete[] swappeddata;
 
 
 	if (status != 0)
 	if (status != 0)
 	{
 	{