Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2013 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "CodecPriv.h"
      9 #include "Resources.h"
     10 #include "SkAndroidCodec.h"
     11 #include "SkBitmap.h"
     12 #include "SkData.h"
     13 #include "SkImage.h"
     14 #include "SkStream.h"
     15 #include "SkTypes.h"
     16 #include "Test.h"
     17 
     18 static unsigned char gGIFData[] = {
     19   0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x03, 0x00, 0x03, 0x00, 0xe3, 0x08,
     20   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00,
     21   0xff, 0x80, 0x80, 0x80, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
     22   0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     23   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     24   0xff, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x04,
     25   0x07, 0x50, 0x1c, 0x43, 0x40, 0x41, 0x23, 0x44, 0x00, 0x3b
     26 };
     27 
     28 static unsigned char gGIFDataNoColormap[] = {
     29   0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
     30   0x21, 0xf9, 0x04, 0x01, 0x0a, 0x00, 0x01, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00,
     31   0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x4c, 0x01, 0x00, 0x3b
     32 };
     33 
     34 static unsigned char gInterlacedGIF[] = {
     35   0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x09, 0x00, 0x09, 0x00, 0xe3, 0x08, 0x00,
     36   0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x80,
     37   0x80, 0x80, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff,
     38   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
     39   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00,
     40   0x00, 0x09, 0x00, 0x09, 0x00, 0x40, 0x04, 0x1b, 0x50, 0x1c, 0x23, 0xe9, 0x44,
     41   0x23, 0x60, 0x9d, 0x09, 0x28, 0x1e, 0xf8, 0x6d, 0x64, 0x56, 0x9d, 0x53, 0xa8,
     42   0x7e, 0xa8, 0x65, 0x94, 0x5c, 0xb0, 0x8a, 0x45, 0x04, 0x00, 0x3b
     43 };
     44 
     45 static void test_gif_data_no_colormap(skiatest::Reporter* r,
     46                                       void* data,
     47                                       size_t size) {
     48     SkBitmap bm;
     49     bool imageDecodeSuccess = decode_memory(data, size, &bm);
     50     REPORTER_ASSERT(r, imageDecodeSuccess);
     51     REPORTER_ASSERT(r, bm.width() == 1);
     52     REPORTER_ASSERT(r, bm.height() == 1);
     53     REPORTER_ASSERT(r, !(bm.empty()));
     54     if (!(bm.empty())) {
     55         REPORTER_ASSERT(r, bm.getColor(0, 0) == 0xFF000000);
     56     }
     57 }
     58 static void test_gif_data(skiatest::Reporter* r, void* data, size_t size) {
     59     SkBitmap bm;
     60     bool imageDecodeSuccess = decode_memory(data, size, &bm);
     61     REPORTER_ASSERT(r, imageDecodeSuccess);
     62     REPORTER_ASSERT(r, bm.width() == 3);
     63     REPORTER_ASSERT(r, bm.height() == 3);
     64     REPORTER_ASSERT(r, !(bm.empty()));
     65     if (!(bm.empty())) {
     66         REPORTER_ASSERT(r, bm.getColor(0, 0) == 0xffff0000);
     67         REPORTER_ASSERT(r, bm.getColor(1, 0) == 0xffffff00);
     68         REPORTER_ASSERT(r, bm.getColor(2, 0) == 0xff00ffff);
     69         REPORTER_ASSERT(r, bm.getColor(0, 1) == 0xff808080);
     70         REPORTER_ASSERT(r, bm.getColor(1, 1) == 0xff000000);
     71         REPORTER_ASSERT(r, bm.getColor(2, 1) == 0xff00ff00);
     72         REPORTER_ASSERT(r, bm.getColor(0, 2) == 0xffffffff);
     73         REPORTER_ASSERT(r, bm.getColor(1, 2) == 0xffff00ff);
     74         REPORTER_ASSERT(r, bm.getColor(2, 2) == 0xff0000ff);
     75     }
     76 }
     77 static void test_gif_data_dims(skiatest::Reporter* r, void* data, size_t size, int width,
     78         int height) {
     79     SkBitmap bm;
     80     bool imageDecodeSuccess = decode_memory(data, size, &bm);
     81     REPORTER_ASSERT(r, imageDecodeSuccess);
     82     REPORTER_ASSERT(r, bm.width() == width);
     83     REPORTER_ASSERT(r, bm.height() == height);
     84     REPORTER_ASSERT(r, !(bm.empty()));
     85 }
     86 static void test_interlaced_gif_data(skiatest::Reporter* r,
     87                                      void* data,
     88                                      size_t size) {
     89     SkBitmap bm;
     90     bool imageDecodeSuccess = decode_memory(data, size, &bm);
     91     REPORTER_ASSERT(r, imageDecodeSuccess);
     92     REPORTER_ASSERT(r, bm.width() == 9);
     93     REPORTER_ASSERT(r, bm.height() == 9);
     94     REPORTER_ASSERT(r, !(bm.empty()));
     95     if (!(bm.empty())) {
     96         REPORTER_ASSERT(r, bm.getColor(0, 0) == 0xffff0000);
     97         REPORTER_ASSERT(r, bm.getColor(1, 0) == 0xffffff00);
     98         REPORTER_ASSERT(r, bm.getColor(2, 0) == 0xff00ffff);
     99 
    100         REPORTER_ASSERT(r, bm.getColor(0, 2) == 0xffffffff);
    101         REPORTER_ASSERT(r, bm.getColor(1, 2) == 0xffff00ff);
    102         REPORTER_ASSERT(r, bm.getColor(2, 2) == 0xff0000ff);
    103 
    104         REPORTER_ASSERT(r, bm.getColor(0, 4) == 0xff808080);
    105         REPORTER_ASSERT(r, bm.getColor(1, 4) == 0xff000000);
    106         REPORTER_ASSERT(r, bm.getColor(2, 4) == 0xff00ff00);
    107 
    108         REPORTER_ASSERT(r, bm.getColor(0, 6) == 0xffff0000);
    109         REPORTER_ASSERT(r, bm.getColor(1, 6) == 0xffffff00);
    110         REPORTER_ASSERT(r, bm.getColor(2, 6) == 0xff00ffff);
    111 
    112         REPORTER_ASSERT(r, bm.getColor(0, 8) == 0xffffffff);
    113         REPORTER_ASSERT(r, bm.getColor(1, 8) == 0xffff00ff);
    114         REPORTER_ASSERT(r, bm.getColor(2, 8) == 0xff0000ff);
    115     }
    116 }
    117 
    118 static void test_gif_data_short(skiatest::Reporter* r,
    119                                 void* data,
    120                                 size_t size) {
    121     SkBitmap bm;
    122     bool imageDecodeSuccess = decode_memory(data, size, &bm);
    123     REPORTER_ASSERT(r, imageDecodeSuccess);
    124     REPORTER_ASSERT(r, bm.width() == 3);
    125     REPORTER_ASSERT(r, bm.height() == 3);
    126     REPORTER_ASSERT(r, !(bm.empty()));
    127     if (!(bm.empty())) {
    128         REPORTER_ASSERT(r, bm.getColor(0, 0) == 0xffff0000);
    129         REPORTER_ASSERT(r, bm.getColor(1, 0) == 0xffffff00);
    130         REPORTER_ASSERT(r, bm.getColor(2, 0) == 0xff00ffff);
    131         REPORTER_ASSERT(r, bm.getColor(0, 1) == 0xff808080);
    132         REPORTER_ASSERT(r, bm.getColor(1, 1) == 0xff000000);
    133         REPORTER_ASSERT(r, bm.getColor(2, 1) == 0xff00ff00);
    134     }
    135 }
    136 
    137 /**
    138   This test will test the ability of the SkCodec to deal with
    139   GIF files which have been mangled somehow.  We want to display as
    140   much of the GIF as possible.
    141 */
    142 DEF_TEST(Gif, reporter) {
    143     // test perfectly good images.
    144     test_gif_data(reporter, static_cast<void *>(gGIFData), sizeof(gGIFData));
    145     test_interlaced_gif_data(reporter, static_cast<void *>(gInterlacedGIF),
    146                           sizeof(gInterlacedGIF));
    147 
    148     unsigned char badData[sizeof(gGIFData)];
    149 
    150     memcpy(badData, gGIFData, sizeof(gGIFData));
    151     badData[6] = 0x01;  // image too wide
    152     test_gif_data(reporter, static_cast<void *>(badData), sizeof(gGIFData));
    153     // "libgif warning [image too wide, expanding output to size]"
    154 
    155     memcpy(badData, gGIFData, sizeof(gGIFData));
    156     badData[8] = 0x01;  // image too tall
    157     test_gif_data(reporter, static_cast<void *>(badData), sizeof(gGIFData));
    158     // "libgif warning [image too tall,  expanding output to size]"
    159 
    160     memcpy(badData, gGIFData, sizeof(gGIFData));
    161     badData[62] = 0x01;  // image shifted right
    162     test_gif_data_dims(reporter, static_cast<void *>(badData), sizeof(gGIFData), 4, 3);
    163 
    164     memcpy(badData, gGIFData, sizeof(gGIFData));
    165     badData[64] = 0x01;  // image shifted down
    166     test_gif_data_dims(reporter, static_cast<void *>(badData), sizeof(gGIFData), 3, 4);
    167 
    168     memcpy(badData, gGIFData, sizeof(gGIFData));
    169     badData[62] = 0xff;  // image shifted right
    170     badData[63] = 0xff;
    171     test_gif_data_dims(reporter, static_cast<void *>(badData), sizeof(gGIFData), 3 + 0xFFFF, 3);
    172 
    173     memcpy(badData, gGIFData, sizeof(gGIFData));
    174     badData[64] = 0xff;  // image shifted down
    175     badData[65] = 0xff;
    176     test_gif_data_dims(reporter, static_cast<void *>(badData), sizeof(gGIFData), 3, 3 + 0xFFFF);
    177 
    178     test_gif_data_no_colormap(reporter, static_cast<void *>(gGIFDataNoColormap),
    179                               sizeof(gGIFDataNoColormap));
    180     // "libgif warning [missing colormap]"
    181 
    182     // test short Gif.  80 is missing a few bytes.
    183     test_gif_data_short(reporter, static_cast<void *>(gGIFData), 80);
    184     // "libgif warning [DGifGetLine]"
    185 
    186     test_interlaced_gif_data(reporter, static_cast<void *>(gInterlacedGIF),
    187                              100);  // 100 is missing a few bytes
    188     // "libgif warning [interlace DGifGetLine]"
    189 }
    190 
    191 // Regression test for decoding a gif image with sampleSize of 4, which was
    192 // previously crashing.
    193 DEF_TEST(Gif_Sampled, r) {
    194     SkAutoTDelete<SkFILEStream> stream(
    195             new SkFILEStream(GetResourcePath("test640x479.gif").c_str()));
    196     REPORTER_ASSERT(r, stream->isValid());
    197     if (!stream->isValid()) {
    198         return;
    199     }
    200 
    201     SkAutoTDelete<SkAndroidCodec> codec(SkAndroidCodec::NewFromStream(stream.detach()));
    202     REPORTER_ASSERT(r, codec);
    203     if (!codec) {
    204         return;
    205     }
    206 
    207     // Construct a color table for the decode if necessary
    208     SkAutoTUnref<SkColorTable> colorTable(nullptr);
    209     SkPMColor* colorPtr = nullptr;
    210     int* colorCountPtr = nullptr;
    211     int maxColors = 256;
    212     if (kIndex_8_SkColorType == codec->getInfo().colorType()) {
    213         SkPMColor colors[256];
    214         colorTable.reset(new SkColorTable(colors, maxColors));
    215         colorPtr = const_cast<SkPMColor*>(colorTable->readColors());
    216         colorCountPtr = &maxColors;
    217     }
    218 
    219     SkAndroidCodec::AndroidOptions options;
    220     options.fSampleSize = 4;
    221     options.fColorPtr = colorPtr;
    222     options.fColorCount = colorCountPtr;
    223 
    224     SkBitmap bm;
    225     bm.allocPixels(codec->getInfo(), nullptr, colorTable.get());
    226     const SkCodec::Result result = codec->getAndroidPixels(codec->getInfo(), bm.getPixels(),
    227             bm.rowBytes(), &options);
    228     REPORTER_ASSERT(r, result == SkCodec::kSuccess);
    229 }
    230