15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/android/java_bitmap.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <android/bitmap.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "base/android/jni_string.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "jni/BitmapHelper_jni.h"
126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "skia/ext/image_operations.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/size.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::android::AttachCurrentThread;
16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)using base::android::ConvertUTF8ToJavaString;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JavaBitmap::JavaBitmap(jobject bitmap)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : bitmap_(bitmap),
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pixels_(NULL) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int err = AndroidBitmap_lockPixels(AttachCurrentThread(), bitmap_, &pixels_);
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!err);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(pixels_);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AndroidBitmapInfo info;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  err = AndroidBitmap_getInfo(AttachCurrentThread(), bitmap_, &info);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!err);
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_ = gfx::Size(info.width, info.height);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  format_ = info.format;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  stride_ = info.stride;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JavaBitmap::~JavaBitmap() {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int err = AndroidBitmap_unlockPixels(AttachCurrentThread(), bitmap_);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!err);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool JavaBitmap::RegisterJavaBitmap(JNIEnv* env) {
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return RegisterNativesImpl(env);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic int SkColorTypeToBitmapFormat(SkColorType color_type) {
46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  switch (color_type) {
47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case kAlpha_8_SkColorType:
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return BITMAP_FORMAT_ALPHA_8;
49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case kARGB_4444_SkColorType:
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return BITMAP_FORMAT_ARGB_4444;
51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case kN32_SkColorType:
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return BITMAP_FORMAT_ARGB_8888;
53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case kRGB_565_SkColorType:
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return BITMAP_FORMAT_RGB_565;
55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case kUnknown_SkColorType:
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    default:
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      NOTREACHED();
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return BITMAP_FORMAT_NO_CONFIG;
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)ScopedJavaLocalRef<jobject> CreateJavaBitmap(int width,
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                             int height,
64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             SkColorType color_type) {
65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_GT(width, 0);
66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_GT(height, 0);
67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int java_bitmap_config = SkColorTypeToBitmapFormat(color_type);
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return Java_BitmapHelper_createBitmap(
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      AttachCurrentThread(), width, height, java_bitmap_config);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedJavaLocalRef<jobject> ConvertToJavaBitmap(const SkBitmap* skbitmap) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(skbitmap);
74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK(!skbitmap->isNull());
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SkColorType color_type = skbitmap->colorType();
76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK((color_type == kRGB_565_SkColorType) ||
77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch         (color_type == kN32_SkColorType));
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ScopedJavaLocalRef<jobject> jbitmap = CreateJavaBitmap(
79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      skbitmap->width(), skbitmap->height(), color_type);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkAutoLockPixels src_lock(*skbitmap);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  JavaBitmap dst_lock(jbitmap.obj());
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* src_pixels = skbitmap->getPixels();
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* dst_pixels = dst_lock.pixels();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(dst_pixels, src_pixels, skbitmap->getSize());
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return jbitmap;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)SkBitmap CreateSkBitmapFromAndroidResource(const char* name, gfx::Size size) {
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(name);
916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(!size.IsEmpty());
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  JNIEnv* env = AttachCurrentThread();
936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ScopedJavaLocalRef<jstring> jname(ConvertUTF8ToJavaString(env, name));
946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::android::ScopedJavaLocalRef<jobject> jobj =
956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      Java_BitmapHelper_decodeDrawableResource(
966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          env, jname.obj(), size.width(), size.height());
976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (jobj.is_null())
996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return SkBitmap();
1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  SkBitmap bitmap = CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(jobj.obj()));
1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (bitmap.isNull())
1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return bitmap;
1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return skia::ImageOperations::Resize(
1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      bitmap, skia::ImageOperations::RESIZE_BOX, size.width(), size.height());
1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
109effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochSkBitmap CreateSkBitmapFromJavaBitmap(const JavaBitmap& jbitmap) {
110effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // TODO(jdduke): Convert to DCHECK's when sufficient data has been capture for
111effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // crbug.com/341406.
112effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  CHECK_EQ(jbitmap.format(), ANDROID_BITMAP_FORMAT_RGBA_8888);
113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  CHECK(!jbitmap.size().IsEmpty());
114effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  CHECK_GT(jbitmap.stride(), 0U);
115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  CHECK(jbitmap.pixels());
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  gfx::Size src_size = jbitmap.size();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SkBitmap skbitmap;
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  skbitmap.allocPixels(SkImageInfo::MakeN32Premul(src_size.width(),
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                  src_size.height()),
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                       jbitmap.stride());
123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const void* src_pixels = jbitmap.pixels();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* dst_pixels = skbitmap.getPixels();
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(dst_pixels, src_pixels, skbitmap.getSize());
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return skbitmap;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
130116680a4aac90f2aa7413d9095a592090648e557Ben MurdochSkColorType ConvertToSkiaColorType(jobject bitmap_config) {
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int jbitmap_config = Java_BitmapHelper_getBitmapFormatForConfig(
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      AttachCurrentThread(), bitmap_config);
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  switch (jbitmap_config) {
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case BITMAP_FORMAT_ALPHA_8:
135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return kAlpha_8_SkColorType;
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case BITMAP_FORMAT_ARGB_4444:
137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return kARGB_4444_SkColorType;
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case BITMAP_FORMAT_ARGB_8888:
139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return kN32_SkColorType;
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case BITMAP_FORMAT_RGB_565:
141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return kRGB_565_SkColorType;
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case BITMAP_FORMAT_NO_CONFIG:
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    default:
144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return kUnknown_SkColorType;
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  //  namespace gfx
149