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