go-libwebp

Experimental translation from libwebp to Go source.
Log | Files | Refs | README | LICENSE

enc_dec_fuzzer.cc (5367B)


      1 // Copyright 2018 Google Inc.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 //
     15 ////////////////////////////////////////////////////////////////////////////////
     16 
     17 #include <cstddef>
     18 #include <cstdint>
     19 #include <cstdio>
     20 #include <cstdlib>
     21 
     22 #include "./fuzz_utils.h"
     23 #include "src/dsp/cpu.h"
     24 #include "src/webp/decode.h"
     25 #include "src/webp/encode.h"
     26 
     27 namespace {
     28 
     29 const VP8CPUInfo default_VP8GetCPUInfo = fuzz_utils::VP8GetCPUInfo;
     30 
     31 void EncDecTest(bool use_argb, int source_image_index, WebPConfig config,
     32                 int optimization_index,
     33                 const fuzz_utils::CropOrScaleParams& crop_or_scale_params) {
     34   fuzz_utils::SetOptimization(default_VP8GetCPUInfo, optimization_index);
     35 
     36   // Init the source picture.
     37   WebPPicture pic = fuzz_utils::GetSourcePicture(source_image_index, use_argb);
     38 
     39   // Crop and scale.
     40   if (!fuzz_utils::CropOrScale(&pic, crop_or_scale_params)) {
     41     const WebPEncodingError error_code = pic.error_code;
     42     WebPPictureFree(&pic);
     43     if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY) return;
     44     fprintf(stderr, "ExtractAndCropOrScale failed. Error code: %d\n",
     45             error_code);
     46     std::abort();
     47   }
     48 
     49   // Skip slow settings on big images, it's likely to timeout.
     50   if (pic.width * pic.height > 32 * 32) {
     51     if (config.lossless) {
     52       if (config.quality > 99.0f && config.method >= 5) {
     53         config.quality = 99.0f;
     54         config.method = 5;
     55       }
     56     } else {
     57       if (config.quality > 99.0f && config.method == 6) {
     58         config.quality = 99.0f;
     59       }
     60     }
     61     if (config.alpha_quality == 100 && config.method == 6) {
     62       config.alpha_quality = 99;
     63     }
     64   }
     65 
     66   // Encode.
     67   WebPMemoryWriter memory_writer;
     68   WebPMemoryWriterInit(&memory_writer);
     69   pic.writer = WebPMemoryWrite;
     70   pic.custom_ptr = &memory_writer;
     71   if (!WebPEncode(&config, &pic)) {
     72     const WebPEncodingError error_code = pic.error_code;
     73     WebPMemoryWriterClear(&memory_writer);
     74     WebPPictureFree(&pic);
     75     if (error_code == VP8_ENC_ERROR_OUT_OF_MEMORY ||
     76         error_code == VP8_ENC_ERROR_BAD_WRITE) {
     77       return;
     78     }
     79     fprintf(stderr, "WebPEncode failed. Error code: %d\n", error_code);
     80     std::abort();
     81   }
     82 
     83   // Try decoding the result.
     84   const uint8_t* const out_data = memory_writer.mem;
     85   const size_t out_size = memory_writer.size;
     86   WebPDecoderConfig dec_config;
     87   if (!WebPInitDecoderConfig(&dec_config)) {
     88     fprintf(stderr, "WebPInitDecoderConfig failed.\n");
     89     WebPMemoryWriterClear(&memory_writer);
     90     WebPPictureFree(&pic);
     91     std::abort();
     92   }
     93 
     94   dec_config.output.colorspace = MODE_BGRA;
     95   const VP8StatusCode status = WebPDecode(out_data, out_size, &dec_config);
     96   if ((status != VP8_STATUS_OK && status != VP8_STATUS_OUT_OF_MEMORY &&
     97        status != VP8_STATUS_USER_ABORT) ||
     98       (status == VP8_STATUS_OK && (dec_config.output.width != pic.width ||
     99                                    dec_config.output.height != pic.height))) {
    100     fprintf(stderr, "WebPDecode failed. status: %d.\n", status);
    101     WebPFreeDecBuffer(&dec_config.output);
    102     WebPMemoryWriterClear(&memory_writer);
    103     WebPPictureFree(&pic);
    104     std::abort();
    105   }
    106 
    107   if (status == VP8_STATUS_OK) {
    108     const uint8_t* const rgba = dec_config.output.u.RGBA.rgba;
    109     const int w = dec_config.output.width;
    110     const int h = dec_config.output.height;
    111 
    112     // Compare the results if exact encoding.
    113     if (pic.use_argb && config.lossless && config.near_lossless == 100) {
    114       const uint32_t* src1 = (const uint32_t*)rgba;
    115       const uint32_t* src2 = pic.argb;
    116       for (int y = 0; y < h; ++y, src1 += w, src2 += pic.argb_stride) {
    117         for (int x = 0; x < w; ++x) {
    118           uint32_t v1 = src1[x], v2 = src2[x];
    119           if (!config.exact) {
    120             if ((v1 & 0xff000000u) == 0 || (v2 & 0xff000000u) == 0) {
    121               // Only keep alpha for comparison of fully transparent area.
    122               v1 &= 0xff000000u;
    123               v2 &= 0xff000000u;
    124             }
    125           }
    126           if (v1 != v2) {
    127             fprintf(stderr, "Lossless compression failed pixel-exactness.\n");
    128             WebPFreeDecBuffer(&dec_config.output);
    129             WebPMemoryWriterClear(&memory_writer);
    130             WebPPictureFree(&pic);
    131             std::abort();
    132           }
    133         }
    134       }
    135     }
    136   }
    137 
    138   WebPFreeDecBuffer(&dec_config.output);
    139   WebPMemoryWriterClear(&memory_writer);
    140   WebPPictureFree(&pic);
    141 }
    142 
    143 }  // namespace
    144 
    145 FUZZ_TEST(EncDec, EncDecTest)
    146     .WithDomains(/*use_argb=*/fuzztest::Arbitrary<bool>(),
    147                  /*source_image_index=*/
    148                  fuzztest::InRange<int>(0, fuzz_utils::kNumSourceImages - 1),
    149                  fuzz_utils::ArbitraryWebPConfig(),
    150                  /*optimization_index=*/
    151                  fuzztest::InRange<uint32_t>(0,
    152                                              fuzz_utils::kMaxOptimizationIndex),
    153                  fuzz_utils::ArbitraryCropOrScaleParams());