Home | History | Annotate | Download | only in android
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "ui/gfx/android/java_bitmap.h"
      6 
      7 #include <android/bitmap.h>
      8 
      9 #include "base/android/jni_string.h"
     10 #include "base/logging.h"
     11 #include "jni/BitmapHelper_jni.h"
     12 #include "skia/ext/image_operations.h"
     13 #include "ui/gfx/size.h"
     14 
     15 using base::android::AttachCurrentThread;
     16 using base::android::ConvertUTF8ToJavaString;
     17 
     18 namespace gfx {
     19 
     20 JavaBitmap::JavaBitmap(jobject bitmap)
     21     : bitmap_(bitmap),
     22       pixels_(NULL) {
     23   int err = AndroidBitmap_lockPixels(AttachCurrentThread(), bitmap_, &pixels_);
     24   DCHECK(!err);
     25   DCHECK(pixels_);
     26 
     27   AndroidBitmapInfo info;
     28   err = AndroidBitmap_getInfo(AttachCurrentThread(), bitmap_, &info);
     29   DCHECK(!err);
     30   size_ = gfx::Size(info.width, info.height);
     31   format_ = info.format;
     32   stride_ = info.stride;
     33 }
     34 
     35 JavaBitmap::~JavaBitmap() {
     36   int err = AndroidBitmap_unlockPixels(AttachCurrentThread(), bitmap_);
     37   DCHECK(!err);
     38 }
     39 
     40 // static
     41 bool JavaBitmap::RegisterJavaBitmap(JNIEnv* env) {
     42   return RegisterNativesImpl(env);
     43 }
     44 
     45 static int SkColorTypeToBitmapFormat(SkColorType color_type) {
     46   switch (color_type) {
     47     case kAlpha_8_SkColorType:
     48       return BITMAP_FORMAT_ALPHA_8;
     49     case kARGB_4444_SkColorType:
     50       return BITMAP_FORMAT_ARGB_4444;
     51     case kN32_SkColorType:
     52       return BITMAP_FORMAT_ARGB_8888;
     53     case kRGB_565_SkColorType:
     54       return BITMAP_FORMAT_RGB_565;
     55     case kUnknown_SkColorType:
     56     default:
     57       NOTREACHED();
     58       return BITMAP_FORMAT_NO_CONFIG;
     59   }
     60 }
     61 
     62 ScopedJavaLocalRef<jobject> CreateJavaBitmap(int width,
     63                                              int height,
     64                                              SkColorType color_type) {
     65   DCHECK_GT(width, 0);
     66   DCHECK_GT(height, 0);
     67   int java_bitmap_config = SkColorTypeToBitmapFormat(color_type);
     68   return Java_BitmapHelper_createBitmap(
     69       AttachCurrentThread(), width, height, java_bitmap_config);
     70 }
     71 
     72 ScopedJavaLocalRef<jobject> ConvertToJavaBitmap(const SkBitmap* skbitmap) {
     73   DCHECK(skbitmap);
     74   DCHECK(!skbitmap->isNull());
     75   SkColorType color_type = skbitmap->colorType();
     76   DCHECK((color_type == kRGB_565_SkColorType) ||
     77          (color_type == kN32_SkColorType));
     78   ScopedJavaLocalRef<jobject> jbitmap = CreateJavaBitmap(
     79       skbitmap->width(), skbitmap->height(), color_type);
     80   SkAutoLockPixels src_lock(*skbitmap);
     81   JavaBitmap dst_lock(jbitmap.obj());
     82   void* src_pixels = skbitmap->getPixels();
     83   void* dst_pixels = dst_lock.pixels();
     84   memcpy(dst_pixels, src_pixels, skbitmap->getSize());
     85 
     86   return jbitmap;
     87 }
     88 
     89 SkBitmap CreateSkBitmapFromAndroidResource(const char* name, gfx::Size size) {
     90   DCHECK(name);
     91   DCHECK(!size.IsEmpty());
     92   JNIEnv* env = AttachCurrentThread();
     93   ScopedJavaLocalRef<jstring> jname(ConvertUTF8ToJavaString(env, name));
     94   base::android::ScopedJavaLocalRef<jobject> jobj =
     95       Java_BitmapHelper_decodeDrawableResource(
     96           env, jname.obj(), size.width(), size.height());
     97 
     98   if (jobj.is_null())
     99     return SkBitmap();
    100 
    101   SkBitmap bitmap = CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(jobj.obj()));
    102   if (bitmap.isNull())
    103     return bitmap;
    104 
    105   return skia::ImageOperations::Resize(
    106       bitmap, skia::ImageOperations::RESIZE_BOX, size.width(), size.height());
    107 }
    108 
    109 SkBitmap CreateSkBitmapFromJavaBitmap(const JavaBitmap& jbitmap) {
    110   // TODO(jdduke): Convert to DCHECK's when sufficient data has been capture for
    111   // crbug.com/341406.
    112   CHECK_EQ(jbitmap.format(), ANDROID_BITMAP_FORMAT_RGBA_8888);
    113   CHECK(!jbitmap.size().IsEmpty());
    114   CHECK_GT(jbitmap.stride(), 0U);
    115   CHECK(jbitmap.pixels());
    116 
    117   gfx::Size src_size = jbitmap.size();
    118 
    119   SkBitmap skbitmap;
    120   skbitmap.allocPixels(SkImageInfo::MakeN32Premul(src_size.width(),
    121                                                   src_size.height()),
    122                        jbitmap.stride());
    123   const void* src_pixels = jbitmap.pixels();
    124   void* dst_pixels = skbitmap.getPixels();
    125   memcpy(dst_pixels, src_pixels, skbitmap.getSize());
    126 
    127   return skbitmap;
    128 }
    129 
    130 SkColorType ConvertToSkiaColorType(jobject bitmap_config) {
    131   int jbitmap_config = Java_BitmapHelper_getBitmapFormatForConfig(
    132       AttachCurrentThread(), bitmap_config);
    133   switch (jbitmap_config) {
    134     case BITMAP_FORMAT_ALPHA_8:
    135       return kAlpha_8_SkColorType;
    136     case BITMAP_FORMAT_ARGB_4444:
    137       return kARGB_4444_SkColorType;
    138     case BITMAP_FORMAT_ARGB_8888:
    139       return kN32_SkColorType;
    140     case BITMAP_FORMAT_RGB_565:
    141       return kRGB_565_SkColorType;
    142     case BITMAP_FORMAT_NO_CONFIG:
    143     default:
    144       return kUnknown_SkColorType;
    145   }
    146 }
    147 
    148 }  //  namespace gfx
    149