Compare commits

..

21 Commits

Author SHA1 Message Date
1e0d4b8c8b Update ChangeLog
Change-Id: I381ab93458df3d1851aec36161cc4b2cbd1265be
2013-03-29 15:55:16 -07:00
d52b405dbd Cosmetic fixes
Change-Id: Ia878115086edc3fdfee3f0ca76e5e74ea5906f21
(cherry picked from commit e9a7990bc5)
2013-03-29 15:49:15 -07:00
6cb4a61825 misc style fix
(cherry picked from commit 142c46291e)

Conflicts:
	src/webp/format_constants.h

Change-Id: Ib764cb09bd78ab6e72c60f495d55b752ad4dbe4d
2013-03-29 15:49:05 -07:00
68111ab02f add missing YUVA->ARGB automatic conversion in WebPEncode()
user can now call WebPEncode() with any YUVA or ARGB format, for
lossy or lossless compression

also: simplified error reporting, which is done in WebPPictureARGBToYUVA()
and WebPPictureYUVAToARGB()

Change-Id: Ifb68909217175bcf5a050e5c68d06de9849468f7
(cherry picked from commit 07d87bda1b)
2013-03-29 15:33:14 -07:00
403bfe820c Container spec: Clarify frame disposal
- Add a note that disposal only applies to the frame rectangle
- Add the formula for alpha-blending.
- Note that alpha-blending would occur for the common rectangle
- Also note the case when both color profile and disposal are
present.

Change-Id: I214787dd64453edf3b0cdaff3951015281a32ee4
2013-03-29 11:42:17 -07:00
3e7a13a008 Merge "Container spec: clarify the background color field" into 0.3.0 2013-03-26 17:38:07 -07:00
14af77452b container doc: add a note about the 'ANMF' payload
this consists of padded chunks, so ANMF should require none

Change-Id: I5dff623b56d8a466dc9be03ee87d1d2d19efc088
2013-03-26 17:25:27 -07:00
cc635efa01 Container spec: clarify the background color field
Change-Id: I03f634cbd147c2851eb06ddbc7b1014e04e21038
2013-03-26 17:22:18 -07:00
e3e339497e container doc: move RIFF description to own section
- remove some little used terms
- condense file header description
- add description of FourCC

Change-Id: Ia873652f41789811f3fb2ec97182a068ac727961
2013-03-26 17:16:12 -07:00
4299f39852 libwebp/mux: fix double free
transfer ownership of chunk passed in ChunkSetNth(). prevents freeing
the chunk in e.g., MuxImageParse() when a partial assignment (alpha but
no image) has occurred.

Change-Id: Ia69656b04fdf50f098f3816b54abd4e191248de3
2013-03-26 13:31:47 -07:00
33f9a692d9 Merge "demux: keep a frame tail pointer; used in AddFrame" into 0.3.0 2013-03-26 13:30:10 -07:00
a2a7b95916 use WebPDataCopy() instead of re-coding it.
also: fix some 0 vs NULL tests

Change-Id: I2b6f65a1e658211e5b4a323c4f9f502744206ec7
2013-03-26 20:40:24 +01:00
6f18f12f99 demux: keep a frame tail pointer; used in AddFrame
this speeds up the parse of a file with a large number of frames.

Change-Id: Ibc61324eb50a04438f811a6f7787d378d763c104
2013-03-26 11:27:51 -07:00
e5af49e9c0 add doc precision about WebPParseHeaders() return codes
Change-Id: I970900f4a5abb4877a716bd4eb15939655ef5dad
2013-03-25 17:54:46 -07:00
db46daab97 Merge "Makefile.vc: fix dynamic builds" into 0.3.0 2013-03-25 16:41:26 -07:00
53c77afc52 Merge "gif2webp: Bgcolor fix for a special case" into 0.3.0 2013-03-25 16:33:51 -07:00
a5ebd143d6 gif2webp: Bgcolor fix for a special case
When transparent color index and background color index are same,
we should set background color to 0x00ffffff (transparent).

For this, we delay setting the background color until we have read the
first frame.

Change-Id: I443609b9c7697a2b94a66992460cff8465b3c127
2013-03-25 16:30:27 -07:00
6378f23876 Merge "vwebp/animation: fix background dispose" into 0.3.0 2013-03-25 16:24:02 -07:00
3c8eb9a806 fix bad saturation order in QuantizeBlock
Saturation was done on input coeff, not quantized one.

This saturation is not absolutely needed: output of FTransformWHT
is in range [-16320, 16321]. At quality 100, max quantization steps is 8,
so the maximal range used by QuantizeBlock() is [-2040, 2040].
But there's some extra bias (mtx->bias_[] and mtx->sharpen_[]) so
it's better to leave this saturation check for now.

addresses issue #145

Change-Id: I4b14f71cdc80c46f9eaadb2a4e8e03d396879d28
2013-03-25 14:53:29 -07:00
04c7a2ecf0 vwebp/animation: fix background dispose
buffer the last frame's details to perform DISPOSE_BACKGROUND on the
image's area, rather than the entire canvas.

also fixes transparent backgrounds with animated images

Change-Id: I53e4d70c441e1eeb136f1d01e7c88de4f9ecff53
2013-03-25 13:39:27 -07:00
81a50695de Makefile.vc: fix dynamic builds
broken since:
e2feefa Makefile.vc: split mux into separate lib

broken even more since:
b65c4b7 Makefile.vc: add libwebpdecoder target

Change-Id: Ibb7a7f2c71ae63434a60d988ce15f0a4ed8fcaee
2013-03-21 19:30:34 -07:00
24 changed files with 233 additions and 157 deletions

View File

@ -1,3 +1,24 @@
d52b405 Cosmetic fixes
6cb4a61 misc style fix
68111ab add missing YUVA->ARGB automatic conversion in WebPEncode()
403bfe8 Container spec: Clarify frame disposal
3e7a13a Merge "Container spec: clarify the background color field" into 0.3.0
14af774 container doc: add a note about the 'ANMF' payload
cc635ef Container spec: clarify the background color field
e3e3394 container doc: move RIFF description to own section
4299f39 libwebp/mux: fix double free
33f9a69 Merge "demux: keep a frame tail pointer; used in AddFrame" into 0.3.0
a2a7b95 use WebPDataCopy() instead of re-coding it.
6f18f12 demux: keep a frame tail pointer; used in AddFrame
e5af49e add doc precision about WebPParseHeaders() return codes
db46daa Merge "Makefile.vc: fix dynamic builds" into 0.3.0
53c77af Merge "gif2webp: Bgcolor fix for a special case" into 0.3.0
a5ebd14 gif2webp: Bgcolor fix for a special case
6378f23 Merge "vwebp/animation: fix background dispose" into 0.3.0
3c8eb9a fix bad saturation order in QuantizeBlock
04c7a2e vwebp/animation: fix background dispose
81a5069 Makefile.vc: fix dynamic builds
5f25c39 update ChangeLog
14d42af examples: don't use C99 %zu
5ccf1fe update ChangeLog
2560c24 update NEWS

View File

@ -105,7 +105,7 @@ DLLC = webp_dll.c
DLLINC = webp_dll.h
DLL_OBJS = $(DIROBJ)\$(DLLC:.c=.obj)
CC = $(CC) /I$(DIROBJ) /FI$(DLLINC) $(RTLIB) /DWEBP_DLL
LIBWEBP = $(DIRLIB)\$(LIBWEBPDECODER_BASENAME)_dll.lib
LIBWEBPDECODER = $(DIRLIB)\$(LIBWEBPDECODER_BASENAME)_dll.lib
LIBWEBP = $(DIRLIB)\$(LIBWEBP_BASENAME)_dll.lib
LIBWEBPMUX = $(DIRLIB)\$(LIBWEBPMUX_BASENAME)_dll.lib
LIBWEBPDEMUX = $(DIRLIB)\$(LIBWEBPMDEMUX_BASENAME)_dll.lib
@ -261,7 +261,7 @@ $(LIBWEBPDEMUX): $(LIBWEBPDEMUX_OBJS)
$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS): $(OUTPUT_DIRS)
!IF "$(DLLBUILD)" == "TRUE"
$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS):
$(LIBWEBP_OBJS) $(LIBWEBPMUX_OBJS) $(LIBWEBPDEMUX_OBJS): \
$(DIROBJ)\$(DLLINC) $(DIROBJ)\$(DLLC)
{$(DIROBJ)}.c{$(DIROBJ)}.obj:

View File

@ -93,11 +93,21 @@ _uint32_
: A 32-bit, little-endian, unsigned integer.
_FourCC_
: A _FourCC_ (four-character code) is a _uint32_ created by concatenating four
ASCII characters in little-endian order.
_1-based_
: An unsigned integer field storing values offset by `-1`. e.g., Such a field
would store value _25_ as _24_.
RIFF file format
----------------
The WebP file format is based on the RIFF (resource interchange file format)
document format.
The basic element of a RIFF file is a _chunk_. It consists of:
0 1 2 3
@ -112,12 +122,12 @@ The basic element of a RIFF file is a _chunk_. It consists of:
Chunk FourCC: 32 bits
: ASCII four character code or _chunk tag_ used for chunk identification.
: ASCII four-character code used for chunk identification.
Chunk Size: 32 bits (_uint32_)
: The size of the chunk (_ckSize_) not including this field, the chunk
identifier and padding.
: The size of the chunk not including this field, the chunk identifier or
padding.
Chunk Payload: _Chunk Size_ bytes
@ -126,43 +136,13 @@ Chunk Payload: _Chunk Size_ bytes
_ChunkHeader('ABCD')_
: This is used to describe the fourcc and size header of individual
chunks, where 'ABCD' is the fourcc for the chunk. This element's
: This is used to describe the _FourCC_ and _Chunk Size_ header of individual
chunks, where 'ABCD' is the FourCC for the chunk. This element's
size is 8 bytes.
: Note that, in this specification, all chunk tag characters are in
file order, not in byte order of a uint32 of any particular
architecture.
_list of chunks_
: A concatenation of multiple chunks.
: We will refer to the first chunk as having _position_ 0, the second
as position 1, etc. By _chunk with index 0 among "ABCD"_ we mean
the first chunk among the chunks of type "ABCD" in the list, the
_chunk with index 1 among "ABCD"_ is the second such chunk, etc.
A WebP file MUST begin with a single chunk with a tag 'RIFF'. All
other defined chunks are contained within this chunk. The file SHOULD
NOT contain anything after it.
The maximum size of RIFF's _ckSize_ is 2^32 minus 10 bytes. The size
of the whole file is at most 4GiB minus 2 bytes.
**Note:** some RIFF libraries are said to have bugs when handling files
larger than 1GiB or 2GiB. If you are using an existing library, check
that it handles large files correctly.
The first four bytes of the RIFF chunk contents (i.e., bytes 8-11 of the file)
MUST be the ASCII string "WEBP". They are followed by a list of chunks. As the
size of any chunk is even, the size of the RIFF chunk is also even. The
contents of the chunks in that list will be described in the following sections.
**Note:** RIFF has a convention that all-uppercase chunks are standard
chunks that apply to any RIFF file format, while chunks specific to a
file format are all lowercase. WebP does not follow this convention.
**Note:** RIFF has a convention that all-uppercase chunk FourCCs are standard
chunks that apply to any RIFF file format, while FourCCs specific to a file
format are all lowercase. WebP does not follow this convention.
WebP file header
----------------
@ -183,12 +163,20 @@ WebP file header
File Size: 32 bits (_uint32_)
: The size of the file in bytes starting at offset 8.
: The size of the file in bytes starting at offset 8. The maximum value of
this field is 2^32 minus 10 bytes and thus the size of the whole file is at
most 4GiB minus 2 bytes.
'WEBP': 32 bits
: The ASCII characters 'W' 'E' 'B' 'P'.
A WebP file MUST begin with a RIFF header with the FourCC 'WEBP'. The file size
in the header is the total size of the chunks that follow plus `4` bytes for
the 'WEBP' FourCC. The file SHOULD NOT contain anything after it. As the size
of any chunk is even, the size given by the RIFF header is also even. The
contents of individual chunks will be described in the following sections.
Simple file format (lossy)
--------------------------
@ -376,6 +364,7 @@ Future specifications MAY add more fields.
An animation is controlled by ANIM and ANMF chunks.
ANIM Chunk:
{:#anim_chunk}
For an animated image, this chunk contains the _global parameters_ of the
animation.
@ -392,10 +381,14 @@ animation.
Background Color: 32 bits (_uint32_)
: The background color of the canvas in \[Blue, Green, Red, Alpha\] byte order.
The background color is the color used for those pixels of the canvas that are
not covered by a frame. Background color is also used when disposal method is
`1`.
: The default background color of the canvas in \[Blue, Green, Red, Alpha\]
byte order. This color is used to fill the unused space on the canvas around the
frames, as well as the transparent pixels of the first frame. Background color
is also used when disposal method is `1`.
**Note**: Viewers that have a preferred background against which to present the
images (web browsers, for example) should ignore this value and use their
preferred background color instead.
Loop Count: 16 bits (_uint16_)
@ -457,14 +450,45 @@ Reserved: 7 bits
Disposal method (D): 1 bit
: Indicates how the area used by this frame is to be treated before rendering
the next frame on canvas:
: Indicates how _the current frame_ is to be treated after it has been displayed
(before rendering the next frame) on the canvas:
* `0`: Do not dispose. Keep the area used by this frame as it is and render
the next frame on top of it.
* `0`: Do not dispose. Leave the canvas as is.
* `1`: Dispose to background color (also part of this chunk). Restore the
area used by this frame to background color before rendering the next frame.
* `1`: Dispose to background color. Fill the _rectangle_ on the canvas covered
by the _current frame_ with background color specified in the
[ANIM chunk](#anim_chunk).
After disposing the current frame, render the next frame on the canvas using
[alpha-blending](#alpha-blending). If the next frame does not have an alpha
channel, assume alpha value of 255, effectively replacing the rectangle.
**Notes**:
* The frame disposal only applies to the _frame rectangle_, that is, the
rectangle defined by _Frame X_, _Frame Y_, _frame width_ and _frame height_.
It may or may not cover the whole canvas.
{:#alpha-blending}
* **Alpha-blending**:
Given that each of the R, G, B and A channels is 8-bit, and the RGB
channels are _not premultiplied_ by alpha, the formula for blending
'dst' onto 'src' is:
~~~~~
blend.A = src.A + dst.A * (1 - src.A / 255)
if blend.A = 0 then
blend.RGB = 0
else
blend.RGB = (src.RGB * src.A +
dst.RGB * dst.A * (1 - src.A / 255)) / blend.A
~~~~~
* Alpha-blending SHOULD be done in linear color space, by taking into account
the [color profile](#color-profile) of the image. If the color profile is
not present, sRGB is to be assumed. (Note that sRGB also needs to be
linearized due to a gamma of ~2.2).
Frame Data: _Chunk Size_ - `16` bytes
@ -478,6 +502,9 @@ Frame Data: _Chunk Size_ - `16` bytes
* An optional list of [unknown chunks](#unknown-chunks).
**Note**: The 'ANMF' payload, _Frame Data_ above, consists of individual
_padded_ chunks as described by the [RIFF file format](#riff-file-format).
#### Fragments _\[status: experimental\]_
For images that are represented by fragments, this chunk contains data for

View File

@ -117,14 +117,17 @@ static int ReadSubImage(GifFileType* gif, WebPPicture* pic, WebPPicture* view) {
return ok;
}
static int GetColorFromIndex(const ColorMapObject* const color_map, GifWord idx,
uint32_t* const argb) {
assert(color_map != NULL && color_map->Colors != NULL);
if (idx >= color_map->ColorCount) {
return 0; // Invalid index.
static int GetBackgroundColor(const ColorMapObject* const color_map,
GifWord bgcolor_idx, uint32_t* const bgcolor) {
if (transparent_index != -1 && bgcolor_idx == transparent_index) {
*bgcolor = TRANSPARENT_COLOR; // Special case.
return 1;
} else if (color_map == NULL || color_map->Colors == NULL
|| bgcolor_idx >= color_map->ColorCount) {
return 0; // Invalid color map or index.
} else {
const GifColorType color = color_map->Colors[idx];
*argb = (0xff << 24)
const GifColorType color = color_map->Colors[bgcolor_idx];
*bgcolor = (0xff << 24)
| (color.Red << 16)
| (color.Green << 8)
| (color.Blue << 0);
@ -199,6 +202,7 @@ int main(int argc, const char *argv[]) {
WebPMuxFrameInfo frame;
WebPMuxAnimParams anim = { WHITE_COLOR, 0 };
int is_first_frame = 1;
int done;
int c;
int quiet = 0;
@ -283,14 +287,6 @@ int main(int argc, const char *argv[]) {
picture.custom_ptr = &memory;
if (!WebPPictureAlloc(&picture)) goto End;
if (gif->SColorMap != NULL &&
!GetColorFromIndex(gif->SColorMap, gif->SBackGroundColor,
&anim.bgcolor)) {
fprintf(stderr, "GIF decode warning: invalid background color index. "
"Assuming white background.\n");
}
ClearPicture(&picture, anim.bgcolor);
mux = WebPMuxNew();
if (mux == NULL) {
fprintf(stderr, "ERROR: could not create a mux object.\n");
@ -379,6 +375,15 @@ int main(int argc, const char *argv[]) {
: WEBP_MUX_DISPOSE_NONE;
}
transparent_index = (flags & GIF_TRANSPARENT_MASK) ? data[4] : -1;
if (is_first_frame) {
if (!GetBackgroundColor(gif->SColorMap, gif->SBackGroundColor,
&anim.bgcolor)) {
fprintf(stderr, "GIF decode warning: invalid background color "
"index. Assuming white background.\n");
}
ClearPicture(&picture, anim.bgcolor);
is_first_frame = 0;
}
break;
}
case PLAINTEXT_EXT_FUNC_CODE: {

View File

@ -62,6 +62,11 @@ static struct {
const WebPDecBuffer* pic;
WebPDemuxer* dmux;
WebPIterator frameiter;
struct {
int width, height;
int x_offset, y_offset;
enum WebPMuxAnimDispose dispose_method;
} prev_frame;
WebPChunkIterator iccp;
} kParams;
@ -287,9 +292,31 @@ static void HandleDisplay(void) {
glRasterPos2f(-1.f + xoff, 1.f - yoff);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, pic->u.RGBA.stride / 4);
if (iter->dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
if (kParams.prev_frame.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) {
// TODO(later): these offsets and those above should factor in window size.
// they will be incorrect if the window is resized.
// glScissor() takes window coordinates (0,0 at bottom left).
const int window_x = kParams.prev_frame.x_offset;
const int window_y = kParams.canvas_height -
kParams.prev_frame.y_offset -
kParams.prev_frame.height;
glEnable(GL_SCISSOR_TEST);
// Only updated the requested area, not the whole canvas.
glScissor(window_x, window_y,
kParams.prev_frame.width, kParams.prev_frame.height);
glClear(GL_COLOR_BUFFER_BIT); // use clear color
DrawCheckerBoard();
glDisable(GL_SCISSOR_TEST);
}
kParams.prev_frame.width = iter->width;
kParams.prev_frame.height = iter->height;
kParams.prev_frame.x_offset = iter->x_offset;
kParams.prev_frame.y_offset = iter->y_offset;
kParams.prev_frame.dispose_method = iter->dispose_method;
glDrawPixels(pic->width, pic->height,
GL_RGBA, GL_UNSIGNED_BYTE,
(GLvoid*)pic->u.RGBA.rgba);
@ -426,6 +453,11 @@ int main(int argc, char *argv[]) {
printf("Canvas: %d x %d\n", kParams.canvas_width, kParams.canvas_height);
}
kParams.prev_frame.width = kParams.canvas_width;
kParams.prev_frame.height = kParams.canvas_height;
kParams.prev_frame.x_offset = kParams.prev_frame.y_offset = 0;
kParams.prev_frame.dispose_method = WEBP_MUX_DISPOSE_BACKGROUND;
memset(&kParams.iccp, 0, sizeof(kParams.iccp));
kParams.has_color_profile =
!!(WebPDemuxGetI(kParams.dmux, WEBP_FF_FORMAT_FLAGS) & ICCP_FLAG);

View File

@ -61,10 +61,10 @@ typedef struct {
} WebPHeaderStructure;
// Skips over all valid chunks prior to the first VP8/VP8L frame header.
// Returns VP8_STATUS_OK on success,
// VP8_STATUS_BITSTREAM_ERROR if an invalid header/chunk is found, and
// VP8_STATUS_NOT_ENOUGH_DATA if case of insufficient data.
// In 'headers', compressed_size, offset, alpha_data, alpha_size and lossless
// Returns: VP8_STATUS_OK, VP8_STATUS_BITSTREAM_ERROR (invalid header/chunk),
// VP8_STATUS_NOT_ENOUGH_DATA (partial input) or VP8_STATUS_UNSUPPORTED_FEATURE
// in the case of non-decodable features (animation for instance).
// In 'headers', compressed_size, offset, alpha_data, alpha_size, and lossless
// fields are updated appropriately upon success.
VP8StatusCode WebPParseHeaders(WebPHeaderStructure* const headers);

View File

@ -69,6 +69,7 @@ struct WebPDemuxer {
uint32_t bgcolor_;
int num_frames_;
Frame* frames_;
Frame** frames_tail_;
Chunk* chunks_; // non-image chunks
};
@ -183,15 +184,12 @@ static void AddChunk(WebPDemuxer* const dmux, Chunk* const chunk) {
// Add a frame to the end of the list, ensuring the last frame is complete.
// Returns true on success, false otherwise.
static int AddFrame(WebPDemuxer* const dmux, Frame* const frame) {
const Frame* last_frame = NULL;
Frame** f = &dmux->frames_;
while (*f != NULL) {
last_frame = *f;
f = &(*f)->next_;
}
const Frame* const last_frame = *dmux->frames_tail_;
if (last_frame != NULL && !last_frame->complete_) return 0;
*f = frame;
*dmux->frames_tail_ = frame;
frame->next_ = NULL;
dmux->frames_tail_ = &frame->next_;
return 1;
}
@ -660,6 +658,7 @@ static void InitDemux(WebPDemuxer* const dmux, const MemBuffer* const mem) {
dmux->bgcolor_ = 0xFFFFFFFF; // White background by default.
dmux->canvas_width_ = -1;
dmux->canvas_height_ = -1;
dmux->frames_tail_ = &dmux->frames_;
dmux->mem_ = *mem;
}

View File

@ -631,13 +631,13 @@ static int QuantizeBlock(int16_t in[16], int16_t out[16],
for (; n < 16; ++n) {
const int j = kZigzag[n];
const int sign = (in[j] < 0);
int coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
if (coeff > 2047) coeff = 2047;
const int coeff = (sign ? -in[j] : in[j]) + mtx->sharpen_[j];
if (coeff > mtx->zthresh_[j]) {
const int Q = mtx->q_[j];
const int iQ = mtx->iq_[j];
const int B = mtx->bias_[j];
out[n] = QUANTDIV(coeff, iQ, B);
if (out[n] > MAX_LEVEL) out[n] = MAX_LEVEL;
if (sign) out[n] = -out[n];
in[j] = out[n] * Q;
if (out[n]) last = n;

View File

@ -776,7 +776,7 @@ static int Disto16x16SSE2(const uint8_t* const a, const uint8_t* const b,
// Simple quantization
static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16],
int n, const VP8Matrix* const mtx) {
const __m128i max_coeff_2047 = _mm_set1_epi16(2047);
const __m128i max_coeff_2047 = _mm_set1_epi16(MAX_LEVEL);
const __m128i zero = _mm_setzero_si128();
__m128i coeff0, coeff8;
__m128i out0, out8;
@ -812,10 +812,6 @@ static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16],
coeff0 = _mm_add_epi16(coeff0, sharpen0);
coeff8 = _mm_add_epi16(coeff8, sharpen8);
// if (coeff > 2047) coeff = 2047
coeff0 = _mm_min_epi16(coeff0, max_coeff_2047);
coeff8 = _mm_min_epi16(coeff8, max_coeff_2047);
// out = (coeff * iQ + B) >> QFIX;
{
// doing calculations with 32b precision (QFIX=17)
@ -843,9 +839,14 @@ static int QuantizeBlockSSE2(int16_t in[16], int16_t out[16],
out_04 = _mm_srai_epi32(out_04, QFIX);
out_08 = _mm_srai_epi32(out_08, QFIX);
out_12 = _mm_srai_epi32(out_12, QFIX);
// pack result as 16b
out0 = _mm_packs_epi32(out_00, out_04);
out8 = _mm_packs_epi32(out_08, out_12);
// if (coeff > 2047) coeff = 2047
out0 = _mm_min_epi16(out0, max_coeff_2047);
out8 = _mm_min_epi16(out8, max_coeff_2047);
}
// get sign back (if (sign[j]) out_n = -out_n)

View File

@ -75,7 +75,7 @@ const uint16_t VP8LevelCodes[MAX_VARIABLE_LEVEL][2] = {
// fixed costs for coding levels, deduce from the coding tree.
// This is only the part that doesn't depend on the probability state.
const uint16_t VP8LevelFixedCosts[2048] = {
const uint16_t VP8LevelFixedCosts[MAX_LEVEL + 1] = {
0, 256, 256, 256, 256, 432, 618, 630,
731, 640, 640, 828, 901, 948, 1021, 1101,
1174, 1221, 1294, 1042, 1085, 1115, 1158, 1202,

View File

@ -18,7 +18,8 @@
extern "C" {
#endif
extern const uint16_t VP8LevelFixedCosts[2048]; // approximate cost per level
// approximate cost per level:
extern const uint16_t VP8LevelFixedCosts[MAX_LEVEL + 1];
extern const uint16_t VP8EntropyCost[256]; // 8bit fixed-point log(p)
// Cost of coding one event with probability 'proba'.

View File

@ -462,7 +462,6 @@ int WebPPictureRescale(WebPPicture* pic, int width, int height) {
(uint8_t*)tmp.argb, width, height,
tmp.argb_stride * 4,
work, 4);
}
WebPPictureFree(pic);
free(work);

View File

@ -29,7 +29,6 @@ static int IsVP8XNeeded(const VP8Encoder* const enc) {
}
static int PutPaddingByte(const WebPPicture* const pic) {
const uint8_t pad_byte[1] = { 0 };
return !!pic->writer(pad_byte, 1, pic);
}

View File

@ -56,7 +56,8 @@ enum { NUM_MB_SEGMENTS = 4,
NUM_CTX = 3,
NUM_PROBAS = 11,
MAX_LF_LEVELS = 64, // Maximum loop filter level
MAX_VARIABLE_LEVEL = 67 // last (inclusive) level with variable cost
MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
MAX_LEVEL = 2047 // max level (note: max codable is 2047 + 67)
};
typedef enum { // Rate-distortion optimization levels

View File

@ -374,11 +374,8 @@ int WebPEncode(const WebPConfig* config, WebPPicture* pic) {
if (!config->lossless) {
VP8Encoder* enc = NULL;
if (pic->y == NULL || pic->u == NULL || pic->v == NULL) {
if (pic->argb != NULL) {
// Make sure we have YUVA samples.
if (!WebPPictureARGBToYUVA(pic, WEBP_YUV420)) return 0;
} else {
return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
}
}
enc = InitVP8Encoder(config, pic);
@ -405,8 +402,10 @@ int WebPEncode(const WebPConfig* config, WebPPicture* pic) {
}
ok &= DeleteVP8Encoder(enc); // must always be called, even if !ok
} else {
if (pic->argb == NULL)
return WebPEncodingSetError(pic, VP8_ENC_ERROR_NULL_PARAMETER);
// Make sure we have ARGB samples.
if (pic->argb == NULL && !WebPPictureYUVAToARGB(pic)) {
return 0;
}
ok = VP8LEncodeImage(config, pic); // Sets pic->error in case of problem.
}

View File

@ -121,7 +121,8 @@ WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
// Sets 'chunk' at nth position in the 'chunk_list'.
// nth = 0 has the special meaning "last of the list".
WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list,
// On success ownership is transferred from 'chunk' to the 'chunk_list'.
WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
uint32_t nth);
// Releases chunk and returns chunk->next_.

View File

@ -96,7 +96,7 @@ CHUNK_INDEX ChunkGetIndexFromFourCC(const char fourcc[4]) {
// Returns next chunk in the chunk list with the given tag.
static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) {
while (chunk && chunk->tag_ != tag) {
while (chunk != NULL && chunk->tag_ != tag) {
chunk = chunk->next_;
}
return chunk;
@ -105,7 +105,7 @@ static WebPChunk* ChunkSearchNextInList(WebPChunk* chunk, uint32_t tag) {
WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) {
uint32_t iter = nth;
first = ChunkSearchNextInList(first, tag);
if (!first) return NULL;
if (first == NULL) return NULL;
while (--iter != 0) {
WebPChunk* next_chunk = ChunkSearchNextInList(first->next_, tag);
@ -121,10 +121,10 @@ WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) {
static int ChunkSearchListToSet(WebPChunk** chunk_list, uint32_t nth,
WebPChunk*** const location) {
uint32_t count = 0;
assert(chunk_list);
assert(chunk_list != NULL);
*location = chunk_list;
while (*chunk_list) {
while (*chunk_list != NULL) {
WebPChunk* const cur_chunk = *chunk_list;
++count;
if (count == nth) return 1; // Found.
@ -149,27 +149,18 @@ WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
ChunkRelease(chunk);
if (data != NULL) {
if (copy_data) {
// Copy data.
chunk->data_.bytes = (uint8_t*)malloc(data->size);
if (chunk->data_.bytes == NULL) return WEBP_MUX_MEMORY_ERROR;
memcpy((uint8_t*)chunk->data_.bytes, data->bytes, data->size);
chunk->data_.size = data->size;
// Chunk is owner of data.
chunk->owner_ = 1;
} else {
// Don't copy data.
if (copy_data) { // Copy data.
if (!WebPDataCopy(data, &chunk->data_)) return WEBP_MUX_MEMORY_ERROR;
chunk->owner_ = 1; // Chunk is owner of data.
} else { // Don't copy data.
chunk->data_ = *data;
}
}
chunk->tag_ = tag;
return WEBP_MUX_OK;
}
WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list,
WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
uint32_t nth) {
WebPChunk* new_chunk;
@ -180,6 +171,7 @@ WebPMuxError ChunkSetNth(const WebPChunk* chunk, WebPChunk** chunk_list,
new_chunk = (WebPChunk*)malloc(sizeof(*new_chunk));
if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR;
*new_chunk = *chunk;
chunk->owner_ = 0;
new_chunk->next_ = *chunk_list;
*chunk_list = new_chunk;
return WEBP_MUX_OK;
@ -199,7 +191,7 @@ WebPChunk* ChunkDelete(WebPChunk* const chunk) {
size_t ChunksListDiskSize(const WebPChunk* chunk_list) {
size_t size = 0;
while (chunk_list) {
while (chunk_list != NULL) {
size += ChunkDiskSize(chunk_list);
chunk_list = chunk_list->next_;
}
@ -220,7 +212,7 @@ static uint8_t* ChunkEmit(const WebPChunk* const chunk, uint8_t* dst) {
}
uint8_t* ChunkListEmit(const WebPChunk* chunk_list, uint8_t* dst) {
while (chunk_list) {
while (chunk_list != NULL) {
dst = ChunkEmit(chunk_list, dst);
chunk_list = chunk_list->next_;
}
@ -281,7 +273,7 @@ static int SearchImageToGetOrDelete(WebPMuxImage** wpi_list, uint32_t nth,
if (nth == 0) return 0; // Not found.
}
while (*wpi_list) {
while (*wpi_list != NULL) {
WebPMuxImage* const cur_wpi = *wpi_list;
++count;
if (count == nth) return 1; // Found.
@ -327,7 +319,7 @@ WebPMuxImage* MuxImageDelete(WebPMuxImage* const wpi) {
}
void MuxImageDeleteAll(WebPMuxImage** const wpi_list) {
while (*wpi_list) {
while (*wpi_list != NULL) {
*wpi_list = MuxImageDelete(*wpi_list);
}
}
@ -370,7 +362,7 @@ size_t MuxImageDiskSize(const WebPMuxImage* const wpi) {
size_t MuxImageListDiskSize(const WebPMuxImage* wpi_list) {
size_t size = 0;
while (wpi_list) {
while (wpi_list != NULL) {
size += MuxImageDiskSize(wpi_list);
wpi_list = wpi_list->next_;
}
@ -409,7 +401,7 @@ uint8_t* MuxImageEmit(const WebPMuxImage* const wpi, uint8_t* dst) {
}
uint8_t* MuxImageListEmit(const WebPMuxImage* wpi_list, uint8_t* dst) {
while (wpi_list) {
while (wpi_list != NULL) {
dst = MuxImageEmit(wpi_list, dst);
wpi_list = wpi_list->next_;
}

View File

@ -266,7 +266,6 @@ enum WebPEncodingError {
// Main exchange structure (input samples, output bytes, statistics)
struct WebPPicture {
// INPUT
//////////////
// Main flag for encoder selecting between ARGB or YUV input.