Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57ee620c authored by Leon Scroggins III's avatar Leon Scroggins III
Browse files

Read premultiplied status from the SkBitmap.

Replace the Java variable with mRequestPremultiplied, to better
reflect what it represents. In both native and Java, the SkBitmap
is used as the decision maker of whether a Bitmap is premultiplied.
When changing other settings, mRequestedPremultiplied is used to
determine whether it should be premultiplied (if the new config/
hasAlpha-ness etc supports it).

ChooseFromColorProc now reads both the colortype (instead of the
deprecated Config) and alphatype on the SkBitmap. Same with
ChooseToColorProc. In the process, this caught a bug, where the
wrong procs were being used for Index8.

Replace instances of SkBitmap::Config with SkColorType where I
was already changing code.

Use the new versions of setConfig/allocPixels that take an SkImageInfo
as a parameter.

Document isPremultiplied's return value for ALPHA_8.

BUG:13618134
Change-Id: I91fc1f1e46e9294364b1af0ab4bdb37c68d7058e
parent 8949bfb9
Loading
Loading
Loading
Loading
+83 −38
Original line number Diff line number Diff line
#include "SkBitmap.h"
#include "SkPixelRef.h"
#include "SkImageEncoder.h"
#include "SkImageInfo.h"
#include "SkColorPriv.h"
#include "GraphicsJNI.h"
#include "SkDither.h"
@@ -97,13 +98,14 @@ static void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
}

// can return NULL
static FromColorProc ChooseFromColorProc(SkBitmap::Config config, bool isPremultiplied) {
    switch (config) {
        case SkBitmap::kARGB_8888_Config:
            return isPremultiplied ? FromColor_D32 : FromColor_D32_Raw;
        case SkBitmap::kARGB_4444_Config:
            return isPremultiplied ? FromColor_D4444 : FromColor_D4444_Raw;
        case SkBitmap::kRGB_565_Config:
static FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
    switch (bitmap.colorType()) {
        case kN32_SkColorType:
            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D32 : FromColor_D32_Raw;
        case kARGB_4444_SkColorType:
            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D4444 :
                    FromColor_D4444_Raw;
        case kRGB_565_SkColorType:
            return FromColor_D565;
        default:
            break;
@@ -112,11 +114,10 @@ static FromColorProc ChooseFromColorProc(SkBitmap::Config config, bool isPremult
}

bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
        int x, int y, int width, int height,
        const SkBitmap& dstBitmap, bool isPremultiplied) {
        int x, int y, int width, int height, const SkBitmap& dstBitmap) {
    SkAutoLockPixels alp(dstBitmap);
    void* dst = dstBitmap.getPixels();
    FromColorProc proc = ChooseFromColorProc(dstBitmap.config(), isPremultiplied);
    FromColorProc proc = ChooseFromColorProc(dstBitmap);

    if (NULL == dst || NULL == proc) {
        return false;
@@ -257,22 +258,46 @@ static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
}

// can return NULL
static ToColorProc ChooseToColorProc(const SkBitmap& src, bool isPremultiplied) {
static ToColorProc ChooseToColorProc(const SkBitmap& src) {
    switch (src.colorType()) {
        case kN32_SkColorType:
            if (src.isOpaque()) return ToColor_S32_Opaque;
            return isPremultiplied ? ToColor_S32_Alpha : ToColor_S32_Raw;
            switch (src.alphaType()) {
                case kOpaque_SkAlphaType:
                    return ToColor_S32_Opaque;
                case kPremul_SkAlphaType:
                    return ToColor_S32_Alpha;
                case kUnpremul_SkAlphaType:
                    return ToColor_S32_Raw;
                default:
                    return NULL;
            }
        case kARGB_4444_SkColorType:
            if (src.isOpaque()) return ToColor_S4444_Opaque;
            return isPremultiplied ? ToColor_S4444_Alpha : ToColor_S4444_Raw;
            switch (src.alphaType()) {
                case kOpaque_SkAlphaType:
                    return ToColor_S4444_Opaque;
                case kPremul_SkAlphaType:
                    return ToColor_S4444_Alpha;
                case kUnpremul_SkAlphaType:
                    return ToColor_S4444_Raw;
                default:
                    return NULL;
            }
        case kRGB_565_SkColorType:
            return ToColor_S565;
        case kIndex_8_SkColorType:
            if (src.getColorTable() == NULL) {
                return NULL;
            }
            if (src.isOpaque()) return ToColor_SI8_Opaque;
            return isPremultiplied ? ToColor_SI8_Raw : ToColor_SI8_Alpha;
            switch (src.alphaType()) {
                case kOpaque_SkAlphaType:
                    return ToColor_SI8_Opaque;
                case kPremul_SkAlphaType:
                    return ToColor_SI8_Alpha;
                case kUnpremul_SkAlphaType:
                    return ToColor_SI8_Raw;
                default:
                    return NULL;
            }
        default:
            break;
    }
@@ -315,7 +340,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,

    if (jColors != NULL) {
        GraphicsJNI::SetPixels(env, jColors, offset, stride,
                0, 0, width, height, bitmap, true);
                0, 0, width, height, bitmap);
    }

    return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff,
@@ -477,22 +502,40 @@ static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
    return static_cast<jint>(bitmap->getGenerationID());
}

static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
    if (bitmap->alphaType() == kPremul_SkAlphaType) {
        return JNI_TRUE;
    }
    return JNI_FALSE;
}

static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
    return !bitmap->isOpaque() ? JNI_TRUE : JNI_FALSE;
}

static void Bitmap_setAlphaAndPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
                                            jboolean hasAlpha, jboolean isPremul) {
static void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
        jboolean hasAlpha, jboolean requestPremul) {
    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
    if (!hasAlpha) {
    if (hasAlpha) {
        bitmap->setAlphaType(requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
    } else {
        bitmap->setAlphaType(kOpaque_SkAlphaType);
    } else if (isPremul) {
    }
}

static void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
        jboolean isPremul) {
    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
    if (!bitmap->isOpaque()) {
        if (isPremul) {
            bitmap->setAlphaType(kPremul_SkAlphaType);
        } else {
            bitmap->setAlphaType(kUnpremul_SkAlphaType);
        }
    }
}

static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
    SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
@@ -661,11 +704,11 @@ static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
///////////////////////////////////////////////////////////////////////////////

static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
        jint x, jint y, jboolean isPremultiplied) {
        jint x, jint y) {
    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
    SkAutoLockPixels alp(*bitmap);

    ToColorProc proc = ChooseToColorProc(*bitmap, isPremultiplied);
    ToColorProc proc = ChooseToColorProc(*bitmap);
    if (NULL == proc) {
        return 0;
    }
@@ -681,11 +724,11 @@ static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,

static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
        jintArray pixelArray, jint offset, jint stride,
        jint x, jint y, jint width, jint height, jboolean isPremultiplied) {
        jint x, jint y, jint width, jint height) {
    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
    SkAutoLockPixels alp(*bitmap);

    ToColorProc proc = ChooseToColorProc(*bitmap, isPremultiplied);
    ToColorProc proc = ChooseToColorProc(*bitmap);
    if (NULL == proc) {
        return;
    }
@@ -708,7 +751,7 @@ static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
///////////////////////////////////////////////////////////////////////////////

static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
        jint x, jint y, jint colorHandle, jboolean isPremultiplied) {
        jint x, jint y, jint colorHandle) {
    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
    SkColor color = static_cast<SkColor>(colorHandle);
    SkAutoLockPixels alp(*bitmap);
@@ -716,7 +759,7 @@ static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
        return;
    }

    FromColorProc proc = ChooseFromColorProc(bitmap->config(), isPremultiplied);
    FromColorProc proc = ChooseFromColorProc(*bitmap);
    if (NULL == proc) {
        return;
    }
@@ -727,10 +770,10 @@ static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,

static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
        jintArray pixelArray, jint offset, jint stride,
        jint x, jint y, jint width, jint height, jboolean isPremultiplied) {
        jint x, jint y, jint width, jint height) {
    const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
    GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
            x, y, width, height, *bitmap, isPremultiplied);
            x, y, width, height, *bitmap);
}

static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
@@ -834,7 +877,9 @@ static JNINativeMethod gBitmapMethods[] = {
    {   "nativeRowBytes",           "(J)I", (void*)Bitmap_rowBytes },
    {   "nativeConfig",             "(J)I", (void*)Bitmap_config },
    {   "nativeHasAlpha",           "(J)Z", (void*)Bitmap_hasAlpha },
    {   "nativeSetAlphaAndPremultiplied", "(JZZ)V", (void*)Bitmap_setAlphaAndPremultiplied},
    {   "nativeIsPremultiplied",    "(J)Z", (void*)Bitmap_isPremultiplied},
    {   "nativeSetHasAlpha",        "(JZZ)V", (void*)Bitmap_setHasAlpha},
    {   "nativeSetPremultiplied",   "(JZ)V", (void*)Bitmap_setPremultiplied},
    {   "nativeHasMipMap",          "(J)Z", (void*)Bitmap_hasMipMap },
    {   "nativeSetHasMipMap",       "(JZ)V", (void*)Bitmap_setHasMipMap },
    {   "nativeCreateFromParcel",
@@ -845,10 +890,10 @@ static JNINativeMethod gBitmapMethods[] = {
    {   "nativeExtractAlpha",       "(JJ[I)Landroid/graphics/Bitmap;",
        (void*)Bitmap_extractAlpha },
    {   "nativeGenerationId",       "(J)I", (void*)Bitmap_getGenerationId },
    {   "nativeGetPixel",           "(JIIZ)I", (void*)Bitmap_getPixel },
    {   "nativeGetPixels",          "(J[IIIIIIIZ)V", (void*)Bitmap_getPixels },
    {   "nativeSetPixel",           "(JIIIZ)V", (void*)Bitmap_setPixel },
    {   "nativeSetPixels",          "(J[IIIIIIIZ)V", (void*)Bitmap_setPixels },
    {   "nativeGetPixel",           "(JII)I", (void*)Bitmap_getPixel },
    {   "nativeGetPixels",          "(J[IIIIIII)V", (void*)Bitmap_getPixels },
    {   "nativeSetPixel",           "(JIII)V", (void*)Bitmap_setPixel },
    {   "nativeSetPixels",          "(J[IIIIIII)V", (void*)Bitmap_setPixels },
    {   "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
                                            (void*)Bitmap_copyPixelsToBuffer },
    {   "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
+4 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include "SkDeque.h"
#include "SkDrawFilter.h"
#include "SkGraphics.h"
#include <SkImageInfo.h>
#include "SkPorterDuff.h"
#include "SkShader.h"
#include "SkTArray.h"
@@ -699,6 +700,8 @@ public:
                                jboolean hasAlpha, jlong paintHandle) {
        SkCanvas* canvas = getNativeCanvas(canvasHandle);
        SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
        // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
        // correct the alphaType to kOpaque_SkAlphaType.
        SkImageInfo info = SkImageInfo::Make(width, height,
                               hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
                               kPremul_SkAlphaType);
@@ -708,7 +711,7 @@ public:
        }

        if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride,
                0, 0, width, height, bitmap, true)) {
                0, 0, width, height, bitmap)) {
            return;
        }

+2 −1
Original line number Diff line number Diff line
@@ -90,10 +90,11 @@ public:

    /** Copy the colors in colors[] to the bitmap, convert to the correct
        format along the way.
        Whether to use premultiplied pixels is determined by dstBitmap's alphaType.
    */
    static bool SetPixels(JNIEnv* env, jintArray colors, int srcOffset,
            int srcStride, int x, int y, int width, int height,
            const SkBitmap& dstBitmap, bool isPremultiplied);
            const SkBitmap& dstBitmap);

    static jbyteArray getBitmapStorageObj(SkPixelRef *pixref);
};
+4 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@

#include <SkBitmap.h>
#include <SkCanvas.h>
#include <SkImageInfo.h>
#include <SkMatrix.h>
#include <SkPaint.h>
#include <SkPorterDuff.h>
@@ -376,6 +377,8 @@ static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject claz
static void android_view_GLES20Canvas_drawBitmapData(JNIEnv* env, jobject clazz,
        jlong rendererPtr, jintArray colors, jint offset, jint stride,
        jfloat left, jfloat top, jint width, jint height, jboolean hasAlpha, jlong paintPtr) {
    // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
    // correct the alphaType to kOpaque_SkAlphaType.
    const SkImageInfo info = SkImageInfo::Make(width, height,
                               hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
                               kPremul_SkAlphaType);
@@ -385,7 +388,7 @@ static void android_view_GLES20Canvas_drawBitmapData(JNIEnv* env, jobject clazz,
        return;
    }

    if (!GraphicsJNI::SetPixels(env, colors, offset, stride, 0, 0, width, height, *bitmap, true)) {
    if (!GraphicsJNI::SetPixels(env, colors, offset, stride, 0, 0, width, height, *bitmap)) {
        delete bitmap;
        return;
    }
+36 −33
Original line number Diff line number Diff line
@@ -59,14 +59,18 @@ public final class Bitmap implements Parcelable {
    private final boolean mIsMutable;

    /**
     * Represents whether the Bitmap's content is expected to be pre-multiplied.
     * Represents whether the Bitmap's content is requested to be pre-multiplied.
     * Note that isPremultiplied() does not directly return this value, because
     * isPremultiplied() may never return true for a 565 Bitmap.
     * isPremultiplied() may never return true for a 565 Bitmap or a bitmap
     * without alpha.
     *
     * setPremultiplied() does directly set the value so that setConfig() and
     * setPremultiplied() aren't order dependent, despite being setters.
     *
     * The native bitmap's premultiplication state is kept up to date by
     * pushing down this preference for every config change.
     */
    private boolean mIsPremultiplied;
    private boolean mRequestPremultiplied;

    private byte[] mNinePatchChunk;   // may be null
    private int[] mLayoutBounds;   // may be null
@@ -105,7 +109,7 @@ public final class Bitmap implements Parcelable {
     */
    @SuppressWarnings({"UnusedDeclaration"}) // called from JNI
    Bitmap(long nativeBitmap, byte[] buffer, int width, int height, int density,
            boolean isMutable, boolean isPremultiplied,
            boolean isMutable, boolean requestPremultiplied,
            byte[] ninePatchChunk, int[] layoutBounds) {
        if (nativeBitmap == 0) {
            throw new RuntimeException("internal error: native bitmap is 0");
@@ -114,7 +118,7 @@ public final class Bitmap implements Parcelable {
        mWidth = width;
        mHeight = height;
        mIsMutable = isMutable;
        mIsPremultiplied = isPremultiplied;
        mRequestPremultiplied = requestPremultiplied;
        mBuffer = buffer;
        // we delete this in our finalizer
        mNativeBitmap = nativeBitmap;
@@ -132,10 +136,10 @@ public final class Bitmap implements Parcelable {
     * width/height values
     */
    @SuppressWarnings({"UnusedDeclaration"}) // called from JNI
    void reinit(int width, int height, boolean isPremultiplied) {
    void reinit(int width, int height, boolean requestPremultiplied) {
        mWidth = width;
        mHeight = height;
        mIsPremultiplied = isPremultiplied;
        mRequestPremultiplied = requestPremultiplied;
    }

    /**
@@ -223,7 +227,7 @@ public final class Bitmap implements Parcelable {
        }

        nativeReconfigure(mNativeBitmap, width, height, config.nativeInt, mBuffer.length,
                mIsPremultiplied);
                mRequestPremultiplied);
        mWidth = width;
        mHeight = height;
    }
@@ -561,7 +565,7 @@ public final class Bitmap implements Parcelable {
        checkRecycled("Can't copy a recycled bitmap");
        Bitmap b = nativeCopy(mNativeBitmap, config.nativeInt, isMutable);
        if (b != null) {
            b.setAlphaAndPremultiplied(hasAlpha(), mIsPremultiplied);
            b.setPremultiplied(mRequestPremultiplied);
            b.mDensity = mDensity;
        }
        return b;
@@ -738,7 +742,8 @@ public final class Bitmap implements Parcelable {
        // The new bitmap was created from a known bitmap source so assume that
        // they use the same density
        bitmap.mDensity = source.mDensity;
        bitmap.setAlphaAndPremultiplied(source.hasAlpha(), source.mIsPremultiplied);
        bitmap.setHasAlpha(source.hasAlpha());
        bitmap.setPremultiplied(source.mRequestPremultiplied);

        canvas.setBitmap(bitmap);
        canvas.drawBitmap(source, srcR, dstR, paint);
@@ -1018,6 +1023,9 @@ public final class Bitmap implements Parcelable {
     * <p>This method always returns false if {@link #getConfig()} is
     * {@link Bitmap.Config#RGB_565}.</p>
     * 
     * <p>The return value is undefined if {@link #getConfig()} is
     * {@link Bitmap.Config#ALPHA_8}.</p>
     *
     * <p>This method only returns true if {@link #hasAlpha()} returns true.
     * A bitmap with no alpha channel can be used both as a pre-multiplied and
     * as a non pre-multiplied bitmap.</p>
@@ -1033,7 +1041,7 @@ public final class Bitmap implements Parcelable {
     * @see BitmapFactory.Options#inPremultiplied
     */
    public final boolean isPremultiplied() {
        return mIsPremultiplied && getConfig() != Config.RGB_565 && hasAlpha();
        return nativeIsPremultiplied(mNativeBitmap);
    }

    /**
@@ -1057,14 +1065,8 @@ public final class Bitmap implements Parcelable {
     * @see BitmapFactory.Options#inPremultiplied
     */
    public final void setPremultiplied(boolean premultiplied) {
        mIsPremultiplied = premultiplied;
        nativeSetAlphaAndPremultiplied(mNativeBitmap, hasAlpha(), premultiplied);
    }

    /** Helper function to set both alpha and premultiplied. **/
    private final void setAlphaAndPremultiplied(boolean hasAlpha, boolean premultiplied) {
        mIsPremultiplied = premultiplied;
        nativeSetAlphaAndPremultiplied(mNativeBitmap, hasAlpha, premultiplied);
        mRequestPremultiplied = premultiplied;
        nativeSetPremultiplied(mNativeBitmap, premultiplied);
    }

    /** Returns the bitmap's width */
@@ -1225,7 +1227,7 @@ public final class Bitmap implements Parcelable {
     * non-opaque per-pixel alpha values.
     */
    public void setHasAlpha(boolean hasAlpha) {
        nativeSetAlphaAndPremultiplied(mNativeBitmap, hasAlpha, mIsPremultiplied);
        nativeSetHasAlpha(mNativeBitmap, hasAlpha, mRequestPremultiplied);
    }

    /**
@@ -1299,7 +1301,7 @@ public final class Bitmap implements Parcelable {
    public int getPixel(int x, int y) {
        checkRecycled("Can't call getPixel() on a recycled bitmap");
        checkPixelAccess(x, y);
        return nativeGetPixel(mNativeBitmap, x, y, mIsPremultiplied);
        return nativeGetPixel(mNativeBitmap, x, y);
    }

    /**
@@ -1333,7 +1335,7 @@ public final class Bitmap implements Parcelable {
        }
        checkPixelsAccess(x, y, width, height, offset, stride, pixels);
        nativeGetPixels(mNativeBitmap, pixels, offset, stride,
                        x, y, width, height, mIsPremultiplied);
                        x, y, width, height);
    }

    /**
@@ -1413,7 +1415,7 @@ public final class Bitmap implements Parcelable {
            throw new IllegalStateException();
        }
        checkPixelAccess(x, y);
        nativeSetPixel(mNativeBitmap, x, y, color, mIsPremultiplied);
        nativeSetPixel(mNativeBitmap, x, y, color);
    }

    /**
@@ -1450,7 +1452,7 @@ public final class Bitmap implements Parcelable {
        }
        checkPixelsAccess(x, y, width, height, offset, stride, pixels);
        nativeSetPixels(mNativeBitmap, pixels, offset, stride,
                        x, y, width, height, mIsPremultiplied);
                        x, y, width, height);
    }

    public static final Parcelable.Creator<Bitmap> CREATOR
@@ -1602,17 +1604,15 @@ public final class Bitmap implements Parcelable {
    private static native int nativeRowBytes(long nativeBitmap);
    private static native int nativeConfig(long nativeBitmap);

    private static native int nativeGetPixel(long nativeBitmap, int x, int y,
                                             boolean isPremultiplied);
    private static native int nativeGetPixel(long nativeBitmap, int x, int y);
    private static native void nativeGetPixels(long nativeBitmap, int[] pixels,
                                               int offset, int stride, int x, int y,
                                               int width, int height, boolean isPremultiplied);
                                               int width, int height);

    private static native void nativeSetPixel(long nativeBitmap, int x, int y,
                                              int color, boolean isPremultiplied);
    private static native void nativeSetPixel(long nativeBitmap, int x, int y, int color);
    private static native void nativeSetPixels(long nativeBitmap, int[] colors,
                                               int offset, int stride, int x, int y,
                                               int width, int height, boolean isPremultiplied);
                                               int width, int height);
    private static native void nativeCopyPixelsToBuffer(long nativeBitmap,
                                                        Buffer dst);
    private static native void nativeCopyPixelsFromBuffer(long nativeBitmap, Buffer src);
@@ -1631,9 +1631,12 @@ public final class Bitmap implements Parcelable {

    private static native void nativePrepareToDraw(long nativeBitmap);
    private static native boolean nativeHasAlpha(long nativeBitmap);
    private static native void nativeSetAlphaAndPremultiplied(long nativeBitmap,
                                                              boolean hasAlpha,
    private static native boolean nativeIsPremultiplied(long nativeBitmap);
    private static native void nativeSetPremultiplied(long nativeBitmap,
                                                      boolean isPremul);
    private static native void nativeSetHasAlpha(long nativeBitmap,
                                                 boolean hasAlpha,
                                                 boolean requestPremul);
    private static native boolean nativeHasMipMap(long nativeBitmap);
    private static native void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap);
    private static native boolean nativeSameAs(long nativeBitmap0, long nativeBitmap1);