// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ui/gfx/android/java_bitmap.h" #include #include "base/android/jni_string.h" #include "base/logging.h" #include "jni/BitmapHelper_jni.h" #include "skia/ext/image_operations.h" #include "ui/gfx/size.h" using base::android::AttachCurrentThread; using base::android::ConvertUTF8ToJavaString; namespace gfx { JavaBitmap::JavaBitmap(jobject bitmap) : bitmap_(bitmap), pixels_(NULL) { int err = AndroidBitmap_lockPixels(AttachCurrentThread(), bitmap_, &pixels_); DCHECK(!err); DCHECK(pixels_); AndroidBitmapInfo info; err = AndroidBitmap_getInfo(AttachCurrentThread(), bitmap_, &info); DCHECK(!err); size_ = gfx::Size(info.width, info.height); format_ = info.format; stride_ = info.stride; } JavaBitmap::~JavaBitmap() { int err = AndroidBitmap_unlockPixels(AttachCurrentThread(), bitmap_); DCHECK(!err); } // static bool JavaBitmap::RegisterJavaBitmap(JNIEnv* env) { return RegisterNativesImpl(env); } static int SkColorTypeToBitmapFormat(SkColorType color_type) { switch (color_type) { case kAlpha_8_SkColorType: return BITMAP_FORMAT_ALPHA_8; case kARGB_4444_SkColorType: return BITMAP_FORMAT_ARGB_4444; case kN32_SkColorType: return BITMAP_FORMAT_ARGB_8888; case kRGB_565_SkColorType: return BITMAP_FORMAT_RGB_565; case kUnknown_SkColorType: default: NOTREACHED(); return BITMAP_FORMAT_NO_CONFIG; } } ScopedJavaLocalRef CreateJavaBitmap(int width, int height, SkColorType color_type) { DCHECK_GT(width, 0); DCHECK_GT(height, 0); int java_bitmap_config = SkColorTypeToBitmapFormat(color_type); return Java_BitmapHelper_createBitmap( AttachCurrentThread(), width, height, java_bitmap_config); } ScopedJavaLocalRef ConvertToJavaBitmap(const SkBitmap* skbitmap) { DCHECK(skbitmap); DCHECK(!skbitmap->isNull()); SkColorType color_type = skbitmap->colorType(); DCHECK((color_type == kRGB_565_SkColorType) || (color_type == kN32_SkColorType)); ScopedJavaLocalRef jbitmap = CreateJavaBitmap( skbitmap->width(), skbitmap->height(), color_type); SkAutoLockPixels src_lock(*skbitmap); JavaBitmap dst_lock(jbitmap.obj()); void* src_pixels = skbitmap->getPixels(); void* dst_pixels = dst_lock.pixels(); memcpy(dst_pixels, src_pixels, skbitmap->getSize()); return jbitmap; } SkBitmap CreateSkBitmapFromAndroidResource(const char* name, gfx::Size size) { DCHECK(name); DCHECK(!size.IsEmpty()); JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef jname(ConvertUTF8ToJavaString(env, name)); base::android::ScopedJavaLocalRef jobj = Java_BitmapHelper_decodeDrawableResource( env, jname.obj(), size.width(), size.height()); if (jobj.is_null()) return SkBitmap(); SkBitmap bitmap = CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(jobj.obj())); if (bitmap.isNull()) return bitmap; return skia::ImageOperations::Resize( bitmap, skia::ImageOperations::RESIZE_BOX, size.width(), size.height()); } SkBitmap CreateSkBitmapFromJavaBitmap(const JavaBitmap& jbitmap) { // TODO(jdduke): Convert to DCHECK's when sufficient data has been capture for // crbug.com/341406. CHECK_EQ(jbitmap.format(), ANDROID_BITMAP_FORMAT_RGBA_8888); CHECK(!jbitmap.size().IsEmpty()); CHECK_GT(jbitmap.stride(), 0U); CHECK(jbitmap.pixels()); gfx::Size src_size = jbitmap.size(); SkBitmap skbitmap; skbitmap.allocPixels(SkImageInfo::MakeN32Premul(src_size.width(), src_size.height()), jbitmap.stride()); const void* src_pixels = jbitmap.pixels(); void* dst_pixels = skbitmap.getPixels(); memcpy(dst_pixels, src_pixels, skbitmap.getSize()); return skbitmap; } SkColorType ConvertToSkiaColorType(jobject bitmap_config) { int jbitmap_config = Java_BitmapHelper_getBitmapFormatForConfig( AttachCurrentThread(), bitmap_config); switch (jbitmap_config) { case BITMAP_FORMAT_ALPHA_8: return kAlpha_8_SkColorType; case BITMAP_FORMAT_ARGB_4444: return kARGB_4444_SkColorType; case BITMAP_FORMAT_ARGB_8888: return kN32_SkColorType; case BITMAP_FORMAT_RGB_565: return kRGB_565_SkColorType; case BITMAP_FORMAT_NO_CONFIG: default: return kUnknown_SkColorType; } } } // namespace gfx