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