13227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin/*
23227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin * Copyright (C) 2009 The Android Open Source Project
33227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin *
43227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin * Licensed under the Apache License, Version 2.0 (the "License");
53227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin * you may not use this file except in compliance with the License.
63227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin * You may obtain a copy of the License at
73227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin *
83227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin *      http://www.apache.org/licenses/LICENSE-2.0
93227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin *
103227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin * Unless required by applicable law or agreed to in writing, software
113227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin * distributed under the License is distributed on an "AS IS" BASIS,
123227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin * See the License for the specific language governing permissions and
143227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin * limitations under the License.
153227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin */
163227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin
173227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin#include <android/bitmap.h>
18cad87d78da79c3d2ac83e1dce6ee2a9d2f6d64e5Andreas Gampe
19cad87d78da79c3d2ac83e1dce6ee2a9d2f6d64e5Andreas Gampe#pragma GCC diagnostic push
20cad87d78da79c3d2ac83e1dce6ee2a9d2f6d64e5Andreas Gampe#pragma GCC diagnostic ignored "-Wunused-parameter"
213227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin#include <GraphicsJNI.h>
22cad87d78da79c3d2ac83e1dce6ee2a9d2f6d64e5Andreas Gampe#pragma GCC diagnostic pop
233227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin
243227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavinint AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
253227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin                          AndroidBitmapInfo* info) {
263227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin    if (NULL == env || NULL == jbitmap) {
273227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin        return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
283227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin    }
293227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin
30ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    SkBitmap bm;
31ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    GraphicsJNI::getSkBitmap(env, jbitmap, &bm);
323227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin
333227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin    if (info) {
34ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck        info->width     = bm.width();
35ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck        info->height    = bm.height();
36ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck        info->stride    = bm.rowBytes();
373227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin        info->flags     = 0;
383227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin
39ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck        switch (bm.colorType()) {
401103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed            case kN32_SkColorType:
413227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin                info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
423227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin                break;
431103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed            case kRGB_565_SkColorType:
443227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin                info->format = ANDROID_BITMAP_FORMAT_RGB_565;
453227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin                break;
461103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed            case kARGB_4444_SkColorType:
473227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin                info->format = ANDROID_BITMAP_FORMAT_RGBA_4444;
483227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin                break;
491103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed            case kAlpha_8_SkColorType:
503227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin                info->format = ANDROID_BITMAP_FORMAT_A_8;
513227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin                break;
523227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin            default:
533227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin                info->format = ANDROID_BITMAP_FORMAT_NONE;
543227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin                break;
553227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin        }
563227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin    }
57eba8254c8cae92d653c5203f65cb36f3fc724f9dAndrew Hsieh    return ANDROID_BITMAP_RESULT_SUCCESS;
583227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin}
593227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin
603227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavinint AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr) {
613227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin    if (NULL == env || NULL == jbitmap) {
623227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin        return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
633227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin    }
643227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin
65ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck    SkPixelRef* pixelRef = GraphicsJNI::refSkPixelRef(env, jbitmap);
66ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    if (!pixelRef) {
673227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin        return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
683227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin    }
693227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin
70ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    pixelRef->lockPixels();
71ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    void* addr = pixelRef->pixels();
723227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin    if (NULL == addr) {
73ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck        pixelRef->unlockPixels();
74ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck        pixelRef->unref();
753227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin        return ANDROID_BITMAP_RESULT_ALLOCATION_FAILED;
763227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin    }
773227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin
783227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin    if (addrPtr) {
793227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin        *addrPtr = addr;
803227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin    }
81eba8254c8cae92d653c5203f65cb36f3fc724f9dAndrew Hsieh    return ANDROID_BITMAP_RESULT_SUCCESS;
823227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin}
833227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin
843227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavinint AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap) {
853227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin    if (NULL == env || NULL == jbitmap) {
863227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin        return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
873227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin    }
883227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin
89ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck    SkPixelRef* pixelRef = GraphicsJNI::refSkPixelRef(env, jbitmap);
90ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    if (!pixelRef) {
913227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin        return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
923227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin    }
933227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin
9417e5f4cc706bed08367af8fa60ffb8c7c3ca7f62Alexandre Elias    // notifyPixelsChanged() needs be called to apply writes to GL-backed
9517e5f4cc706bed08367af8fa60ffb8c7c3ca7f62Alexandre Elias    // bitmaps.  Note that this will slow down read-only accesses to the
9617e5f4cc706bed08367af8fa60ffb8c7c3ca7f62Alexandre Elias    // bitmaps, but the NDK methods are primarily intended to be used for
9717e5f4cc706bed08367af8fa60ffb8c7c3ca7f62Alexandre Elias    // writes.
98ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    pixelRef->notifyPixelsChanged();
99ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck
100ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    pixelRef->unlockPixels();
101ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck    // Awkward in that we need to double-unref as the call to get the SkPixelRef
102ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck    // did a ref(), so we need to unref() for the local ref and for the previous
103ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck    // AndroidBitmap_lockPixels(). However this keeps GraphicsJNI a bit safer
104ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck    // if others start using it without knowing about android::Bitmap's "fun"
105ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck    // ref counting mechanism(s).
106ae2e8b4891491e8e89bed5f2c9626415adee09cbJohn Reck    pixelRef->unref();
107ed207b92747234eac88dd3664ecfb535e45d8ed1John Reck    pixelRef->unref();
10817e5f4cc706bed08367af8fa60ffb8c7c3ca7f62Alexandre Elias
109eba8254c8cae92d653c5203f65cb36f3fc724f9dAndrew Hsieh    return ANDROID_BITMAP_RESULT_SUCCESS;
1103227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin}
1113227631fe99c271a47f9f5135c4ffe1bec3e72f0Dima Zavin
112