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.
This commit is contained in:
Andrew Kensler 2021-07-03 23:39:43 -07:00 committed by Fabian Giesen
parent 14c224c84e
commit db6e91b7d8

View File

@ -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