From patchwork Mon Aug 30 12:10:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maryla X-Patchwork-Id: 29879 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6602:2a4a:0:0:0:0 with SMTP id k10csp3894472iov; Mon, 30 Aug 2021 05:11:09 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxyyUNfzA53g5RBj2upM5oKg7U2RgIafR6dT52fXaZuBjMTDEwZx7Rjjz4YakkjCHWC0nOx X-Received: by 2002:a17:906:a3c3:: with SMTP id ca3mr24734733ejb.337.1630325468817; Mon, 30 Aug 2021 05:11:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1630325468; cv=none; d=google.com; s=arc-20160816; b=zF0zS81xGKhLEhisj+baIQQUX12Z4cTNYGNpLYb+CKIcpAusfm1odSy9xjxIhqna5n aElMt/dIXuklXkSfT/DqzU08DEZziz5GwRMIGCd4Fd8yntDS4LwBsc98f8dMuucjlOmE wB8j7Wpw/yvNnnO/OR4t718JcD5fnipmzzpomUgq+Wi4na6ob+HYlwkCHyj0JoeuW7K7 saxo7MhakYMDKAFmrvEJztt+AGHC4J33jitHY36ouGjKp4AJWttwZ/O5iMJo6lGG5vUL XYokzT3qz07x2lVTL0blLR+Vk/V8RJ3Qu2ru5WTZm5Vj/Sasyo6Rn/qO9qRc2TYwEiJT xV4Q== 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:references:mime-version:message-id :in-reply-to:date:dkim-signature:delivered-to; bh=16oJv4l72OAqyW9sJXH3s+2d3ZGjAmGSmgfz71Up3fw=; b=rnO4RFHN2KR4ikkWtlpDQLEDMX9wlIsHGgMBJcObqx6Jft5spjVOF9r7lIe0x7RJwV /QB8ncRE9pQTnQ7wA9qtP7ODNdXQCFSadXICpepeIlOTbGVxL18uHi2bwpyZ0ZPpQGNM 1NDirLFBhEgLwLHScHGgK+zab/qddmh/CECsk99QbrCH/cA3A5MSdU3/+2URdl0C94o1 8k1Qk09g8o+6YBcGOl6vv/yw+L2KQlM/AAYv/bHS6i5kEFrEyufm9LIWMpWMxIupmCl9 evCVffHPHuK1Zzy2u04+gbZ4O/qG+3BzM4UYKD45+sS4V3bg+OfIDtsVQa2crX3TX+xu wbww== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@google.com header.s=20161025 header.b=LhyabFVi; 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 s18si9652134eji.655.2021.08.30.05.11.07; Mon, 30 Aug 2021 05:11:08 -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=LhyabFVi; 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 42AA7689902; Mon, 30 Aug 2021 15:11:03 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f73.google.com (mail-wm1-f73.google.com [209.85.128.73]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 712D1680C28 for ; Mon, 30 Aug 2021 15:10:56 +0300 (EEST) Received: by mail-wm1-f73.google.com with SMTP id c4-20020a1c9a04000000b002e864b7edd1so4624993wme.6 for ; Mon, 30 Aug 2021 05:10:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to; bh=ZwkjYik8oepQ7OAg6nY/rlCWmDBJ/TH+b2ZYV/ng5T8=; b=LhyabFViP/r0020uv6uo9uP2je6/XfyBC5jNNsPiHS6yyEImMIWY8FmK/5zLJg/veY Z83fDESv9hI3k3iDzYtg4nvH4Kpj8K0ManN0NQMKhKeC6i/tN1xUB9705FrdoD2yVgIq WW5NvdMH8vkQQ1JBG5/7hO1fweex191laoQVAIr9vNii+TiqJ2sdDPLQu5tAYrKilNZH nHkOMhfVjzN+mJrcTIq/B/2my4sXgQMRPnMZ+sHCzSxYJzbeqQ686oyMq8Hmvr1Zz5SJ v4SC5Kcf6q+7qejNTZtw7owUoLMX1GyIymZDn2OstD7w52zzO1xtsjGPyJ7+PkMSz9Bj McDA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to; bh=ZwkjYik8oepQ7OAg6nY/rlCWmDBJ/TH+b2ZYV/ng5T8=; b=ULSThBE7PAqTz/4t3e56A6FESrasgOxsTusAEFGkcyAV+b5XbDQpSTNXyldFOmQTOh gKK3JM9dcahQqwGEa1KbsPcKDjinpAkPG7MAmd45VZmu4bY27WiKJ56raOTZNbLLAObX //g6hzFbNOwCeqj8TrFqEsXON10YNk1pL/mLHZP3UkWBKHq4J1UtFN5qzyPACQSOofrq zpLy5wQVbB+zo3BSqk8c5kZw1GZj0L36SsTtuszMo3tc4CDQgwR5ddZ38wqNn4oxeTGf jozTyoKsmO3rk9DJ1irlwC7Ljs1LhXB/tIAtfgrPFL6bbTHacXTKVWIM0JXc5sH/yESS /wHw== X-Gm-Message-State: AOAM5328dwZicK39v/l0XvXc+Y7uHzn7lhkCDJ5+tNUd6oTEV5eK0Dse A6yCj3DnEKBj+NmemQVwwRsVa7ISMT+msIOkB4mnz0wXgSqIPVlqrG+koBHUV+gPutIaUj5Bq8G ZiGoj8l4CycUukI0J9jdC40pKUXlNNmSs5BStMNy5AYmmGwRarMtq1EEBdva0ktA= X-Received: from maryla2.par.corp.google.com ([2a00:79e0:a0:1:75d:76cc:bb53:b417]) (user=maryla job=sendgmr) by 2002:a05:600c:1c2a:: with SMTP id j42mr686741wms.0.1630325455022; Mon, 30 Aug 2021 05:10:55 -0700 (PDT) Date: Mon, 30 Aug 2021 14:10:51 +0200 In-Reply-To: Message-Id: <20210830121051.1703262-1-maryla@google.com> Mime-Version: 1.0 References: X-Mailer: git-send-email 2.33.0.259.gc128427fd7-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: drRbE2T0IPcS 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. Updated patch with added fate test. The source image dual_transform.webp can be downloaded by cloning https://chromium.googlesource.com/webm/libwebp-test-data/ Fixes: 9368 --- libavcodec/webp.c | 34 ++++++++++--------- tests/fate/image.mak | 3 ++ .../fate/webp-rgb-lossless-palette-predictor | 6 ++++ 3 files changed, 27 insertions(+), 16 deletions(-) create mode 100644 tests/ref/fate/webp-rgb-lossless-palette-predictor diff --git a/libavcodec/webp.c b/libavcodec/webp.c index 3efd4438d9..e4c67adc3a 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; @@ -925,7 +926,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); @@ -965,7 +966,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); @@ -985,7 +986,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]; @@ -1004,7 +1005,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; @@ -1030,6 +1031,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 @@ -1126,7 +1128,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); diff --git a/tests/fate/image.mak b/tests/fate/image.mak index 3b58972a53..ea9c801990 100644 --- a/tests/fate/image.mak +++ b/tests/fate/image.mak @@ -517,6 +517,9 @@ fate-webp-rgb-lena-lossless-rgb24: CMD = framecrc -i $(TARGET_SAMPLES)/webp/rgb_ FATE_WEBP += fate-webp-rgba-lossless fate-webp-rgba-lossless: CMD = framecrc -i $(TARGET_SAMPLES)/webp/rgba_lossless.webp +FATE_WEBP += fate-webp-rgb-lossless-palette-predictor +fate-webp-rgb-lossless-palette-predictor: CMD = framecrc -i $(TARGET_SAMPLES)/webp/dual_transform.webp + FATE_WEBP += fate-webp-rgb-lossy-q80 fate-webp-rgb-lossy-q80: CMD = framecrc -i $(TARGET_SAMPLES)/webp/rgb_q80.webp diff --git a/tests/ref/fate/webp-rgb-lossless-palette-predictor b/tests/ref/fate/webp-rgb-lossless-palette-predictor new file mode 100644 index 0000000000..92a4ad9810 --- /dev/null +++ b/tests/ref/fate/webp-rgb-lossless-palette-predictor @@ -0,0 +1,6 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 100x30 +#sar 0: 0/1 +0, 0, 0, 1, 12000, 0xb200d843