diff --git a/doc/webp-lossless-bitstream-spec.txt b/doc/webp-lossless-bitstream-spec.txt index 1f934c4b..e732887d 100644 --- a/doc/webp-lossless-bitstream-spec.txt +++ b/doc/webp-lossless-bitstream-spec.txt @@ -888,6 +888,9 @@ if (num_symbols == 2) { } ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The two symbols should be different. Duplicate symbols are allowed, but +inefficient. + **Note:** Another special case is when _all_ prefix code lengths are _zeros_ (an empty prefix code). For example, a prefix code for distance can be empty if there are no backward references. Similarly, prefix codes for alpha, red, and diff --git a/examples/cwebp.c b/examples/cwebp.c index 835579d9..cab70054 100644 --- a/examples/cwebp.c +++ b/examples/cwebp.c @@ -306,6 +306,7 @@ static int MyWriter(const uint8_t* data, size_t data_size, // Dumps a picture as a PGM file using the IMC4 layout. static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) { int y; + int ok = 0; const int uv_width = (picture->width + 1) / 2; const int uv_height = (picture->height + 1) / 2; const int stride = (picture->width + 1) & ~1; @@ -320,23 +321,26 @@ static int DumpPicture(const WebPPicture* const picture, const char* PGM_name) { if (f == NULL) return 0; fprintf(f, "P5\n%d %d\n255\n", stride, height); for (y = 0; y < picture->height; ++y) { - if (fwrite(src_y, picture->width, 1, f) != 1) return 0; + if (fwrite(src_y, picture->width, 1, f) != 1) goto Error; if (picture->width & 1) fputc(0, f); // pad src_y += picture->y_stride; } for (y = 0; y < uv_height; ++y) { - if (fwrite(src_u, uv_width, 1, f) != 1) return 0; - if (fwrite(src_v, uv_width, 1, f) != 1) return 0; + if (fwrite(src_u, uv_width, 1, f) != 1) goto Error; + if (fwrite(src_v, uv_width, 1, f) != 1) goto Error; src_u += picture->uv_stride; src_v += picture->uv_stride; } for (y = 0; y < alpha_height; ++y) { - if (fwrite(src_a, picture->width, 1, f) != 1) return 0; + if (fwrite(src_a, picture->width, 1, f) != 1) goto Error; if (picture->width & 1) fputc(0, f); // pad src_a += picture->a_stride; } + ok = 1; + + Error: fclose(f); - return 1; + return ok; } // ----------------------------------------------------------------------------- diff --git a/examples/webpinfo.c b/examples/webpinfo.c index 356abae5..1d2278ee 100644 --- a/examples/webpinfo.c +++ b/examples/webpinfo.c @@ -357,12 +357,12 @@ static WebPInfoStatus ParseLossyHeader(const ChunkData* const chunk_data, } data += 3; data_size -= 3; - printf(" Key frame: %s\n" - " Profile: %d\n" - " Display: %s\n" - " Part. 0 length: %d\n", - key_frame ? "Yes" : "No", profile, - display ? "Yes" : "No", partition0_length); + printf( + " Key frame: %s\n" + " Profile: %d\n" + " Display: Yes\n" + " Part. 0 length: %d\n", + key_frame ? "Yes" : "No", profile, partition0_length); if (key_frame) { if (!(data[0] == 0x9d && data[1] == 0x01 && data[2] == 0x2a)) { LOG_ERROR("Invalid lossy bitstream signature."); diff --git a/imageio/image_enc.c b/imageio/image_enc.c index e06bcaf5..d58477f3 100644 --- a/imageio/image_enc.c +++ b/imageio/image_enc.c @@ -260,14 +260,20 @@ int WebPWritePAM(FILE* fout, const WebPDecBuffer* const buffer) { // Save 16b mode (RGBA4444, RGB565, ...) for debugging purpose. int WebPWrite16bAsPGM(FILE* fout, const WebPDecBuffer* const buffer) { - const uint32_t width = buffer->width; - const uint32_t height = buffer->height; - const uint8_t* rgba = buffer->u.RGBA.rgba; - const int stride = buffer->u.RGBA.stride; + uint32_t width, height; + uint8_t* rgba; + int stride; const uint32_t bytes_per_px = 2; uint32_t y; - if (fout == NULL || buffer == NULL || rgba == NULL) return 0; + if (fout == NULL || buffer == NULL) return 0; + + width = buffer->width; + height = buffer->height; + rgba = buffer->u.RGBA.rgba; + stride = buffer->u.RGBA.stride; + + if (rgba == NULL) return 0; fprintf(fout, "P5\n%u %u\n255\n", width * bytes_per_px, height); for (y = 0; y < height; ++y) { @@ -295,22 +301,29 @@ static void PutLE32(uint8_t* const dst, uint32_t value) { #define BMP_HEADER_SIZE 54 #define BMP_HEADER_ALPHA_EXTRA_SIZE 16 // for alpha info int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) { - const int has_alpha = WebPIsAlphaMode(buffer->colorspace); - const int header_size = - BMP_HEADER_SIZE + (has_alpha ? BMP_HEADER_ALPHA_EXTRA_SIZE : 0); - const uint32_t width = buffer->width; - const uint32_t height = buffer->height; - const uint8_t* rgba = buffer->u.RGBA.rgba; - const int stride = buffer->u.RGBA.stride; - const uint32_t bytes_per_px = has_alpha ? 4 : 3; + int has_alpha, header_size; + uint32_t width, height; + uint8_t* rgba; + int stride; uint32_t y; - const uint32_t line_size = bytes_per_px * width; - const uint32_t bmp_stride = (line_size + 3) & ~3; // pad to 4 - const uint32_t image_size = bmp_stride * height; - const uint32_t total_size = image_size + header_size; + uint32_t bytes_per_px, line_size, image_size, bmp_stride, total_size; uint8_t bmp_header[BMP_HEADER_SIZE + BMP_HEADER_ALPHA_EXTRA_SIZE] = { 0 }; - if (fout == NULL || buffer == NULL || rgba == NULL) return 0; + if (fout == NULL || buffer == NULL) return 0; + + has_alpha = WebPIsAlphaMode(buffer->colorspace); + header_size = BMP_HEADER_SIZE + (has_alpha ? BMP_HEADER_ALPHA_EXTRA_SIZE : 0); + width = buffer->width; + height = buffer->height; + rgba = buffer->u.RGBA.rgba; + stride = buffer->u.RGBA.stride; + bytes_per_px = has_alpha ? 4 : 3; + line_size = bytes_per_px * width; + bmp_stride = (line_size + 3) & ~3; // pad to 4 + image_size = bmp_stride * height; + total_size = image_size + header_size; + + if (rgba == NULL) return 0; // bitmap file header PutLE16(bmp_header + 0, 0x4d42); // signature 'BM' @@ -372,17 +385,14 @@ int WebPWriteBMP(FILE* fout, const WebPDecBuffer* const buffer) { #define TIFF_HEADER_SIZE (EXTRA_DATA_OFFSET + EXTRA_DATA_SIZE) int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) { - const int has_alpha = WebPIsAlphaMode(buffer->colorspace); - const uint32_t width = buffer->width; - const uint32_t height = buffer->height; - const uint8_t* rgba = buffer->u.RGBA.rgba; - const int stride = buffer->u.RGBA.stride; - const uint8_t bytes_per_px = has_alpha ? 4 : 3; - const uint8_t assoc_alpha = - WebPIsPremultipliedMode(buffer->colorspace) ? 1 : 2; + int has_alpha; + uint32_t width, height; + uint8_t* rgba; + int stride; + uint8_t bytes_per_px = 0; + const uint8_t assoc_alpha = 0; // For non-alpha case, we omit tag 0x152 (ExtraSamples). - const uint8_t num_ifd_entries = has_alpha ? NUM_IFD_ENTRIES - : NUM_IFD_ENTRIES - 1; + const uint8_t num_ifd_entries = 0; uint8_t tiff_header[TIFF_HEADER_SIZE] = { 0x49, 0x49, 0x2a, 0x00, // little endian signature 8, 0, 0, 0, // offset to the unique IFD that follows @@ -416,7 +426,20 @@ int WebPWriteTIFF(FILE* fout, const WebPDecBuffer* const buffer) { }; uint32_t y; - if (fout == NULL || buffer == NULL || rgba == NULL) return 0; + if (fout == NULL || buffer == NULL) return 0; + + has_alpha = WebPIsAlphaMode(buffer->colorspace); + width = buffer->width; + height = buffer->height; + rgba = buffer->u.RGBA.rgba; + stride = buffer->u.RGBA.stride; + + if (rgba == NULL) return 0; + + // Update bytes_per_px, num_ifd_entries and assoc_alpha. + tiff_header[38] = tiff_header[102] = bytes_per_px = has_alpha ? 4 : 3; + tiff_header[8] = has_alpha ? NUM_IFD_ENTRIES : NUM_IFD_ENTRIES - 1; + tiff_header[186] = WebPIsPremultipliedMode(buffer->colorspace) ? 1 : 2; // Fill placeholders in IFD: PutLE32(tiff_header + 10 + 8, width); diff --git a/src/dec/buffer_dec.c b/src/dec/buffer_dec.c index 4786cf0d..11ce76f1 100644 --- a/src/dec/buffer_dec.c +++ b/src/dec/buffer_dec.c @@ -75,7 +75,7 @@ static VP8StatusCode CheckDecBuffer(const WebPDecBuffer* const buffer) { const WebPRGBABuffer* const buf = &buffer->u.RGBA; const int stride = abs(buf->stride); const uint64_t size = - MIN_BUFFER_SIZE(width * kModeBpp[mode], height, stride); + MIN_BUFFER_SIZE((uint64_t)width * kModeBpp[mode], height, stride); ok &= (size <= buf->size); ok &= (stride >= width * kModeBpp[mode]); ok &= (buf->rgba != NULL); diff --git a/src/dsp/quant.h b/src/dsp/quant.h index bf7734cb..dcbc11c7 100644 --- a/src/dsp/quant.h +++ b/src/dsp/quant.h @@ -36,8 +36,9 @@ static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks, int thresh) { const int16x8_t tst_ones = vdupq_n_s16(-1); uint32x4_t sum = vdupq_n_u32(0); + int i; - for (int i = 0; i < num_blocks; ++i) { + for (i = 0; i < num_blocks; ++i) { // Set DC to zero. const int16x8_t a_0 = vsetq_lane_s16(0, vld1q_s16(levels), 0); const int16x8_t a_1 = vld1q_s16(levels + 8); diff --git a/src/enc/alpha_enc.c b/src/enc/alpha_enc.c index 26f00348..4a599f88 100644 --- a/src/enc/alpha_enc.c +++ b/src/enc/alpha_enc.c @@ -55,7 +55,7 @@ static int EncodeLossless(const uint8_t* const data, int width, int height, WebPConfig config; WebPPicture picture; - WebPPictureInit(&picture); + if (!WebPPictureInit(&picture)) return 0; picture.width = width; picture.height = height; picture.use_argb = 1; diff --git a/src/enc/frame_enc.c b/src/enc/frame_enc.c index 9a98dc1f..01860ca7 100644 --- a/src/enc/frame_enc.c +++ b/src/enc/frame_enc.c @@ -578,7 +578,7 @@ static uint64_t OneStatPass(VP8Encoder* const enc, VP8RDLevel rd_opt, uint64_t size = 0; uint64_t size_p0 = 0; uint64_t distortion = 0; - const uint64_t pixel_count = nb_mbs * 384; + const uint64_t pixel_count = (uint64_t)nb_mbs * 384; VP8IteratorInit(enc, &it); SetLoopParams(enc, s->q); @@ -789,7 +789,7 @@ int VP8EncTokenLoop(VP8Encoder* const enc) { VP8EncIterator it; VP8EncProba* const proba = &enc->proba_; const VP8RDLevel rd_opt = enc->rd_opt_level_; - const uint64_t pixel_count = enc->mb_w_ * enc->mb_h_ * 384; + const uint64_t pixel_count = (uint64_t)enc->mb_w_ * enc->mb_h_ * 384; PassStats stats; int ok; diff --git a/src/enc/histogram_enc.c b/src/enc/histogram_enc.c index 9e1d18f1..3ca67b3a 100644 --- a/src/enc/histogram_enc.c +++ b/src/enc/histogram_enc.c @@ -1181,7 +1181,7 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize, const int entropy_combine_num_bins = low_effort ? NUM_PARTITIONS : BIN_SIZE; int entropy_combine; uint16_t* const map_tmp = - WebPSafeMalloc(2 * image_histo_raw_size, sizeof(map_tmp)); + WebPSafeMalloc(2 * image_histo_raw_size, sizeof(*map_tmp)); uint16_t* const cluster_mappings = map_tmp + image_histo_raw_size; int num_used = image_histo_raw_size; if (orig_histo == NULL || map_tmp == NULL) { diff --git a/src/enc/vp8l_enc.c b/src/enc/vp8l_enc.c index ee684cbe..f64ceb70 100644 --- a/src/enc/vp8l_enc.c +++ b/src/enc/vp8l_enc.c @@ -1192,7 +1192,7 @@ static void ClearTransformBuffer(VP8LEncoder* const enc) { // enc->use_predict_, enc->use_cross_color_ static int AllocateTransformBuffer(VP8LEncoder* const enc, int width, int height) { - const uint64_t image_size = width * height; + const uint64_t image_size = (uint64_t)width * height; // VP8LResidualImage needs room for 2 scanlines of uint32 pixels with an extra // pixel in each, plus 2 regular scanlines of bytes. // TODO(skal): Clean up by using arithmetic in bytes instead of words. @@ -1202,7 +1202,7 @@ static int AllocateTransformBuffer(VP8LEncoder* const enc, int width, : 0; const uint64_t transform_data_size = (enc->use_predict_ || enc->use_cross_color_) - ? VP8LSubSampleSize(width, enc->transform_bits_) * + ? (uint64_t)VP8LSubSampleSize(width, enc->transform_bits_) * VP8LSubSampleSize(height, enc->transform_bits_) : 0; const uint64_t max_alignment_in_words = diff --git a/src/mux/anim_encode.c b/src/mux/anim_encode.c index 7078d9ae..d1c61a2f 100644 --- a/src/mux/anim_encode.c +++ b/src/mux/anim_encode.c @@ -593,16 +593,17 @@ int WebPAnimEncoderRefineRect( int is_lossless, float quality, int* const x_offset, int* const y_offset, int* const width, int* const height) { FrameRectangle rect; - const int right = clip(*x_offset + *width, 0, curr_canvas->width); - const int left = clip(*x_offset, 0, curr_canvas->width - 1); - const int bottom = clip(*y_offset + *height, 0, curr_canvas->height); - const int top = clip(*y_offset, 0, curr_canvas->height - 1); + int right, left, bottom, top; if (prev_canvas == NULL || curr_canvas == NULL || prev_canvas->width != curr_canvas->width || prev_canvas->height != curr_canvas->height || !prev_canvas->use_argb || !curr_canvas->use_argb) { return 0; } + right = clip(*x_offset + *width, 0, curr_canvas->width); + left = clip(*x_offset, 0, curr_canvas->width - 1); + bottom = clip(*y_offset + *height, 0, curr_canvas->height); + top = clip(*y_offset, 0, curr_canvas->height - 1); rect.x_offset_ = left; rect.y_offset_ = top; rect.width_ = clip(right - left, 0, curr_canvas->width - rect.x_offset_); diff --git a/src/mux/muxedit.c b/src/mux/muxedit.c index 63e71a0a..aab479cc 100644 --- a/src/mux/muxedit.c +++ b/src/mux/muxedit.c @@ -555,7 +555,8 @@ static WebPMuxError MuxCleanup(WebPMux* const mux) { if (num_frames == 1) { WebPMuxImage* frame = NULL; err = MuxImageGetNth((const WebPMuxImage**)&mux->images_, 1, &frame); - assert(err == WEBP_MUX_OK); // We know that one frame does exist. + if (err != WEBP_MUX_OK) return err; + // We know that one frame does exist. assert(frame != NULL); if (frame->header_ != NULL && ((mux->canvas_width_ == 0 && mux->canvas_height_ == 0) || diff --git a/src/utils/palette.c b/src/utils/palette.c index 1e357517..515da210 100644 --- a/src/utils/palette.c +++ b/src/utils/palette.c @@ -97,7 +97,7 @@ int GetColorPalette(const WebPPicture* const pic, uint32_t* const palette) { int x, y; int num_colors = 0; uint8_t in_use[COLOR_HASH_SIZE] = {0}; - uint32_t colors[COLOR_HASH_SIZE]; + uint32_t colors[COLOR_HASH_SIZE] = {0}; const uint32_t* argb = pic->argb; const int width = pic->width; const int height = pic->height;