-
Notifications
You must be signed in to change notification settings - Fork 48
Optimize LodePNG #106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Optimize LodePNG #106
Changes from 2 commits
f0410a3
bb5a5c6
a987294
6d94323
17434f6
8a1f29a
e7f5f47
c365263
5cd91bc
672aa1c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1629,11 +1629,9 @@ static unsigned getValueRequiredBits(unsigned char value) { | |
|
|
||
| /*stats must already have been inited. */ | ||
| unsigned lodepng_compute_color_stats(LodePNGColorStats* stats, | ||
| const unsigned char* in, unsigned w, unsigned h, | ||
| const unsigned char* in, const size_t numpixels, | ||
| const LodePNGColorMode* mode_in) { | ||
| size_t i; | ||
| ColorTree tree; | ||
| size_t numpixels = (size_t)w * (size_t)h; | ||
| unsigned error = 0; | ||
|
|
||
| /* mark things as done already if it would be impossible to have a more expensive case */ | ||
|
|
@@ -1706,6 +1704,7 @@ unsigned lodepng_compute_color_stats(LodePNGColorStats* stats, | |
| } | ||
| } | ||
| } else /* < 16-bit */ { | ||
| ColorTree tree; | ||
| color_tree_init(&tree); | ||
| unsigned char r = 0, g = 0, b = 0, a = 0; | ||
| for(i = 0; i != numpixels; ++i) { | ||
|
|
@@ -1766,6 +1765,8 @@ unsigned lodepng_compute_color_stats(LodePNGColorStats* stats, | |
| if(alpha_done && numcolors_done && colored_done && bits_done) break; | ||
| } | ||
|
|
||
| color_tree_cleanup(&tree); | ||
|
|
||
| if(stats->key && !stats->alpha) { | ||
| for(i = 0; i != numpixels; ++i) { | ||
| getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); | ||
|
|
@@ -1783,13 +1784,7 @@ unsigned lodepng_compute_color_stats(LodePNGColorStats* stats, | |
| stats->key_r += (stats->key_r << 8); | ||
| stats->key_g += (stats->key_g << 8); | ||
| stats->key_b += (stats->key_b << 8); | ||
| color_tree_cleanup(&tree); | ||
| } | ||
|
|
||
| unsigned char r = 0, g = 0, b = 0, a = 0; | ||
| getPixelColorRGBA8(&r, &g, &b, &a, in, 0, mode_in); | ||
| stats->white = stats->numcolors == 1 && stats->colored == 0 && r == 255 && w > 20 && h > 20 && ((w>225 && h > 225) || w*h > 75000 || (w> 250 && w*h > 40000)); | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
|
|
@@ -2093,36 +2088,32 @@ output image, e.g. grey if there are only grayscale pixels, palette if there | |
| are less than 256 colors, ... | ||
| Updates values of mode with a potentially smaller color model. mode_out should | ||
| contain the user chosen color model, but will be overwritten with the new chosen one.*/ | ||
| static unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out, | ||
| const unsigned char* image, unsigned w, unsigned h, | ||
| const LodePNGColorMode* mode_in, unsigned div) { | ||
| LodePNGColorStats prof; | ||
| static unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in, | ||
| const LodePNGColorStats* stats, size_t numpixels, unsigned div) { | ||
| unsigned error = 0; | ||
| unsigned palettebits; | ||
| unsigned palettebits, palette_ok, gray_ok; | ||
| size_t i, n; | ||
| lodepng_color_stats_init(&prof); | ||
| error = lodepng_compute_color_stats(&prof, image, w, h, mode_in); | ||
| if(error) return error; | ||
| unsigned palette_ok, gray_ok; | ||
|
|
||
| LodePNGColorStats* stats = &prof; | ||
| unsigned alpha = stats->alpha; | ||
| unsigned key = stats->key; | ||
| unsigned bits = stats->bits; | ||
|
|
||
| mode_out->key_defined = 0; | ||
|
|
||
| if(stats->key && (unsigned long long)w * h <= 49) { | ||
| prof.alpha = 1; /*too few pixels to justify tRNS chunk overhead*/ | ||
| prof.key = 0; | ||
| if(prof.bits < 8) prof.bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ | ||
| if(key && numpixels <= 49) { | ||
| alpha = 1; /*too few pixels to justify tRNS chunk overhead*/ | ||
| key = 0; | ||
| if(bits < 8) bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ | ||
| } | ||
|
|
||
| gray_ok = !stats->colored; | ||
| if(!gray_ok && prof.bits < 8) prof.bits = 8; | ||
| if(!gray_ok && bits < 8) bits = 8; | ||
|
|
||
| n = stats->numcolors; | ||
| palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8)); | ||
| palette_ok = n <= 256 && prof.bits <= 8; | ||
| if(8 + n * 4 > (unsigned long long)w * h / div) {palette_ok = 0;} /*don't add palette overhead if image has only a few pixels*/ | ||
| if(gray_ok && !prof.alpha && prof.bits <= palettebits && !prof.white) {palette_ok = 0;} /*gray is less overhead*/ | ||
| palette_ok = n <= 256 && bits <= 8; | ||
| if(8 + n * 4 > numpixels / div) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/ | ||
| if(gray_ok && !alpha && bits <= palettebits && !stats->white) palette_ok = 0; /*gray is less overhead*/ | ||
|
|
||
| if(palette_ok) { | ||
| const unsigned char* p = stats->palette; | ||
|
|
@@ -2135,9 +2126,9 @@ static unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out, | |
| mode_out->colortype = LCT_PALETTE; | ||
| mode_out->bitdepth = palettebits; | ||
| } else /*8-bit or 16-bit per channel*/ { | ||
| mode_out->bitdepth = prof.bits; | ||
| mode_out->colortype = prof.alpha ? (prof.colored ? LCT_RGBA : LCT_GREY_ALPHA) | ||
| : (prof.colored ? LCT_RGB : LCT_GREY); | ||
| mode_out->bitdepth = bits; | ||
| mode_out->colortype = alpha ? (stats->colored ? LCT_RGBA : LCT_GREY_ALPHA) | ||
| : (stats->colored ? LCT_RGB : LCT_GREY); | ||
|
|
||
| if(stats->key) { | ||
| unsigned mask = (1u << mode_out->bitdepth) - 1u; /*stats always uses 16-bit, mask converts it*/ | ||
|
|
@@ -3287,47 +3278,53 @@ static void filterScanline(unsigned char* out, const unsigned char* scanline, co | |
| size_t i; | ||
| switch(filterType) { | ||
| case 0: /*None*/ | ||
| for(i = 0; i != length; ++i) out[i] = scanline[i]; | ||
| memcpy(out, scanline, length); | ||
| break; | ||
| case 1: /*Sub*/ | ||
| for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; | ||
| for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - scanline[i - bytewidth]; | ||
| case 1: { /*Sub*/ | ||
| size_t j = 0; | ||
| memcpy(out, scanline, bytewidth); | ||
| for(i = bytewidth; i != length; ++i, ++j) out[i] = scanline[i] - scanline[j]; | ||
| break; | ||
| } | ||
| case 2: /*Up*/ | ||
| if(prevline) { | ||
| for(i = 0; i != length; ++i) out[i] = scanline[i] - prevline[i]; | ||
| } else { | ||
| for(i = 0; i != length; ++i) out[i] = scanline[i]; | ||
| memcpy(out, scanline, length); | ||
| } | ||
| break; | ||
| case 3: /*Average*/ | ||
| case 3: { /*Average*/ | ||
| size_t j = 0; | ||
| if(prevline) { | ||
| for(i = 0; i != bytewidth; ++i) out[i] = scanline[i] - (prevline[i] >> 1); | ||
| for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) >> 1); | ||
| for(i = 0; i != bytewidth; ++i) out[i] = scanline[i] - (prevline[i] >> 1u); | ||
| for(i = bytewidth; i < length; ++i, ++j) out[i] = scanline[i] - ((scanline[j] + prevline[i]) >> 1u); | ||
| } else { | ||
| for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; | ||
| for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - (scanline[i - bytewidth] >> 1); | ||
| memcpy(out, scanline, bytewidth); | ||
| for(i = bytewidth; i < length; ++i, ++j) out[i] = scanline[i] - (scanline[j] >> 1u); | ||
| } | ||
| break; | ||
| case 4: /*Paeth*/ | ||
| } | ||
| case 4: { /*Paeth*/ | ||
| size_t j = 0; | ||
| if(prevline) { | ||
| /*paethPredictor(0, prevline[i], 0) is always prevline[i]*/ | ||
| for(i = 0; i != bytewidth; ++i) out[i] = (scanline[i] - prevline[i]); | ||
| for(i = bytewidth; i < length; ++i) { | ||
| out[i] = (scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth])); | ||
| for(i = 0; i != bytewidth; ++i) out[i] = scanline[i] - prevline[i]; | ||
| for(i = bytewidth; i != length; ++i, ++j) { | ||
| out[i] = scanline[i] - paethPredictor(scanline[j], prevline[i], prevline[j]); | ||
| } | ||
| } else { | ||
| for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; | ||
| memcpy(out, scanline, bytewidth); | ||
| /*paethPredictor(scanline[i - bytewidth], 0, 0) is always scanline[i - bytewidth]*/ | ||
| for(i = bytewidth; i < length; ++i) out[i] = (scanline[i] - scanline[i - bytewidth]); | ||
| for(i = bytewidth; i != length; ++i, ++j) out[i] = scanline[i] - scanline[j]; | ||
| } | ||
| break; | ||
| } | ||
| default: return; /*invalid filter type given*/ | ||
| } | ||
| } | ||
|
|
||
| static void filterScanline2(unsigned char* scanline, const unsigned char* prevline, | ||
| size_t length, unsigned char filterType, unsigned char forReal) { | ||
| size_t length, unsigned char filterType) { | ||
| if (!filterType) { | ||
| for(int i = 0; i < length; i+=4) { | ||
| if (!scanline[i + 3]) { | ||
|
|
@@ -3389,8 +3386,8 @@ static void filterScanline2(unsigned char* scanline, const unsigned char* prevli | |
| } | ||
| } | ||
| } | ||
| } else if(filterType == 4 && forReal) { | ||
| if(!prevline) { | ||
| } else if(filterType == 4) { /*forReal var is always zero, so the code is commented out for now*/ | ||
| /*if(!prevline) { | ||
| if(!scanline[3]) { | ||
| *(unsigned*)scanline = 0; | ||
| } | ||
|
|
@@ -3414,7 +3411,7 @@ static void filterScanline2(unsigned char* scanline, const unsigned char* prevli | |
| scanline[i + 2] = paethPredictor(scanline[i - 2], prevline[i], prevline[i - 2]); | ||
| } | ||
| } | ||
| } | ||
| }*/ | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -3548,7 +3545,7 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, | |
| memcpy(rem, &in2[y * linebytes], linebytes * clean); | ||
| for(type = 0; type != 5; ++type) { | ||
| if(clean) { | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, type, 0); | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, type); | ||
| filterScanline(attempt[type], &in2[y * linebytes], prevline, linebytes, bytewidth, type); | ||
| } else { | ||
| filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); | ||
|
|
@@ -3583,7 +3580,7 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, | |
| out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ | ||
| for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; | ||
| if(clean) { | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, bestType, 0); | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, bestType); | ||
| prevline = &in2[y * linebytes]; | ||
| } else { | ||
| prevline = &in[y * linebytes]; | ||
|
|
@@ -3642,7 +3639,7 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, | |
| { | ||
| if(clean) { | ||
| memcpy(linebuf, &in[y * linebytes], linebytes); | ||
| filterScanline2(linebuf, prevline2, linebytes, type, 0); | ||
| filterScanline2(linebuf, prevline2, linebytes, type); | ||
| filterScanline(attempt[type], linebuf, prevline2, linebytes, bytewidth, type); | ||
| } else { | ||
| filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); | ||
|
|
@@ -3670,7 +3667,7 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, | |
|
|
||
| if(clean) { | ||
| memcpy(linebuf, &in[y * linebytes], linebytes); | ||
| filterScanline2(linebuf, prevline2, linebytes, bestType, 0); | ||
| filterScanline2(linebuf, prevline2, linebytes, bestType); | ||
| filterScanline(attempt[bestType], linebuf, prevline2, linebytes, bytewidth, bestType); | ||
| } else { | ||
| filterScanline(attempt[bestType], &in[y * linebytes], prevline, linebytes, bytewidth, bestType); | ||
|
|
@@ -3688,7 +3685,7 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, | |
| prevline = &in[y * linebytes]; | ||
| if(clean) { | ||
| memcpy(linebuf, &in[y * linebytes], linebytes); | ||
| filterScanline2(linebuf, prevline2, linebytes, bestType, 0); | ||
| filterScanline2(linebuf, prevline2, linebytes, bestType); | ||
| memcpy(prevlinebuf, linebuf, linebytes); | ||
| prevline2 = prevlinebuf; | ||
| } | ||
|
|
@@ -3723,7 +3720,7 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, | |
| for(type = 0; type != 5; ++type) { | ||
| size_t sum = 0; | ||
| if(clean) { | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, type, 0); | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, type); | ||
| filterScanline(attempt[type], &in2[y * linebytes], prevline, linebytes, bytewidth, type); | ||
| } else { | ||
| filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); | ||
|
|
@@ -3756,7 +3753,7 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, | |
| out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ | ||
| for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; | ||
| if(clean) { | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, bestType, 0); | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, bestType); | ||
| prevline = &in2[y * linebytes]; | ||
| } else { | ||
| prevline = &in[y * linebytes]; | ||
|
|
@@ -3783,7 +3780,7 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, | |
| for(type = 0; type != 5; ++type) { | ||
| size_t sum = 0; | ||
| if(clean) { | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, type, 0); | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, type); | ||
| filterScanline(attempt[type], &in2[y * linebytes], prevline, linebytes, bytewidth, type); | ||
| } else { | ||
| filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); | ||
|
|
@@ -3808,7 +3805,7 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, | |
| out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ | ||
| for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; | ||
| if(clean) { | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, bestType, 0); | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, bestType); | ||
| prevline = &in2[y * linebytes]; | ||
| } else { | ||
| prevline = &in[y * linebytes]; | ||
|
|
@@ -3834,7 +3831,7 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, | |
| for(type = 0; type != 5; ++type) { | ||
| size_t sum = 0; | ||
| if(clean) { | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, type, 0); | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, type); | ||
| filterScanline(attempt[type], &in2[y * linebytes], prevline, linebytes, bytewidth, type); | ||
| } else { | ||
| filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); | ||
|
|
@@ -3859,7 +3856,7 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, | |
| out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ | ||
| for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; | ||
| if(clean) { | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, bestType, 0); | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, bestType); | ||
| prevline = &in2[y * linebytes]; | ||
| } else { | ||
| prevline = &in[y * linebytes]; | ||
|
|
@@ -3883,7 +3880,7 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, | |
| /*try the 5 filter types*/ | ||
| for(type = 0; type != 5; ++type) { | ||
| if(clean) { | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, type, 0); | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, type); | ||
| filterScanline(attempt[type], &in2[y * linebytes], prevline, linebytes, bytewidth, type); | ||
| } else { | ||
| filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); | ||
|
|
@@ -3910,7 +3907,7 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, | |
| out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ | ||
| for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; | ||
| if(clean) { | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, bestType, 0); | ||
| filterScanline2(&in2[y * linebytes], prevline, linebytes, bestType); | ||
| prevline = &in2[y * linebytes]; | ||
| } else { | ||
| prevline = &in[y * linebytes]; | ||
|
|
@@ -3981,7 +3978,7 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, | |
| out[y * (linebytes + 1)] = type; | ||
| if(clean) { | ||
| memcpy(linebuf, &in[y * linebytes], linebytes); | ||
| filterScanline2(linebuf, prevline, linebytes, type, 0); | ||
| filterScanline2(linebuf, prevline, linebytes, type); | ||
| filterScanline(&out[y * (linebytes + 1) + 1], linebuf, prevline, linebytes, bytewidth, type); | ||
| memcpy(prevlinebuf, linebuf, linebytes); | ||
| prevline = prevlinebuf; | ||
|
|
@@ -4074,7 +4071,7 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, | |
| out[y * (linebytes + 1)] = type; | ||
| if(clean) { | ||
| memcpy(linebuf, &in[y * linebytes], linebytes); | ||
| filterScanline2(linebuf, prevline, linebytes, type, 0); | ||
| filterScanline2(linebuf, prevline, linebytes, type); | ||
| filterScanline(&out[y * (linebytes + 1) + 1], linebuf, prevline, linebytes, bytewidth, type); | ||
| memcpy(prevlinebuf, linebuf, linebytes); | ||
| prevline = prevlinebuf; | ||
|
|
@@ -4104,7 +4101,7 @@ static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, | |
| out[y * (linebytes + 1)] = type; | ||
| if(clean) { | ||
| memcpy(linebuf, &in[y * linebytes], linebytes); | ||
| filterScanline2(linebuf, prevline, linebytes, type, 0); | ||
| filterScanline2(linebuf, prevline, linebytes, type); | ||
| filterScanline(&out[y * (linebytes + 1) + 1], linebuf, prevline, linebytes, bytewidth, type); | ||
| memcpy(prevlinebuf, linebuf, linebytes); | ||
| prevline = prevlinebuf; | ||
|
|
@@ -4292,6 +4289,7 @@ static unsigned lodepng_encode(unsigned char** out, size_t* outsize, | |
| LodePNGState* state, LodePNGPaletteSettings palset) { | ||
| unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/ | ||
| size_t datasize = 0; | ||
| size_t numpixels = (size_t)w * (size_t)h; | ||
| ucvector outv = ucvector_init(0, 0); | ||
| LodePNGInfo info; | ||
| const LodePNGInfo* info_png = &state->info_png; | ||
|
|
@@ -4324,7 +4322,19 @@ static unsigned lodepng_encode(unsigned char** out, size_t* outsize, | |
| /* color convert and compute scanline filter types */ | ||
| lodepng_info_copy(&info, &state->info_png); | ||
| if(state->encoder.auto_convert) { | ||
| state->error = lodepng_auto_choose_color(&info.color, image, w, h, &state->info_raw, state->div); | ||
| LodePNGColorStats stats; | ||
| lodepng_color_stats_init(&stats); | ||
|
|
||
| state->error = lodepng_compute_color_stats(&stats, image, numpixels, &state->info_raw); | ||
| if(state->error) goto cleanup; | ||
| else { /*check if image is white only if no error is detected in previous function*/ | ||
| unsigned char r = 0, g = 0, b = 0, a = 0; | ||
| getPixelColorRGBA8(&r, &g, &b, &a, image, 0, &state->info_raw); | ||
| stats.white = stats.numcolors == 1 && stats.colored == 0 && r == 255 && w > 20 && h > 20 | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does this get moved?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This reduces the number of variables passed to lodepng_compute_color_stats by one, this change also gets around calculating numpixels twice |
||
| && ((w > 225 && h > 225) || numpixels > 75000 || (w > 250 && numpixels > 40000)); | ||
| } | ||
|
|
||
| state->error = lodepng_auto_choose_color(&info.color, &state->info_raw, &stats, numpixels, state->div); | ||
| if(state->error) goto cleanup; | ||
| if(info.color.colortype == LCT_PALETTE && palset.order != LPOS_NONE) { | ||
| if (palset._first & 1) { | ||
|
|
@@ -4351,7 +4361,7 @@ static unsigned lodepng_encode(unsigned char** out, size_t* outsize, | |
| } | ||
| if(!lodepng_color_mode_equal(&state->info_raw, &info.color)) { | ||
| unsigned char* converted; | ||
| size_t size = ((size_t)w * (size_t)h * (size_t)lodepng_get_bpp(&info.color) + 7u) / 8u; | ||
| size_t size = (numpixels * (size_t)lodepng_get_bpp(&info.color) + 7u) / 8u; | ||
|
|
||
| converted = (unsigned char*)lodepng_malloc(size); | ||
| if(!converted && size) state->error = 83; /*alloc fail*/ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since bytewidth will be at most 8, memcpy shouldn't make a difference here