• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 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 "SkData.h"
11 #include "SkImageGenerator.h"
12 #include "SkForceLinking.h"
13 #include "SkImageDecoder.h"
14 #include "SkOSFile.h"
15 #include "SkRandom.h"
16 #include "SkStream.h"
17 #include "Test.h"
18 
19 __SK_FORCE_IMAGE_DECODER_LINKING;
20 
21 /**
22  * First, make sure that writing an 8-bit RGBA KTX file and then
23  * reading it produces the same bitmap.
24  */
DEF_TEST(KtxReadWrite,reporter)25 DEF_TEST(KtxReadWrite, reporter) {
26 
27     // Random number generator with explicit seed for reproducibility
28     SkRandom rand(0x1005cbad);
29 
30     SkBitmap bm8888;
31     bm8888.allocN32Pixels(128, 128);
32 
33     uint8_t *pixels = reinterpret_cast<uint8_t*>(bm8888.getPixels());
34     REPORTER_ASSERT(reporter, pixels);
35 
36     if (NULL == pixels) {
37         return;
38     }
39 
40     uint8_t *row = pixels;
41     for (int y = 0; y < bm8888.height(); ++y) {
42         for (int x = 0; x < bm8888.width(); ++x) {
43             uint8_t a = rand.nextRangeU(0, 255);
44             uint8_t r = rand.nextRangeU(0, 255);
45             uint8_t g = rand.nextRangeU(0, 255);
46             uint8_t b = rand.nextRangeU(0, 255);
47 
48             SkPMColor &pixel = *(reinterpret_cast<SkPMColor*>(row + x*sizeof(SkPMColor)));
49             pixel = SkPreMultiplyARGB(a, r, g, b);
50         }
51         row += bm8888.rowBytes();
52     }
53     REPORTER_ASSERT(reporter, !(bm8888.empty()));
54 
55     SkAutoDataUnref encodedData(SkImageEncoder::EncodeData(bm8888, SkImageEncoder::kKTX_Type, 0));
56     REPORTER_ASSERT(reporter, encodedData);
57 
58     SkAutoTDelete<SkMemoryStream> stream(SkNEW_ARGS(SkMemoryStream, (encodedData)));
59     REPORTER_ASSERT(reporter, stream);
60 
61     SkBitmap decodedBitmap;
62     bool imageDecodeSuccess = SkImageDecoder::DecodeStream(stream, &decodedBitmap);
63     REPORTER_ASSERT(reporter, imageDecodeSuccess);
64 
65     REPORTER_ASSERT(reporter, decodedBitmap.colorType() == bm8888.colorType());
66     REPORTER_ASSERT(reporter, decodedBitmap.alphaType() == bm8888.alphaType());
67     REPORTER_ASSERT(reporter, decodedBitmap.width() == bm8888.width());
68     REPORTER_ASSERT(reporter, decodedBitmap.height() == bm8888.height());
69     REPORTER_ASSERT(reporter, !(decodedBitmap.empty()));
70 
71     uint8_t *decodedPixels = reinterpret_cast<uint8_t*>(decodedBitmap.getPixels());
72     REPORTER_ASSERT(reporter, decodedPixels);
73     REPORTER_ASSERT(reporter, decodedBitmap.getSize() == bm8888.getSize());
74 
75     if (NULL == decodedPixels) {
76         return;
77     }
78 
79     REPORTER_ASSERT(reporter, memcmp(decodedPixels, pixels, decodedBitmap.getSize()) == 0);
80 }
81 
82 /**
83  * Next test is to see whether or not reading an unpremultiplied KTX file accurately
84  * creates a premultiplied buffer...
85  */
DEF_TEST(KtxReadUnpremul,reporter)86 DEF_TEST(KtxReadUnpremul, reporter) {
87 
88     static const uint8_t kHalfWhiteKTX[] = {
89         0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, // First twelve bytes is magic
90         0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A, // KTX identifier string
91         0x01, 0x02, 0x03, 0x04, // Then magic endian specifier
92         0x01, 0x14, 0x00, 0x00, // uint32_t fGLType;
93         0x01, 0x00, 0x00, 0x00, // uint32_t fGLTypeSize;
94         0x08, 0x19, 0x00, 0x00, // uint32_t fGLFormat;
95         0x58, 0x80, 0x00, 0x00, // uint32_t fGLInternalFormat;
96         0x08, 0x19, 0x00, 0x00, // uint32_t fGLBaseInternalFormat;
97         0x02, 0x00, 0x00, 0x00, // uint32_t fPixelWidth;
98         0x02, 0x00, 0x00, 0x00, // uint32_t fPixelHeight;
99         0x00, 0x00, 0x00, 0x00, // uint32_t fPixelDepth;
100         0x00, 0x00, 0x00, 0x00, // uint32_t fNumberOfArrayElements;
101         0x01, 0x00, 0x00, 0x00, // uint32_t fNumberOfFaces;
102         0x01, 0x00, 0x00, 0x00, // uint32_t fNumberOfMipmapLevels;
103         0x00, 0x00, 0x00, 0x00, // uint32_t fBytesOfKeyValueData;
104         0x10, 0x00, 0x00, 0x00, // image size: 2x2 image of RGBA = 4 * 4 = 16 bytes
105         0xFF, 0xFF, 0xFF, 0x80, // Pixel 1
106         0xFF, 0xFF, 0xFF, 0x80, // Pixel 2
107         0xFF, 0xFF, 0xFF, 0x80, // Pixel 3
108         0xFF, 0xFF, 0xFF, 0x80};// Pixel 4
109 
110     SkAutoTDelete<SkMemoryStream> stream(
111         SkNEW_ARGS(SkMemoryStream, (kHalfWhiteKTX, sizeof(kHalfWhiteKTX))));
112     REPORTER_ASSERT(reporter, stream);
113 
114     SkBitmap decodedBitmap;
115     bool imageDecodeSuccess = SkImageDecoder::DecodeStream(stream, &decodedBitmap);
116     REPORTER_ASSERT(reporter, imageDecodeSuccess);
117 
118     REPORTER_ASSERT(reporter, decodedBitmap.colorType() == kN32_SkColorType);
119     REPORTER_ASSERT(reporter, decodedBitmap.alphaType() == kPremul_SkAlphaType);
120     REPORTER_ASSERT(reporter, decodedBitmap.width() == 2);
121     REPORTER_ASSERT(reporter, decodedBitmap.height() == 2);
122     REPORTER_ASSERT(reporter, !(decodedBitmap.empty()));
123 
124     uint8_t *decodedPixels = reinterpret_cast<uint8_t*>(decodedBitmap.getPixels());
125     REPORTER_ASSERT(reporter, decodedPixels);
126 
127     uint8_t *row = decodedPixels;
128     for (int j = 0; j < decodedBitmap.height(); ++j) {
129         for (int i = 0; i < decodedBitmap.width(); ++i) {
130             SkPMColor pixel = *(reinterpret_cast<SkPMColor*>(row + i*sizeof(SkPMColor)));
131             REPORTER_ASSERT(reporter, SkPreMultiplyARGB(0x80, 0xFF, 0xFF, 0xFF) == pixel);
132         }
133         row += decodedBitmap.rowBytes();
134     }
135 }
136 
137 /**
138  * Finally, make sure that if we get ETC1 data from a PKM file that we can then
139  * accurately write it out into a KTX file (i.e. transferring the ETC1 data from
140  * the PKM to the KTX should produce an identical KTX to the one we have on file)
141  */
DEF_TEST(KtxReexportPKM,reporter)142 DEF_TEST(KtxReexportPKM, reporter) {
143     SkString pkmFilename = GetResourcePath("mandrill_128.pkm");
144 
145     // Load PKM file into a bitmap
146     SkBitmap etcBitmap;
147     SkAutoTUnref<SkData> fileData(SkData::NewFromFileName(pkmFilename.c_str()));
148     if (NULL == fileData) {
149         SkDebugf("KtxReexportPKM: can't load test file %s\n", pkmFilename.c_str());
150         return;
151     }
152 
153     bool installDiscardablePixelRefSuccess =
154         SkInstallDiscardablePixelRef(fileData, &etcBitmap);
155     REPORTER_ASSERT(reporter, installDiscardablePixelRefSuccess);
156 
157     // Write the bitmap out to a KTX file.
158     SkData *ktxDataPtr = SkImageEncoder::EncodeData(etcBitmap, SkImageEncoder::kKTX_Type, 0);
159     SkAutoDataUnref newKtxData(ktxDataPtr);
160     REPORTER_ASSERT(reporter, ktxDataPtr);
161 
162     // See is this data is identical to data in existing ktx file.
163     SkString ktxFilename = GetResourcePath("mandrill_128.ktx");
164     SkAutoDataUnref oldKtxData(SkData::NewFromFileName(ktxFilename.c_str()));
165     REPORTER_ASSERT(reporter, oldKtxData->equals(newKtxData));
166 }
167