@@ -39,6 +39,11 @@ namespace Common
3939namespace ImageFile
4040{
4141
42+ #define PNG_SHIFT_R32 (0 )
43+ #define PNG_SHIFT_G32 (8 )
44+ #define PNG_SHIFT_B32 (16 )
45+ #define PNG_SHIFT_A32 (24 )
46+
4247static int STB_IO_read (void *user, char *data, int size)
4348{
4449 return static_cast <int >(static_cast <IStreamBase*>(user)->Read (data, size));
@@ -89,27 +94,31 @@ PixelBuffer LoadPNG(Stream *in, PixelFormat *src_fmt, RGB *pal)
8994 }
9095
9196 PixelBuffer pxbuf;
92- if (stb_format == STBI_grey || stb_format == STBI_rgb || stb_format == STBI_rgb_alpha )
97+ if (stb_format == STBI_grey)
9398 {
9499 // FIXME: support PixelBuffer with custom deleter, then we may attach stb buffer here
95100 pxbuf = PixelBuffer (width, height, px_fmt);
96- // stb_format matches bytes-per-pixel in this case
97- std::memcpy (pxbuf.GetData (), pixels, width * height * stb_format);
101+ std::memcpy (pxbuf.GetData (), pixels, width * height);
98102 // Set a grayscale palette for gray images
99- if (stb_format == STBI_grey )
103+ if (pal )
100104 {
101- if (pal )
105+ for ( int i = 0 ; i < PAL_SIZE ; ++i )
102106 {
103- for (int i = 0 ; i < PAL_SIZE ; ++i)
104- {
105- pal[i].r = (uint8_t )i;
106- pal[i].g = (uint8_t )i;
107- pal[i].b = (uint8_t )i;
108- pal[i].a = 0 ;
109- }
107+ pal[i].r = (uint8_t )i;
108+ pal[i].g = (uint8_t )i;
109+ pal[i].b = (uint8_t )i;
110+ pal[i].a = 0 ;
110111 }
111112 }
112113 }
114+ else if (stb_format == STBI_rgb || stb_format == STBI_rgb_alpha)
115+ {
116+ // TODO: what about 16-bit images, are they even possible here?
117+ pxbuf = PixelBuffer (width, height, px_fmt);
118+ PixelOp::CopySwapRGBA (pixels, width * stb_format, PNG_SHIFT_R32 , PNG_SHIFT_G32 , PNG_SHIFT_B32 , PNG_SHIFT_A32 ,
119+ pxbuf.GetData (), GetStrideForPixelFormat (px_fmt, width), _rgb_r_shift_32, _rgb_g_shift_32, _rgb_b_shift_32, _rgb_a_shift_32,
120+ width, height, px_fmt);
121+ }
113122 else if (stb_format == STBI_grey_alpha)
114123 {
115124 pxbuf = PixelBuffer (width, height, px_fmt);
@@ -137,7 +146,7 @@ PixelBuffer LoadPNG(Stream *in, PixelFormat *src_fmt, RGB *pal)
137146 }
138147
139148 stbi_image_free (pixels);
140- if (src_fmt)
149+ if (pxbuf && src_fmt)
141150 *src_fmt = px_fmt;
142151 return pxbuf;
143152}
@@ -147,9 +156,21 @@ bool SavePNG(const BitmapData &bmp, bool skip_alpha, const RGB *pal, Stream *out
147156 // TODO: support skip_alpha
148157 // FIXME: support saving palette!!
149158
159+ PixelBuffer png_buf;
160+ if (bmp.GetBytesPerPixel () > 1 )
161+ {
162+ png_buf = PixelBuffer (bmp.GetWidth (), bmp.GetHeight (), bmp.GetFormat ());
163+ if (bmp.GetBytesPerPixel () == 2 )
164+ PixelOp::CopySwapRGBA (bmp.GetData (), _rgb_r_shift_16, _rgb_g_shift_16, _rgb_b_shift_16, 0 ,
165+ png_buf.GetData (), 0 , 5 , 11 /* FIXME!*/ , 0 , bmp.GetWidth (), bmp.GetHeight (), bmp.GetFormat ());
166+ else
167+ PixelOp::CopySwapRGBA (bmp.GetData (), _rgb_r_shift_32, _rgb_g_shift_32, _rgb_b_shift_32, _rgb_a_shift_32,
168+ png_buf.GetData (), PNG_SHIFT_R32 , PNG_SHIFT_G32 , PNG_SHIFT_B32 , PNG_SHIFT_A32 , bmp.GetWidth (), bmp.GetHeight (), bmp.GetFormat ());
169+ }
170+
150171 // Write a compressed PNG to memory
151172 size_t size = 0 ;
152- void *png = tdefl_write_image_to_png_file_in_memory_ex (bmp.GetData (), bmp.GetWidth (), bmp.GetHeight (), bmp.GetBytesPerPixel (),
173+ void *png = tdefl_write_image_to_png_file_in_memory_ex (png_buf ? png_buf. GetData () : bmp.GetData (), bmp.GetWidth (), bmp.GetHeight (), bmp.GetBytesPerPixel (),
153174 &size, Z_DEFAULT_COMPRESSION , MZ_FALSE );
154175
155176 // Write a result PNG from memory to file
0 commit comments