2 * Copyright 2013 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
10 #include "sk_tool_utils.h"
11 #include "Resources.h"
12 #include "SampleCode.h"
13 #include "SkBlurMask.h"
14 #include "SkBlurDrawLooper.h"
16 #include "SkColorPriv.h"
17 #include "SkForceLinking.h"
18 #include "SkImageDecoder.h"
22 #include "SkSystemEventTypes.h"
27 __SK_FORCE_IMAGE_DECODER_LINKING;
30 * Interprets c as an unpremultiplied color, and returns the
31 * premultiplied equivalent.
33 static SkPMColor premultiply_unpmcolor(SkPMColor c) {
34 U8CPU a = SkGetPackedA32(c);
35 U8CPU r = SkGetPackedR32(c);
36 U8CPU g = SkGetPackedG32(c);
37 U8CPU b = SkGetPackedB32(c);
38 return SkPreMultiplyARGB(a, r, g, b);
41 class UnpremulView : public SampleView {
43 UnpremulView(SkString res)
46 , fDecodeSucceeded(false) {
51 // overrides from SkEventSink
52 bool onQuery(SkEvent* evt) SK_OVERRIDE {
53 if (SampleCode::TitleQ(*evt)) {
54 SampleCode::TitleR(evt, "unpremul");
58 if (SampleCode::CharQ(*evt, &uni)) {
59 char utf8[kMaxBytesInUTF8Sequence];
60 size_t size = SkUTF8_FromUnichar(uni, utf8);
61 // Only consider events for single char keys
67 case fTogglePremulChar:
75 return this->INHERITED::onQuery(evt);
78 void onDrawBackground(SkCanvas* canvas) SK_OVERRIDE {
79 sk_tool_utils::draw_checkerboard(canvas, 0xFFCCCCCC, 0xFFFFFFFF, 12);
82 void onDrawContent(SkCanvas* canvas) SK_OVERRIDE {
84 paint.setAntiAlias(true);
85 paint.setTextSize(SkIntToScalar(24));
86 SkAutoTUnref<SkBlurDrawLooper> looper(
87 SkBlurDrawLooper::Create(SK_ColorBLUE,
88 SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(2)),
90 paint.setLooper(looper);
91 SkScalar height = paint.getFontMetrics(NULL);
92 if (!fDecodeSucceeded) {
94 if (fResPath.size() == 0) {
95 failure.printf("resource path is required!");
97 failure.printf("Failed to decode %s", fCurrFile.c_str());
99 canvas->drawText(failure.c_str(), failure.size(), 0, height, paint);
103 // Name, size of the file, and whether or not it is premultiplied.
104 SkString header(SkOSPath::Basename(fCurrFile.c_str()));
105 header.appendf(" [%dx%d] %s", fBitmap.width(), fBitmap.height(),
106 (fPremul ? "premultiplied" : "unpremultiplied"));
107 canvas->drawText(header.c_str(), header.size(), 0, height, paint);
108 canvas->translate(0, height);
111 header.printf("Press '%c' to move to the next image.'", fNextImageChar);
112 canvas->drawText(header.c_str(), header.size(), 0, height, paint);
113 canvas->translate(0, height);
115 header.printf("Press '%c' to toggle premultiplied decode.", fTogglePremulChar);
116 canvas->drawText(header.c_str(), header.size(), 0, height, paint);
118 // Now draw the image itself.
119 canvas->translate(height * 2, height * 2);
121 // A premultiplied bitmap cannot currently be drawn.
122 SkAutoLockPixels alp(fBitmap);
123 // Copy it to a bitmap which can be drawn, converting
126 bm.allocN32Pixels(fBitmap.width(), fBitmap.height());
127 for (int i = 0; i < fBitmap.width(); ++i) {
128 for (int j = 0; j < fBitmap.height(); ++j) {
129 *bm.getAddr32(i, j) = premultiply_unpmcolor(*fBitmap.getAddr32(i, j));
132 canvas->drawBitmap(bm, 0, 0);
134 canvas->drawBitmap(fBitmap, 0, 0);
139 const SkString fResPath;
142 bool fDecodeSucceeded;
144 SkOSFile::Iter fFileIter;
146 static const char fNextImageChar = 'j';
147 static const char fTogglePremulChar = 'h';
150 if (fResPath.size() == 0) {
154 if (!fFileIter.next(&basename)) {
155 fFileIter.reset(fResPath.c_str());
156 if (!fFileIter.next(&basename)) {
157 // Perhaps this should draw some error message?
161 fCurrFile = SkOSPath::Join(fResPath.c_str(), basename.c_str());
162 this->decodeCurrFile();
165 void decodeCurrFile() {
166 if (fCurrFile.size() == 0) {
167 fDecodeSucceeded = false;
170 SkFILEStream stream(fCurrFile.c_str());
171 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream));
172 if (NULL == decoder.get()) {
173 fDecodeSucceeded = false;
177 decoder->setRequireUnpremultipliedColors(true);
179 fDecodeSucceeded = decoder->decode(&stream, &fBitmap, kN32_SkColorType,
180 SkImageDecoder::kDecodePixels_Mode) != SkImageDecoder::kFailure;
184 void togglePremul() {
186 this->decodeCurrFile();
189 typedef SampleView INHERITED;
192 //////////////////////////////////////////////////////////////////////////////
194 static SkView* MyFactory() {
195 return new UnpremulView(GetResourcePath());
197 static SkViewRegister reg(MyFactory);