15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2011 Google Inc. All Rights Reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// that can be found in the COPYING file in the root of the source 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// tree. An additional intellectual property rights grant can be found 6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// in the file PATENTS. All contributing project authors may 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// be found in the AUTHORS file in the root of the source tree. 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ----------------------------------------------------------------------------- 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// functions for sample output. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Skal (pascal.massimino@gmail.com) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h> 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "../dec/vp8i.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "./webpi.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "../dsp/dsp.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "../dsp/yuv.h" 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "../utils/utils.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Main YUV<->RGB conversion functions 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int EmitYUV(const VP8Io* const io, WebPDecParams* const p) { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPDecBuffer* output = p->output; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebPYUVABuffer* const buf = &output->u.YUVA; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t* const y_dst = buf->y + io->mb_y * buf->y_stride; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t* const u_dst = buf->u + (io->mb_y >> 1) * buf->u_stride; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t* const v_dst = buf->v + (io->mb_y >> 1) * buf->v_stride; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int mb_w = io->mb_w; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int mb_h = io->mb_h; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int uv_w = (mb_w + 1) / 2; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int uv_h = (mb_h + 1) / 2; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (j = 0; j < mb_h; ++j) { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(y_dst + j * buf->y_stride, io->y + j * io->y_stride, mb_w); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (j = 0; j < uv_h; ++j) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(u_dst + j * buf->u_stride, io->u + j * io->uv_stride, uv_w); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(v_dst + j * buf->v_stride, io->v + j * io->uv_stride, uv_w); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return io->mb_h; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Point-sampling U/V sampler. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int EmitSampledRGB(const VP8Io* const io, WebPDecParams* const p) { 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPDecBuffer* const output = p->output; 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPRGBABuffer* const buf = &output->u.RGBA; 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint8_t* const dst = buf->rgba + io->mb_y * buf->stride; 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPSamplerProcessPlane(io->y, io->y_stride, 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io->u, io->v, io->uv_stride, 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dst, buf->stride, io->mb_w, io->mb_h, 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPSamplers[output->colorspace]); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return io->mb_h; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// YUV444 -> RGB conversion 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0 // TODO(skal): this is for future rescaling. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int EmitRGB(const VP8Io* const io, WebPDecParams* const p) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPDecBuffer* output = p->output; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebPRGBABuffer* const buf = &output->u.RGBA; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t* dst = buf->rgba + io->mb_y * buf->stride; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8_t* y_src = io->y; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8_t* u_src = io->u; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8_t* v_src = io->v; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebPYUV444Converter convert = WebPYUV444Converters[output->colorspace]; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int mb_w = io->mb_w; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int last = io->mb_h; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (j = 0; j < last; ++j) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) convert(y_src, u_src, v_src, dst, mb_w); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y_src += io->y_stride; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u_src += io->uv_stride; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v_src += io->uv_stride; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dst += buf->stride; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return io->mb_h; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Fancy upsampling 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef FANCY_UPSAMPLING 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int EmitFancyRGB(const VP8Io* const io, WebPDecParams* const p) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_lines_out = io->mb_h; // a priori guess 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebPRGBABuffer* const buf = &p->output->u.RGBA; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t* dst = buf->rgba + io->mb_y * buf->stride; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPUpsampleLinePairFunc upsample = WebPUpsamplers[p->output->colorspace]; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8_t* cur_y = io->y; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8_t* cur_u = io->u; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8_t* cur_v = io->v; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8_t* top_u = p->tmp_u; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8_t* top_v = p->tmp_v; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y = io->mb_y; 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int y_end = io->mb_y + io->mb_h; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int mb_w = io->mb_w; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int uv_w = (mb_w + 1) / 2; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (y == 0) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First line is special cased. We mirror the u/v samples at boundary. 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, mb_w); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can finish the left-over line from previous call. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) upsample(p->tmp_y, cur_y, top_u, top_v, cur_u, cur_v, 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dst - buf->stride, dst, mb_w); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++num_lines_out; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Loop over each output pairs of row. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; y + 2 < y_end; y += 2) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_u = cur_u; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_v = cur_v; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur_u += io->uv_stride; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur_v += io->uv_stride; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dst += 2 * buf->stride; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur_y += 2 * io->y_stride; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) upsample(cur_y - io->y_stride, cur_y, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_u, top_v, cur_u, cur_v, 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dst - buf->stride, dst, mb_w); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // move to last row 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur_y += io->y_stride; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (io->crop_top + y_end < io->crop_bottom) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Save the unfinished samples for next call (as we're not done yet). 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(p->tmp_y, cur_y, mb_w * sizeof(*p->tmp_y)); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(p->tmp_u, cur_u, uv_w * sizeof(*p->tmp_u)); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(p->tmp_v, cur_v, uv_w * sizeof(*p->tmp_v)); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The fancy upsampler leaves a row unfinished behind 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (except for the very last row) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_lines_out--; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Process the very last row of even-sized picture 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(y_end & 1)) { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dst + buf->stride, NULL, mb_w); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return num_lines_out; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* FANCY_UPSAMPLING */ 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int EmitAlphaYUV(const VP8Io* const io, WebPDecParams* const p) { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8_t* alpha = io->a; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebPYUVABuffer* const buf = &p->output->u.YUVA; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int mb_w = io->mb_w; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int mb_h = io->mb_h; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t* dst = buf->a + io->mb_y * buf->a_stride; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (alpha != NULL) { 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (j = 0; j < mb_h; ++j) { 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(dst, alpha, mb_w * sizeof(*dst)); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alpha += io->width; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dst += buf->a_stride; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (buf->a != NULL) { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the user requested alpha, but there is none, set it to opaque. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (j = 0; j < mb_h; ++j) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(dst, 0xff, mb_w * sizeof(*dst)); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dst += buf->a_stride; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static int GetAlphaSourceRow(const VP8Io* const io, 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const uint8_t** alpha, int* const num_rows) { 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int start_y = io->mb_y; 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *num_rows = io->mb_h; 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Compensate for the 1-line delay of the fancy upscaler. 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is similar to EmitFancyRGB(). 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (io->fancy_upsampling) { 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (start_y == 0) { 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We don't process the last row yet. It'll be done during the next call. 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) --*num_rows; 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) --start_y; 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Fortunately, *alpha data is persistent, so we can go back 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // one row and finish alpha blending, now that the fancy upscaler 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // completed the YUV->RGB interpolation. 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *alpha -= io->width; 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (io->crop_top + io->mb_y + io->mb_h == io->crop_bottom) { 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If it's the very last call, we process all the remaining rows! 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *num_rows = io->crop_bottom - io->crop_top - start_y; 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return start_y; 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int EmitAlphaRGB(const VP8Io* const io, WebPDecParams* const p) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8_t* alpha = io->a; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (alpha != NULL) { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int mb_w = io->mb_w; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WEBP_CSP_MODE colorspace = p->output->colorspace; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int alpha_first = 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (colorspace == MODE_ARGB || colorspace == MODE_Argb); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebPRGBABuffer* const buf = &p->output->u.RGBA; 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int num_rows; 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows); 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8_t* const base_rgba = buf->rgba + start_y * buf->stride; 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8_t* dst = base_rgba + (alpha_first ? 0 : 3); 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t alpha_mask = 0xff; 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int i, j; 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (j = 0; j < num_rows; ++j) { 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (i = 0; i < mb_w; ++i) { 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const uint32_t alpha_value = alpha[i]; 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dst[4 * i] = alpha_value; 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) alpha_mask &= alpha_value; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) alpha += io->width; 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dst += buf->stride; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // alpha_mask is < 0xff if there's non-trivial alpha to premultiply with. 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (alpha_mask != 0xff && WebPIsPremultipliedMode(colorspace)) { 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebPApplyAlphaMultiply(base_rgba, alpha_first, 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mb_w, num_rows, buf->stride); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int EmitAlphaRGBA4444(const VP8Io* const io, WebPDecParams* const p) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8_t* alpha = io->a; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (alpha != NULL) { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int mb_w = io->mb_w; 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const WEBP_CSP_MODE colorspace = p->output->colorspace; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebPRGBABuffer* const buf = &p->output->u.RGBA; 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int num_rows; 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int start_y = GetAlphaSourceRow(io, &alpha, &num_rows); 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8_t* const base_rgba = buf->rgba + start_y * buf->stride; 2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef WEBP_SWAP_16BIT_CSP 2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint8_t* alpha_dst = base_rgba; 2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t* alpha_dst = base_rgba + 1; 2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t alpha_mask = 0x0f; 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int i, j; 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (j = 0; j < num_rows; ++j) { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < mb_w; ++i) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fill in the alpha value (converted to 4 bits). 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const uint32_t alpha_value = alpha[i] >> 4; 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value; 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) alpha_mask &= alpha_value; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alpha += io->width; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alpha_dst += buf->stride; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (alpha_mask != 0x0f && WebPIsPremultipliedMode(colorspace)) { 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebPApplyAlphaMultiply4444(base_rgba, mb_w, num_rows, buf->stride); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// YUV rescaling (no final RGB conversion needed) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int Rescale(const uint8_t* src, int src_stride, 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int new_lines, WebPRescaler* const wrk) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_lines_out = 0; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (new_lines > 0) { // import new contributions of source rows. 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int lines_in = WebPRescalerImport(wrk, new_lines, src, src_stride); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) src += lines_in * src_stride; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_lines -= lines_in; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_lines_out += WebPRescalerExport(wrk); // emit output row(s) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return num_lines_out; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int EmitRescaledYUV(const VP8Io* const io, WebPDecParams* const p) { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int mb_h = io->mb_h; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int uv_mb_h = (mb_h + 1) >> 1; 2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPRescaler* const scaler = &p->scaler_y; 2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int num_lines_out = 0; 2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (WebPIsAlphaMode(p->output->colorspace) && io->a != NULL) { 2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Before rescaling, we premultiply the luma directly into the io->y 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // internal buffer. This is OK since these samples are not used for 2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // intra-prediction (the top samples are saved in cache_y_/u_/v_). 2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // But we need to cast the const away, though. 2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPMultRows((uint8_t*)io->y, io->y_stride, 2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io->a, io->width, io->mb_w, mb_h, 0); 2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) num_lines_out = Rescale(io->y, io->y_stride, mb_h, scaler); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Rescale(io->u, io->uv_stride, uv_mb_h, &p->scaler_u); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Rescale(io->v, io->uv_stride, uv_mb_h, &p->scaler_v); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return num_lines_out; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int EmitRescaledAlphaYUV(const VP8Io* const io, WebPDecParams* const p) { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (io->a != NULL) { 3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const WebPYUVABuffer* const buf = &p->output->u.YUVA; 3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint8_t* dst_y = buf->y + p->last_y * buf->y_stride; 3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const uint8_t* src_a = buf->a + p->last_y * buf->a_stride; 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int num_lines_out = Rescale(io->a, io->width, io->mb_h, &p->scaler_a); 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (num_lines_out > 0) { // unmultiply the Y 3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPMultRows(dst_y, buf->y_stride, src_a, buf->a_stride, 3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) p->scaler_a.dst_width, num_lines_out, 1); 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int InitYUVRescaler(const VP8Io* const io, WebPDecParams* const p) { 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int has_alpha = WebPIsAlphaMode(p->output->colorspace); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebPYUVABuffer* const buf = &p->output->u.YUVA; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int out_width = io->scaled_width; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int out_height = io->scaled_height; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int uv_out_width = (out_width + 1) >> 1; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int uv_out_height = (out_height + 1) >> 1; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int uv_in_width = (io->mb_w + 1) >> 1; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int uv_in_height = (io->mb_h + 1) >> 1; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t work_size = 2 * out_width; // scratch memory for luma rescaler 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t uv_work_size = 2 * uv_out_width; // and for each u/v ones 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t tmp_size; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32_t* work; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tmp_size = (work_size + 2 * uv_work_size) * sizeof(*work); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_alpha) { 3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tmp_size += work_size * sizeof(*work); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) p->memory = WebPSafeCalloc(1ULL, tmp_size); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p->memory == NULL) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; // memory error 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) work = (int32_t*)p->memory; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h, 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf->y, out_width, out_height, buf->y_stride, 1, 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io->mb_w, out_width, io->mb_h, out_height, 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) work); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height, 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf->u, uv_out_width, uv_out_height, buf->u_stride, 1, 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uv_in_width, uv_out_width, 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uv_in_height, uv_out_height, 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) work + work_size); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height, 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf->v, uv_out_width, uv_out_height, buf->v_stride, 1, 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uv_in_width, uv_out_width, 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uv_in_height, uv_out_height, 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) work + work_size + uv_work_size); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->emit = EmitRescaledYUV; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_alpha) { 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h, 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf->a, out_width, out_height, buf->a_stride, 1, 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io->mb_w, out_width, io->mb_h, out_height, 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) work + work_size + 2 * uv_work_size); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->emit_alpha = EmitRescaledAlphaYUV; 3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPInitAlphaProcessing(); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RGBA rescaling 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ExportRGB(WebPDecParams* const p, int y_pos) { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebPYUV444Converter convert = 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPYUV444Converters[p->output->colorspace]; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebPRGBABuffer* const buf = &p->output->u.RGBA; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t* dst = buf->rgba + (p->last_y + y_pos) * buf->stride; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_lines_out = 0; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For RGB rescaling, because of the YUV420, current scan position 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // U/V can be +1/-1 line from the Y one. Hence the double test. 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (WebPRescalerHasPendingOutput(&p->scaler_y) && 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPRescalerHasPendingOutput(&p->scaler_u)) { 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(p->last_y + y_pos + num_lines_out < p->output->height); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(p->scaler_u.y_accum == p->scaler_v.y_accum); 3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPRescalerExportRow(&p->scaler_y, 0); 3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPRescalerExportRow(&p->scaler_u, 0); 3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPRescalerExportRow(&p->scaler_v, 0); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) convert(p->scaler_y.dst, p->scaler_u.dst, p->scaler_v.dst, 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dst, p->scaler_y.dst_width); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dst += buf->stride; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++num_lines_out; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return num_lines_out; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int EmitRescaledRGB(const VP8Io* const io, WebPDecParams* const p) { 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int mb_h = io->mb_h; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int uv_mb_h = (mb_h + 1) >> 1; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j = 0, uv_j = 0; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_lines_out = 0; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (j < mb_h) { 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int y_lines_in = 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPRescalerImport(&p->scaler_y, mb_h - j, 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io->y + j * io->y_stride, io->y_stride); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int u_lines_in = 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPRescalerImport(&p->scaler_u, uv_mb_h - uv_j, 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io->u + uv_j * io->uv_stride, io->uv_stride); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int v_lines_in = 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPRescalerImport(&p->scaler_v, uv_mb_h - uv_j, 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io->v + uv_j * io->uv_stride, io->uv_stride); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)v_lines_in; // remove a gcc warning 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(u_lines_in == v_lines_in); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j += y_lines_in; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uv_j += u_lines_in; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_lines_out += ExportRGB(p, num_lines_out); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return num_lines_out; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ExportAlpha(WebPDecParams* const p, int y_pos) { 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebPRGBABuffer* const buf = &p->output->u.RGBA; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t* const base_rgba = buf->rgba + (p->last_y + y_pos) * buf->stride; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WEBP_CSP_MODE colorspace = p->output->colorspace; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int alpha_first = 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (colorspace == MODE_ARGB || colorspace == MODE_Argb); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t* dst = base_rgba + (alpha_first ? 0 : 3); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_lines_out = 0; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t alpha_mask = 0xff; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int width = p->scaler_a.dst_width; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (WebPRescalerHasPendingOutput(&p->scaler_a)) { 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(p->last_y + y_pos + num_lines_out < p->output->height); 4285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPRescalerExportRow(&p->scaler_a, 0); 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (i = 0; i < width; ++i) { 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const uint32_t alpha_value = p->scaler_a.dst[i]; 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dst[4 * i] = alpha_value; 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) alpha_mask &= alpha_value; 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dst += buf->stride; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++num_lines_out; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (is_premult_alpha && alpha_mask != 0xff) { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPApplyAlphaMultiply(base_rgba, alpha_first, 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) width, num_lines_out, buf->stride); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return num_lines_out; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int ExportAlphaRGBA4444(WebPDecParams* const p, int y_pos) { 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebPRGBABuffer* const buf = &p->output->u.RGBA; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t* const base_rgba = buf->rgba + (p->last_y + y_pos) * buf->stride; 4475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef WEBP_SWAP_16BIT_CSP 4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uint8_t* alpha_dst = base_rgba; 4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t* alpha_dst = base_rgba + 1; 4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_lines_out = 0; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WEBP_CSP_MODE colorspace = p->output->colorspace; 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int width = p->scaler_a.dst_width; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int is_premult_alpha = WebPIsPremultipliedMode(colorspace); 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t alpha_mask = 0x0f; 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (WebPRescalerHasPendingOutput(&p->scaler_a)) { 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(p->last_y + y_pos + num_lines_out < p->output->height); 4615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPRescalerExportRow(&p->scaler_a, 0); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < width; ++i) { 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fill in the alpha value (converted to 4 bits). 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const uint32_t alpha_value = p->scaler_a.dst[i] >> 4; 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) alpha_dst[2 * i] = (alpha_dst[2 * i] & 0xf0) | alpha_value; 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) alpha_mask &= alpha_value; 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alpha_dst += buf->stride; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++num_lines_out; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (is_premult_alpha && alpha_mask != 0x0f) { 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPApplyAlphaMultiply4444(base_rgba, width, num_lines_out, buf->stride); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return num_lines_out; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int EmitRescaledAlphaRGB(const VP8Io* const io, WebPDecParams* const p) { 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (io->a != NULL) { 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPRescaler* const scaler = &p->scaler_a; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j = 0; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pos = 0; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (j < io->mb_h) { 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j += WebPRescalerImport(scaler, io->mb_h - j, 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io->a + j * io->width, io->width); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos += p->emit_alpha_row(p, pos); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int InitRGBRescaler(const VP8Io* const io, WebPDecParams* const p) { 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int has_alpha = WebPIsAlphaMode(p->output->colorspace); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int out_width = io->scaled_width; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int out_height = io->scaled_height; 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int uv_in_width = (io->mb_w + 1) >> 1; 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int uv_in_height = (io->mb_h + 1) >> 1; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t work_size = 2 * out_width; // scratch memory for one rescaler 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32_t* work; // rescalers work area 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t* tmp; // tmp storage for scaled YUV444 samples before RGB conversion 5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t tmp_size1, tmp_size2, total_size; 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp_size1 = 3 * work_size; 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp_size2 = 3 * out_width; 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_alpha) { 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp_size1 += work_size; 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp_size2 += out_width; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) total_size = tmp_size1 * sizeof(*work) + tmp_size2 * sizeof(*tmp); 5095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) p->memory = WebPSafeCalloc(1ULL, total_size); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p->memory == NULL) { 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; // memory error 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) work = (int32_t*)p->memory; 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp = (uint8_t*)(work + tmp_size1); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPRescalerInit(&p->scaler_y, io->mb_w, io->mb_h, 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp + 0 * out_width, out_width, out_height, 0, 1, 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io->mb_w, out_width, io->mb_h, out_height, 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) work + 0 * work_size); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPRescalerInit(&p->scaler_u, uv_in_width, uv_in_height, 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp + 1 * out_width, out_width, out_height, 0, 1, 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io->mb_w, 2 * out_width, io->mb_h, 2 * out_height, 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) work + 1 * work_size); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPRescalerInit(&p->scaler_v, uv_in_width, uv_in_height, 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp + 2 * out_width, out_width, out_height, 0, 1, 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io->mb_w, 2 * out_width, io->mb_h, 2 * out_height, 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) work + 2 * work_size); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->emit = EmitRescaledRGB; 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_alpha) { 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPRescalerInit(&p->scaler_a, io->mb_w, io->mb_h, 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp + 3 * out_width, out_width, out_height, 0, 1, 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io->mb_w, out_width, io->mb_h, out_height, 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) work + 3 * work_size); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->emit_alpha = EmitRescaledAlphaRGB; 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p->output->colorspace == MODE_RGBA_4444 || 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->output->colorspace == MODE_rgbA_4444) { 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->emit_alpha_row = ExportAlphaRGBA4444; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->emit_alpha_row = ExportAlpha; 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPInitAlphaProcessing(); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Default custom functions 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int CustomSetup(VP8Io* io) { 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPDecParams* const p = (WebPDecParams*)io->opaque; 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WEBP_CSP_MODE colorspace = p->output->colorspace; 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int is_rgb = WebPIsRGBMode(colorspace); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int is_alpha = WebPIsAlphaMode(colorspace); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->memory = NULL; 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->emit = NULL; 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->emit_alpha = NULL; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->emit_alpha_row = NULL; 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!WebPIoInitFromOptions(p->options, io, is_alpha ? MODE_YUV : MODE_YUVA)) { 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (is_alpha && WebPIsPremultipliedMode(colorspace)) { 5635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPInitUpsamplers(); 5645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (io->use_scaling) { 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int ok = is_rgb ? InitRGBRescaler(io, p) : InitYUVRescaler(io, p); 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ok) { 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; // memory error 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_rgb) { 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->emit = EmitSampledRGB; // default 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (io->fancy_upsampling) { 5745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef FANCY_UPSAMPLING 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int uv_width = (io->mb_w + 1) >> 1; 5765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) p->memory = WebPSafeMalloc(1ULL, (size_t)(io->mb_w + 2 * uv_width)); 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p->memory == NULL) { 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; // memory error. 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->tmp_y = (uint8_t*)p->memory; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->tmp_u = p->tmp_y + io->mb_w; 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->tmp_v = p->tmp_u + uv_width; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->emit = EmitFancyRGB; 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPInitUpsamplers(); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 5865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 5875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPInitSamplers(); 5885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->emit = EmitYUV; 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_alpha) { // need transparency output 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->emit_alpha = 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (colorspace == MODE_RGBA_4444 || colorspace == MODE_rgbA_4444) ? 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EmitAlphaRGBA4444 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : is_rgb ? EmitAlphaRGB 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : EmitAlphaYUV; 5985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (is_rgb) { 5995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPInitAlphaProcessing(); 6005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_rgb) { 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VP8YUVInit(); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int CustomPut(const VP8Io* io) { 6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebPDecParams* const p = (WebPDecParams*)io->opaque; 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int mb_w = io->mb_w; 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int mb_h = io->mb_h; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_lines_out; 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(!(io->mb_y & 1)); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mb_w <= 0 || mb_h <= 0) { 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_lines_out = p->emit(io, p); 6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (p->emit_alpha != NULL) { 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->emit_alpha(io, p); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->last_y += num_lines_out; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void CustomTeardown(const VP8Io* io) { 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebPDecParams* const p = (WebPDecParams*)io->opaque; 6345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) WebPSafeFree(p->memory); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->memory = NULL; 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Main entry point 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WebPInitCustomIo(WebPDecParams* const params, VP8Io* const io) { 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io->put = CustomPut; 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io->setup = CustomSetup; 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io->teardown = CustomTeardown; 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io->opaque = params; 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 649