aboutsummaryrefslogtreecommitdiff
path: root/src/enc/vp8l.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/enc/vp8l.c')
-rw-r--r--src/enc/vp8l.c121
1 files changed, 58 insertions, 63 deletions
diff --git a/src/enc/vp8l.c b/src/enc/vp8l.c
index 2798d670..41aa62b7 100644
--- a/src/enc/vp8l.c
+++ b/src/enc/vp8l.c
@@ -37,8 +37,7 @@ extern "C" {
static int CompareColors(const void* p1, const void* p2) {
const uint32_t a = *(const uint32_t*)p1;
const uint32_t b = *(const uint32_t*)p2;
- assert(a != b);
- return (a < b) ? -1 : 1;
+ return (a < b) ? -1 : (a > b) ? 1 : 0;
}
// If number of colors in the image is less than or equal to MAX_PALETTE_SIZE,
@@ -221,7 +220,7 @@ static int GetHuffBitLengthsAndCodes(
}
// Create Huffman trees.
- for (i = 0; ok && (i < histogram_image_size); ++i) {
+ for (i = 0; i < histogram_image_size; ++i) {
HuffmanTreeCode* const codes = &huffman_codes[5 * i];
VP8LHistogram* const histo = histogram_image->histograms[i];
ok = ok && VP8LCreateHuffmanTree(histo->literal_, 15, codes + 0);
@@ -232,11 +231,7 @@ static int GetHuffBitLengthsAndCodes(
}
End:
- if (!ok) {
- free(mem_buf);
- // If one VP8LCreateHuffmanTree() above fails, we need to clean up behind.
- memset(huffman_codes, 0, 5 * histogram_image_size * sizeof(*huffman_codes));
- }
+ if (!ok) free(mem_buf);
return ok;
}
@@ -411,10 +406,9 @@ static int StoreHuffmanCode(VP8LBitWriter* const bw,
}
static void WriteHuffmanCode(VP8LBitWriter* const bw,
- const HuffmanTreeCode* const code,
- int code_index) {
- const int depth = code->code_lengths[code_index];
- const int symbol = code->codes[code_index];
+ const HuffmanTreeCode* const code, int index) {
+ const int depth = code->code_lengths[index];
+ const int symbol = code->codes[index];
VP8LWriteBits(bw, depth, symbol);
}
@@ -535,12 +529,7 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
sizeof(*histogram_symbols));
assert(histogram_bits >= MIN_HUFFMAN_BITS);
assert(histogram_bits <= MAX_HUFFMAN_BITS);
-
- if (histogram_image == NULL || histogram_symbols == NULL) {
- free(histogram_image);
- free(histogram_symbols);
- return 0;
- }
+ if (histogram_image == NULL || histogram_symbols == NULL) goto Error;
// Calculate backward references from ARGB image.
if (!VP8LGetBackwardReferences(width, height, argb, quality, cache_bits,
@@ -582,10 +571,10 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
uint32_t i;
if (histogram_argb == NULL) goto Error;
for (i = 0; i < histogram_image_xysize; ++i) {
- const int symbol_index = histogram_symbols[i] & 0xffff;
- histogram_argb[i] = 0xff000000 | (symbol_index << 8);
- if (symbol_index >= max_index) {
- max_index = symbol_index + 1;
+ const int index = histogram_symbols[i] & 0xffff;
+ histogram_argb[i] = 0xff000000 | (index << 8);
+ if (index >= max_index) {
+ max_index = index + 1;
}
}
histogram_image_size = max_index;
@@ -717,6 +706,13 @@ static int ApplyCrossColorFilter(const VP8LEncoder* const enc,
// -----------------------------------------------------------------------------
+static void PutLE32(uint8_t* const data, uint32_t val) {
+ data[0] = (val >> 0) & 0xff;
+ data[1] = (val >> 8) & 0xff;
+ data[2] = (val >> 16) & 0xff;
+ data[3] = (val >> 24) & 0xff;
+}
+
static WebPEncodingError WriteRiffHeader(const WebPPicture* const pic,
size_t riff_size, size_t vp8l_size) {
uint8_t riff[RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE + VP8L_SIGNATURE_SIZE] = {
@@ -811,24 +807,30 @@ static WebPEncodingError AllocateTransformBuffer(VP8LEncoder* const enc,
return err;
}
-// Bundles multiple (1, 2, 4 or 8) pixels into a single pixel.
-static void BundleColorMap(const uint8_t* const row, int width,
- int xbits, uint32_t* const dst) {
- int x;
- if (xbits > 0) {
- const int bit_depth = 1 << (3 - xbits);
- const int mask = (1 << xbits) - 1;
- uint32_t code = 0xff000000;
+// Bundles multiple (2, 4 or 8) pixels into a single pixel.
+// Returns the new xsize.
+static void BundleColorMap(const WebPPicture* const pic,
+ int xbits, uint32_t* bundled_argb, int xs) {
+ int y;
+ const int bit_depth = 1 << (3 - xbits);
+ uint32_t code = 0;
+ const uint32_t* argb = pic->argb;
+ const int width = pic->width;
+ const int height = pic->height;
+
+ for (y = 0; y < height; ++y) {
+ int x;
for (x = 0; x < width; ++x) {
+ const int mask = (1 << xbits) - 1;
const int xsub = x & mask;
if (xsub == 0) {
- code = 0xff000000;
+ code = 0;
}
- code |= row[x] << (8 + bit_depth * xsub);
- dst[x >> xbits] = code;
+ // TODO(vikasa): simplify the bundling logic.
+ code |= (argb[x] & 0xff00) << (bit_depth * xsub);
+ bundled_argb[y * xs + (x >> xbits)] = 0xff000000 | code;
}
- } else {
- for (x = 0; x < width; ++x) dst[x] = 0xff000000 | (row[x] << 8);
+ argb += pic->argb_stride;
}
}
@@ -840,43 +842,24 @@ static WebPEncodingError ApplyPalette(VP8LBitWriter* const bw,
WebPEncodingError err = VP8_ENC_OK;
int i, x, y;
const WebPPicture* const pic = enc->pic_;
- uint32_t* src = pic->argb;
- uint32_t* dst;
+ uint32_t* argb = pic->argb;
const int width = pic->width;
const int height = pic->height;
uint32_t* const palette = enc->palette_;
const int palette_size = enc->palette_size_;
- uint8_t* row = NULL;
- int xbits;
// Replace each input pixel by corresponding palette index.
- // This is done line by line.
- if (palette_size <= 4) {
- xbits = (palette_size <= 2) ? 3 : 2;
- } else {
- xbits = (palette_size <= 16) ? 1 : 0;
- }
-
- err = AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height);
- if (err != VP8_ENC_OK) goto Error;
- dst = enc->argb_;
-
- row = WebPSafeMalloc((uint64_t)width, sizeof(*row));
- if (row == NULL) return VP8_ENC_ERROR_OUT_OF_MEMORY;
-
for (y = 0; y < height; ++y) {
for (x = 0; x < width; ++x) {
- const uint32_t pix = src[x];
+ const uint32_t pix = argb[x];
for (i = 0; i < palette_size; ++i) {
if (pix == palette[i]) {
- row[x] = i;
+ argb[x] = 0xff000000u | (i << 8);
break;
}
}
}
- BundleColorMap(row, width, xbits, dst);
- src += pic->argb_stride;
- dst += enc->current_width_;
+ argb += pic->argb_stride;
}
// Save palette to bitstream.
@@ -892,8 +875,20 @@ static WebPEncodingError ApplyPalette(VP8LBitWriter* const bw,
goto Error;
}
+ if (palette_size <= 16) {
+ // Image can be packed (multiple pixels per uint32_t).
+ int xbits = 1;
+ if (palette_size <= 2) {
+ xbits = 3;
+ } else if (palette_size <= 4) {
+ xbits = 2;
+ }
+ err = AllocateTransformBuffer(enc, VP8LSubSampleSize(width, xbits), height);
+ if (err != VP8_ENC_OK) goto Error;
+ BundleColorMap(pic, xbits, enc->argb_, enc->current_width_);
+ }
+
Error:
- free(row);
return err;
}
@@ -903,13 +898,13 @@ static int GetHistoBits(const WebPConfig* const config,
const WebPPicture* const pic) {
const int width = pic->width;
const int height = pic->height;
- const uint64_t hist_size = sizeof(VP8LHistogram);
+ const size_t hist_size = sizeof(VP8LHistogram);
// Make tile size a function of encoding method (Range: 0 to 6).
int histo_bits = 7 - config->method;
while (1) {
- const uint64_t huff_image_size = VP8LSubSampleSize(width, histo_bits) *
- VP8LSubSampleSize(height, histo_bits) *
- hist_size;
+ const size_t huff_image_size = VP8LSubSampleSize(width, histo_bits) *
+ VP8LSubSampleSize(height, histo_bits) *
+ hist_size;
if (huff_image_size <= MAX_HUFF_IMAGE_SIZE) break;
++histo_bits;
}