mirror of
https://github.com/webmproject/libwebp.git
synced 2025-07-19 07:20:02 +02:00
Compare commits
6 Commits
v1.2.2-rc1
...
v1.2.2-rc2
Author | SHA1 | Date | |
---|---|---|---|
9195ea0538 | |||
4acae017bd | |||
883f063397 | |||
567e1f442b | |||
f084244d9f | |||
b217b4fff7 |
@ -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
4
NEWS
@ -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
2
README
@ -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
|
||||||
|
@ -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");
|
||||||
|
@ -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_);
|
||||||
|
@ -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
|
||||||
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user