Compare commits

..

6 Commits

Author SHA1 Message Date
9195ea0538 update ChangeLog
Bug: webp:541
Change-Id: I6cfb9da3a3944f66efa681cffec7f3e6a84c8800
2022-01-11 18:46:37 -08:00
4acae017bd update NEWS
Bug: webp:541
Change-Id: I529210f8ecaa8f2e9a6fae2518ba71f7fd56a701
2022-01-11 18:45:55 -08:00
883f063397 man/img2webp.1: update date
after:
a80954a1 Reword img2webp synopsis command line

Change-Id: I0a5c18f7947d15fcd66dc32fab9b525186f7fcc5
(cherry picked from commit 1b0c15db02)
2022-01-11 02:03:24 +00:00
567e1f442b Reword img2webp synopsis command line
See https://bugs.chromium.org/p/webp/issues/detail?id=549

Change-Id: I75562d2ad021d8ec107eb4ced5b28e0abf373324
(cherry picked from commit a80954a1d9)
2022-01-11 02:02:57 +00:00
f084244d9f anim_decode: fix alpha blending with big-endian
images are decoded in RGBA/BGRA, but represented as uint32_t during the
blend process; this fixes the channel extraction

Bug: webp:548
Change-Id: Ie74aa43d8f87d3552d5afc0abba466335f5d1617
(cherry picked from commit e4886716d3)
2021-12-23 14:49:14 +00:00
b217b4fff7 webpinfo: fix fourcc comparison w/big-endian
store the recognized fourccs in little-endian order to match how the
fourcc is being read from the file

Bug: webp:548
Change-Id: I9de77db92208709d5e711846908a51e563102fa5
(cherry picked from commit e3cb052ca5)
2021-12-23 14:48:19 +00:00
7 changed files with 53 additions and 35 deletions

View File

@ -1,3 +1,8 @@
883f0633 man/img2webp.1: update date
567e1f44 Reword img2webp synopsis command line
f084244d anim_decode: fix alpha blending with big-endian
b217b4ff webpinfo: fix fourcc comparison w/big-endian
f035d2e4 update ChangeLog (tag: v1.2.2-rc1)
7031946a update NEWS 7031946a update NEWS
973390b6 bump version to 1.2.2 973390b6 bump version to 1.2.2
abd6664f update AUTHORS abd6664f update AUTHORS

4
NEWS
View File

@ -1,10 +1,10 @@
- 12/15/2021: version 1.2.2 - 1/11/2022: version 1.2.2
This is a binary compatible release. This is a binary compatible release.
* webpmux: add "-set bgcolor A,R,G,B" * webpmux: add "-set bgcolor A,R,G,B"
* add ARM64 NEON support for MSVC builds (#539) * add ARM64 NEON support for MSVC builds (#539)
* fix duplicate include error in Xcode when using multiple XCFrameworks in a * fix duplicate include error in Xcode when using multiple XCFrameworks in a
project (#542) project (#542)
* doc updates and bug fixes (#538, #544) * doc updates and bug fixes (#538, #544, #548, #550)
- 7/20/2021: version 1.2.1 - 7/20/2021: version 1.2.1
This is a binary compatible release. This is a binary compatible release.

2
README
View File

@ -456,7 +456,7 @@ modes, etc.
Usage: Usage:
img2webp [file-level options] [image files...] [per-frame options...] img2webp [file_options] [[frame_options] frame_file]...
File-level options (only used at the start of compression): File-level options (only used at the start of compression):
-min_size ............ minimize size -min_size ............ minimize size

View File

@ -35,8 +35,7 @@
static void Help(void) { static void Help(void) {
printf("Usage:\n\n"); printf("Usage:\n\n");
printf(" img2webp [file-level options] [image files...] " printf(" img2webp [file_options] [[frame_options] frame_file]...\n");
"[per-frame options...]\n");
printf("\n"); printf("\n");
printf("File-level options (only used at the start of compression):\n"); printf("File-level options (only used at the start of compression):\n");

View File

@ -125,16 +125,16 @@ static void WebPInfoInit(WebPInfo* const webp_info) {
memset(webp_info, 0, sizeof(*webp_info)); memset(webp_info, 0, sizeof(*webp_info));
} }
static const char kWebPChunkTags[CHUNK_TYPES][4] = { static const uint32_t kWebPChunkTags[CHUNK_TYPES] = {
{ 'V', 'P', '8', ' ' }, MKFOURCC('V', 'P', '8', ' '),
{ 'V', 'P', '8', 'L' }, MKFOURCC('V', 'P', '8', 'L'),
{ 'V', 'P', '8', 'X' }, MKFOURCC('V', 'P', '8', 'X'),
{ 'A', 'L', 'P', 'H' }, MKFOURCC('A', 'L', 'P', 'H'),
{ 'A', 'N', 'I', 'M' }, MKFOURCC('A', 'N', 'I', 'M'),
{ 'A', 'N', 'M', 'F' }, MKFOURCC('A', 'N', 'M', 'F'),
{ 'I', 'C', 'C', 'P' }, MKFOURCC('I', 'C', 'C', 'P'),
{ 'E', 'X', 'I', 'F' }, MKFOURCC('E', 'X', 'I', 'F'),
{ 'X', 'M', 'P', ' ' }, MKFOURCC('X', 'M', 'P', ' '),
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -644,7 +644,7 @@ static WebPInfoStatus ParseChunk(const WebPInfo* const webp_info,
return WEBP_INFO_TRUNCATED_DATA; return WEBP_INFO_TRUNCATED_DATA;
} }
for (i = 0; i < CHUNK_TYPES; ++i) { for (i = 0; i < CHUNK_TYPES; ++i) {
if (!memcmp(kWebPChunkTags[i], &fourcc, TAG_SIZE)) break; if (kWebPChunkTags[i] == fourcc) break;
} }
chunk_data->offset_ = chunk_start_offset; chunk_data->offset_ = chunk_start_offset;
chunk_data->size_ = chunk_size; chunk_data->size_ = chunk_size;
@ -939,7 +939,13 @@ static WebPInfoStatus ProcessChunk(const ChunkData* const chunk_data,
LOG_WARN(error_message); LOG_WARN(error_message);
} else { } else {
if (!webp_info->quiet_) { if (!webp_info->quiet_) {
const char* tag = kWebPChunkTags[chunk_data->id_]; char tag[4];
uint32_t fourcc = kWebPChunkTags[chunk_data->id_];
#ifdef WORDS_BIGENDIAN
fourcc = (fourcc >> 24) | ((fourcc >> 8) & 0xff00) |
((fourcc << 8) & 0xff0000) | (fourcc << 24);
#endif
memcpy(tag, &fourcc, sizeof(tag));
printf("Chunk %c%c%c%c at offset %6d, length %6d\n", printf("Chunk %c%c%c%c at offset %6d, length %6d\n",
tag[0], tag[1], tag[2], tag[3], (int)chunk_data->offset_, tag[0], tag[1], tag[2], tag[3], (int)chunk_data->offset_,
(int)chunk_data->size_); (int)chunk_data->size_);

View File

@ -1,10 +1,10 @@
.\" Hey, EMACS: -*- nroff -*- .\" Hey, EMACS: -*- nroff -*-
.TH IMG2WEBP 1 "November 17, 2021" .TH IMG2WEBP 1 "January 5, 2022"
.SH NAME .SH NAME
img2webp \- create animated WebP file from a sequence of input images. img2webp \- create animated WebP file from a sequence of input images.
.SH SYNOPSIS .SH SYNOPSIS
.B img2webp .B img2webp
[file_level_options] [files] [per_frame_options...] [file_options] [[frame_options] frame_file]...
.br .br
.B img2webp argument_file_name .B img2webp argument_file_name
.br .br

View File

@ -23,6 +23,14 @@
#define NUM_CHANNELS 4 #define NUM_CHANNELS 4
// Channel extraction from a uint32_t representation of a uint8_t RGBA/BGRA
// buffer.
#ifdef WORDS_BIGENDIAN
#define CHANNEL_SHIFT(i) (24 - (i) * 8)
#else
#define CHANNEL_SHIFT(i) ((i) * 8)
#endif
typedef void (*BlendRowFunc)(uint32_t* const, const uint32_t* const, int); typedef void (*BlendRowFunc)(uint32_t* const, const uint32_t* const, int);
static void BlendPixelRowNonPremult(uint32_t* const src, static void BlendPixelRowNonPremult(uint32_t* const src,
const uint32_t* const dst, int num_pixels); const uint32_t* const dst, int num_pixels);
@ -209,35 +217,35 @@ static uint8_t BlendChannelNonPremult(uint32_t src, uint8_t src_a,
const uint8_t dst_channel = (dst >> shift) & 0xff; const uint8_t dst_channel = (dst >> shift) & 0xff;
const uint32_t blend_unscaled = src_channel * src_a + dst_channel * dst_a; const uint32_t blend_unscaled = src_channel * src_a + dst_channel * dst_a;
assert(blend_unscaled < (1ULL << 32) / scale); assert(blend_unscaled < (1ULL << 32) / scale);
return (blend_unscaled * scale) >> 24; return (blend_unscaled * scale) >> CHANNEL_SHIFT(3);
} }
// Blend 'src' over 'dst' assuming they are NOT pre-multiplied by alpha. // Blend 'src' over 'dst' assuming they are NOT pre-multiplied by alpha.
static uint32_t BlendPixelNonPremult(uint32_t src, uint32_t dst) { static uint32_t BlendPixelNonPremult(uint32_t src, uint32_t dst) {
const uint8_t src_a = (src >> 24) & 0xff; const uint8_t src_a = (src >> CHANNEL_SHIFT(3)) & 0xff;
if (src_a == 0) { if (src_a == 0) {
return dst; return dst;
} else { } else {
const uint8_t dst_a = (dst >> 24) & 0xff; const uint8_t dst_a = (dst >> CHANNEL_SHIFT(3)) & 0xff;
// This is the approximate integer arithmetic for the actual formula: // This is the approximate integer arithmetic for the actual formula:
// dst_factor_a = (dst_a * (255 - src_a)) / 255. // dst_factor_a = (dst_a * (255 - src_a)) / 255.
const uint8_t dst_factor_a = (dst_a * (256 - src_a)) >> 8; const uint8_t dst_factor_a = (dst_a * (256 - src_a)) >> 8;
const uint8_t blend_a = src_a + dst_factor_a; const uint8_t blend_a = src_a + dst_factor_a;
const uint32_t scale = (1UL << 24) / blend_a; const uint32_t scale = (1UL << 24) / blend_a;
const uint8_t blend_r = const uint8_t blend_r = BlendChannelNonPremult(
BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 0); src, src_a, dst, dst_factor_a, scale, CHANNEL_SHIFT(0));
const uint8_t blend_g = const uint8_t blend_g = BlendChannelNonPremult(
BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 8); src, src_a, dst, dst_factor_a, scale, CHANNEL_SHIFT(1));
const uint8_t blend_b = const uint8_t blend_b = BlendChannelNonPremult(
BlendChannelNonPremult(src, src_a, dst, dst_factor_a, scale, 16); src, src_a, dst, dst_factor_a, scale, CHANNEL_SHIFT(2));
assert(src_a + dst_factor_a < 256); assert(src_a + dst_factor_a < 256);
return (blend_r << 0) | return ((uint32_t)blend_r << CHANNEL_SHIFT(0)) |
(blend_g << 8) | ((uint32_t)blend_g << CHANNEL_SHIFT(1)) |
(blend_b << 16) | ((uint32_t)blend_b << CHANNEL_SHIFT(2)) |
((uint32_t)blend_a << 24); ((uint32_t)blend_a << CHANNEL_SHIFT(3));
} }
} }
@ -247,7 +255,7 @@ static void BlendPixelRowNonPremult(uint32_t* const src,
const uint32_t* const dst, int num_pixels) { const uint32_t* const dst, int num_pixels) {
int i; int i;
for (i = 0; i < num_pixels; ++i) { for (i = 0; i < num_pixels; ++i) {
const uint8_t src_alpha = (src[i] >> 24) & 0xff; const uint8_t src_alpha = (src[i] >> CHANNEL_SHIFT(3)) & 0xff;
if (src_alpha != 0xff) { if (src_alpha != 0xff) {
src[i] = BlendPixelNonPremult(src[i], dst[i]); src[i] = BlendPixelNonPremult(src[i], dst[i]);
} }
@ -264,7 +272,7 @@ static WEBP_INLINE uint32_t ChannelwiseMultiply(uint32_t pix, uint32_t scale) {
// Blend 'src' over 'dst' assuming they are pre-multiplied by alpha. // Blend 'src' over 'dst' assuming they are pre-multiplied by alpha.
static uint32_t BlendPixelPremult(uint32_t src, uint32_t dst) { static uint32_t BlendPixelPremult(uint32_t src, uint32_t dst) {
const uint8_t src_a = (src >> 24) & 0xff; const uint8_t src_a = (src >> CHANNEL_SHIFT(3)) & 0xff;
return src + ChannelwiseMultiply(dst, 256 - src_a); return src + ChannelwiseMultiply(dst, 256 - src_a);
} }
@ -274,7 +282,7 @@ static void BlendPixelRowPremult(uint32_t* const src, const uint32_t* const dst,
int num_pixels) { int num_pixels) {
int i; int i;
for (i = 0; i < num_pixels; ++i) { for (i = 0; i < num_pixels; ++i) {
const uint8_t src_alpha = (src[i] >> 24) & 0xff; const uint8_t src_alpha = (src[i] >> CHANNEL_SHIFT(3)) & 0xff;
if (src_alpha != 0xff) { if (src_alpha != 0xff) {
src[i] = BlendPixelPremult(src[i], dst[i]); src[i] = BlendPixelPremult(src[i], dst[i]);
} }