SampleEncode.cpp revision 2d970b5128f7270cd01a93e4ce68d0c3ea67ac71
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
29static 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
83static const SkColorType gColorTypes[] = {
84    kN32_SkColorType,
85    kRGB_565_SkColorType,
86    kIndex_8_SkColorType,   // opaque
87    kIndex_8_SkColorType    // alpha
88};
89
90static 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[]
95static const SkImageEncoder::Type gTypes[] = {
96    SkImageEncoder::kJPEG_Type,
97    SkImageEncoder::kPNG_Type
98};
99
100// must match up with gTypes[]
101static const char* const gExt[] = {
102    ".jpg", ".png"
103};
104
105#include <sys/stat.h>
106
107class EncodeView : public SampleView {
108public:
109    SkBitmap*        fBitmaps;
110    SkAutoDataUnref* fEncodedPNGs;
111    SkAutoDataUnref* fEncodedJPEGs;
112    int              fBitmapCount;
113
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
146    virtual ~EncodeView() {
147        delete[] fBitmaps;
148        delete[] fEncodedPNGs;
149        delete[] fEncodedJPEGs;
150    }
151
152protected:
153    // overrides from SkEventSink
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
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
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
229private:
230    typedef SampleView INHERITED;
231};
232
233//////////////////////////////////////////////////////////////////////////////
234
235static SkView* MyFactory() { return new EncodeView; }
236static SkViewRegister reg(MyFactory);
237