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

Side by Side Diff: third_party/libwebp/dec/io.c

Issue 12942006: libwebp: update snapshot to v0.3.0-rc6 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: local webkit layout expectations Created 7 years, 9 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
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 // This code is licensed under the same terms as WebM:
4 // Software License Agreement: http://www.webmproject.org/license/software/ 4 // Software License Agreement: http://www.webmproject.org/license/software/
5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ 5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/
6 // ----------------------------------------------------------------------------- 6 // -----------------------------------------------------------------------------
7 // 7 //
8 // functions for sample output. 8 // functions for sample output.
9 // 9 //
10 // Author: Skal (pascal.massimino@gmail.com) 10 // Author: Skal (pascal.massimino@gmail.com)
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 int num_lines_out = io->mb_h; // a priori guess 104 int num_lines_out = io->mb_h; // a priori guess
105 const WebPRGBABuffer* const buf = &p->output->u.RGBA; 105 const WebPRGBABuffer* const buf = &p->output->u.RGBA;
106 uint8_t* dst = buf->rgba + io->mb_y * buf->stride; 106 uint8_t* dst = buf->rgba + io->mb_y * buf->stride;
107 WebPUpsampleLinePairFunc upsample = WebPUpsamplers[p->output->colorspace]; 107 WebPUpsampleLinePairFunc upsample = WebPUpsamplers[p->output->colorspace];
108 const uint8_t* cur_y = io->y; 108 const uint8_t* cur_y = io->y;
109 const uint8_t* cur_u = io->u; 109 const uint8_t* cur_u = io->u;
110 const uint8_t* cur_v = io->v; 110 const uint8_t* cur_v = io->v;
111 const uint8_t* top_u = p->tmp_u; 111 const uint8_t* top_u = p->tmp_u;
112 const uint8_t* top_v = p->tmp_v; 112 const uint8_t* top_v = p->tmp_v;
113 int y = io->mb_y; 113 int y = io->mb_y;
114 int y_end = io->mb_y + io->mb_h; 114 const int y_end = io->mb_y + io->mb_h;
115 const int mb_w = io->mb_w; 115 const int mb_w = io->mb_w;
116 const int uv_w = (mb_w + 1) / 2; 116 const int uv_w = (mb_w + 1) / 2;
117 117
118 if (y == 0) { 118 if (y == 0) {
119 // First line is special cased. We mirror the u/v samples at boundary. 119 // First line is special cased. We mirror the u/v samples at boundary.
120 upsample(NULL, cur_y, cur_u, cur_v, cur_u, cur_v, NULL, dst, mb_w); 120 upsample(NULL, cur_y, cur_u, cur_v, cur_u, cur_v, NULL, dst, mb_w);
121 } else { 121 } else {
122 // We can finish the left-over line from previous call. 122 // We can finish the left-over line from previous call.
123 upsample(p->tmp_y, cur_y, top_u, top_v, cur_u, cur_v, 123 upsample(p->tmp_y, cur_y, top_u, top_v, cur_u, cur_v,
124 dst - buf->stride, dst, mb_w); 124 dst - buf->stride, dst, mb_w);
(...skipping 18 matching lines...) Expand all
143 memcpy(p->tmp_y, cur_y, mb_w * sizeof(*p->tmp_y)); 143 memcpy(p->tmp_y, cur_y, mb_w * sizeof(*p->tmp_y));
144 memcpy(p->tmp_u, cur_u, uv_w * sizeof(*p->tmp_u)); 144 memcpy(p->tmp_u, cur_u, uv_w * sizeof(*p->tmp_u));
145 memcpy(p->tmp_v, cur_v, uv_w * sizeof(*p->tmp_v)); 145 memcpy(p->tmp_v, cur_v, uv_w * sizeof(*p->tmp_v));
146 // The fancy upsampler leaves a row unfinished behind 146 // The fancy upsampler leaves a row unfinished behind
147 // (except for the very last row) 147 // (except for the very last row)
148 num_lines_out--; 148 num_lines_out--;
149 } else { 149 } else {
150 // Process the very last row of even-sized picture 150 // Process the very last row of even-sized picture
151 if (!(y_end & 1)) { 151 if (!(y_end & 1)) {
152 upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, 152 upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v,
153 dst + buf->stride, NULL, mb_w); 153 dst + buf->stride, NULL, mb_w);
154 } 154 }
155 } 155 }
156 return num_lines_out; 156 return num_lines_out;
157 } 157 }
158 158
159 #endif /* FANCY_UPSAMPLING */ 159 #endif /* FANCY_UPSAMPLING */
160 160
161 //------------------------------------------------------------------------------ 161 //------------------------------------------------------------------------------
162 162
163 static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p) { 163 static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p) {
(...skipping 13 matching lines...) Expand all
177 } else if (buf->a != NULL) { 177 } else if (buf->a != NULL) {
178 // the user requested alpha, but there is none, set it to opaque. 178 // the user requested alpha, but there is none, set it to opaque.
179 for (j = 0; j < mb_h; ++j) { 179 for (j = 0; j < mb_h; ++j) {
180 memset(dst, 0xff, mb_w * sizeof(*dst)); 180 memset(dst, 0xff, mb_w * sizeof(*dst));
181 dst += buf->a_stride; 181 dst += buf->a_stride;
182 } 182 }
183 } 183 }
184 return 0; 184 return 0;
185 } 185 }
186 186
187 static int GetAlphaSourceRow(const VP8Io* const io,
188 const uint8_t** alpha, int* const num_rows) {
189 int start_y = io->mb_y;
190 *num_rows = io->mb_h;
191
192 // Compensate for the 1-line delay of the fancy upscaler.
193 // This is similar to EmitFancyRGB().
194 if (io->fancy_upsampling) {
195 if (start_y == 0) {
196 // We don't process the last row yet. It'll be done during the next call.
197 --*num_rows;
fbarchard 2013/03/22 18:56:44 this may be a tad slower than you hope. If perfor
198 } else {
199 --start_y;
200 // Fortunately, *alpha data is persistent, so we can go back
201 // one row and finish alpha blending, now that the fancy upscaler
202 // completed the YUV->RGB interpolation.
203 *alpha -= io->width;
204 }
205 if (io->crop_top + io->mb_y + io->mb_h == io->crop_bottom) {
206 // If it's the very last call, we process all the remaining rows!
207 *num_rows = io->crop_bottom - io->crop_top - start_y;
208 }
209 }
210 return start_y;
211 }
212
187 static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p) { 213 static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
188 const uint8_t* alpha = io->a; 214 const uint8_t* alpha = io->a;
189 if (alpha != NULL) { 215 if (alpha != NULL) {
190 const int mb_w = io->mb_w; 216 const int mb_w = io->mb_w;
191 const int mb_h = io->mb_h;
192 int i, j;
193 const WEBP_CSP_MODE colorspace = p->output->colorspace; 217 const WEBP_CSP_MODE colorspace = p->output->colorspace;
194 const int alpha_first = 218 const int alpha_first =
195 (colorspace == MODE_ARGB || colorspace == MODE_Argb); 219 (colorspace == MODE_ARGB || colorspace == MODE_Argb);
196 const WebPRGBABuffer* const buf = &p->output->u.RGBA; 220 const WebPRGBABuffer* const buf = &p->output->u.RGBA;
197 int start_y = io->mb_y; 221 int num_rows;
198 int num_rows = mb_h; 222 const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
223 uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
224 uint8_t* dst = base_rgba + (alpha_first ? 0 : 3);
fbarchard 2013/03/22 18:56:44 this is a little scarey, but works argb, abgr, bgr
225 uint32_t alpha_mask = 0xff;
226 int i, j;
199 227
200 // We compensate for the 1-line delay of fancy upscaler. 228 for (j = 0; j < num_rows; ++j) {
201 // This is similar to EmitFancyRGB(). 229 for (i = 0; i < mb_w; ++i) {
202 if (io->fancy_upsampling) { 230 const uint32_t alpha_value = alpha[i];
fbarchard 2013/03/22 18:56:44 this code would lend itself to simd. but as C, it'
203 if (start_y == 0) { 231 dst[4 * i] = alpha_value;
204 // We don't process the last row yet. It'll be done during next call. 232 alpha_mask &= alpha_value;
205 --num_rows;
206 } else {
207 --start_y;
208 // Fortunately, *alpha data is persistent, so we can go back
209 // one row and finish alpha blending, now that the fancy upscaler
210 // completed the YUV->RGB interpolation.
211 alpha -= io->width;
212 } 233 }
213 if (io->crop_top + io->mb_y + mb_h == io->crop_bottom) { 234 alpha += io->width;
214 // If it's the very last call, we process all the remaing rows! 235 dst += buf->stride;
215 num_rows = io->crop_bottom - io->crop_top - start_y;
216 }
217 } 236 }
218 { 237 // alpha_mask is < 0xff if there's non-trivial alpha to premultiply with.
219 uint8_t* const base_rgba = buf->rgba + start_y * buf->stride; 238 if (alpha_mask != 0xff && WebPIsPremultipliedMode(colorspace)) {
220 uint8_t* dst = base_rgba + (alpha_first ? 0 : 3); 239 WebPApplyAlphaMultiply(base_rgba, alpha_first,
221 for (j = 0; j < num_rows; ++j) { 240 mb_w, num_rows, buf->stride);
222 for (i = 0; i < mb_w; ++i) dst[4 * i] = alpha[i];
223 alpha += io->width;
224 dst += buf->stride;
225 }
226 if (WebPIsPremultipliedMode(colorspace)) {
227 WebPApplyAlphaMultiply(base_rgba, alpha_first,
228 mb_w, num_rows, buf->stride);
229 }
230 } 241 }
231 } 242 }
232 return 0; 243 return 0;
233 } 244 }
234 245
235 static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p) { 246 static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p) {
236 const uint8_t* alpha = io->a; 247 const uint8_t* alpha = io->a;
237 if (alpha != NULL) { 248 if (alpha != NULL) {
238 const int mb_w = io->mb_w; 249 const int mb_w = io->mb_w;
239 const int mb_h = io->mb_h; 250 const WEBP_CSP_MODE colorspace = p->output->colorspace;
251 const WebPRGBABuffer* const buf = &p->output->u.RGBA;
252 int num_rows;
253 const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows);
254 uint8_t* const base_rgba = buf->rgba + start_y * buf->stride;
255 uint8_t* alpha_dst = base_rgba + 1;
256 uint32_t alpha_mask = 0x0f;
240 int i, j; 257 int i, j;
241 const WebPRGBABuffer* const buf = &p->output->u.RGBA; 258
242 uint8_t* const base_rgba = buf->rgba + io->mb_y * buf->stride; 259 for (j = 0; j < num_rows; ++j) {
243 uint8_t* alpha_dst = base_rgba + 1;
244 for (j = 0; j < mb_h; ++j) {
245 for (i = 0; i < mb_w; ++i) { 260 for (i = 0; i < mb_w; ++i) {
fbarchard 2013/03/22 18:56:44 ditto. unrolling to 2 at a time will help
246 // Fill in the alpha value (converted to 4 bits). 261 // Fill in the alpha value (converted to 4 bits).
247 const uint32_t alpha_val = VP8Clip4Bits(alpha[i]); 262 const uint32_t alpha_value = alpha[i] >> 4;
248 alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_val; 263 alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value;
264 alpha_mask &= alpha_value;
249 } 265 }
250 alpha += io->width; 266 alpha += io->width;
251 alpha_dst += buf->stride; 267 alpha_dst += buf->stride;
252 } 268 }
253 if (p->output->colorspace == MODE_rgbA_4444) { 269 if (alpha_mask != 0x0f && WebPIsPremultipliedMode(colorspace)) {
254 WebPApplyAlphaMultiply4444(base_rgba, mb_w, mb_h, buf->stride); 270 WebPApplyAlphaMultiply4444(base_rgba, mb_w, num_rows, buf->stride);
255 } 271 }
256 } 272 }
257 return 0; 273 return 0;
258 } 274 }
259 275
260 //------------------------------------------------------------------------------ 276 //------------------------------------------------------------------------------
261 // YUV rescaling (no final RGB conversion needed) 277 // YUV rescaling (no final RGB conversion needed)
262 278
263 static int Rescale(const uint8_t* src, int src_stride, 279 static int Rescale(const uint8_t* src, int src_stride,
264 int new_lines, WebPRescaler* const wrk) { 280 int new_lines, WebPRescaler* const wrk) {
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 405
390 static int ExportAlpha(WebPDecParams* const p, int y_pos) { 406 static int ExportAlpha(WebPDecParams* const p, int y_pos) {
391 const WebPRGBABuffer* const buf = &p->output->u.RGBA; 407 const WebPRGBABuffer* const buf = &p->output->u.RGBA;
392 uint8_t* const base_rgba = buf->rgba + (p->last_y + y_pos) * buf->stride; 408 uint8_t* const base_rgba = buf->rgba + (p->last_y + y_pos) * buf->stride;
393 const WEBP_CSP_MODE colorspace = p->output->colorspace; 409 const WEBP_CSP_MODE colorspace = p->output->colorspace;
394 const int alpha_first = 410 const int alpha_first =
395 (colorspace == MODE_ARGB || colorspace == MODE_Argb); 411 (colorspace == MODE_ARGB || colorspace == MODE_Argb);
396 uint8_t* dst = base_rgba + (alpha_first ? 0 : 3); 412 uint8_t* dst = base_rgba + (alpha_first ? 0 : 3);
397 int num_lines_out = 0; 413 int num_lines_out = 0;
398 const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); 414 const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
415 uint32_t alpha_mask = 0xff;
399 const int width = p->scaler_a.dst_width; 416 const int width = p->scaler_a.dst_width;
400 417
401 while (WebPRescalerHasPendingOutput(&p->scaler_a)) { 418 while (WebPRescalerHasPendingOutput(&p->scaler_a)) {
402 int i; 419 int i;
403 assert(p->last_y + y_pos + num_lines_out < p->output->height); 420 assert(p->last_y + y_pos + num_lines_out < p->output->height);
404 WebPRescalerExportRow(&p->scaler_a); 421 WebPRescalerExportRow(&p->scaler_a);
405 for (i = 0; i < width; ++i) dst[4 * i] = p->scaler_a.dst[i]; 422 for (i = 0; i < width; ++i) {
423 const uint32_t alpha_value = p->scaler_a.dst[i];
424 dst[4 * i] = alpha_value;
425 alpha_mask &= alpha_value;
426 }
406 dst += buf->stride; 427 dst += buf->stride;
407 ++num_lines_out; 428 ++num_lines_out;
408 } 429 }
409 if (is_premult_alpha) { 430 if (is_premult_alpha && alpha_mask != 0xff) {
410 WebPApplyAlphaMultiply(base_rgba, alpha_first, 431 WebPApplyAlphaMultiply(base_rgba, alpha_first,
411 width, num_lines_out, buf->stride); 432 width, num_lines_out, buf->stride);
412 } 433 }
413 return num_lines_out; 434 return num_lines_out;
414 } 435 }
415 436
416 static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos) { 437 static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos) {
417 const WebPRGBABuffer* const buf = &p->output->u.RGBA; 438 const WebPRGBABuffer* const buf = &p->output->u.RGBA;
418 uint8_t* const base_rgba = buf->rgba + (p->last_y + y_pos) * buf->stride; 439 uint8_t* const base_rgba = buf->rgba + (p->last_y + y_pos) * buf->stride;
419 uint8_t* alpha_dst = base_rgba + 1; 440 uint8_t* alpha_dst = base_rgba + 1;
420 int num_lines_out = 0; 441 int num_lines_out = 0;
421 const WEBP_CSP_MODE colorspace = p->output->colorspace; 442 const WEBP_CSP_MODE colorspace = p->output->colorspace;
422 const int width = p->scaler_a.dst_width; 443 const int width = p->scaler_a.dst_width;
423 const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); 444 const int is_premult_alpha = WebPIsPremultipliedMode(colorspace);
445 uint32_t alpha_mask = 0x0f;
424 446
425 while (WebPRescalerHasPendingOutput(&p->scaler_a)) { 447 while (WebPRescalerHasPendingOutput(&p->scaler_a)) {
426 int i; 448 int i;
427 assert(p->last_y + y_pos + num_lines_out < p->output->height); 449 assert(p->last_y + y_pos + num_lines_out < p->output->height);
428 WebPRescalerExportRow(&p->scaler_a); 450 WebPRescalerExportRow(&p->scaler_a);
429 for (i = 0; i < width; ++i) { 451 for (i = 0; i < width; ++i) {
430 // Fill in the alpha value (converted to 4 bits). 452 // Fill in the alpha value (converted to 4 bits).
431 const uint32_t alpha_val = VP8Clip4Bits(p->scaler_a.dst[i]); 453 const uint32_t alpha_value = p->scaler_a.dst[i] >> 4;
432 alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_val; 454 alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value;
455 alpha_mask &= alpha_value;
433 } 456 }
434 alpha_dst += buf->stride; 457 alpha_dst += buf->stride;
435 ++num_lines_out; 458 ++num_lines_out;
436 } 459 }
437 if (is_premult_alpha) { 460 if (is_premult_alpha && alpha_mask != 0x0f) {
438 WebPApplyAlphaMultiply4444(base_rgba, width, num_lines_out, buf->stride); 461 WebPApplyAlphaMultiply4444(base_rgba, width, num_lines_out, buf->stride);
439 } 462 }
440 return num_lines_out; 463 return num_lines_out;
441 } 464 }
442 465
443 static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p) { 466 static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p) {
444 if (io->a != NULL) { 467 if (io->a != NULL) {
445 WebPRescaler* const scaler = &p->scaler_a; 468 WebPRescaler* const scaler = &p->scaler_a;
446 int j = 0; 469 int j = 0;
447 int pos = 0; 470 int pos = 0;
(...skipping 16 matching lines...) Expand all
464 int32_t* work; // rescalers work area 487 int32_t* work; // rescalers work area
465 uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion 488 uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion
466 size_t tmp_size1, tmp_size2; 489 size_t tmp_size1, tmp_size2;
467 490
468 tmp_size1 = 3 * work_size; 491 tmp_size1 = 3 * work_size;
469 tmp_size2 = 3 * out_width; 492 tmp_size2 = 3 * out_width;
470 if (has_alpha) { 493 if (has_alpha) {
471 tmp_size1 += work_size; 494 tmp_size1 += work_size;
472 tmp_size2 += out_width; 495 tmp_size2 += out_width;
473 } 496 }
474 p->memory = 497 p->memory = calloc(1, tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp));
475 calloc(1, tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp));
476 if (p->memory == NULL) { 498 if (p->memory == NULL) {
477 return 0; // memory error 499 return 0; // memory error
478 } 500 }
479 work = (int32_t*)p->memory; 501 work = (int32_t*)p->memory;
480 tmp = (uint8_t*)(work + tmp_size1); 502 tmp = (uint8_t*)(work + tmp_size1);
481 WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h, 503 WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h,
482 tmp + 0 * out_width, out_width, out_height, 0, 1, 504 tmp + 0 * out_width, out_width, out_height, 0, 1,
483 io->mb_w, out_width, io->mb_h, out_height, 505 io->mb_w, out_width, io->mb_h, out_height,
484 work + 0 * work_size); 506 work + 0 * work_size);
485 WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height, 507 WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height,
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 584
563 if (is_rgb) { 585 if (is_rgb) {
564 VP8YUVInit(); 586 VP8YUVInit();
565 } 587 }
566 return 1; 588 return 1;
567 } 589 }
568 590
569 //------------------------------------------------------------------------------ 591 //------------------------------------------------------------------------------
570 592
571 static int CustomPut(const VP8Io* io) { 593 static int CustomPut(const VP8Io* io) {
572 WebPDecParams* p = (WebPDecParams*)io->opaque; 594 WebPDecParams* const p = (WebPDecParams*)io->opaque;
573 const int mb_w = io->mb_w; 595 const int mb_w = io->mb_w;
574 const int mb_h = io->mb_h; 596 const int mb_h = io->mb_h;
575 int num_lines_out; 597 int num_lines_out;
576 assert(!(io->mb_y & 1)); 598 assert(!(io->mb_y & 1));
577 599
578 if (mb_w <= 0 || mb_h <= 0) { 600 if (mb_w <= 0 || mb_h <= 0) {
579 return 0; 601 return 0;
580 } 602 }
581 num_lines_out = p->emit(io, p); 603 num_lines_out = p->emit(io, p);
582 if (p->emit_alpha) { 604 if (p->emit_alpha) {
(...skipping 19 matching lines...) Expand all
602 io->setup = CustomSetup; 624 io->setup = CustomSetup;
603 io->teardown = CustomTeardown; 625 io->teardown = CustomTeardown;
604 io->opaque = params; 626 io->opaque = params;
605 } 627 }
606 628
607 //------------------------------------------------------------------------------ 629 //------------------------------------------------------------------------------
608 630
609 #if defined(__cplusplus) || defined(c_plusplus) 631 #if defined(__cplusplus) || defined(c_plusplus)
610 } // extern "C" 632 } // extern "C"
611 #endif 633 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698