blob: 0ad24969c2435fe67d6d5019ee4da67e9743ccad [file] [log] [blame]
krajcevskic250d2e2014-06-06 06:16:28 -07001/*
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
tfarinabcbc1782014-06-18 14:32:48 -07008#include "Resources.h"
krajcevskic250d2e2014-06-06 06:16:28 -07009#include "SkBitmap.h"
10#include "SkData.h"
reed13f48dc2015-09-28 08:58:53 -070011#include "SkImage.h"
reed5965c8a2015-01-07 18:04:45 -080012#include "SkImageGenerator.h"
krajcevskic250d2e2014-06-06 06:16:28 -070013#include "SkForceLinking.h"
14#include "SkImageDecoder.h"
15#include "SkOSFile.h"
16#include "SkRandom.h"
17#include "SkStream.h"
18#include "Test.h"
19
20__SK_FORCE_IMAGE_DECODER_LINKING;
21
22/**
23 * First, make sure that writing an 8-bit RGBA KTX file and then
24 * reading it produces the same bitmap.
25 */
26DEF_TEST(KtxReadWrite, reporter) {
27
28 // Random number generator with explicit seed for reproducibility
29 SkRandom rand(0x1005cbad);
30
31 SkBitmap bm8888;
reed84825042014-09-02 12:50:45 -070032 bm8888.allocN32Pixels(128, 128);
krajcevskic250d2e2014-06-06 06:16:28 -070033
34 uint8_t *pixels = reinterpret_cast<uint8_t*>(bm8888.getPixels());
bsalomon49f085d2014-09-05 13:34:00 -070035 REPORTER_ASSERT(reporter, pixels);
krajcevskic250d2e2014-06-06 06:16:28 -070036
halcanary96fcdcc2015-08-27 07:41:13 -070037 if (nullptr == pixels) {
krajcevskic250d2e2014-06-06 06:16:28 -070038 return;
39 }
40
41 uint8_t *row = pixels;
42 for (int y = 0; y < bm8888.height(); ++y) {
43 for (int x = 0; x < bm8888.width(); ++x) {
44 uint8_t a = rand.nextRangeU(0, 255);
45 uint8_t r = rand.nextRangeU(0, 255);
46 uint8_t g = rand.nextRangeU(0, 255);
47 uint8_t b = rand.nextRangeU(0, 255);
48
49 SkPMColor &pixel = *(reinterpret_cast<SkPMColor*>(row + x*sizeof(SkPMColor)));
50 pixel = SkPreMultiplyARGB(a, r, g, b);
51 }
52 row += bm8888.rowBytes();
53 }
54 REPORTER_ASSERT(reporter, !(bm8888.empty()));
55
56 SkAutoDataUnref encodedData(SkImageEncoder::EncodeData(bm8888, SkImageEncoder::kKTX_Type, 0));
bsalomon49f085d2014-09-05 13:34:00 -070057 REPORTER_ASSERT(reporter, encodedData);
krajcevskic250d2e2014-06-06 06:16:28 -070058
halcanary385fe4d2015-08-26 13:07:48 -070059 SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(encodedData));
bsalomon49f085d2014-09-05 13:34:00 -070060 REPORTER_ASSERT(reporter, stream);
krajcevskic250d2e2014-06-06 06:16:28 -070061
62 SkBitmap decodedBitmap;
63 bool imageDecodeSuccess = SkImageDecoder::DecodeStream(stream, &decodedBitmap);
64 REPORTER_ASSERT(reporter, imageDecodeSuccess);
65
reedc3b32662014-06-17 08:38:31 -070066 REPORTER_ASSERT(reporter, decodedBitmap.colorType() == bm8888.colorType());
krajcevskic250d2e2014-06-06 06:16:28 -070067 REPORTER_ASSERT(reporter, decodedBitmap.alphaType() == bm8888.alphaType());
68 REPORTER_ASSERT(reporter, decodedBitmap.width() == bm8888.width());
69 REPORTER_ASSERT(reporter, decodedBitmap.height() == bm8888.height());
70 REPORTER_ASSERT(reporter, !(decodedBitmap.empty()));
71
72 uint8_t *decodedPixels = reinterpret_cast<uint8_t*>(decodedBitmap.getPixels());
bsalomon49f085d2014-09-05 13:34:00 -070073 REPORTER_ASSERT(reporter, decodedPixels);
krajcevskic250d2e2014-06-06 06:16:28 -070074 REPORTER_ASSERT(reporter, decodedBitmap.getSize() == bm8888.getSize());
75
halcanary96fcdcc2015-08-27 07:41:13 -070076 if (nullptr == decodedPixels) {
krajcevskic250d2e2014-06-06 06:16:28 -070077 return;
78 }
79
80 REPORTER_ASSERT(reporter, memcmp(decodedPixels, pixels, decodedBitmap.getSize()) == 0);
81}
82
83/**
84 * Next test is to see whether or not reading an unpremultiplied KTX file accurately
85 * creates a premultiplied buffer...
86 */
87DEF_TEST(KtxReadUnpremul, reporter) {
88
89 static const uint8_t kHalfWhiteKTX[] = {
90 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, // First twelve bytes is magic
91 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A, // KTX identifier string
92 0x01, 0x02, 0x03, 0x04, // Then magic endian specifier
93 0x01, 0x14, 0x00, 0x00, // uint32_t fGLType;
94 0x01, 0x00, 0x00, 0x00, // uint32_t fGLTypeSize;
95 0x08, 0x19, 0x00, 0x00, // uint32_t fGLFormat;
96 0x58, 0x80, 0x00, 0x00, // uint32_t fGLInternalFormat;
97 0x08, 0x19, 0x00, 0x00, // uint32_t fGLBaseInternalFormat;
98 0x02, 0x00, 0x00, 0x00, // uint32_t fPixelWidth;
99 0x02, 0x00, 0x00, 0x00, // uint32_t fPixelHeight;
100 0x00, 0x00, 0x00, 0x00, // uint32_t fPixelDepth;
101 0x00, 0x00, 0x00, 0x00, // uint32_t fNumberOfArrayElements;
102 0x01, 0x00, 0x00, 0x00, // uint32_t fNumberOfFaces;
103 0x01, 0x00, 0x00, 0x00, // uint32_t fNumberOfMipmapLevels;
104 0x00, 0x00, 0x00, 0x00, // uint32_t fBytesOfKeyValueData;
105 0x10, 0x00, 0x00, 0x00, // image size: 2x2 image of RGBA = 4 * 4 = 16 bytes
106 0xFF, 0xFF, 0xFF, 0x80, // Pixel 1
107 0xFF, 0xFF, 0xFF, 0x80, // Pixel 2
108 0xFF, 0xFF, 0xFF, 0x80, // Pixel 3
109 0xFF, 0xFF, 0xFF, 0x80};// Pixel 4
110
halcanary385fe4d2015-08-26 13:07:48 -0700111 SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(kHalfWhiteKTX, sizeof(kHalfWhiteKTX)));
bsalomon49f085d2014-09-05 13:34:00 -0700112 REPORTER_ASSERT(reporter, stream);
krajcevskic250d2e2014-06-06 06:16:28 -0700113
114 SkBitmap decodedBitmap;
115 bool imageDecodeSuccess = SkImageDecoder::DecodeStream(stream, &decodedBitmap);
116 REPORTER_ASSERT(reporter, imageDecodeSuccess);
117
reed0689d7b2014-06-14 05:30:20 -0700118 REPORTER_ASSERT(reporter, decodedBitmap.colorType() == kN32_SkColorType);
krajcevskic250d2e2014-06-06 06:16:28 -0700119 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());
bsalomon49f085d2014-09-05 13:34:00 -0700125 REPORTER_ASSERT(reporter, decodedPixels);
krajcevskic250d2e2014-06-06 06:16:28 -0700126
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 */
142DEF_TEST(KtxReexportPKM, reporter) {
tfarinac846f4a2014-07-01 12:35:49 -0700143 SkString pkmFilename = GetResourcePath("mandrill_128.pkm");
krajcevskic250d2e2014-06-06 06:16:28 -0700144
145 // Load PKM file into a bitmap
146 SkBitmap etcBitmap;
tfarinac846f4a2014-07-01 12:35:49 -0700147 SkAutoTUnref<SkData> fileData(SkData::NewFromFileName(pkmFilename.c_str()));
halcanary96fcdcc2015-08-27 07:41:13 -0700148 if (nullptr == fileData) {
reed15c74602014-10-28 07:12:37 -0700149 SkDebugf("KtxReexportPKM: can't load test file %s\n", pkmFilename.c_str());
reed7a7c3162014-07-02 05:57:50 -0700150 return;
151 }
krajcevskic250d2e2014-06-06 06:16:28 -0700152
reed13f48dc2015-09-28 08:58:53 -0700153 SkAutoTUnref<SkImage> image(SkImage::NewFromEncoded(fileData));
154 REPORTER_ASSERT(reporter, image.get());
krajcevskic250d2e2014-06-06 06:16:28 -0700155
reed13f48dc2015-09-28 08:58:53 -0700156 SkAutoDataUnref newKtxData(image->encode(SkImageEncoder::kKTX_Type, 0));
157 REPORTER_ASSERT(reporter, newKtxData.get());
krajcevskic250d2e2014-06-06 06:16:28 -0700158
159 // See is this data is identical to data in existing ktx file.
tfarinac846f4a2014-07-01 12:35:49 -0700160 SkString ktxFilename = GetResourcePath("mandrill_128.ktx");
krajcevskic250d2e2014-06-06 06:16:28 -0700161 SkAutoDataUnref oldKtxData(SkData::NewFromFileName(ktxFilename.c_str()));
162 REPORTER_ASSERT(reporter, oldKtxData->equals(newKtxData));
163}