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 "Resources.h"
9#include "SkBitmap.h"
10#include "SkCanvas.h"
11#include "SkColor.h"
12#include "SkColorPriv.h"
13#include "SkData.h"
14#include "SkDecodingImageGenerator.h"
15#include "SkDiscardableMemoryPool.h"
16#include "SkForceLinking.h"
17#include "SkGradientShader.h"
18#include "SkImageDecoder.h"
19#include "SkImageEncoder.h"
20#include "SkImageGeneratorPriv.h"
21#include "SkImagePriv.h"
22#include "SkOSFile.h"
23#include "SkPoint.h"
24#include "SkShader.h"
25#include "SkStream.h"
26#include "SkString.h"
27#include "Test.h"
28
29__SK_FORCE_IMAGE_DECODER_LINKING;
30
31/**
32 *  Interprets c as an unpremultiplied color, and returns the
33 *  premultiplied equivalent.
34 */
35static SkPMColor premultiply_unpmcolor(SkPMColor c) {
36    U8CPU a = SkGetPackedA32(c);
37    U8CPU r = SkGetPackedR32(c);
38    U8CPU g = SkGetPackedG32(c);
39    U8CPU b = SkGetPackedB32(c);
40    return SkPreMultiplyARGB(a, r, g, b);
41}
42
43/**
44 *  Return true if this stream format should be skipped, due
45 *  to do being an opaque format or not a valid format.
46 */
47static bool skip_image_format(SkImageDecoder::Format format) {
48    switch (format) {
49        case SkImageDecoder::kPNG_Format:
50        case SkImageDecoder::kWEBP_Format:
51            return false;
52        // Skip unknown since it will not be decoded anyway.
53        case SkImageDecoder::kUnknown_Format:
54        // Technically ICO and BMP supports alpha channels, but our image
55        // decoders do not, so skip them as well.
56        case SkImageDecoder::kICO_Format:
57        case SkImageDecoder::kBMP_Format:
58        // KTX and ASTC are texture formats so it's not particularly clear how to
59        // decode the alpha from them.
60        case SkImageDecoder::kKTX_Format:
61        case SkImageDecoder::kASTC_Format:
62        // The rest of these are opaque.
63        case SkImageDecoder::kPKM_Format:
64        case SkImageDecoder::kWBMP_Format:
65        case SkImageDecoder::kGIF_Format:
66        case SkImageDecoder::kJPEG_Format:
67            return true;
68    }
69    SkASSERT(false);
70    return true;
71}
72
73/**
74 *  Test decoding an image in premultiplied mode and unpremultiplied mode and compare
75 *  them.
76 */
77static void compare_unpremul(skiatest::Reporter* reporter, const SkString& filename) {
78    // Decode a resource:
79    SkBitmap bm8888;
80    SkBitmap bm8888Unpremul;
81
82    SkFILEStream stream(filename.c_str());
83
84    SkImageDecoder::Format format = SkImageDecoder::GetStreamFormat(&stream);
85    if (skip_image_format(format)) {
86        return;
87    }
88
89    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream));
90    if (NULL == decoder.get()) {
91        SkDebugf("couldn't decode %s\n", filename.c_str());
92        return;
93    }
94
95    bool success = decoder->decode(&stream, &bm8888, kN32_SkColorType,
96                                   SkImageDecoder::kDecodePixels_Mode);
97    if (!success) {
98        return;
99    }
100
101    success = stream.rewind();
102    REPORTER_ASSERT(reporter, success);
103    if (!success) {
104        return;
105    }
106
107    decoder->setRequireUnpremultipliedColors(true);
108    success = decoder->decode(&stream, &bm8888Unpremul, kN32_SkColorType,
109                              SkImageDecoder::kDecodePixels_Mode);
110    if (!success) {
111        return;
112    }
113
114    bool dimensionsMatch = bm8888.width() == bm8888Unpremul.width()
115                           && bm8888.height() == bm8888Unpremul.height();
116    REPORTER_ASSERT(reporter, dimensionsMatch);
117    if (!dimensionsMatch) {
118        return;
119    }
120
121    // Only do the comparison if the two bitmaps are both 8888.
122    if (bm8888.colorType() != kN32_SkColorType || bm8888Unpremul.colorType() != kN32_SkColorType) {
123        return;
124    }
125
126    // Now compare the two bitmaps.
127    for (int i = 0; i < bm8888.width(); ++i) {
128        for (int j = 0; j < bm8888.height(); ++j) {
129            // "c0" is the color of the premultiplied bitmap at (i, j).
130            const SkPMColor c0 = *bm8888.getAddr32(i, j);
131            // "c1" is the result of premultiplying the color of the unpremultiplied
132            // bitmap at (i, j).
133            const SkPMColor c1 = premultiply_unpmcolor(*bm8888Unpremul.getAddr32(i, j));
134            // Compute the difference for each component.
135            int da = SkAbs32(SkGetPackedA32(c0) - SkGetPackedA32(c1));
136            int dr = SkAbs32(SkGetPackedR32(c0) - SkGetPackedR32(c1));
137            int dg = SkAbs32(SkGetPackedG32(c0) - SkGetPackedG32(c1));
138            int db = SkAbs32(SkGetPackedB32(c0) - SkGetPackedB32(c1));
139
140            // Alpha component must be exactly the same.
141            REPORTER_ASSERT(reporter, 0 == da);
142
143            // Color components may not match exactly due to rounding error.
144            REPORTER_ASSERT(reporter, dr <= 1);
145            REPORTER_ASSERT(reporter, dg <= 1);
146            REPORTER_ASSERT(reporter, db <= 1);
147        }
148    }
149}
150
151static void test_unpremul(skiatest::Reporter* reporter) {
152    // This test cannot run if there is no resource path.
153    SkString resourcePath = GetResourcePath();
154    if (resourcePath.isEmpty()) {
155        SkDebugf("Could not run unpremul test because resourcePath not specified.");
156        return;
157    }
158    SkOSFile::Iter iter(resourcePath.c_str());
159    SkString basename;
160    if (iter.next(&basename)) {
161        do {
162            SkString filename = SkOSPath::Join(resourcePath.c_str(), basename.c_str());
163            // SkDebugf("about to decode \"%s\"\n", filename.c_str());
164            compare_unpremul(reporter, filename);
165        } while (iter.next(&basename));
166    } else {
167        SkDebugf("Failed to find any files :(\n");
168    }
169}
170
171#if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX)
172// Test that the alpha type is what we expect.
173static void test_alphaType(skiatest::Reporter* reporter, const SkString& filename,
174                           bool requireUnpremul) {
175    SkBitmap bm;
176    SkFILEStream stream(filename.c_str());
177
178    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream));
179    if (NULL == decoder.get()) {
180        return;
181    }
182
183    decoder->setRequireUnpremultipliedColors(requireUnpremul);
184
185    // Decode just the bounds. This should always succeed.
186    bool success = decoder->decode(&stream, &bm, kN32_SkColorType,
187                                   SkImageDecoder::kDecodeBounds_Mode);
188    REPORTER_ASSERT(reporter, success);
189    if (!success) {
190        return;
191    }
192
193    // Keep track of the alpha type for testing later. If the full decode
194    // succeeds, the alpha type should be the same, unless the full decode
195    // determined that the alpha type should actually be opaque, which may
196    // not be known when only decoding the bounds.
197    const SkAlphaType boundsAlphaType = bm.alphaType();
198
199    // rewind should always succeed on SkFILEStream.
200    success = stream.rewind();
201    REPORTER_ASSERT(reporter, success);
202    if (!success) {
203        return;
204    }
205
206    success = decoder->decode(&stream, &bm, kN32_SkColorType, SkImageDecoder::kDecodePixels_Mode);
207
208    if (!success) {
209        // When the decoder is set to require unpremul, if it does not support
210        // unpremul it will fail. This is the only reason the decode should
211        // fail (since we know the files we are using to test can be decoded).
212        REPORTER_ASSERT(reporter, requireUnpremul);
213        return;
214    }
215
216    // The bounds decode should return with either the requested
217    // premul/unpremul or opaque, if that value could be determined when only
218    // decoding the bounds.
219    if (requireUnpremul) {
220        REPORTER_ASSERT(reporter, kUnpremul_SkAlphaType == boundsAlphaType
221                                  || kOpaque_SkAlphaType == boundsAlphaType);
222    } else {
223        REPORTER_ASSERT(reporter, kPremul_SkAlphaType == boundsAlphaType
224                                  || kOpaque_SkAlphaType == boundsAlphaType);
225    }
226
227    // When decoding the full image, the alpha type should match the one
228    // returned by the bounds decode, unless the full decode determined that
229    // the alpha type is actually opaque.
230    REPORTER_ASSERT(reporter, bm.alphaType() == boundsAlphaType
231                              || bm.alphaType() == kOpaque_SkAlphaType);
232}
233
234DEF_TEST(ImageDecoding_alphaType, reporter) {
235    SkString resourcePath = GetResourcePath();
236    if (resourcePath.isEmpty()) {
237        SkDebugf("Could not run alphaType test because resourcePath not specified.");
238        return;
239    }
240
241    SkOSFile::Iter iter(resourcePath.c_str());
242    SkString basename;
243    if (iter.next(&basename)) {
244        do {
245            SkString filename = SkOSPath::Join(resourcePath.c_str(), basename.c_str());
246            for (int truth = 0; truth <= 1; ++truth) {
247                test_alphaType(reporter, filename, SkToBool(truth));
248            }
249        } while (iter.next(&basename));
250    } else {
251        SkDebugf("Failed to find any files :(\n");
252    }
253
254}
255
256// Using known images, test that decoding into unpremul and premul behave as expected.
257DEF_TEST(ImageDecoding_unpremul, reporter) {
258    SkString resourcePath = GetResourcePath();
259    if (resourcePath.isEmpty()) {
260        SkDebugf("Could not run unpremul test because resourcePath not specified.");
261        return;
262    }
263    const char* root = "half-transparent-white-pixel";
264    const char* suffixes[] = { ".png", ".webp" };
265
266    for (size_t i = 0; i < SK_ARRAY_COUNT(suffixes); ++i) {
267        SkString basename = SkStringPrintf("%s%s", root, suffixes[i]);
268        SkString fullName = SkOSPath::Join(resourcePath.c_str(), basename.c_str());
269
270        SkBitmap bm;
271        SkFILEStream stream(fullName.c_str());
272
273        if (!stream.isValid()) {
274            SkDebugf("file %s missing from resource directoy %s\n",
275                     basename.c_str(), resourcePath.c_str());
276            continue;
277        }
278
279        // This should never fail since we know the images we're decoding.
280        SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream));
281        REPORTER_ASSERT(reporter, decoder.get());
282        if (NULL == decoder.get()) {
283            continue;
284        }
285
286        // Test unpremultiplied. We know what color this should result in.
287        decoder->setRequireUnpremultipliedColors(true);
288        bool success = decoder->decode(&stream, &bm, kN32_SkColorType,
289                                       SkImageDecoder::kDecodePixels_Mode);
290        REPORTER_ASSERT(reporter, success);
291        if (!success) {
292            continue;
293        }
294
295        REPORTER_ASSERT(reporter, bm.width() == 1 && bm.height() == 1);
296        {
297            SkAutoLockPixels alp(bm);
298            REPORTER_ASSERT(reporter, bm.getAddr32(0, 0)[0] == 0x7fffffff);
299        }
300
301        success = stream.rewind();
302        REPORTER_ASSERT(reporter, success);
303        if (!success) {
304            continue;
305        }
306
307        // Test premultiplied. Once again, we know which color this should
308        // result in.
309        decoder->setRequireUnpremultipliedColors(false);
310        success = decoder->decode(&stream, &bm, kN32_SkColorType,
311                                  SkImageDecoder::kDecodePixels_Mode);
312        REPORTER_ASSERT(reporter, success);
313        if (!success) {
314            continue;
315        }
316
317        REPORTER_ASSERT(reporter, bm.width() == 1 && bm.height() == 1);
318        {
319            SkAutoLockPixels alp(bm);
320            REPORTER_ASSERT(reporter, bm.getAddr32(0, 0)[0] == 0x7f7f7f7f);
321        }
322    }
323}
324#endif // SK_BUILD_FOR_UNIX/ANDROID skbug.com/2388
325
326#ifdef SK_DEBUG
327// Create a stream containing a bitmap encoded to Type type.
328static SkMemoryStream* create_image_stream(SkImageEncoder::Type type) {
329    SkBitmap bm;
330    const int size = 50;
331    bm.allocN32Pixels(size, size);
332    SkCanvas canvas(bm);
333    SkPoint points[2] = {
334        { SkIntToScalar(0), SkIntToScalar(0) },
335        { SkIntToScalar(size), SkIntToScalar(size) }
336    };
337    SkColor colors[2] = { SK_ColorWHITE, SK_ColorBLUE };
338    SkShader* shader = SkGradientShader::CreateLinear(points, colors, NULL,
339                                                      SK_ARRAY_COUNT(colors),
340                                                      SkShader::kClamp_TileMode);
341    SkPaint paint;
342    paint.setShader(shader)->unref();
343    canvas.drawPaint(paint);
344    // Now encode it to a stream.
345    SkAutoTUnref<SkData> data(SkImageEncoder::EncodeData(bm, type, 100));
346    if (NULL == data.get()) {
347        return NULL;
348    }
349    return SkNEW_ARGS(SkMemoryStream, (data.get()));
350}
351
352// For every format that supports tile based decoding, ensure that
353// calling decodeSubset will not fail if the caller has unreffed the
354// stream provided in buildTileIndex.
355// Only runs in debug mode since we are testing for a crash.
356static void test_stream_life() {
357    const SkImageEncoder::Type gTypes[] = {
358#ifdef SK_BUILD_FOR_ANDROID
359        SkImageEncoder::kJPEG_Type,
360        SkImageEncoder::kPNG_Type,
361#endif
362        SkImageEncoder::kWEBP_Type,
363    };
364    for (size_t i = 0; i < SK_ARRAY_COUNT(gTypes); ++i) {
365        // SkDebugf("encoding to %i\n", i);
366        SkAutoTUnref<SkMemoryStream> stream(create_image_stream(gTypes[i]));
367        if (NULL == stream.get()) {
368            SkDebugf("no stream\n");
369            continue;
370        }
371        SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream));
372        if (NULL == decoder.get()) {
373            SkDebugf("no decoder\n");
374            continue;
375        }
376        int width, height;
377        if (!decoder->buildTileIndex(stream.get(), &width, &height)) {
378            SkDebugf("could not build a tile index\n");
379            continue;
380        }
381        // Now unref the stream to make sure it survives
382        stream.reset(NULL);
383        SkBitmap bm;
384        decoder->decodeSubset(&bm, SkIRect::MakeWH(width, height), kN32_SkColorType);
385    }
386}
387
388// Test inside SkScaledBitmapSampler.cpp
389extern void test_row_proc_choice();
390
391#endif  // SK_DEBUG
392
393DEF_TEST(ImageDecoding, reporter) {
394    test_unpremul(reporter);
395#ifdef SK_DEBUG
396    test_stream_life();
397    test_row_proc_choice();
398#endif
399}
400
401// expected output for 8x8 bitmap
402static const int kExpectedWidth = 8;
403static const int kExpectedHeight = 8;
404static const SkColor kExpectedPixels[] = {
405    0xffbba570, 0xff395f5d, 0xffe25c39, 0xff197666,
406    0xff3cba27, 0xffdefcb0, 0xffc13874, 0xfffa0093,
407    0xffbda60e, 0xffc01db6, 0xff2bd688, 0xff9362d4,
408    0xffc641b2, 0xffa5cede, 0xff606eba, 0xff8f4bf3,
409    0xff3bf742, 0xff8f02a8, 0xff5509df, 0xffc7027e,
410    0xff24aa8a, 0xff886c96, 0xff625481, 0xff403689,
411    0xffc52152, 0xff78ccd6, 0xffdcb4ab, 0xff09d27d,
412    0xffca00f3, 0xff605d47, 0xff446fb2, 0xff576e46,
413    0xff273df9, 0xffb41a83, 0xfff812c3, 0xffccab67,
414    0xff034218, 0xff7db9a7, 0xff821048, 0xfffe4ab4,
415    0xff6fac98, 0xff941d27, 0xff5fe411, 0xfffbb283,
416    0xffd86e99, 0xff169162, 0xff71128c, 0xff39cab4,
417    0xffa7fe63, 0xff4c956b, 0xffbc22e0, 0xffb272e4,
418    0xff129f4a, 0xffe34513, 0xff3d3742, 0xffbd190a,
419    0xffb07222, 0xff2e23f8, 0xfff089d9, 0xffb35738,
420    0xffa86022, 0xff3340fe, 0xff95fe71, 0xff6a71df
421};
422SK_COMPILE_ASSERT((kExpectedWidth * kExpectedHeight)
423                  == SK_ARRAY_COUNT(kExpectedPixels), array_size_mismatch);
424
425DEF_TEST(WebP, reporter) {
426    const unsigned char encodedWebP[] = {
427        0x52, 0x49, 0x46, 0x46, 0x2c, 0x01, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50,
428        0x56, 0x50, 0x38, 0x4c, 0x20, 0x01, 0x00, 0x00, 0x2f, 0x07, 0xc0, 0x01,
429        0x00, 0xff, 0x01, 0x45, 0x03, 0x00, 0xe2, 0xd5, 0xae, 0x60, 0x2b, 0xad,
430        0xd9, 0x68, 0x76, 0xb6, 0x8d, 0x6a, 0x1d, 0xc0, 0xe6, 0x19, 0xd6, 0x16,
431        0xb7, 0xb4, 0xef, 0xcf, 0xc3, 0x15, 0x6c, 0xb3, 0xbd, 0x77, 0x0d, 0x85,
432        0x6d, 0x1b, 0xa9, 0xb1, 0x2b, 0xdc, 0x3d, 0x83, 0xdb, 0x00, 0x00, 0xc8,
433        0x26, 0xe5, 0x01, 0x99, 0x8a, 0xd5, 0xdd, 0xfc, 0x82, 0xcd, 0xcd, 0x9a,
434        0x8c, 0x13, 0xcc, 0x1b, 0xba, 0xf5, 0x05, 0xdb, 0xee, 0x6a, 0xdb, 0x38,
435        0x60, 0xfe, 0x43, 0x2c, 0xd4, 0x6a, 0x99, 0x4d, 0xc6, 0xc0, 0xd3, 0x28,
436        0x1b, 0xc1, 0xb1, 0x17, 0x4e, 0x43, 0x0e, 0x3d, 0x27, 0xe9, 0xe4, 0x84,
437        0x4f, 0x24, 0x62, 0x69, 0x85, 0x43, 0x8d, 0xc2, 0x04, 0x00, 0x07, 0x59,
438        0x60, 0xfd, 0x8b, 0x4d, 0x60, 0x32, 0x72, 0xcf, 0x88, 0x0c, 0x2f, 0x2f,
439        0xad, 0x62, 0xbd, 0x27, 0x09, 0x16, 0x70, 0x78, 0x6c, 0xd9, 0x82, 0xef,
440        0x1a, 0xa2, 0xcc, 0xf0, 0xf1, 0x6f, 0xd8, 0x78, 0x2e, 0x39, 0xa1, 0xcf,
441        0x14, 0x4b, 0x89, 0xb4, 0x1b, 0x48, 0x15, 0x7c, 0x48, 0x6f, 0x8c, 0x20,
442        0xb7, 0x00, 0xcf, 0xfc, 0xdb, 0xd0, 0xe9, 0xe7, 0x42, 0x09, 0xa4, 0x03,
443        0x40, 0xac, 0xda, 0x40, 0x01, 0x00, 0x5f, 0xa1, 0x3d, 0x64, 0xe1, 0xf4,
444        0x03, 0x45, 0x29, 0xe0, 0xe2, 0x4a, 0xc3, 0xa2, 0xe8, 0xe0, 0x25, 0x12,
445        0x74, 0xc6, 0xe8, 0xfb, 0x93, 0x4f, 0x9f, 0x5e, 0xc0, 0xa6, 0x91, 0x1b,
446        0xa4, 0x24, 0x82, 0xc3, 0x61, 0x07, 0x4c, 0x49, 0x4f, 0x53, 0xae, 0x5f,
447        0x5d, 0x39, 0x36, 0xc0, 0x5b, 0x57, 0x54, 0x60, 0x10, 0x00, 0x00, 0xd1,
448        0x68, 0xb6, 0x6d, 0xdb, 0x36, 0x22, 0xfa, 0x1f, 0x35, 0x75, 0x22, 0xec,
449        0x31, 0xbc, 0x5d, 0x8f, 0x87, 0x53, 0xa2, 0x05, 0x8c, 0x2f, 0xcd, 0xa8,
450        0xa7, 0xf3, 0xa3, 0xbd, 0x83, 0x8b, 0x2a, 0xc8, 0x58, 0xf5, 0xac, 0x80,
451        0xe3, 0xfe, 0x66, 0xa4, 0x7c, 0x1b, 0x6c, 0xd1, 0xa9, 0xd8, 0x14, 0xd0,
452        0xc5, 0xb5, 0x39, 0x71, 0x97, 0x19, 0x19, 0x1b
453    };
454    SkAutoDataUnref encoded(SkData::NewWithCopy(encodedWebP,
455                                                sizeof(encodedWebP)));
456    SkBitmap bm;
457
458    bool success = SkInstallDiscardablePixelRef(
459        SkDecodingImageGenerator::Create(encoded,
460            SkDecodingImageGenerator::Options()), &bm);
461
462    REPORTER_ASSERT(reporter, success);
463    if (!success) {
464        return;
465    }
466    SkAutoLockPixels alp(bm);
467
468    bool rightSize = ((kExpectedWidth == bm.width())
469                      && (kExpectedHeight == bm.height()));
470    REPORTER_ASSERT(reporter, rightSize);
471    if (rightSize) {
472        bool error = false;
473        const SkColor* correctPixel = kExpectedPixels;
474        for (int y = 0; y < bm.height(); ++y) {
475            for (int x = 0; x < bm.width(); ++x) {
476                error |= (*correctPixel != bm.getColor(x, y));
477                ++correctPixel;
478            }
479        }
480        REPORTER_ASSERT(reporter, !error);
481    }
482}
483
484////////////////////////////////////////////////////////////////////////////////
485
486// example of how Android will do this inside their BitmapFactory
487static SkPixelRef* install_pixel_ref(SkBitmap* bitmap,
488                                     SkStreamRewindable* stream,
489                                     int sampleSize, bool ditherImage) {
490    SkASSERT(bitmap != NULL);
491    SkASSERT(stream != NULL);
492    SkASSERT(stream->rewind());
493    SkASSERT(stream->unique());
494    SkColorType colorType = bitmap->colorType();
495    SkDecodingImageGenerator::Options opts(sampleSize, ditherImage, colorType);
496    if (SkInstallDiscardablePixelRef(
497                SkDecodingImageGenerator::Create(stream, opts), bitmap)) {
498        return bitmap->pixelRef();
499    }
500    return NULL;
501}
502/**
503 *  A test for the SkDecodingImageGenerator::Create and
504 *  SkInstallDiscardablePixelRef functions.
505 */
506DEF_TEST(ImprovedBitmapFactory, reporter) {
507    SkString pngFilename = GetResourcePath("randPixels.png");
508    SkAutoTUnref<SkStreamRewindable> stream(SkStream::NewFromFile(pngFilename.c_str()));
509    if (sk_exists(pngFilename.c_str())) {
510        SkBitmap bm;
511        SkAssertResult(bm.setInfo(SkImageInfo::MakeN32Premul(1, 1)));
512        REPORTER_ASSERT(reporter,
513            install_pixel_ref(&bm, stream.detach(), 1, true));
514        SkAutoLockPixels alp(bm);
515        REPORTER_ASSERT(reporter, bm.getPixels());
516    }
517}
518
519
520////////////////////////////////////////////////////////////////////////////////
521
522#if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX)
523static inline bool check_rounding(int value, int dividend, int divisor) {
524    // returns true if the value is greater than floor(dividend/divisor)
525    // and less than SkNextPow2(ceil(dividend - divisor))
526    return (((divisor * value) > (dividend - divisor))
527            && value <= SkNextPow2(((dividend - 1) / divisor) + 1));
528}
529#endif  // SK_BUILD_FOR_ANDROID || SK_BUILD_FOR_UNIX
530
531
532#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
533    #define kBackwards_SkColorType kRGBA_8888_SkColorType
534#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
535    #define kBackwards_SkColorType kBGRA_8888_SkColorType
536#else
537    #error "SK_*32_SHFIT values must correspond to BGRA or RGBA byte order"
538#endif
539
540static inline const char* SkColorType_to_string(SkColorType colorType) {
541    switch(colorType) {
542        case kAlpha_8_SkColorType:   return "Alpha_8";
543        case kRGB_565_SkColorType:   return "RGB_565";
544        case kARGB_4444_SkColorType: return "ARGB_4444";
545        case kN32_SkColorType:       return "N32";
546        case kBackwards_SkColorType: return "Backwards";
547        case kIndex_8_SkColorType:   return "Index_8";
548        default:                     return "ERROR";
549    }
550}
551
552static inline const char* options_colorType(
553        const SkDecodingImageGenerator::Options& opts) {
554    if (opts.fUseRequestedColorType) {
555        return SkColorType_to_string(opts.fRequestedColorType);
556    } else {
557        return "(none)";
558    }
559}
560
561static inline const char* yn(bool value) {
562    if (value) {
563        return "yes";
564    } else {
565        return "no";
566    }
567}
568
569/**
570 * Given either a SkStream or a SkData, try to decode the encoded
571 * image using the specified options and report errors.
572 */
573static void test_options(skiatest::Reporter* reporter,
574                         const SkDecodingImageGenerator::Options& opts,
575                         SkStreamRewindable* encodedStream,
576                         SkData* encodedData,
577                         bool useData,
578                         const SkString& path) {
579    SkBitmap bm;
580    bool success = false;
581    if (useData) {
582        if (NULL == encodedData) {
583            return;
584        }
585        success = SkInstallDiscardablePixelRef(
586            SkDecodingImageGenerator::Create(encodedData, opts), &bm);
587    } else {
588        if (NULL == encodedStream) {
589            return;
590        }
591        success = SkInstallDiscardablePixelRef(
592            SkDecodingImageGenerator::Create(encodedStream->duplicate(), opts), &bm);
593    }
594    if (!success) {
595        if (opts.fUseRequestedColorType
596            && (kARGB_4444_SkColorType == opts.fRequestedColorType)) {
597            return;  // Ignore known conversion inabilities.
598        }
599        // If we get here, it's a failure and we will need more
600        // information about why it failed.
601        ERRORF(reporter, "Bounds decode failed [sampleSize=%d dither=%s "
602               "colorType=%s %s]", opts.fSampleSize, yn(opts.fDitherImage),
603               options_colorType(opts), path.c_str());
604        return;
605    }
606    #if defined(SK_BUILD_FOR_ANDROID) || defined(SK_BUILD_FOR_UNIX)
607    // Android is the only system that use Skia's image decoders in
608    // production.  For now, we'll only verify that samplesize works
609    // on systems where it already is known to work.
610    REPORTER_ASSERT(reporter, check_rounding(bm.height(), kExpectedHeight,
611                                             opts.fSampleSize));
612    REPORTER_ASSERT(reporter, check_rounding(bm.width(), kExpectedWidth,
613                                             opts.fSampleSize));
614    // The ImageDecoder API doesn't guarantee that SampleSize does
615    // anything at all, but the decoders that this test excercises all
616    // produce an output size in the following range:
617    //    (((sample_size * out_size) > (in_size - sample_size))
618    //     && out_size <= SkNextPow2(((in_size - 1) / sample_size) + 1));
619    #endif  // SK_BUILD_FOR_ANDROID || SK_BUILD_FOR_UNIX
620    SkAutoLockPixels alp(bm);
621    if (bm.getPixels() == NULL) {
622        ERRORF(reporter, "Pixel decode failed [sampleSize=%d dither=%s "
623               "colorType=%s %s]", opts.fSampleSize, yn(opts.fDitherImage),
624               options_colorType(opts), path.c_str());
625        return;
626    }
627
628    SkColorType requestedColorType = opts.fRequestedColorType;
629    REPORTER_ASSERT(reporter,
630                    (!opts.fUseRequestedColorType)
631                    || (bm.colorType() == requestedColorType));
632
633    // Condition under which we should check the decoding results:
634    if ((kN32_SkColorType == bm.colorType())
635        && (!path.endsWith(".jpg"))  // lossy
636        && (opts.fSampleSize == 1)) {  // scaled
637        const SkColor* correctPixels = kExpectedPixels;
638        SkASSERT(bm.height() == kExpectedHeight);
639        SkASSERT(bm.width() == kExpectedWidth);
640        int pixelErrors = 0;
641        for (int y = 0; y < bm.height(); ++y) {
642            for (int x = 0; x < bm.width(); ++x) {
643                if (*correctPixels != bm.getColor(x, y)) {
644                    ++pixelErrors;
645                }
646                ++correctPixels;
647            }
648        }
649        if (pixelErrors != 0) {
650            ERRORF(reporter, "Pixel-level mismatch (%d of %d) "
651                   "[sampleSize=%d dither=%s colorType=%s %s]",
652                   pixelErrors, kExpectedHeight * kExpectedWidth,
653                   opts.fSampleSize, yn(opts.fDitherImage),
654                   options_colorType(opts), path.c_str());
655        }
656    }
657}
658
659/**
660 *  SkDecodingImageGenerator has an Options struct which lets the
661 *  client of the generator set sample size, dithering, and bitmap
662 *  config.  This test loops through many possible options and tries
663 *  them on a set of 5 small encoded images (each in a different
664 *  format).  We test both SkData and SkStreamRewindable decoding.
665 */
666DEF_TEST(ImageDecoderOptions, reporter) {
667    const char* files[]  = {
668        "randPixels.bmp",
669        "randPixels.jpg",
670        "randPixels.png",
671        "randPixels.webp",
672        #if !defined(SK_BUILD_FOR_WIN)
673        // TODO(halcanary): Find out why this fails sometimes.
674        "randPixels.gif",
675        #endif
676    };
677
678    SkString resourceDir = GetResourcePath();
679    if (!sk_exists(resourceDir.c_str())) {
680        return;
681    }
682
683    int scaleList[] = {1, 2, 3, 4};
684    bool ditherList[] = {true, false};
685    SkColorType colorList[] = {
686        kAlpha_8_SkColorType,
687        kRGB_565_SkColorType,
688        kARGB_4444_SkColorType,  // Most decoders will fail on 4444.
689        kN32_SkColorType
690        // Note that indexed color is left out of the list.  Lazy
691        // decoding doesn't do indexed color.
692    };
693    const bool useDataList[] = {true, false};
694
695    for (size_t fidx = 0; fidx < SK_ARRAY_COUNT(files); ++fidx) {
696        SkString path = SkOSPath::Join(resourceDir.c_str(), files[fidx]);
697        if (!sk_exists(path.c_str())) {
698            continue;
699        }
700
701        SkAutoDataUnref encodedData(SkData::NewFromFileName(path.c_str()));
702        REPORTER_ASSERT(reporter, encodedData.get() != NULL);
703        SkAutoTUnref<SkStreamRewindable> encodedStream(
704            SkStream::NewFromFile(path.c_str()));
705        REPORTER_ASSERT(reporter, encodedStream.get() != NULL);
706
707        for (size_t i = 0; i < SK_ARRAY_COUNT(scaleList); ++i) {
708            for (size_t j = 0; j < SK_ARRAY_COUNT(ditherList); ++j) {
709                for (size_t m = 0; m < SK_ARRAY_COUNT(useDataList); ++m) {
710                    for (size_t k = 0; k < SK_ARRAY_COUNT(colorList); ++k) {
711                        SkDecodingImageGenerator::Options opts(scaleList[i],
712                                                               ditherList[j],
713                                                               colorList[k]);
714                        test_options(reporter, opts, encodedStream, encodedData,
715                                     useDataList[m], path);
716
717                    }
718                    SkDecodingImageGenerator::Options options(scaleList[i],
719                                                              ditherList[j]);
720                    test_options(reporter, options, encodedStream, encodedData,
721                                 useDataList[m], path);
722                }
723            }
724        }
725    }
726}
727
728DEF_TEST(DiscardablePixelRef_SecondLockColorTableCheck, r) {
729    SkString resourceDir = GetResourcePath();
730    SkString path = SkOSPath::Join(resourceDir.c_str(), "randPixels.gif");
731    if (!sk_exists(path.c_str())) {
732        return;
733    }
734    SkAutoDataUnref encoded(SkData::NewFromFileName(path.c_str()));
735    SkBitmap bitmap;
736    if (!SkInstallDiscardablePixelRef(
737            SkDecodingImageGenerator::Create(
738                    encoded, SkDecodingImageGenerator::Options()), &bitmap)) {
739        #ifndef SK_BUILD_FOR_WIN
740        ERRORF(r, "SkInstallDiscardablePixelRef [randPixels.gif] failed.");
741        #endif
742        return;
743    }
744    if (kIndex_8_SkColorType != bitmap.colorType()) {
745        return;
746    }
747    {
748        SkAutoLockPixels alp(bitmap);
749        REPORTER_ASSERT(r, bitmap.getColorTable() && "first pass");
750    }
751    {
752        SkAutoLockPixels alp(bitmap);
753        REPORTER_ASSERT(r, bitmap.getColorTable() && "second pass");
754    }
755}
756
757
758////////////////////////////////////////////////////////////////////////////////
759namespace {
760class SingleAllocator : public SkBitmap::Allocator {
761public:
762    SingleAllocator(void* p, size_t s) : fPixels(p), fSize(s) { }
763    ~SingleAllocator() {}
764    // If the pixels in fPixels are big enough, use them.
765    virtual bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) SK_OVERRIDE {
766        SkASSERT(bm);
767        if (bm->info().getSafeSize(bm->rowBytes()) <= fSize) {
768            bm->setPixels(fPixels, ct);
769            fPixels = NULL;
770            fSize = 0;
771            return true;
772        }
773        return bm->tryAllocPixels(NULL, ct);
774    }
775    bool ready() { return fPixels != NULL; }
776private:
777    void* fPixels;
778    size_t fSize;
779};
780}  // namespace
781
782/*  This tests for a bug in libjpeg where INT32 is typedefed to long
783    and memory can be written to outside of the array. */
784DEF_TEST(ImageDecoding_JpegOverwrite, r) {
785    SkString resourceDir = GetResourcePath();
786    SkString path = SkOSPath::Join(resourceDir.c_str(), "randPixels.jpg");
787    SkAutoTUnref<SkStreamAsset> stream(
788            SkStream::NewFromFile(path.c_str()));
789    if (!stream.get()) {
790        SkDebugf("\nPath '%s' missing.\n", path.c_str());
791        return;
792    }
793    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream));
794    if (NULL == decoder.get()) {
795        ERRORF(r, "\nSkImageDecoder::Factory failed.\n");
796        return;
797    }
798    SkAssertResult(stream->rewind());
799
800    static const uint16_t sentinal = 0xBEEF;
801    static const int pixelCount = 16;
802    SkAutoTMalloc<uint16_t> pixels(pixelCount + 1);
803    // pixels.get() should be 4-byte aligned.
804    // This is necessary to reproduce the bug.
805
806    pixels[pixelCount] = sentinal;  // This value should not be changed.
807
808    SkAutoTUnref<SingleAllocator> allocator(
809            SkNEW_ARGS(SingleAllocator,
810                       ((void*)pixels.get(), sizeof(uint16_t) * pixelCount)));
811    decoder->setAllocator(allocator);
812    decoder->setSampleSize(2);
813    SkBitmap bitmap;
814    bool success = decoder->decode(stream, &bitmap, kRGB_565_SkColorType,
815                                   SkImageDecoder::kDecodePixels_Mode);
816    REPORTER_ASSERT(r, success);
817    REPORTER_ASSERT(r, !allocator->ready());  // Decoder used correct memory
818    REPORTER_ASSERT(r, sentinal == pixels[pixelCount]);
819}
820