|
|
@@ -875,8 +875,10 @@ MINIZ_STATIC size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len
|
|
|
// Function returns a pointer to the compressed data, or NULL on failure.
|
|
|
// *pLen_out will be set to the size of the PNG image file.
|
|
|
// The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed.
|
|
|
-MINIZ_STATIC void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, int bpl, size_t *pLen_out, mz_uint level, mz_bool flip);
|
|
|
+MINIZ_STATIC void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, int bpl, size_t *pLen_out, mz_uint level, mz_bool flip, mz_uint8 *plte, int plte_size, mz_uint8 *trns, int trns_size);
|
|
|
+#ifndef MINIZ_SDL_NOUNUSED
|
|
|
MINIZ_STATIC void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, int bpl, size_t *pLen_out);
|
|
|
+#endif
|
|
|
|
|
|
// Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time.
|
|
|
typedef mz_bool (*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser);
|
|
|
@@ -2911,29 +2913,27 @@ mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int
|
|
|
// Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at
|
|
|
// http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
|
|
|
// This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck.
|
|
|
-MINIZ_STATIC void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, int bpl, size_t *pLen_out, mz_uint level, mz_bool flip)
|
|
|
+MINIZ_STATIC void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, int bpl, size_t *pLen_out, mz_uint level, mz_bool flip, mz_uint8 *plte, int plte_size, mz_uint8 *trns, int trns_size)
|
|
|
{
|
|
|
// Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined.
|
|
|
static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
|
|
|
- tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); tdefl_output_buffer out_buf; int i, y, z; mz_uint32 c; *pLen_out = 0;
|
|
|
+ tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); tdefl_output_buffer out_buf; int i, y, z = 0; mz_uint32 c; *pLen_out = 0; size_t data_start, data_size;
|
|
|
if (!pComp) return NULL;
|
|
|
- MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE; out_buf.m_capacity = 57+MZ_MAX(64, (1+bpl)*h); if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; }
|
|
|
- // write dummy header
|
|
|
- for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf);
|
|
|
- // compress image data
|
|
|
- tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
|
|
|
- for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); }
|
|
|
- if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
|
|
|
- // write real header
|
|
|
- *pLen_out = out_buf.m_size-41;
|
|
|
+ MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE;
|
|
|
+ out_buf.m_capacity = 57+MZ_MAX(64, (1+bpl)*h);
|
|
|
+ if (plte_size > 0)
|
|
|
+ out_buf.m_capacity += 12+plte_size;
|
|
|
+ if (trns_size > 0)
|
|
|
+ out_buf.m_capacity += 12+trns_size;
|
|
|
+ if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; }
|
|
|
+ // write header
|
|
|
{
|
|
|
static const mz_uint8 chans[] = {0x00, 0x00, 0x04, 0x02, 0x06};
|
|
|
|
|
|
- mz_uint8 pnghdr[41]={ 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,
|
|
|
+ mz_uint8 pnghdr[33]={ 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,
|
|
|
0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
- 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
- 0x00,0x00,0x00,0x00,0x49,0x44,0x41,0x54};
|
|
|
+ 0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
|
|
|
|
|
|
pnghdr[18] = (mz_uint8)(w>>8);
|
|
|
pnghdr[19] = (mz_uint8)(w>>0);
|
|
|
@@ -2941,31 +2941,76 @@ MINIZ_STATIC void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage
|
|
|
pnghdr[22] = (mz_uint8)(h>>8);
|
|
|
pnghdr[23] = (mz_uint8)(h>>0);
|
|
|
|
|
|
- pnghdr[25] = (chans[num_chans]);
|
|
|
-
|
|
|
- pnghdr[33] = (mz_uint8)(*pLen_out>>24);
|
|
|
- pnghdr[34] = (mz_uint8)(*pLen_out>>16);
|
|
|
- pnghdr[35] = (mz_uint8)(*pLen_out>> 8);
|
|
|
- pnghdr[36] = (mz_uint8)(*pLen_out>> 0);
|
|
|
+ if (num_chans == 1 && plte_size > 0)
|
|
|
+ pnghdr[25] = 3;
|
|
|
+ else
|
|
|
+ pnghdr[25] = (chans[num_chans]);
|
|
|
|
|
|
c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,pnghdr+12,17);
|
|
|
for (i=0; i<4; ++i, c<<=8) ((mz_uint8*)(pnghdr+29))[i] = (mz_uint8)(c>>24);
|
|
|
- memcpy(out_buf.m_pBuf, pnghdr, 41);
|
|
|
+ if (!tdefl_output_buffer_putter(pnghdr, sizeof(pnghdr), &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
|
|
|
+ }
|
|
|
+ // write PLTE chunk
|
|
|
+ if (plte_size > 0)
|
|
|
+ {
|
|
|
+ mz_uint8 hdr[8]={0x00,0x00,0x00,0x00,0x50,0x4c,0x54,0x45};
|
|
|
+
|
|
|
+ hdr[0] = (mz_uint8)(plte_size>>24);
|
|
|
+ hdr[1] = (mz_uint8)(plte_size>>16);
|
|
|
+ hdr[2] = (mz_uint8)(plte_size>> 8);
|
|
|
+ hdr[3] = (mz_uint8)(plte_size>> 0);
|
|
|
+ if (!tdefl_output_buffer_putter(hdr, sizeof(hdr), &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
|
|
|
+ data_start = out_buf.m_size;
|
|
|
+ if (!tdefl_output_buffer_putter(plte, plte_size, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
|
|
|
+ if (!tdefl_output_buffer_putter("\0\0\0\0", 4, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
|
|
|
+ c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+data_start-4, plte_size+4);
|
|
|
+ for (i=0; i<4; ++i, c<<=8) (out_buf.m_pBuf+out_buf.m_size-4)[i] = (mz_uint8)(c >> 24);
|
|
|
+ }
|
|
|
+ // write tRNS chunk
|
|
|
+ if (trns_size > 0)
|
|
|
+ {
|
|
|
+ mz_uint8 hdr[8]={0x00,0x00,0x00,0x00,0x74,0x52,0x4E,0x53};
|
|
|
+
|
|
|
+ hdr[0] = (mz_uint8)(trns_size>>24);
|
|
|
+ hdr[1] = (mz_uint8)(trns_size>>16);
|
|
|
+ hdr[2] = (mz_uint8)(trns_size>> 8);
|
|
|
+ hdr[3] = (mz_uint8)(trns_size>> 0);
|
|
|
+ if (!tdefl_output_buffer_putter(hdr, sizeof(hdr), &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
|
|
|
+ data_start = out_buf.m_size;
|
|
|
+ if (!tdefl_output_buffer_putter(trns, trns_size, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
|
|
|
+ if (!tdefl_output_buffer_putter("\0\0\0\0", 4, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
|
|
|
+ c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+data_start-4, trns_size+4);
|
|
|
+ for (i=0; i<4; ++i, c<<=8) (out_buf.m_pBuf+out_buf.m_size-4)[i] = (mz_uint8)(c >> 24);
|
|
|
}
|
|
|
+ // write IDAT chunk
|
|
|
+ if (!tdefl_output_buffer_putter("\0\0\0\0\x49\x44\x41\x54", 8, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
|
|
|
+ data_start = out_buf.m_size;
|
|
|
+ // compress image data
|
|
|
+ tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
|
|
|
+ for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); }
|
|
|
+ if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
|
|
|
+ // write IDAT size
|
|
|
+ data_size = out_buf.m_size-data_start;
|
|
|
+ (out_buf.m_pBuf+data_start-8)[0] = (mz_uint8)(data_size>>24);
|
|
|
+ (out_buf.m_pBuf+data_start-8)[1] = (mz_uint8)(data_size>>16);
|
|
|
+ (out_buf.m_pBuf+data_start-8)[2] = (mz_uint8)(data_size>> 8);
|
|
|
+ (out_buf.m_pBuf+data_start-8)[3] = (mz_uint8)(data_size>> 0);
|
|
|
// write footer (IDAT CRC-32, followed by IEND chunk)
|
|
|
if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
|
|
|
- c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+41-4, *pLen_out+4);
|
|
|
+ c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+data_start-4, data_size+4);
|
|
|
for (i=0; i<4; ++i, c<<=8) (out_buf.m_pBuf+out_buf.m_size-16)[i] = (mz_uint8)(c >> 24);
|
|
|
// compute final size of file, grab compressed data buffer and return
|
|
|
- *pLen_out += 57;
|
|
|
+ *pLen_out = out_buf.m_size;
|
|
|
MZ_FREE(pComp);
|
|
|
return out_buf.m_pBuf;
|
|
|
}
|
|
|
+#ifndef MINIZ_SDL_NOUNUSED
|
|
|
MINIZ_STATIC void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, int bpl, size_t *pLen_out)
|
|
|
{
|
|
|
// Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out)
|
|
|
- return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, bpl, pLen_out, 6, MZ_FALSE);
|
|
|
+ return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, bpl, pLen_out, 6, MZ_FALSE, NULL, 0, NULL, 0);
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
#pragma warning (pop)
|