1
2 /*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8 #include "SampleCode.h"
9 #include "SkView.h"
10 #include "SkCanvas.h"
11 #include "SkData.h"
12 #include "SkDecodingImageGenerator.h"
13 #include "SkGradientShader.h"
14 #include "SkGraphics.h"
15 #include "SkImageDecoder.h"
16 #include "SkImageEncoder.h"
17 #include "SkPath.h"
18 #include "SkRegion.h"
19 #include "SkShader.h"
20 #include "SkUtils.h"
21 #include "SkXfermode.h"
22 #include "SkColorPriv.h"
23 #include "SkColorFilter.h"
24 #include "SkTime.h"
25 #include "SkTypeface.h"
26
27 #include "SkStream.h"
28
make_image(SkBitmap * bm,SkColorType ct,int configIndex)29 static void make_image(SkBitmap* bm, SkColorType ct, int configIndex) {
30 const int width = 98;
31 const int height = 100;
32 const SkImageInfo info = SkImageInfo::Make(width, height, ct, kPremul_SkAlphaType);
33
34 SkBitmap device;
35 device.allocN32Pixels(width, height);
36 SkCanvas canvas(device);
37 SkPaint paint;
38
39 paint.setAntiAlias(true);
40 canvas.drawColor(SK_ColorRED);
41 paint.setColor(SK_ColorBLUE);
42 canvas.drawCircle(SkIntToScalar(width)/2, SkIntToScalar(height)/2,
43 SkIntToScalar(width)/2, paint);
44
45 switch (ct) {
46 case kN32_SkColorType:
47 bm->swap(device);
48 break;
49 case kRGB_565_SkColorType: {
50 bm->allocPixels(info);
51 for (int y = 0; y < height; y++) {
52 for (int x = 0; x < width; x++) {
53 *bm->getAddr16(x, y) = SkPixel32ToPixel16(*device.getAddr32(x, y));
54 }
55 }
56 break;
57 }
58 case kIndex_8_SkColorType: {
59 SkPMColor colors[256];
60 for (int i = 0; i < 256; i++) {
61 if (configIndex & 1) {
62 colors[i] = SkPackARGB32(255-i, 0, 0, 255-i);
63 } else {
64 colors[i] = SkPackARGB32(0xFF, i, 0, 255-i);
65 }
66 }
67 SkColorTable* ctable = new SkColorTable(colors, 256);
68 bm->allocPixels(info, NULL, ctable);
69 ctable->unref();
70 for (int y = 0; y < height; y++) {
71 for (int x = 0; x < width; x++) {
72 *bm->getAddr8(x, y) = SkGetPackedR32(*device.getAddr32(x, y));
73 }
74 }
75 break;
76 }
77 default:
78 SkASSERT(0);
79 }
80 }
81
82 // configs to build the original bitmap in. Can be at most these 3
83 static const SkColorType gColorTypes[] = {
84 kN32_SkColorType,
85 kRGB_565_SkColorType,
86 kIndex_8_SkColorType, // opaque
87 kIndex_8_SkColorType // alpha
88 };
89
90 static const char* const gConfigLabels[] = {
91 "8888", "565", "Index8", "Index8 alpha"
92 };
93
94 // types to encode into. Can be at most these 3. Must match up with gExt[]
95 static const SkImageEncoder::Type gTypes[] = {
96 SkImageEncoder::kJPEG_Type,
97 SkImageEncoder::kPNG_Type
98 };
99
100 // must match up with gTypes[]
101 static const char* const gExt[] = {
102 ".jpg", ".png"
103 };
104
105 #include <sys/stat.h>
106
107 class EncodeView : public SampleView {
108 public:
109 SkBitmap* fBitmaps;
110 SkAutoDataUnref* fEncodedPNGs;
111 SkAutoDataUnref* fEncodedJPEGs;
112 int fBitmapCount;
113
EncodeView()114 EncodeView() {
115 fBitmapCount = SK_ARRAY_COUNT(gColorTypes);
116 fBitmaps = new SkBitmap[fBitmapCount];
117 fEncodedPNGs = new SkAutoDataUnref[fBitmapCount];
118 fEncodedJPEGs = new SkAutoDataUnref[fBitmapCount];
119 for (int i = 0; i < fBitmapCount; i++) {
120 make_image(&fBitmaps[i], gColorTypes[i], i);
121
122 for (size_t j = 0; j < SK_ARRAY_COUNT(gTypes); j++) {
123 SkAutoTDelete<SkImageEncoder> codec(
124 SkImageEncoder::Create(gTypes[j]));
125 if (NULL == codec.get()) {
126 SkDebugf("[%s:%d] failed to encode %s%s\n",
127 __FILE__, __LINE__,gConfigLabels[i], gExt[j]);
128 continue;
129 }
130 SkAutoDataUnref data(codec->encodeData(fBitmaps[i], 100));
131 if (NULL == data.get()) {
132 SkDebugf("[%s:%d] failed to encode %s%s\n",
133 __FILE__, __LINE__,gConfigLabels[i], gExt[j]);
134 continue;
135 }
136 if (SkImageEncoder::kJPEG_Type == gTypes[j]) {
137 fEncodedJPEGs[i].reset(data.detach());
138 } else if (SkImageEncoder::kPNG_Type == gTypes[j]) {
139 fEncodedPNGs[i].reset(data.detach());
140 }
141 }
142 }
143 this->setBGColor(0xFFDDDDDD);
144 }
145
~EncodeView()146 virtual ~EncodeView() {
147 delete[] fBitmaps;
148 delete[] fEncodedPNGs;
149 delete[] fEncodedJPEGs;
150 }
151
152 protected:
153 // overrides from SkEventSink
onQuery(SkEvent * evt)154 virtual bool onQuery(SkEvent* evt) {
155 if (SampleCode::TitleQ(*evt)) {
156 SampleCode::TitleR(evt, "ImageEncoder");
157 return true;
158 }
159 return this->INHERITED::onQuery(evt);
160 }
161
onDrawContent(SkCanvas * canvas)162 virtual void onDrawContent(SkCanvas* canvas) {
163 if (fBitmapCount == 0) {
164 return;
165 }
166
167 SkPaint paint;
168 paint.setAntiAlias(true);
169 paint.setTextAlign(SkPaint::kCenter_Align);
170
171 canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
172
173 SkScalar x = 0, y = 0, maxX = 0;
174 const int SPACER = 10;
175
176 for (int i = 0; i < fBitmapCount; i++) {
177 canvas->drawText(gConfigLabels[i], strlen(gConfigLabels[i]),
178 x + SkIntToScalar(fBitmaps[i].width()) / 2, 0,
179 paint);
180 y = paint.getTextSize();
181
182 canvas->drawBitmap(fBitmaps[i], x, y);
183
184 SkScalar yy = y;
185 for (size_t j = 0; j < SK_ARRAY_COUNT(gTypes); j++) {
186 yy += SkIntToScalar(fBitmaps[i].height() + 10);
187
188 SkBitmap bm;
189 SkData* encoded = NULL;
190 if (SkImageEncoder::kJPEG_Type == gTypes[j]) {
191 encoded = fEncodedJPEGs[i].get();
192 } else if (SkImageEncoder::kPNG_Type == gTypes[j]) {
193 encoded = fEncodedPNGs[i].get();
194 }
195 if (encoded) {
196 if (!SkInstallDiscardablePixelRef(
197 SkDecodingImageGenerator::Create(encoded,
198 SkDecodingImageGenerator::Options()),
199 &bm)) {
200 SkDebugf("[%s:%d] failed to decode %s%s\n",
201 __FILE__, __LINE__,gConfigLabels[i], gExt[j]);
202 }
203 canvas->drawBitmap(bm, x, yy);
204 }
205 }
206
207 x += SkIntToScalar(fBitmaps[i].width() + SPACER);
208 if (x > maxX) {
209 maxX = x;
210 }
211 }
212
213 y = (paint.getTextSize() + SkIntToScalar(fBitmaps[0].height())) * 3 / 2;
214 x = maxX + SkIntToScalar(10);
215 paint.setTextAlign(SkPaint::kLeft_Align);
216
217 for (size_t j = 0; j < SK_ARRAY_COUNT(gExt); j++) {
218 canvas->drawText(gExt[j], strlen(gExt[j]), x, y, paint);
219 y += SkIntToScalar(fBitmaps[0].height() + SPACER);
220 }
221 }
222
onFindClickHandler(SkScalar x,SkScalar y,unsigned modi)223 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y,
224 unsigned modi) {
225 this->inval(NULL);
226 return this->INHERITED::onFindClickHandler(x, y, modi);
227 }
228
229 private:
230 typedef SampleView INHERITED;
231 };
232
233 //////////////////////////////////////////////////////////////////////////////
234
MyFactory()235 static SkView* MyFactory() { return new EncodeView; }
236 static SkViewRegister reg(MyFactory);
237