From patchwork Thu Aug 19 07:56:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maryla X-Patchwork-Id: 29611 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6602:2a4a:0:0:0:0 with SMTP id k10csp71956iov; Thu, 19 Aug 2021 00:56:25 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxVNWLwYcXxOHc5vaubScqgrMYbDors1Qyvt/lSLPIzMCgdGQHgPMWtBl+XFtItqT6CdX8l X-Received: by 2002:a17:906:165a:: with SMTP id n26mr14503277ejd.236.1629359785003; Thu, 19 Aug 2021 00:56:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1629359784; cv=none; d=google.com; s=arc-20160816; b=fAawz0c/tUmNevnDqL6Cf8nOvAAddf3VQOihlSmILPJPr87UKVxTL6LDRCHLOzaIs7 bUSpV7JD8SiKd9ZSMM2dwplhldoZuAO93WhBFEU+ItmpgeLYAk7e3uRZBLthHFybD653 P4IxkSXnZ5LeW00iH+m77BafDfxnbZGSgZZotNKgOcN9Un/7Puxc8Z/L7g/byHRQ6Tc9 iQjV6djNC+FJeIn3SYn7hx8sfJKTVk83DBd+DKOfeTMmkxOpQAnQtOerxIOCwdJ195eL V3wCH4fO6iU3zAVcS1hm10B/7A+qgVjjqMkFYA6pxIfM/h7BsPKaVUPp9d8LzvrSLPJu m2mg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:to:from:mime-version:message-id:date :dkim-signature:delivered-to; bh=Pzd9LZfTF31QDkYyLzCpOe03ZSUCV+PNbspz8XEbbWQ=; b=K8dG8oIy0wmRKUdoSLrrq5iMuLGBnSKXN5UqF6un9ca7kDZChhWjXc/ifHrSvQBAsi K8B18sbpsMBx6vM8AG39yUNOKlB5Mk5lRT+QKXNws9qyPtxPzuan3/q20qVrhGPpaJlM HkKVIohGfo9IwxpgnYzZ01kUb0JQj4kdzo3wu0PdgYliRjQx4q1+sYeb/QdOs6C9UMFZ NN1eXTf6BOIhwyE0nzbJSfGJDO3r2jfszHh9btnK4JY2GbcRvVeMcQPQQex4m6RDh9SX cfBMUbMKvCMLWrlmIEat+IUseFXiuLVRGkiSJodaGQN+4cGdJOQcW8kgrCYapUtzvOen lxyA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@google.com header.s=20161025 header.b=nCh6tzO4; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id o5si2663640ejd.0.2021.08.19.00.56.22; Thu, 19 Aug 2021 00:56:24 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@google.com header.s=20161025 header.b=nCh6tzO4; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id C66A1689AA0; Thu, 19 Aug 2021 10:56:20 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-qk1-f201.google.com (mail-qk1-f201.google.com [209.85.222.201]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id D2620688051 for ; Thu, 19 Aug 2021 10:56:13 +0300 (EEST) Received: by mail-qk1-f201.google.com with SMTP id k5-20020a05620a414500b003d5da483eafso680429qko.22 for ; Thu, 19 Aug 2021 00:56:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to; bh=DWFdDtOuI44Jyt0c+ZlcQs007SXmY3DMWtO4aE2gVvE=; b=nCh6tzO45oEV54QvTbz3GR898Wh/xAHcHP8IPRqJV5kkkkUbz3GVPDEzDXbYwegbbr KnDyN4THal9givGEI+UwJypwq9OlENARRaLL39GWssYRAgw9bZOub2AYICNt7uyjnsRN t8IAYklrLlODiBH5STlyMZmRLcrCKW462Yr6TnLV0GA1JRwnOpeaQR7UYGjoRnf47eEh g6KQ+jFwFYOjrcAz5EhWAtZ9H5YVDcceBUJMXILQtYegLHmkRH2BfYTpNtaIz46vYhxq xyYoJ1Aj0bHztQffXvtE/T5jfF9X3FtFD9kEQIOVYlx9qssWN7bBXrU/b7pVGDQ0uk5j uCVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:mime-version:subject:from:to; bh=DWFdDtOuI44Jyt0c+ZlcQs007SXmY3DMWtO4aE2gVvE=; b=HEofGb83zBbuQs28JBq/C74MphFaNSuq1nodLi2rAZof2gIjMZ6FDswlVdFnYwn6+w OENiPMJjHTygoYwllWcN5iYXeGqZlUuX5OqHB8q/oOnsVf9qpAfCL2dgC1NNNDBKcjfD ybz5LZ4zipIgCXsYbxVW8ymKq9YOQPeqMgODBpKI0zLOb9PbZ6XPlShMX/zs6iI7F+cz V/3VNpA/h8MhjIi/Q30SDlfSbjxXYIHq/i15yxhsJKFrYzlRVxkMrRHBJUzOMj++Xc4i QlHOR69ukn8pv6DgPSlT48dg6wrj/50XGxbtt8S/P9x0xpCIeH2QGc0/4D5YtlspTiUj GMpw== X-Gm-Message-State: AOAM531sVrcP+fs+aBCPSvPARfMETAxZ5oKrlMO+4se3R/uSaE+9Qzzp VMCimCS8OB4b/43zNCXPPDeG41Srt72ndCcjrihUzzpPU0jAnMM6jOHxkSbARM089Hr+HE1jp5t Y9ySAk4Us4BdH+APWQVtqRuZwxKTxEyWnIL9kVAK928rPsQdXv8nSHeBk1qM0yNA= X-Received: from maryla2.par.corp.google.com ([2a00:79e0:a0:1:aa11:89c3:850:9ea2]) (user=maryla job=sendgmr) by 2002:a0c:a916:: with SMTP id y22mr13119666qva.34.1629359772321; Thu, 19 Aug 2021 00:56:12 -0700 (PDT) Date: Thu, 19 Aug 2021 09:56:09 +0200 Message-Id: <20210819075609.20021-1-maryla@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.33.0.rc1.237.g0d66db33f3-goog From: Maryla To: ffmpeg-devel@ffmpeg.org Subject: [FFmpeg-devel] [PATCH] webp: fix transforms after a palette with pixel packing. X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: PQBu21g9eVcV When a color indexing transform with 16 or fewer colors is used, WebP uses "pixel packing", i.e. storing several pixels in one byte, which virtually reduces the width of the image (see WebPContext's reduced_width field). This reduced_width should always be used when reading and applying subsequent transforms. Fixes: 9368 --- libavcodec/webp.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/libavcodec/webp.c b/libavcodec/webp.c index 83371ef6fd..52e5a4f65a 100644 --- a/libavcodec/webp.c +++ b/libavcodec/webp.c @@ -181,7 +181,10 @@ typedef struct ImageContext { uint32_t *color_cache; /* color cache data */ int nb_huffman_groups; /* number of huffman groups */ HuffReader *huffman_groups; /* reader for each huffman group */ - int size_reduction; /* relative size compared to primary image, log2 */ + /* relative size compared to primary image, log2. + * for IMAGE_ROLE_COLOR_INDEXING with <= 16 colors, this is log2 of the + * number of pixels per byte in the primary image (pixel packing) */ + int size_reduction; int is_alpha_primary; } ImageContext; @@ -205,7 +208,9 @@ typedef struct WebPContext { int nb_transforms; /* number of transforms */ enum TransformType transforms[4]; /* transformations used in the image, in order */ - int reduced_width; /* reduced width for index image, if applicable */ + /* reduced width when using a color indexing transform with <= 16 colors (pixel packing) + * before pixels are unpacked, or same as width otherwise. */ + int reduced_width; int nb_huffman_groups; /* number of huffman groups in the primary image */ ImageContext image[IMAGE_ROLE_NB]; /* image context for each role */ } WebPContext; @@ -425,13 +430,9 @@ static int decode_entropy_coded_image(WebPContext *s, enum ImageRole role, static int decode_entropy_image(WebPContext *s) { ImageContext *img; - int ret, block_bits, width, blocks_w, blocks_h, x, y, max; + int ret, block_bits, blocks_w, blocks_h, x, y, max; - width = s->width; - if (s->reduced_width > 0) - width = s->reduced_width; - - PARSE_BLOCK_SIZE(width, s->height); + PARSE_BLOCK_SIZE(s->reduced_width, s->height); ret = decode_entropy_coded_image(s, IMAGE_ROLE_ENTROPY, blocks_w, blocks_h); if (ret < 0) @@ -460,7 +461,7 @@ static int parse_transform_predictor(WebPContext *s) { int block_bits, blocks_w, blocks_h, ret; - PARSE_BLOCK_SIZE(s->width, s->height); + PARSE_BLOCK_SIZE(s->reduced_width, s->height); ret = decode_entropy_coded_image(s, IMAGE_ROLE_PREDICTOR, blocks_w, blocks_h); @@ -476,7 +477,7 @@ static int parse_transform_color(WebPContext *s) { int block_bits, blocks_w, blocks_h, ret; - PARSE_BLOCK_SIZE(s->width, s->height); + PARSE_BLOCK_SIZE(s->reduced_width, s->height); ret = decode_entropy_coded_image(s, IMAGE_ROLE_COLOR_TRANSFORM, blocks_w, blocks_h); @@ -620,7 +621,7 @@ static int decode_entropy_coded_image(WebPContext *s, enum ImageRole role, } width = img->frame->width; - if (role == IMAGE_ROLE_ARGB && s->reduced_width > 0) + if (role == IMAGE_ROLE_ARGB) width = s->reduced_width; x = 0; y = 0; @@ -922,7 +923,7 @@ static int apply_predictor_transform(WebPContext *s) int x, y; for (y = 0; y < img->frame->height; y++) { - for (x = 0; x < img->frame->width; x++) { + for (x = 0; x < s->reduced_width; x++) { int tx = x >> pimg->size_reduction; int ty = y >> pimg->size_reduction; enum PredictionMode m = GET_PIXEL_COMP(pimg->frame, tx, ty, 2); @@ -962,7 +963,7 @@ static int apply_color_transform(WebPContext *s) cimg = &s->image[IMAGE_ROLE_COLOR_TRANSFORM]; for (y = 0; y < img->frame->height; y++) { - for (x = 0; x < img->frame->width; x++) { + for (x = 0; x < s->reduced_width; x++) { cx = x >> cimg->size_reduction; cy = y >> cimg->size_reduction; cp = GET_PIXEL(cimg->frame, cx, cy); @@ -982,7 +983,7 @@ static int apply_subtract_green_transform(WebPContext *s) ImageContext *img = &s->image[IMAGE_ROLE_ARGB]; for (y = 0; y < img->frame->height; y++) { - for (x = 0; x < img->frame->width; x++) { + for (x = 0; x < s->reduced_width; x++) { uint8_t *p = GET_PIXEL(img->frame, x, y); p[1] += p[2]; p[3] += p[2]; @@ -1001,7 +1002,7 @@ static int apply_color_indexing_transform(WebPContext *s) img = &s->image[IMAGE_ROLE_ARGB]; pal = &s->image[IMAGE_ROLE_COLOR_INDEXING]; - if (pal->size_reduction > 0) { + if (pal->size_reduction > 0) { // undo pixel packing GetBitContext gb_g; uint8_t *line; int pixel_bits = 8 >> pal->size_reduction; @@ -1027,6 +1028,7 @@ static int apply_color_indexing_transform(WebPContext *s) } } av_free(line); + s->reduced_width = s->width; // we are back to full size } // switch to local palette if it's worth initializing it @@ -1123,7 +1125,7 @@ static int vp8_lossless_decode_frame(AVCodecContext *avctx, AVFrame *p, /* parse transformations */ s->nb_transforms = 0; - s->reduced_width = 0; + s->reduced_width = s->width; used = 0; while (get_bits1(&s->gb)) { enum TransformType transform = get_bits(&s->gb, 2);