From db6e91b7d867f33eb5e9c5012324e2702a1eeedd Mon Sep 17 00:00:00 2001 From: Andrew Kensler Date: Sat, 3 Jul 2021 23:39:43 -0700 Subject: [PATCH] Store uncompressed if compression was worse If the data was uncompressible and this deflate implementation expanded by more than the overhead of simply storing it uncompressed, fall back to deflate's uncompressed storage mode. This bounds the maximum deflated size at the original size plus an overhead of 6 fixed bytes with another 5 bytes per 32767 byte block. Fixes issue #948. --- stb_image_write.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/stb_image_write.h b/stb_image_write.h index 271d4ac..a909e82 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -140,6 +140,7 @@ CREDITS: Ivan Tikhonov github:ignotion Adam Schackart + Andrew Kensler LICENSE @@ -969,6 +970,23 @@ STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, i (void) stbiw__sbfree(hash_table[i]); STBIW_FREE(hash_table); + // store uncompressed instead if compression was worse + if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) { + stbiw__sbn(out) = 2; // truncate to DEFLATE 32K window and FLEVEL = 1 + for (j = 0; j < data_len;) { + int blocklen = data_len - j; + if (blocklen > 32767) blocklen = 32767; + stbiw__sbpush(out, data_len - j == blocklen); // BFINAL = ?, BTYPE = 0 -- no compression + stbiw__sbpush(out, STBIW_UCHAR(blocklen)); // LEN + stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(~blocklen)); // NLEN + stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8)); + memcpy(out+stbiw__sbn(out), data+j, blocklen); + stbiw__sbn(out) += blocklen; + j += blocklen; + } + } + { // compute adler32 on input unsigned int s1=1, s2=0; @@ -1599,6 +1617,8 @@ STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history + 1.15 ( ) + make Deflate code emit uncompressed blocks when it would otherwise expand 1.14 (2020-02-02) updated JPEG writer to downsample chroma channels 1.13 1.12