/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkData.h"
#include "SkDecodingImageGenerator.h"
#include "SkGradientShader.h"
#include "SkGraphics.h"
#include "SkImageDecoder.h"
#include "SkImageEncoder.h"
#include "SkPath.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkUtils.h"
#include "SkXfermode.h"
#include "SkColorPriv.h"
#include "SkColorFilter.h"
#include "SkTime.h"
#include "SkTypeface.h"
#include "SkStream.h"
static void make_image(SkBitmap* bm, SkColorType ct, int configIndex) {
const int width = 98;
const int height = 100;
const SkImageInfo info = SkImageInfo::Make(width, height, ct, kPremul_SkAlphaType);
SkBitmap device;
device.allocN32Pixels(width, height);
SkCanvas canvas(device);
SkPaint paint;
paint.setAntiAlias(true);
canvas.drawColor(SK_ColorRED);
paint.setColor(SK_ColorBLUE);
canvas.drawCircle(SkIntToScalar(width)/2, SkIntToScalar(height)/2,
SkIntToScalar(width)/2, paint);
switch (ct) {
case kN32_SkColorType:
bm->swap(device);
break;
case kRGB_565_SkColorType: {
bm->allocPixels(info);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
*bm->getAddr16(x, y) = SkPixel32ToPixel16(*device.getAddr32(x, y));
}
}
break;
}
case kIndex_8_SkColorType: {
SkPMColor colors[256];
for (int i = 0; i < 256; i++) {
if (configIndex & 1) {
colors[i] = SkPackARGB32(255-i, 0, 0, 255-i);
} else {
colors[i] = SkPackARGB32(0xFF, i, 0, 255-i);
}
}
SkColorTable* ctable = new SkColorTable(colors, 256);
bm->allocPixels(info, NULL, ctable);
ctable->unref();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
*bm->getAddr8(x, y) = SkGetPackedR32(*device.getAddr32(x, y));
}
}
break;
}
default:
SkASSERT(0);
}
}
// configs to build the original bitmap in. Can be at most these 3
static const SkColorType gColorTypes[] = {
kN32_SkColorType,
kRGB_565_SkColorType,
kIndex_8_SkColorType, // opaque
kIndex_8_SkColorType // alpha
};
static const char* const gConfigLabels[] = {
"8888", "565", "Index8", "Index8 alpha"
};
// types to encode into. Can be at most these 3. Must match up with gExt[]
static const SkImageEncoder::Type gTypes[] = {
SkImageEncoder::kJPEG_Type,
SkImageEncoder::kPNG_Type
};
// must match up with gTypes[]
static const char* const gExt[] = {
".jpg", ".png"
};
#include <sys/stat.h>
class EncodeView : public SampleView {
public:
SkBitmap* fBitmaps;
SkAutoDataUnref* fEncodedPNGs;
SkAutoDataUnref* fEncodedJPEGs;
int fBitmapCount;
EncodeView() {
fBitmapCount = SK_ARRAY_COUNT(gColorTypes);
fBitmaps = new SkBitmap[fBitmapCount];
fEncodedPNGs = new SkAutoDataUnref[fBitmapCount];
fEncodedJPEGs = new SkAutoDataUnref[fBitmapCount];
for (int i = 0; i < fBitmapCount; i++) {
make_image(&fBitmaps[i], gColorTypes[i], i);
for (size_t j = 0; j < SK_ARRAY_COUNT(gTypes); j++) {
SkAutoTDelete<SkImageEncoder> codec(
SkImageEncoder::Create(gTypes[j]));
if (NULL == codec.get()) {
SkDebugf("[%s:%d] failed to encode %s%s\n",
__FILE__, __LINE__,gConfigLabels[i], gExt[j]);
continue;
}
SkAutoDataUnref data(codec->encodeData(fBitmaps[i], 100));
if (NULL == data.get()) {
SkDebugf("[%s:%d] failed to encode %s%s\n",
__FILE__, __LINE__,gConfigLabels[i], gExt[j]);
continue;
}
if (SkImageEncoder::kJPEG_Type == gTypes[j]) {
fEncodedJPEGs[i].reset(data.detach());
} else if (SkImageEncoder::kPNG_Type == gTypes[j]) {
fEncodedPNGs[i].reset(data.detach());
}
}
}
this->setBGColor(0xFFDDDDDD);
}
virtual ~EncodeView() {
delete[] fBitmaps;
delete[] fEncodedPNGs;
delete[] fEncodedJPEGs;
}
protected:
// overrides from SkEventSink
virtual bool onQuery(SkEvent* evt) {
if (SampleCode::TitleQ(*evt)) {
SampleCode::TitleR(evt, "ImageEncoder");
return true;
}
return this->INHERITED::onQuery(evt);
}
virtual void onDrawContent(SkCanvas* canvas) {
if (fBitmapCount == 0) {
return;
}
SkPaint paint;
paint.setAntiAlias(true);
paint.setTextAlign(SkPaint::kCenter_Align);
canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
SkScalar x = 0, y = 0, maxX = 0;
const int SPACER = 10;
for (int i = 0; i < fBitmapCount; i++) {
canvas->drawText(gConfigLabels[i], strlen(gConfigLabels[i]),
x + SkIntToScalar(fBitmaps[i].width()) / 2, 0,
paint);
y = paint.getTextSize();
canvas->drawBitmap(fBitmaps[i], x, y);
SkScalar yy = y;
for (size_t j = 0; j < SK_ARRAY_COUNT(gTypes); j++) {
yy += SkIntToScalar(fBitmaps[i].height() + 10);
SkBitmap bm;
SkData* encoded = NULL;
if (SkImageEncoder::kJPEG_Type == gTypes[j]) {
encoded = fEncodedJPEGs[i].get();
} else if (SkImageEncoder::kPNG_Type == gTypes[j]) {
encoded = fEncodedPNGs[i].get();
}
if (encoded) {
if (!SkInstallDiscardablePixelRef(
SkDecodingImageGenerator::Create(encoded,
SkDecodingImageGenerator::Options()),
&bm)) {
SkDebugf("[%s:%d] failed to decode %s%s\n",
__FILE__, __LINE__,gConfigLabels[i], gExt[j]);
}
canvas->drawBitmap(bm, x, yy);
}
}
x += SkIntToScalar(fBitmaps[i].width() + SPACER);
if (x > maxX) {
maxX = x;
}
}
y = (paint.getTextSize() + SkIntToScalar(fBitmaps[0].height())) * 3 / 2;
x = maxX + SkIntToScalar(10);
paint.setTextAlign(SkPaint::kLeft_Align);
for (size_t j = 0; j < SK_ARRAY_COUNT(gExt); j++) {
canvas->drawText(gExt[j], strlen(gExt[j]), x, y, paint);
y += SkIntToScalar(fBitmaps[0].height() + SPACER);
}
}
virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y,
unsigned modi) {
this->inval(NULL);
return this->INHERITED::onFindClickHandler(x, y, modi);
}
private:
typedef SampleView INHERITED;
};
//////////////////////////////////////////////////////////////////////////////
static SkView* MyFactory() { return new EncodeView; }
static SkViewRegister reg(MyFactory);