Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(247)

Side by Side Diff: third_party/libwebp/enc/alpha.c

Issue 16871017: libwebp-0.3.1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 0.3.1 final -> no changes since rc2 Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/libwebp/dsp/yuv.c ('k') | third_party/libwebp/enc/analysis.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 Google Inc. All Rights Reserved. 1 // Copyright 2011 Google Inc. All Rights Reserved.
2 // 2 //
3 // This code is licensed under the same terms as WebM: 3 // Use of this source code is governed by a BSD-style license
4 // Software License Agreement: http://www.webmproject.org/license/software/ 4 // that can be found in the COPYING file in the root of the source
5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ 5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
6 // ----------------------------------------------------------------------------- 8 // -----------------------------------------------------------------------------
7 // 9 //
8 // Alpha-plane compression. 10 // Alpha-plane compression.
9 // 11 //
10 // Author: Skal (pascal.massimino@gmail.com) 12 // Author: Skal (pascal.massimino@gmail.com)
11 13
12 #include <assert.h> 14 #include <assert.h>
13 #include <stdlib.h> 15 #include <stdlib.h>
14 16
15 #include "./vp8enci.h" 17 #include "./vp8enci.h"
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 } 75 }
74 src += width; 76 src += width;
75 dst += picture.argb_stride; 77 dst += picture.argb_stride;
76 } 78 }
77 } 79 }
78 80
79 WebPConfigInit(&config); 81 WebPConfigInit(&config);
80 config.lossless = 1; 82 config.lossless = 1;
81 config.method = effort_level; // impact is very small 83 config.method = effort_level; // impact is very small
82 // Set a moderate default quality setting for alpha. 84 // Set a moderate default quality setting for alpha.
83 config.quality = 5.f * effort_level; 85 config.quality = 10.f * effort_level;
84 assert(config.quality >= 0 && config.quality <= 100.f); 86 assert(config.quality >= 0 && config.quality <= 100.f);
85 87
86 ok = VP8LBitWriterInit(&tmp_bw, (width * height) >> 3); 88 ok = VP8LBitWriterInit(&tmp_bw, (width * height) >> 3);
87 ok = ok && (VP8LEncodeStream(&config, &picture, &tmp_bw) == VP8_ENC_OK); 89 ok = ok && (VP8LEncodeStream(&config, &picture, &tmp_bw) == VP8_ENC_OK);
88 WebPPictureFree(&picture); 90 WebPPictureFree(&picture);
89 if (ok) { 91 if (ok) {
90 const uint8_t* const buffer = VP8LBitWriterFinish(&tmp_bw); 92 const uint8_t* const buffer = VP8LBitWriterFinish(&tmp_bw);
91 const size_t buffer_size = VP8LBitWriterNumBytes(&tmp_bw); 93 const size_t buffer_size = VP8LBitWriterNumBytes(&tmp_bw);
92 VP8BitWriterAppend(bw, buffer, buffer_size); 94 VP8BitWriterAppend(bw, buffer, buffer_size);
93 } 95 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 // TODO(skal): move to dsp/ ? 151 // TODO(skal): move to dsp/ ?
150 static void CopyPlane(const uint8_t* src, int src_stride, 152 static void CopyPlane(const uint8_t* src, int src_stride,
151 uint8_t* dst, int dst_stride, int width, int height) { 153 uint8_t* dst, int dst_stride, int width, int height) {
152 while (height-- > 0) { 154 while (height-- > 0) {
153 memcpy(dst, src, width); 155 memcpy(dst, src, width);
154 src += src_stride; 156 src += src_stride;
155 dst += dst_stride; 157 dst += dst_stride;
156 } 158 }
157 } 159 }
158 160
161 static int GetNumColors(const uint8_t* data, int width, int height,
162 int stride) {
163 int j;
164 int colors = 0;
165 uint8_t color[256] = { 0 };
166
167 for (j = 0; j < height; ++j) {
168 int i;
169 const uint8_t* const p = data + j * stride;
170 for (i = 0; i < width; ++i) {
171 color[p[i]] = 1;
172 }
173 }
174 for (j = 0; j < 256; ++j) {
175 if (color[j] > 0) ++colors;
176 }
177 return colors;
178 }
179
159 static int EncodeAlpha(VP8Encoder* const enc, 180 static int EncodeAlpha(VP8Encoder* const enc,
160 int quality, int method, int filter, 181 int quality, int method, int filter,
161 int effort_level, 182 int effort_level,
162 uint8_t** const output, size_t* const output_size) { 183 uint8_t** const output, size_t* const output_size) {
163 const WebPPicture* const pic = enc->pic_; 184 const WebPPicture* const pic = enc->pic_;
164 const int width = pic->width; 185 const int width = pic->width;
165 const int height = pic->height; 186 const int height = pic->height;
166 187
167 uint8_t* quant_alpha = NULL; 188 uint8_t* quant_alpha = NULL;
168 const size_t data_size = width * height; 189 const size_t data_size = width * height;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 // and Quality:]70, 100] -> Levels:]16, 256]. 221 // and Quality:]70, 100] -> Levels:]16, 256].
201 const int alpha_levels = (quality <= 70) ? (2 + quality / 5) 222 const int alpha_levels = (quality <= 70) ? (2 + quality / 5)
202 : (16 + (quality - 70) * 8); 223 : (16 + (quality - 70) * 8);
203 ok = QuantizeLevels(quant_alpha, width, height, alpha_levels, &sse); 224 ok = QuantizeLevels(quant_alpha, width, height, alpha_levels, &sse);
204 } 225 }
205 226
206 if (ok) { 227 if (ok) {
207 VP8BitWriter bw; 228 VP8BitWriter bw;
208 int test_filter; 229 int test_filter;
209 uint8_t* filtered_alpha = NULL; 230 uint8_t* filtered_alpha = NULL;
231 int try_filter_none = (effort_level > 3);
210 232
211 // We always test WEBP_FILTER_NONE first. 233 if (filter == WEBP_FILTER_FAST) { // Quick estimate of the best candidate.
212 ok = EncodeAlphaInternal(quant_alpha, width, height, 234 const int kMinColorsForFilterNone = 16;
213 method, WEBP_FILTER_NONE, reduce_levels, 235 const int kMaxColorsForFilterNone = 192;
214 effort_level, NULL, &bw, pic->stats); 236 const int num_colors = GetNumColors(quant_alpha, width, height, width);
215 if (!ok) { 237 // For low number of colors, NONE yeilds better compression.
216 VP8BitWriterWipeOut(&bw); 238 filter = (num_colors <= kMinColorsForFilterNone) ? WEBP_FILTER_NONE :
217 goto End; 239 EstimateBestFilter(quant_alpha, width, height, width);
240 // For large number of colors, try FILTER_NONE in addition to the best
241 // filter as well.
242 if (num_colors > kMaxColorsForFilterNone) {
243 try_filter_none = 1;
244 }
218 } 245 }
219 246
220 if (filter == WEBP_FILTER_FAST) { // Quick estimate of a second candidate? 247 // Test for WEBP_FILTER_NONE for higher effort levels.
221 filter = EstimateBestFilter(quant_alpha, width, height, width); 248 if (try_filter_none || filter == WEBP_FILTER_NONE) {
249 ok = EncodeAlphaInternal(quant_alpha, width, height,
250 method, WEBP_FILTER_NONE, reduce_levels,
251 effort_level, NULL, &bw, pic->stats);
252
253 if (!ok) {
254 VP8BitWriterWipeOut(&bw);
255 goto End;
256 }
222 } 257 }
223 // Stop? 258 // Stop?
224 if (filter == WEBP_FILTER_NONE) { 259 if (filter == WEBP_FILTER_NONE) {
225 goto Ok; 260 goto Ok;
226 } 261 }
227 262
228 filtered_alpha = (uint8_t*)malloc(data_size); 263 filtered_alpha = (uint8_t*)malloc(data_size);
229 ok = (filtered_alpha != NULL); 264 ok = (filtered_alpha != NULL);
230 if (!ok) { 265 if (!ok) {
231 goto End; 266 goto End;
232 } 267 }
233 268
234 // Try the other mode(s). 269 // Try the other mode(s).
235 { 270 {
236 WebPAuxStats best_stats; 271 WebPAuxStats best_stats;
237 size_t best_score = VP8BitWriterSize(&bw); 272 size_t best_score = try_filter_none ?
273 VP8BitWriterSize(&bw) : (size_t)~0U;
274 int wipe_tmp_bw = try_filter_none;
238 275
239 memset(&best_stats, 0, sizeof(best_stats)); // prevent spurious warning 276 memset(&best_stats, 0, sizeof(best_stats)); // prevent spurious warning
240 if (pic->stats != NULL) best_stats = *pic->stats; 277 if (pic->stats != NULL) best_stats = *pic->stats;
241 for (test_filter = WEBP_FILTER_HORIZONTAL; 278 for (test_filter =
279 try_filter_none ? WEBP_FILTER_HORIZONTAL : WEBP_FILTER_NONE;
242 ok && (test_filter <= WEBP_FILTER_GRADIENT); 280 ok && (test_filter <= WEBP_FILTER_GRADIENT);
243 ++test_filter) { 281 ++test_filter) {
244 VP8BitWriter tmp_bw; 282 VP8BitWriter tmp_bw;
245 if (filter != WEBP_FILTER_BEST && test_filter != filter) { 283 if (filter != WEBP_FILTER_BEST && test_filter != filter) {
246 continue; 284 continue;
247 } 285 }
248 ok = EncodeAlphaInternal(quant_alpha, width, height, 286 ok = EncodeAlphaInternal(quant_alpha, width, height,
249 method, test_filter, reduce_levels, 287 method, test_filter, reduce_levels,
250 effort_level, filtered_alpha, &tmp_bw, 288 effort_level, filtered_alpha, &tmp_bw,
251 pic->stats); 289 pic->stats);
252 if (ok) { 290 if (ok) {
253 const size_t score = VP8BitWriterSize(&tmp_bw); 291 const size_t score = VP8BitWriterSize(&tmp_bw);
254 if (score < best_score) { 292 if (score < best_score) {
255 // swap bitwriter objects. 293 // swap bitwriter objects.
256 VP8BitWriter tmp = tmp_bw; 294 VP8BitWriter tmp = tmp_bw;
257 tmp_bw = bw; 295 tmp_bw = bw;
258 bw = tmp; 296 bw = tmp;
259 best_score = score; 297 best_score = score;
260 if (pic->stats != NULL) best_stats = *pic->stats; 298 if (pic->stats != NULL) best_stats = *pic->stats;
261 } 299 }
262 } else { 300 } else {
263 VP8BitWriterWipeOut(&bw); 301 VP8BitWriterWipeOut(&bw);
264 } 302 }
265 VP8BitWriterWipeOut(&tmp_bw); 303 if (wipe_tmp_bw) {
304 VP8BitWriterWipeOut(&tmp_bw);
305 }
306 wipe_tmp_bw = 1; // For next filter trial for WEBP_FILTER_BEST.
266 } 307 }
267 if (pic->stats != NULL) *pic->stats = best_stats; 308 if (pic->stats != NULL) *pic->stats = best_stats;
268 } 309 }
269 Ok: 310 Ok:
270 if (ok) { 311 if (ok) {
271 *output_size = VP8BitWriterSize(&bw); 312 *output_size = VP8BitWriterSize(&bw);
272 *output = VP8BitWriterBuf(&bw); 313 *output = VP8BitWriterBuf(&bw);
273 if (pic->stats != NULL) { // need stats? 314 if (pic->stats != NULL) { // need stats?
274 pic->stats->coded_size += (int)(*output_size); 315 pic->stats->coded_size += (int)(*output_size);
275 enc->sse_[3] = sse; 316 enc->sse_[3] = sse;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 free(enc->alpha_data_); 399 free(enc->alpha_data_);
359 enc->alpha_data_ = NULL; 400 enc->alpha_data_ = NULL;
360 enc->alpha_data_size_ = 0; 401 enc->alpha_data_size_ = 0;
361 enc->has_alpha_ = 0; 402 enc->has_alpha_ = 0;
362 return ok; 403 return ok;
363 } 404 }
364 405
365 #if defined(__cplusplus) || defined(c_plusplus) 406 #if defined(__cplusplus) || defined(c_plusplus)
366 } // extern "C" 407 } // extern "C"
367 #endif 408 #endif
OLDNEW
« no previous file with comments | « third_party/libwebp/dsp/yuv.c ('k') | third_party/libwebp/enc/analysis.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698