Bitmap.java revision 5acc476878bce8b72c0059e05cbbd5b43ffee5d5
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.graphics;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.annotation.CheckResult;
208cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chenimport android.annotation.ColorInt;
212784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackbornimport android.annotation.NonNull;
22ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasaniimport android.annotation.Nullable;
238cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chenimport android.os.Parcel;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcelable;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Trace;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.DisplayMetrics;
278cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chenimport android.util.Log;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport libcore.util.NativeAllocationRegistry;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.OutputStream;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.nio.Buffer;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.nio.ByteBuffer;
3311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackbornimport java.nio.IntBuffer;
3411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackbornimport java.nio.ShortBuffer;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackbornpublic final class Bitmap implements Parcelable {
3711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    private static final String TAG = "Bitmap";
38ce0537b80087a6225273040a987414b1dd081aa0Romain Guy
39ce0537b80087a6225273040a987414b1dd081aa0Romain Guy    /**
40ce0537b80087a6225273040a987414b1dd081aa0Romain Guy     * Indicates that the bitmap was created for an unknown pixel density.
41ce0537b80087a6225273040a987414b1dd081aa0Romain Guy     *
42ce0537b80087a6225273040a987414b1dd081aa0Romain Guy     * @see Bitmap#getDensity()
43ce0537b80087a6225273040a987414b1dd081aa0Romain Guy     * @see Bitmap#setDensity(int)
44ce0537b80087a6225273040a987414b1dd081aa0Romain Guy     */
458cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    public static final int DENSITY_NONE = 0;
46e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy
47e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy    // Estimated size of the Bitmap native allocation, not including
48e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy    // pixel data.
49e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy    private static final long NATIVE_ALLOCATION_SIZE = 32;
50e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy
51e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy    // Convenience for JNI access
52e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy    private final long mNativePtr;
53e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy
54e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy    private final boolean mIsMutable;
552361098da3b9d9c3eeed410dc72ba62c0e9177cfRomain Guy
56e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy    /**
57e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy     * Represents whether the Bitmap's content is requested to be pre-multiplied.
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Note that isPremultiplied() does not directly return this value, because
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * isPremultiplied() may never return true for a 565 Bitmap or a bitmap
60ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     * without alpha.
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * setPremultiplied() does directly set the value so that setConfig() and
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * setPremultiplied() aren't order dependent, despite being setters.
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * The native bitmap's premultiplication state is kept up to date by
663849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy     * pushing down this preference for every config change.
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    private boolean mRequestPremultiplied;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7096e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn    private byte[] mNinePatchChunk; // may be null
7102890fd0f98b3b8d98baf0bda1ea906afd723d8bRomain Guy    private NinePatch.InsetStruct mNinePatchInsets; // may be null
7296e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn    private int mWidth;
7396e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn    private int mHeight;
7496e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn    private boolean mRecycled;
7596e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn
7696e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn    private ColorSpace mColorSpace;
7796e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn
7896e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn    /** @hide */
7996e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn    public int mDensity = getDefaultDensity();
803849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy
813849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy    private static volatile Matrix sScaleMatrix;
8296e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn
8396e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn    private static volatile int sDefaultDensity = -1;
8496e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn
8596e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn    /**
8696e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn     * For backwards compatibility, allows the app layer to change the default
8796e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn     * density when running old apps.
8896e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn     * @hide
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static void setDefaultDensity(int density) {
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sDefaultDensity = density;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @SuppressWarnings("deprecation")
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static int getDefaultDensity() {
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sDefaultDensity >= 0) {
973849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy            return sDefaultDensity;
98e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy        }
99ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani        sDefaultDensity = DisplayMetrics.DENSITY_DEVICE;
100ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani        return sDefaultDensity;
101ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani    }
102ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani
103ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani    /**
104ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     * Private constructor that must received an already allocated native bitmap
105ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     * int (pointer).
106ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     */
107ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani    // called from JNI
108ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani    Bitmap(long nativeBitmap, int width, int height, int density,
109ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani            boolean isMutable, boolean requestPremultiplied,
1103849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy            byte[] ninePatchChunk, NinePatch.InsetStruct ninePatchInsets) {
111ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani        if (nativeBitmap == 0) {
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new RuntimeException("internal error: native bitmap is 0");
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1158cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        mWidth = width;
116e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy        mHeight = height;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIsMutable = isMutable;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRequestPremultiplied = requestPremultiplied;
119e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy
120e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy        mNinePatchChunk = ninePatchChunk;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNinePatchInsets = ninePatchInsets;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (density >= 0) {
123ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani            mDensity = density;
124de0dfb7b65a02d4dd74c271b558adee0973fc267Dianne Hackborn        }
125de0dfb7b65a02d4dd74c271b558adee0973fc267Dianne Hackborn
126de0dfb7b65a02d4dd74c271b558adee0973fc267Dianne Hackborn        mNativePtr = nativeBitmap;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long nativeSize = NATIVE_ALLOCATION_SIZE + getAllocationByteCount();
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        NativeAllocationRegistry registry = new NativeAllocationRegistry(
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), nativeSize);
13011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        registry.registerNativeAllocation(this, nativeBitmap);
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13296e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn
13396e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn    /**
13496e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn     * Return the pointer to the native object.
13596e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn     * @hide
13696e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn     */
13796e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn    public long getNativeInstance() {
13896e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn        return mNativePtr;
13996e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn    }
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14196e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn    /**
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Native bitmap has been reconfigured, so set premult and cached
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * width/height values
14411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     */
145a53b828635fce8b6b2d3e3377d74d72070056623Dianne Hackborn    @SuppressWarnings("unused") // called from JNI
14611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    void reinit(int width, int height, boolean requestPremultiplied) {
14711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        mWidth = width;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeight = height;
14911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        mRequestPremultiplied = requestPremultiplied;
15011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        mColorSpace = null;
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
15411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * <p>Returns the density for this bitmap.</p>
15511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     *
15611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * <p>The default density is the same density as the current display,
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * unless the current application does not support different screen
15811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * densities in which case it is
15911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * {@link android.util.DisplayMetrics#DENSITY_DEFAULT}.  Note that
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * compatibility mode is determined by the application that was initially
16111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * loaded into a process -- applications that share the same process should
162a53b828635fce8b6b2d3e3377d74d72070056623Dianne Hackborn     * all have the same compatibility, or ensure they explicitly set the
16311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * density of their bitmaps appropriately.</p>
16411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     *
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A scaling factor of the default density or {@link #DENSITY_NONE}
16611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     *         if the scaling factor is unknown.
16711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     *
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setDensity(int)
16911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @see android.util.DisplayMetrics#DENSITY_DEFAULT
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see android.util.DisplayMetrics#densityDpi
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #DENSITY_NONE
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getDensity() {
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRecycled) {
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Called getDensity() on a recycle()'d bitmap! This is undefined behavior!");
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mDensity;
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1808cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    /**
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Specifies the density for this bitmap.  When the bitmap is
182ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     * drawn to a Canvas that also has a density, it will be scaled
18317471d730f20ee785c9c48a99eb331a40550612bRomain Guy     * appropriately.</p>
184ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     *
185ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     * @param density The density scaling factor to use with this bitmap or
186ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     *        {@link #DENSITY_NONE} if the density is unknown.
187ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     *
188ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     * @see #getDensity()
189ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     * @see android.util.DisplayMetrics#DENSITY_DEFAULT
190ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     * @see android.util.DisplayMetrics#densityDpi
191ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     * @see #DENSITY_NONE
192a383b3f646cbc1fd870f2694d4fac24340834916Patrick Dubroy     */
193a383b3f646cbc1fd870f2694d4fac24340834916Patrick Dubroy    public void setDensity(int density) {
194a383b3f646cbc1fd870f2694d4fac24340834916Patrick Dubroy        mDensity = density;
195a383b3f646cbc1fd870f2694d4fac24340834916Patrick Dubroy    }
196a383b3f646cbc1fd870f2694d4fac24340834916Patrick Dubroy
197a383b3f646cbc1fd870f2694d4fac24340834916Patrick Dubroy    /**
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Modifies the bitmap to have a specified width, height, and {@link
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Config}, without affecting the underlying allocation backing the bitmap.
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Bitmap pixel data is not re-initialized for the new configuration.</p>
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>This method can be used to avoid allocating a new bitmap, instead
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * reusing an existing bitmap's allocation for a new configuration of equal
204e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy     * or lesser size. If the Bitmap's allocation isn't large enough to support
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the new configuration, an IllegalArgumentException will be thrown and the
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * bitmap will not be modified.</p>
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The result of {@link #getByteCount()} will reflect the new configuration,
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * while {@link #getAllocationByteCount()} will reflect that of the initial
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * configuration.</p>
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Note: This may change this result of hasAlpha(). When converting to 565,
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the new bitmap will always be considered opaque. When converting from 565,
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the new bitmap will be considered non-opaque, and will respect the value
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * set by setPremultiplied().</p>
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>WARNING: This method should NOT be called on a bitmap currently in use
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the view system, Canvas, or the AndroidBitmap NDK API. It does not
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * make guarantees about how the underlying pixel buffer is remapped to the
2208cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen     * new config, just that the allocation is reused. Additionally, the view
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * system does not account for bitmap properties being modifying during use,
2220bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy     * e.g. while attached to drawables.</p>
2230bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy     *
2240bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy     * <p>In order to safely ensure that a Bitmap is no longer in use by the
2250bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy     * View system it is necessary to wait for a draw pass to occur after
2260bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy     * invalidate()'ing any view that had previously drawn the Bitmap in the last
2270bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy     * draw pass due to hardware acceleration's caching of draw commands. As
2280bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy     * an example, here is how this can be done for an ImageView:
2290bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy     * <pre class="prettyprint">
2300bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy     *      ImageView myImageView = ...;
2310bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy     *      final Bitmap myBitmap = ...;
2320bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy     *      myImageView.setImageDrawable(null);
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *      myImageView.post(new Runnable() {
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *          public void run() {
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *              // myBitmap is now no longer in use by the ImageView
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *              // and can be safely reconfigured.
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *              myBitmap.reconfigure(...);
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *          }
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *      });
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * </pre></p>
2418cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen     *
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setWidth(int)
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setHeight(int)
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setConfig(Config)
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void reconfigure(int width, int height, Config config) {
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkRecycled("Can't call reconfigure() on a recycled bitmap");
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (width <= 0 || height <= 0) {
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("width and height must be > 0");
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isMutable()) {
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException("only mutable bitmaps may be reconfigured");
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        nativeReconfigure(mNativePtr, width, height, config.nativeInt, mRequestPremultiplied);
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWidth = width;
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHeight = height;
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mColorSpace = null;
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Convenience method for calling {@link #reconfigure(int, int, Config)}
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * with the current height and config.</p>
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>WARNING: this method should not be used on bitmaps currently used by
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the view system, see {@link #reconfigure(int, int, Config)} for more
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * details.</p>
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #reconfigure(int, int, Config)
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setHeight(int)
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setConfig(Config)
272676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     */
273676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy    public void setWidth(int width) {
274676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy        reconfigure(width, getHeight(), getConfig());
275676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy    }
276676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Convenience method for calling {@link #reconfigure(int, int, Config)}
279676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * with the current width and config.</p>
280676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     *
281676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * <p>WARNING: this method should not be used on bitmaps currently used by
282676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * the view system, see {@link #reconfigure(int, int, Config)} for more
283676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * details.</p>
284676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     *
285676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * @see #reconfigure(int, int, Config)
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setWidth(int)
287676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * @see #setConfig(Config)
288676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     */
289676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy    public void setHeight(int height) {
290676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy        reconfigure(getWidth(), height, getConfig());
291676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy    }
292676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy
293676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy    /**
294676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * <p>Convenience method for calling {@link #reconfigure(int, int, Config)}
295676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * with the current height and width.</p>
296676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     *
297676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * <p>WARNING: this method should not be used on bitmaps currently used by
298676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * the view system, see {@link #reconfigure(int, int, Config)} for more
299676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * details.</p>
300676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     *
301676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * @see #reconfigure(int, int, Config)
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see #setWidth(int)
303676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * @see #setHeight(int)
304676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     */
305676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy    public void setConfig(Config config) {
306676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy        reconfigure(getWidth(), getHeight(), config);
307676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy    }
308676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy
309676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy    /**
310676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * Sets the nine patch chunk.
311676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     *
312676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * @param chunk The definition of the nine patch
313676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     *
314676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * @hide
315676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     */
316676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy    public void setNinePatchChunk(byte[] chunk) {
317676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy        mNinePatchChunk = chunk;
318676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy    }
319676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
321676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * Free the native object associated with this bitmap, and clear the
322676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * reference to the pixel data. This will not free the pixel data synchronously;
323676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * it simply allows it to be garbage collected if there are no other references.
324676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * The bitmap is marked as "dead", meaning it will throw an exception if
325676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * getPixels() or setPixels() is called, and will draw nothing. This operation
326676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * cannot be reversed, so it should only be called if you are sure there are no
327676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * further uses for the bitmap. This is an advanced call, and normally need
328676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * not be called, since the normal GC process will free up this memory when
329676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * there are no more references to this bitmap.
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void recycle() {
332676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy        if (!mRecycled && mNativePtr != 0) {
333676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy            if (nativeRecycle(mNativePtr)) {
334676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy                // return value indicates whether native pixel object was actually recycled.
335676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy                // false indicates that it is still in use at the native level and these
336676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy                // objects should not be collected now. They will be collected later when the
337676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy                // Bitmap itself is collected.
338676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy                mNinePatchChunk = null;
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRecycled = true;
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3428cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    }
343676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if this bitmap has been recycled. If so, then it is an error
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to try to access its pixels, and the bitmap will not draw.
3478cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen     *
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the bitmap has been recycled
3493849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy     */
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final boolean isRecycled() {
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mRecycled;
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3533849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy
3543849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy    /**
3553849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy     * Returns the generation ID of this bitmap. The generation ID changes
3563849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy     * whenever the bitmap is modified. This can be used as an efficient way to
3573849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy     * check if a bitmap has changed.
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The current generation ID for this bitmap.
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getGenerationId() {
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRecycled) {
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.w(TAG, "Called getGenerationId() on a recycle()'d bitmap! This is undefined behavior!");
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return nativeGenerationId(mNativePtr);
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is called by methods that want to throw an exception if the bitmap
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * has already been recycled.
3718cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen     */
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void checkRecycled(String errorMessage) {
373f7f9d9c39df22ad6929f001f07588469f77e8bf5Jesse Wilson        if (mRecycled) {
3748cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen            throw new IllegalStateException(errorMessage);
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3788cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    /**
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is called by methods that want to throw an exception if the bitmap
3808cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen     * is {@link Config#HARDWARE}.
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void checkHardware(String errorMessage) {
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (getConfig() == Config.HARDWARE) {
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalStateException(errorMessage);
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3883849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy    /**
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Common code for checking that x and y are >= 0
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3913849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy     * @param x x coordinate to ensure is >= 0
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y y coordinate to ensure is >= 0
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void checkXYSign(int x, int y) {
3958cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        if (x < 0) {
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("x must be >= 0");
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (y < 0) {
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("y must be >= 0");
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Common code for checking that width and height are > 0
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width  width to ensure is > 0
4078cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen     * @param height height to ensure is > 0
4083849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy     */
409f7f9d9c39df22ad6929f001f07588469f77e8bf5Jesse Wilson    private static void checkWidthHeight(int width, int height) {
4108cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        if (width <= 0) {
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("width must be > 0");
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (height <= 0) {
4148cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen            throw new IllegalArgumentException("height must be > 0");
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4178cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Possible bitmap configurations. A bitmap configuration describes
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * how pixels are stored. This affects the quality (color depth) as
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * well as the ability to display transparent/translucent colors.
42296e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn     */
42396e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn    public enum Config {
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // these native values must match up with the enum in SkBitmap.h
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Each pixel is stored as a single translucency (alpha) channel.
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * This is very useful to efficiently store masks for instance.
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * No color information is stored.
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * With this configuration, each pixel requires 1 byte of memory.
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
43296e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn        ALPHA_8     (1),
43396e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn
43496e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn        /**
43596e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn         * Each pixel is stored on 2 bytes and only the RGB channels are
43696e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn         * encoded: red is stored with 5 bits of precision (32 possible
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * values), green is stored with 6 bits of precision (64 possible
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * values) and blue is stored with 5 bits of precision.
43902d9102b3bdebac6989c2b7d12c080fb7c1f8e2bBrad Fitzpatrick         *
440f12f6f058f169ead83a546a1c3a51e49452a30b3Romain Guy         * This configuration can produce slight visual artifacts depending
441f12f6f058f169ead83a546a1c3a51e49452a30b3Romain Guy         * on the configuration of the source. For instance, without
442f12f6f058f169ead83a546a1c3a51e49452a30b3Romain Guy         * dithering, the result might show a greenish tint. To get better
443f12f6f058f169ead83a546a1c3a51e49452a30b3Romain Guy         * results dithering should be applied.
44402d9102b3bdebac6989c2b7d12c080fb7c1f8e2bBrad Fitzpatrick         *
44502d9102b3bdebac6989c2b7d12c080fb7c1f8e2bBrad Fitzpatrick         * This configuration may be useful when using opaque bitmaps
44602d9102b3bdebac6989c2b7d12c080fb7c1f8e2bBrad Fitzpatrick         * that do not require high color fidelity.
44702d9102b3bdebac6989c2b7d12c080fb7c1f8e2bBrad Fitzpatrick         */
44802d9102b3bdebac6989c2b7d12c080fb7c1f8e2bBrad Fitzpatrick        RGB_565     (3),
449f12f6f058f169ead83a546a1c3a51e49452a30b3Romain Guy
45002d9102b3bdebac6989c2b7d12c080fb7c1f8e2bBrad Fitzpatrick        /**
451f12f6f058f169ead83a546a1c3a51e49452a30b3Romain Guy         * Each pixel is stored on 2 bytes. The three RGB color channels
452f12f6f058f169ead83a546a1c3a51e49452a30b3Romain Guy         * and the alpha channel (translucency) are stored with a 4 bits
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * precision (16 possible values.)
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * This configuration is mostly useful if the application needs
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * to store translucency information but also needs to save
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * memory.
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * It is recommended to use {@link #ARGB_8888} instead of this
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * configuration.
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Note: as of {@link android.os.Build.VERSION_CODES#KITKAT},
4638cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen         * any bitmap created with this configuration will be created
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * using {@link #ARGB_8888} instead.
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * @deprecated Because of the poor quality of this configuration,
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *             it is advised to use {@link #ARGB_8888} instead.
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Deprecated
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ARGB_4444   (4),
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * Each pixel is stored on 4 bytes. Each channel (RGB and alpha
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * for translucency) is stored with 8 bits of precision (256
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * possible values.)
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * This configuration is very flexible and offers the best
4788cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen         * quality. It should be used whenever possible.
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
4808cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        ARGB_8888   (5),
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
48396e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn         * Each pixels is stored on 8 bytes. Each channel (RGB and alpha
48496e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn         * for translucency) is stored as a
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * {@link android.util.Half half-precision floating point value}.
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * This configuration is particularly suited for wide-gamut and
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * HDR content.
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        RGBA_F16    (6),
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /**
493f12f6f058f169ead83a546a1c3a51e49452a30b3Romain Guy         * Special configuration, when bitmap is stored only in graphic memory.
494f12f6f058f169ead83a546a1c3a51e49452a30b3Romain Guy         * Bitmaps in this configuration are always immutable.
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         *
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * It is optimal for cases, when the only operation with the bitmap is to draw it on a
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         * screen.
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        HARDWARE    (7);
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
501f12f6f058f169ead83a546a1c3a51e49452a30b3Romain Guy        final int nativeInt;
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private static Config sConfigs[] = {
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888, RGBA_F16, HARDWARE
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        };
5068cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Config(int ni) {
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            this.nativeInt = ni;
509f12f6f058f169ead83a546a1c3a51e49452a30b3Romain Guy        }
510f12f6f058f169ead83a546a1c3a51e49452a30b3Romain Guy
51196e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn        static Config nativeToConfig(int ni) {
512f12f6f058f169ead83a546a1c3a51e49452a30b3Romain Guy            return sConfigs[ni];
513f12f6f058f169ead83a546a1c3a51e49452a30b3Romain Guy        }
514f12f6f058f169ead83a546a1c3a51e49452a30b3Romain Guy    }
515f12f6f058f169ead83a546a1c3a51e49452a30b3Romain Guy
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Copy the bitmap's pixels into the specified buffer (allocated by the
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * caller). An exception is thrown if the buffer is not large enough to
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * hold all of the pixels (taking into account the number of bytes per
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * pixel) or if the Buffer subclass is not one of the support types
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (ByteBuffer, ShortBuffer, IntBuffer).</p>
52260b88edea7132ddce90f2dced07c6706f1502270Ken Shirriff     * <p>The content of the bitmap is copied into the buffer as-is. This means
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that if this bitmap stores its pixels pre-multiplied
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * (see {@link #isPremultiplied()}, the values in the buffer will also be
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * pre-multiplied.</p>
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>After this method returns, the current position of the buffer is
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * updated: the position is incremented by the number of elements written
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in the buffer.</p>
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE}
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void copyPixelsToBuffer(Buffer dst) {
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkHardware("unable to copyPixelsToBuffer, "
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + "pixel access is not supported on Config#HARDWARE bitmaps");
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int elements = dst.remaining();
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int shift;
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (dst instanceof ByteBuffer) {
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            shift = 0;
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (dst instanceof ShortBuffer) {
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            shift = 1;
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (dst instanceof IntBuffer) {
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            shift = 2;
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new RuntimeException("unsupported Buffer subclass");
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long bufferSize = (long)elements << shift;
5478cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        long pixelSize = getByteCount();
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (bufferSize < pixelSize) {
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new RuntimeException("Buffer not large enough for pixels");
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        nativeCopyPixelsToBuffer(mNativePtr, dst);
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // now update the buffer's position
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int position = dst.position();
557feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy        position += pixelSize >> shift;
558feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy        dst.position(position);
559feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy    }
560feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy
561feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy    /**
562feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy     * <p>Copy the pixels from the buffer, beginning at the current position,
563feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy     * overwriting the bitmap's pixels. The data in the buffer is not changed
564feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy     * in any way (unlike setPixels(), which converts from unpremultipled 32bit
565feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy     * to whatever the bitmap's native format is.</p>
566feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy     * <p>After this method returns, the current position of the buffer is
567feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy     * updated: the position is incremented by the number of elements read from
568676b17391fb6583e5df944c36b1bd4c1be835689Romain Guy     * the buffer. If you need to read the bitmap from the buffer again you must
569feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy     * first rewind the buffer.</p>
570feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy     * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE}
571feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy     */
572feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy    public void copyPixelsFromBuffer(Buffer src) {
573feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy        checkRecycled("copyPixelsFromBuffer called on recycled bitmap");
574feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy        checkHardware("unable to copyPixelsFromBuffer, Config#HARDWARE bitmaps are immutable");
575feeea8f07c854e6b0ae2fec3aa2d239c17f32b5bRomain Guy
576d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy        int elements = src.remaining();
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int shift;
578d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy        if (src instanceof ByteBuffer) {
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            shift = 0;
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (src instanceof ShortBuffer) {
581d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy            shift = 1;
582d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy        } else if (src instanceof IntBuffer) {
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            shift = 2;
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
585d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy            throw new RuntimeException("unsupported Buffer subclass");
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
588d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy        long bufferBytes = (long) elements << shift;
589d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy        long bitmapBytes = getByteCount();
590d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy
591d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy        if (bufferBytes < bitmapBytes) {
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new RuntimeException("Buffer not large enough for pixels");
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
594d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        nativeCopyPixelsFromBuffer(mNativePtr, src);
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
597d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy        // now update the buffer's position
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int position = src.position();
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        position += bitmapBytes >> shift;
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        src.position(position);
60196e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn    }
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
60311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    /**
60411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Tries to make a new bitmap based on the dimensions of this bitmap,
60596e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn     * setting the new bitmap's config to the one specified, and then copying
60696e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn     * this bitmap's pixels into the new bitmap. If the conversion is not
60796e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn     * supported, or the allocator fails, then this returns NULL.  The returned
6086311d0a079702b29984c0d31937345be105e1a5eDianne Hackborn     * bitmap initially has the same density as the original.
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param config    The desired config for the resulting bitmap
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param isMutable True if the resulting bitmap should be mutable (i.e.
6128cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen     *                  its pixels can be modified)
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the new bitmap, or null if the copy could not be made.
61496e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn     * @throws IllegalArgumentException if config is {@link Config#HARDWARE} and isMutable is true
61596e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn     */
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Bitmap copy(Config config, boolean isMutable) {
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkRecycled("Can't copy a recycled bitmap");
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (config == Config.HARDWARE && isMutable) {
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("Hardware bitmaps are always immutable");
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bitmap b = nativeCopy(mNativePtr, config.nativeInt, isMutable);
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (b != null) {
623d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy            b.setPremultiplied(mRequestPremultiplied);
624d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy            b.mDensity = mDensity;
625d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy        }
626d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy        return b;
627d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy    }
628d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy
629d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy    /**
630d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy     * Creates a new immutable bitmap backed by ashmem which can efficiently
631d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy     * be passed between processes.
632d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy     *
633d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy     * @hide
634d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy     */
635d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy    public Bitmap createAshmemBitmap() {
636d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy        checkRecycled("Can't copy a recycled bitmap");
637d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy        Bitmap b = nativeCopyAshmem(mNativePtr);
638d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy        if (b != null) {
639d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy            b.setPremultiplied(mRequestPremultiplied);
640e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy            b.mDensity = mDensity;
641e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy        }
642e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy        return b;
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
644d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy
6451373a8eb581fe3c8e9a036e69042015f98a7e346Christopher Tate    /**
646d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy     * Creates a new immutable bitmap backed by ashmem which can efficiently
647d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy     * be passed between processes.
6481373a8eb581fe3c8e9a036e69042015f98a7e346Christopher Tate     *
6491373a8eb581fe3c8e9a036e69042015f98a7e346Christopher Tate     * @hide
6501373a8eb581fe3c8e9a036e69042015f98a7e346Christopher Tate     */
6511373a8eb581fe3c8e9a036e69042015f98a7e346Christopher Tate    public Bitmap createAshmemBitmap(Config config) {
652d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy        checkRecycled("Can't copy a recycled bitmap");
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bitmap b = nativeCopyAshmemConfig(mNativePtr, config.nativeInt);
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (b != null) {
6558cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen            b.setPremultiplied(mRequestPremultiplied);
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            b.mDensity = mDensity;
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
65896e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn        return b;
65996e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn    }
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create hardware bitmap backed GraphicBuffer.
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Bitmap or null if this GraphicBuffer has unsupported PixelFormat.
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         currently PIXEL_FORMAT_RGBA_8888 is the only supported format
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap createHardwareBitmap(GraphicBuffer graphicBuffer) {
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return nativeCreateHardwareBitmap(graphicBuffer);
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Creates a new bitmap, scaled from an existing bitmap, when possible. If the
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * specified width and height are the same as the current width and height of
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the source bitmap, the source bitmap is returned and no new bitmap is
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * created.
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param src       The source bitmap.
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param dstWidth  The new bitmap's desired width.
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param dstHeight The new bitmap's desired height.
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param filter    true if the source should be filtered.
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The new scaled bitmap or the source bitmap if no scaling is required.
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalArgumentException if width is <= 0, or height is <= 0
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight,
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean filter) {
687e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy        Matrix m;
688e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy        synchronized (Bitmap.class) {
689e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy            // small pool of just 1 matrix
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            m = sScaleMatrix;
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sScaleMatrix = null;
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (m == null) {
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            m = new Matrix();
69696e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn        }
69796e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int width = src.getWidth();
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int height = src.getHeight();
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float sx = dstWidth  / (float)width;
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final float sy = dstHeight / (float)height;
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        m.setScale(sx, sy);
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bitmap b = Bitmap.createBitmap(src, 0, 0, width, height, m, filter);
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (Bitmap.class) {
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // do we need to check for null? why not just assign everytime?
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sScaleMatrix == null) {
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sScaleMatrix = m;
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return b;
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns an immutable bitmap from the source bitmap. The new bitmap may
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be the same object as source, or a copy may have been made.  It is
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * initialized with the same density as the original bitmap.
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap createBitmap(Bitmap src) {
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return createBitmap(src, 0, 0, src.getWidth(), src.getHeight());
722ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani    }
723ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani
724ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani    /**
725ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     * Returns an immutable bitmap from the specified subset of the source
726ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     * bitmap. The new bitmap may be the same object as source, or a copy may
727ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     * have been made. It is initialized with the same density as the original
728ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     * bitmap.
729ec4a50428d5f26a22df3edaf7e5b08f41d5cb54bAmith Yamasani     *
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param source   The bitmap we are subsetting
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x        The x coordinate of the first pixel in source
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y        The y coordinate of the first pixel in source
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width    The number of pixels in each row
7342305ac9e4a262ed09fd034ae417e9b1dda4c0ccbVikas Arora     * @param height   The number of rows
7352305ac9e4a262ed09fd034ae417e9b1dda4c0ccbVikas Arora     * @return A copy of a subset of the source bitmap or the source bitmap itself.
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalArgumentException if the x, y, width, height values are
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         outside of the dimensions of the source bitmap, or width is <= 0,
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         or height is <= 0
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height) {
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return createBitmap(source, x, y, width, height, null, false);
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns an immutable bitmap from subset of the source bitmap,
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * transformed by the optional matrix. The new bitmap may be the
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * same object as source, or a copy may have been made. It is
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * initialized with the same density as the original bitmap.
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If the source bitmap is immutable and the requested subset is the
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * same as the source bitmap itself, then the source bitmap is
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * returned and no new bitmap is created.
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param source   The bitmap we are subsetting
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param x        The x coordinate of the first pixel in source
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y        The y coordinate of the first pixel in source
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width    The number of pixels in each row
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height   The number of rows
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param m        Optional matrix to be applied to the pixels
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param filter   true if the source should be filtered.
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                   Only applies if the matrix contains more than just
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                   translation.
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A bitmap that represents the specified subset of source
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalArgumentException if the x, y, width, height values are
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         outside of the dimensions of the source bitmap, or width is <= 0,
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         or height is <= 0
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Matrix m, boolean filter) {
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkXYSign(x, y);
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkWidthHeight(width, height);
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (x + width > source.getWidth()) {
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("x + width must be <= bitmap.width()");
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (y + height > source.getHeight()) {
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("y + height must be <= bitmap.height()");
7788cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        }
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // check if we can just return our argument unchanged
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!source.isMutable() && x == 0 && y == 0 && width == source.getWidth() &&
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                height == source.getHeight() && (m == null || m.isIdentity())) {
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return source;
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7863849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        boolean isHardware = source.getConfig() == Config.HARDWARE;
7873849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        if (isHardware) {
7883849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy            source = nativeCopyPreserveInternalConfig(source.mNativePtr);
7893849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        }
7903849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy
7913849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        int neww = width;
7923849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        int newh = height;
7933849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        Canvas canvas = new Canvas();
7943849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        Bitmap bitmap;
7953849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        Paint paint;
7963849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy
7973849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        Rect srcR = new Rect(x, y, x + width, y + height);
7983849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        RectF dstR = new RectF(0, 0, width, height);
7993849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy
8003849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        Config newConfig = Config.ARGB_8888;
8013849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        final Config config = source.getConfig();
8023849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        // GIF files generate null configs, assume ARGB_8888
8033849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        if (config != null) {
8043849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy            switch (config) {
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case RGB_565:
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    newConfig = Config.RGB_565;
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case ALPHA_8:
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    newConfig = Config.ALPHA_8;
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case RGBA_F16:
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    newConfig = Config.RGBA_F16;
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
8148cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen                //noinspection deprecation
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case ARGB_4444:
81611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn                case ARGB_8888:
81711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn                default:
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    newConfig = Config.ARGB_8888;
8192784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn                    break;
82011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            }
8212784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn        }
8222784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn
8232784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn        if (m == null || m.isIdentity()) {
82411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            bitmap = createBitmap(neww, newh, newConfig, source.hasAlpha());
82511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            paint = null;   // not needed
8262784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn        } else {
8272784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn            final boolean transformed = !m.rectStaysRect();
82811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
82911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            RectF deviceR = new RectF();
83011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            m.mapRect(deviceR, dstR);
83111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
83211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            neww = Math.round(deviceR.width());
83311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            newh = Math.round(deviceR.height());
83411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
83511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            Config transformedConfig = newConfig;
83611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            if (transformed) {
83711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn                if (transformedConfig != Config.ARGB_8888 && transformedConfig != Config.RGBA_F16) {
83811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn                    transformedConfig = Config.ARGB_8888;
83911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn                }
84011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            }
84111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            bitmap = createBitmap(neww, newh, transformedConfig, transformed || source.hasAlpha());
84211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
84311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            canvas.translate(-deviceR.left, -deviceR.top);
84411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn            canvas.concat(m);
8452784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn
8462784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn            paint = new Paint();
8472784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn            paint.setFilterBitmap(filter);
8482784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn            if (transformed) {
8492784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn                paint.setAntiAlias(true);
8502784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn            }
85111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        }
8522784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn
8532784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn        // The new bitmap was created from a known bitmap source so assume that
85411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        // they use the same density
85511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        bitmap.mDensity = source.mDensity;
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bitmap.setHasAlpha(source.hasAlpha());
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bitmap.setPremultiplied(source.mRequestPremultiplied);
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        canvas.setBitmap(bitmap);
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        canvas.drawBitmap(source, srcR, dstR, paint);
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        canvas.setBitmap(null);
86211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        if (isHardware) {
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return bitmap.copy(Config.HARDWARE, false);
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
86511ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn        return bitmap;
86611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    }
86711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn
86811ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    /**
86911ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * Returns a mutable bitmap with the specified width and height.  Its
87011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * initial density is as per {@link #getDensity}.
87111ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     *
87211ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @param width    The width of the bitmap
87311ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @param height   The height of the bitmap
87411ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     * @param config   The bitmap config to create.
8752784ff0af88128f66ae690b73d48fb7e4a211e68Dianne Hackborn     * @throws IllegalArgumentException if the width or height are <= 0, or if
87611ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     *         Config is Config.HARDWARE, because hardware bitmaps are always immutable
87711ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn     */
878366a84056c9a695ee6702d9d30bf9f3b521ba7ccRomain Guy    public static Bitmap createBitmap(int width, int height, Config config) {
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return createBitmap(width, height, config, true);
88011ea33471e1a14a8594f0b2cd012d86340dd3bd8Dianne Hackborn    }
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a mutable bitmap with the specified width and height.  Its
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * initial density is determined from the given {@link DisplayMetrics}.
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param display  Display metrics for the display this bitmap will be
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 drawn on.
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width    The width of the bitmap
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height   The height of the bitmap
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param config   The bitmap config to create.
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalArgumentException if the width or height are <= 0, or if
8928cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen     *         Config is Config.HARDWARE, because hardware bitmaps are always immutable
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
894f7f9d9c39df22ad6929f001f07588469f77e8bf5Jesse Wilson    public static Bitmap createBitmap(DisplayMetrics display, int width,
895f7f9d9c39df22ad6929f001f07588469f77e8bf5Jesse Wilson            int height, Config config) {
896f7f9d9c39df22ad6929f001f07588469f77e8bf5Jesse Wilson        return createBitmap(display, width, height, config, true);
897f7f9d9c39df22ad6929f001f07588469f77e8bf5Jesse Wilson    }
898f7f9d9c39df22ad6929f001f07588469f77e8bf5Jesse Wilson
899f7f9d9c39df22ad6929f001f07588469f77e8bf5Jesse Wilson    /**
900f7f9d9c39df22ad6929f001f07588469f77e8bf5Jesse Wilson     * Returns a mutable bitmap with the specified width and height.  Its
901f7f9d9c39df22ad6929f001f07588469f77e8bf5Jesse Wilson     * initial density is as per {@link #getDensity}.
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width    The width of the bitmap
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height   The height of the bitmap
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param config   The bitmap config to create.
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 mark the bitmap as opaque. Doing so will clear the bitmap in black
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 instead of transparent.
909a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed     *
910a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed     * @throws IllegalArgumentException if the width or height are <= 0, or if
911a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed     *         Config is Config.HARDWARE, because hardware bitmaps are always immutable
912a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed     */
913a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed    public static Bitmap createBitmap(int width, int height, Config config, boolean hasAlpha) {
914a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed        return createBitmap(null, width, height, config, hasAlpha);
915a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed    }
916a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a mutable bitmap with the specified width and height.  Its
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * initial density is determined from the given {@link DisplayMetrics}.
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param display  Display metrics for the display this bitmap will be
922a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed     *                 drawn on.
923a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed     * @param width    The width of the bitmap
924366a84056c9a695ee6702d9d30bf9f3b521ba7ccRomain Guy     * @param height   The height of the bitmap
925366a84056c9a695ee6702d9d30bf9f3b521ba7ccRomain Guy     * @param config   The bitmap config to create.
926a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed     * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
927a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed     *                 mark the bitmap as opaque. Doing so will clear the bitmap in black
928a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed     *                 instead of transparent.
929a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed     *
930a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed     * @throws IllegalArgumentException if the width or height are <= 0, or if
931a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed     *         Config is Config.HARDWARE, because hardware bitmaps are always immutable
932a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed     */
933a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed    public static Bitmap createBitmap(DisplayMetrics display, int width, int height,
934a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed            Config config, boolean hasAlpha) {
935a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed        if (width <= 0 || height <= 0) {
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("width and height must be > 0");
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (config == Config.HARDWARE) {
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("can't create mutable bitmap with Config.HARDWARE");
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bitmap bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true);
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (display != null) {
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bm.mDensity = display.densityDpi;
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bm.setHasAlpha(hasAlpha);
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((config == Config.ARGB_8888 || config == Config.RGBA_F16) && !hasAlpha) {
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            nativeErase(bm.mNativePtr, 0xff000000);
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // No need to initialize the bitmap to zeroes with other configs;
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // it is backed by a VM byte array which is by definition preinitialized
9513849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        // to all zeroes.
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return bm;
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a immutable bitmap with the specified width and height, with each
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * pixel value set to the corresponding value in the colors array.  Its
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * initial density is as per {@link #getDensity}.
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param colors   Array of {@link Color} used to initialize the pixels.
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param offset   Number of values to skip before the first color in the
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 array of colors.
9638cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen     * @param stride   Number of colors in the array between rows (must be >=
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 width or <= -width).
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width    The width of the bitmap
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height   The height of the bitmap
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param config   The bitmap config to create. If the config does not
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
9693849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy     *                 bytes in the colors[] will be ignored (assumed to be FF)
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalArgumentException if the width or height are <= 0, or if
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         the color array's length is less than the number of pixels.
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap createBitmap(int colors[], int offset, int stride,
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int width, int height, Config config) {
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return createBitmap(null, colors, offset, stride, width, height, config);
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a immutable bitmap with the specified width and height, with each
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * pixel value set to the corresponding value in the colors array.  Its
9813849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy     * initial density is determined from the given {@link DisplayMetrics}.
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param display  Display metrics for the display this bitmap will be
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 drawn on.
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param colors   Array of {@link Color} used to initialize the pixels.
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param offset   Number of values to skip before the first color in the
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 array of colors.
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param stride   Number of colors in the array between rows (must be >=
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 width or <= -width).
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width    The width of the bitmap
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height   The height of the bitmap
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param config   The bitmap config to create. If the config does not
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 bytes in the colors[] will be ignored (assumed to be FF)
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalArgumentException if the width or height are <= 0, or if
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         the color array's length is less than the number of pixels.
9978cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen     */
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap createBitmap(DisplayMetrics display, int colors[],
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int offset, int stride, int width, int height, Config config) {
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10013849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        checkWidthHeight(width, height);
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Math.abs(stride) < width) {
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("abs(stride) must be >= width");
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int lastScanline = offset + (height - 1) * stride;
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int length = colors.length;
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (offset < 0 || (offset + width > length) || lastScanline < 0 ||
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (lastScanline + width > length)) {
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new ArrayIndexOutOfBoundsException();
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (width <= 0 || height <= 0) {
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("width and height must be > 0");
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Bitmap bm = nativeCreate(colors, offset, stride, width, height,
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            config.nativeInt, false);
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (display != null) {
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bm.mDensity = display.densityDpi;
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return bm;
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a immutable bitmap with the specified width and height, with each
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * pixel value set to the corresponding value in the colors array.  Its
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * initial density is as per {@link #getDensity}.
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param colors   Array of {@link Color} used to initialize the pixels.
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 This array must be at least as large as width * height.
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width    The width of the bitmap
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height   The height of the bitmap
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param config   The bitmap config to create. If the config does not
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 bytes in the colors[] will be ignored (assumed to be FF)
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @throws IllegalArgumentException if the width or height are <= 0, or if
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         the color array's length is less than the number of pixels.
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Bitmap createBitmap(int colors[], int width, int height, Config config) {
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return createBitmap(null, colors, 0, width, width, height, config);
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns a immutable bitmap with the specified width and height, with each
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * pixel value set to the corresponding value in the colors array.  Its
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * initial density is determined from the given {@link DisplayMetrics}.
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param display  Display metrics for the display this bitmap will be
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 drawn on.
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param colors   Array of {@link Color} used to initialize the pixels.
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 This array must be at least as large as width * height.
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param width    The width of the bitmap
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param height   The height of the bitmap
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param config   The bitmap config to create. If the config does not
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 support per-pixel alpha (e.g. RGB_565), then the alpha
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 bytes in the colors[] will be ignored (assumed to be FF)
10558cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen     * @throws IllegalArgumentException if the width or height are <= 0, or if
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         the color array's length is less than the number of pixels.
10573849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy     */
10583849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy    public static Bitmap createBitmap(DisplayMetrics display, int colors[],
10593849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy            int width, int height, Config config) {
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return createBitmap(display, colors, 0, width, width, height, config);
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10633849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy    /**
10643849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy     * Returns an optional array of private data, used by the UI system for
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * some bitmaps. Not intended to be called by applications.
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public byte[] getNinePatchChunk() {
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mNinePatchChunk;
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Populates a rectangle with the bitmap's optical insets.
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param outInsets Rect to populate with optical insets
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10778cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    public void getOpticalInsets(@NonNull Rect outInsets) {
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNinePatchInsets == null) {
10793849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy            outInsets.setEmpty();
10803849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        } else {
10813849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy            outInsets.set(mNinePatchInsets.opticalRect);
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** @hide */
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public NinePatch.InsetStruct getNinePatchInsets() {
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mNinePatchInsets;
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Specifies the known formats a bitmap can be compressed into
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public enum CompressFormat {
10943849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy        JPEG    (0),
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PNG     (1),
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        WEBP    (2);
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        CompressFormat(int nativeInt) {
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            this.nativeInt = nativeInt;
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int nativeInt;
11023849f93b3c2b29ca3873b602897dccac039a0b98Romain Guy    }
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Number of bytes of temp storage we use for communicating between the
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * native compressor and the java OutputStream.
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final static int WORKING_COMPRESS_STORAGE = 4096;
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Write a compressed version of the bitmap to the specified outputstream.
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If this returns true, the bitmap can be reconstructed by passing a
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * corresponding inputstream to BitmapFactory.decodeStream(). Note: not
11148cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen     * all Formats support all bitmap configs directly, so it is possible that
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the returned bitmap from BitmapFactory could be in a different bitdepth,
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * and/or may have lost per-pixel alpha (e.g. JPEG only supports opaque
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * pixels).
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param format   The format of the compressed image
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param quality  Hint to the compressor, 0-100. 0 meaning compress for
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 small size, 100 meaning compress for max quality. Some
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 formats, like PNG which is lossless, will ignore the
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *                 quality setting
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param stream   The outputstream to write the compressed data.
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if successfully compressed to the specified stream.
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean compress(CompressFormat format, int quality, OutputStream stream) {
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkRecycled("Can't compress a recycled bitmap");
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // do explicit check before calling the native method
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (stream == null) {
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new NullPointerException();
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (quality < 0 || quality > 100) {
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("quality must be 0..100");
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "Bitmap.compress");
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean result = nativeCompress(mNativePtr, format.nativeInt,
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                quality, stream, new byte[WORKING_COMPRESS_STORAGE]);
1139b6377170960d40e66858d8b4d335a95eac773762Bart Sears        Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns true if the bitmap is marked as mutable (i.e.&nbsp;can be drawn into)
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final boolean isMutable() {
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mIsMutable;
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1149de0dfb7b65a02d4dd74c271b558adee0973fc267Dianne Hackborn
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Indicates whether pixels stored in this bitmaps are stored pre-multiplied.
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * When a pixel is pre-multiplied, the RGB components have been multiplied by
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the alpha component. For instance, if the original color is a 50%
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * translucent red <code>(128, 255, 0, 0)</code>, the pre-multiplied form is
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <code>(128, 128, 0, 0)</code>.</p>
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>This method always returns false if {@link #getConfig()} is
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link Bitmap.Config#RGB_565}.</p>
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>The return value is undefined if {@link #getConfig()} is
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link Bitmap.Config#ALPHA_8}.</p>
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>This method only returns true if {@link #hasAlpha()} returns true.
11648cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen     * A bitmap with no alpha channel can be used both as a pre-multiplied and
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * as a non pre-multiplied bitmap.</p>
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Only pre-multiplied bitmaps may be drawn by the view system or
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link Canvas}. If a non-pre-multiplied bitmap with an alpha channel is
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * drawn to a Canvas, a RuntimeException will be thrown.</p>
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the underlying pixels have been pre-multiplied, false
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         otherwise
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see Bitmap#setPremultiplied(boolean)
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see BitmapFactory.Options#inPremultiplied
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
117796e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn    public final boolean isPremultiplied() {
117896e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn        if (mRecycled) {
117996e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn            Log.w(TAG, "Called isPremultiplied() on a recycle()'d bitmap! This is undefined behavior!");
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return nativeIsPremultiplied(mNativePtr);
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets whether the bitmap should treat its data as pre-multiplied.
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Bitmaps are always treated as pre-multiplied by the view system and
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link Canvas} for performance reasons. Storing un-pre-multiplied data in
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a Bitmap (through {@link #setPixel}, {@link #setPixels}, or {@link
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * BitmapFactory.Options#inPremultiplied BitmapFactory.Options.inPremultiplied})
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * can lead to incorrect blending if drawn by the framework.</p>
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>This method will not affect the behavior of a bitmap without an alpha
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * channel, or if {@link #hasAlpha()} returns false.</p>
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>Calling {@link #createBitmap} or {@link #createScaledBitmap} with a source
119796e240f25a97c10bba863df328ed73a82c34ff61Dianne Hackborn     * Bitmap whose colors are not pre-multiplied may result in a RuntimeException,
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * since those functions require drawing the source, which is not supported for
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * un-pre-multiplied Bitmaps.</p>
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12018cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen     * @see Bitmap#isPremultiplied()
120276d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed     * @see BitmapFactory.Options#inPremultiplied
120376d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed     */
120476d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    public final void setPremultiplied(boolean premultiplied) {
120576d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed        checkRecycled("setPremultiplied called on a recycled bitmap");
120676d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed        mRequestPremultiplied = premultiplied;
1207366a84056c9a695ee6702d9d30bf9f3b521ba7ccRomain Guy        nativeSetPremultiplied(mNativePtr, premultiplied);
120876d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    }
120976d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed
121076d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    /** Returns the bitmap's width */
12118cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    public final int getWidth() {
12128cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        if (mRecycled) {
12138cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen            Log.w(TAG, "Called getWidth() on a recycle()'d bitmap! This is undefined behavior!");
12148cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        }
12158cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        return mWidth;
12168cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    }
12178cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen
12188cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    /** Returns the bitmap's height */
12198cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    public final int getHeight() {
12208cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        if (mRecycled) {
12218cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen            Log.w(TAG, "Called getHeight() on a recycle()'d bitmap! This is undefined behavior!");
12228cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        }
12238cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen        return mHeight;
12248cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    }
1225e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy
1226e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy    /**
122702890fd0f98b3b8d98baf0bda1ea906afd723d8bRomain Guy     * Convenience for calling {@link #getScaledWidth(int)} with the target
1228e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy     * density of the given {@link Canvas}.
1229e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy     */
123002890fd0f98b3b8d98baf0bda1ea906afd723d8bRomain Guy    public int getScaledWidth(Canvas canvas) {
123102890fd0f98b3b8d98baf0bda1ea906afd723d8bRomain Guy        return scaleFromDensity(getWidth(), mDensity, canvas.mDensity);
123202890fd0f98b3b8d98baf0bda1ea906afd723d8bRomain Guy    }
1233e4ac2d6b5723c95e648c489b187ddde449452c13Patrick Dubroy
1234366a84056c9a695ee6702d9d30bf9f3b521ba7ccRomain Guy    /**
1235366a84056c9a695ee6702d9d30bf9f3b521ba7ccRomain Guy     * Convenience for calling {@link #getScaledHeight(int)} with the target
1236366a84056c9a695ee6702d9d30bf9f3b521ba7ccRomain Guy     * density of the given {@link Canvas}.
1237366a84056c9a695ee6702d9d30bf9f3b521ba7ccRomain Guy     */
1238366a84056c9a695ee6702d9d30bf9f3b521ba7ccRomain Guy    public int getScaledHeight(Canvas canvas) {
1239366a84056c9a695ee6702d9d30bf9f3b521ba7ccRomain Guy        return scaleFromDensity(getHeight(), mDensity, canvas.mDensity);
1240366a84056c9a695ee6702d9d30bf9f3b521ba7ccRomain Guy    }
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12438cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen     * Convenience for calling {@link #getScaledWidth(int)} with the target
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * density of the given {@link DisplayMetrics}.
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getScaledWidth(DisplayMetrics metrics) {
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return scaleFromDensity(getWidth(), mDensity, metrics.densityDpi);
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Convenience for calling {@link #getScaledHeight(int)} with the target
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * density of the given {@link DisplayMetrics}.
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getScaledHeight(DisplayMetrics metrics) {
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return scaleFromDensity(getHeight(), mDensity, metrics.densityDpi);
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Convenience method that returns the width of this bitmap divided
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the density scale factor.
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param targetDensity The density of the target canvas of the bitmap.
12638cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen     * @return The scaled width of this bitmap, according to the density scale factor.
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getScaledWidth(int targetDensity) {
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return scaleFromDensity(getWidth(), mDensity, targetDensity);
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12688cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Convenience method that returns the height of this bitmap divided
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * by the density scale factor.
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param targetDensity The density of the target canvas of the bitmap.
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The scaled height of this bitmap, according to the density scale factor.
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getScaledHeight(int targetDensity) {
12770bbae0836426ba2704e38e7f90a9d0ca502ab71dRomain Guy        return scaleFromDensity(getHeight(), mDensity, targetDensity);
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @hide
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1283de0dfb7b65a02d4dd74c271b558adee0973fc267Dianne Hackborn    static public int scaleFromDensity(int size, int sdensity, int tdensity) {
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sdensity == DENSITY_NONE || tdensity == DENSITY_NONE || sdensity == tdensity) {
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return size;
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Scale by tdensity / sdensity, rounding up.
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ((size * tdensity) + (sdensity >> 1)) / sdensity;
12908cdcb12752b716d0407733fecefcf1d9e926310aWei-Ta Chen    }
1291a78b0a2d9ebb38b86ed802b3d86de07d0b301262Mike Reed
129276d1e01d5e65c4631c827831e98ad4e300d99eabMike Reed    /**
1293d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy     * Return the number of bytes between rows in the bitmap's pixels. Note that
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this refers to the pixels as stored natively by the bitmap. If you call
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * getPixels() or setPixels(), then the pixels are uniformly treated as
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * 32bit values, packed according to the Color class.
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1298     * <p>As of {@link android.os.Build.VERSION_CODES#KITKAT}, this method
1299     * should not be used to calculate the memory usage of the bitmap. Instead,
1300     * see {@link #getAllocationByteCount()}.
1301     *
1302     * @return number of bytes between rows of the native bitmap pixels.
1303     */
1304    public final int getRowBytes() {
1305        if (mRecycled) {
1306            Log.w(TAG, "Called getRowBytes() on a recycle()'d bitmap! This is undefined behavior!");
1307        }
1308        return nativeRowBytes(mNativePtr);
1309    }
1310
1311    /**
1312     * Returns the minimum number of bytes that can be used to store this bitmap's pixels.
1313     *
1314     * <p>As of {@link android.os.Build.VERSION_CODES#KITKAT}, the result of this method can
1315     * no longer be used to determine memory usage of a bitmap. See {@link
1316     * #getAllocationByteCount()}.</p>
1317     */
1318    public final int getByteCount() {
1319        if (mRecycled) {
1320            Log.w(TAG, "Called getByteCount() on a recycle()'d bitmap! "
1321                    + "This is undefined behavior!");
1322            return 0;
1323        }
1324        // int result permits bitmaps up to 46,340 x 46,340
1325        return getRowBytes() * getHeight();
1326    }
1327
1328    /**
1329     * Returns the size of the allocated memory used to store this bitmap's pixels.
1330     *
1331     * <p>This can be larger than the result of {@link #getByteCount()} if a bitmap is reused to
1332     * decode other bitmaps of smaller size, or by manual reconfiguration. See {@link
1333     * #reconfigure(int, int, Config)}, {@link #setWidth(int)}, {@link #setHeight(int)}, {@link
1334     * #setConfig(Bitmap.Config)}, and {@link BitmapFactory.Options#inBitmap
1335     * BitmapFactory.Options.inBitmap}. If a bitmap is not modified in this way, this value will be
1336     * the same as that returned by {@link #getByteCount()}.</p>
1337     *
1338     * <p>This value will not change over the lifetime of a Bitmap.</p>
1339     *
1340     * @see #reconfigure(int, int, Config)
1341     */
1342    public final int getAllocationByteCount() {
1343        if (mRecycled) {
1344            Log.w(TAG, "Called getAllocationByteCount() on a recycle()'d bitmap! "
1345                    + "This is undefined behavior!");
1346            return 0;
1347        }
1348        return nativeGetAllocationByteCount(mNativePtr);
1349    }
1350
1351    /**
1352     * If the bitmap's internal config is in one of the public formats, return
1353     * that config, otherwise return null.
1354     */
1355    public final Config getConfig() {
1356        if (mRecycled) {
1357            Log.w(TAG, "Called getConfig() on a recycle()'d bitmap! This is undefined behavior!");
1358        }
1359        return Config.nativeToConfig(nativeConfig(mNativePtr));
1360    }
1361
1362    /** Returns true if the bitmap's config supports per-pixel alpha, and
1363     * if the pixels may contain non-opaque alpha values. For some configs,
1364     * this is always false (e.g. RGB_565), since they do not support per-pixel
1365     * alpha. However, for configs that do, the bitmap may be flagged to be
1366     * known that all of its pixels are opaque. In this case hasAlpha() will
1367     * also return false. If a config such as ARGB_8888 is not so flagged,
1368     * it will return true by default.
1369     */
1370    public final boolean hasAlpha() {
1371        if (mRecycled) {
1372            Log.w(TAG, "Called hasAlpha() on a recycle()'d bitmap! This is undefined behavior!");
1373        }
1374        return nativeHasAlpha(mNativePtr);
1375    }
1376
1377    /**
1378     * Tell the bitmap if all of the pixels are known to be opaque (false)
1379     * or if some of the pixels may contain non-opaque alpha values (true).
1380     * Note, for some configs (e.g. RGB_565) this call is ignored, since it
1381     * does not support per-pixel alpha values.
1382     *
1383     * This is meant as a drawing hint, as in some cases a bitmap that is known
1384     * to be opaque can take a faster drawing case than one that may have
1385     * non-opaque per-pixel alpha values.
1386     */
1387    public void setHasAlpha(boolean hasAlpha) {
1388        checkRecycled("setHasAlpha called on a recycled bitmap");
1389        nativeSetHasAlpha(mNativePtr, hasAlpha, mRequestPremultiplied);
1390    }
1391
1392    /**
1393     * Indicates whether the renderer responsible for drawing this
1394     * bitmap should attempt to use mipmaps when this bitmap is drawn
1395     * scaled down.
1396     *
1397     * If you know that you are going to draw this bitmap at less than
1398     * 50% of its original size, you may be able to obtain a higher
1399     * quality
1400     *
1401     * This property is only a suggestion that can be ignored by the
1402     * renderer. It is not guaranteed to have any effect.
1403     *
1404     * @return true if the renderer should attempt to use mipmaps,
1405     *         false otherwise
1406     *
1407     * @see #setHasMipMap(boolean)
1408     */
1409    public final boolean hasMipMap() {
1410        if (mRecycled) {
1411            Log.w(TAG, "Called hasMipMap() on a recycle()'d bitmap! This is undefined behavior!");
1412        }
1413        return nativeHasMipMap(mNativePtr);
1414    }
1415
1416    /**
1417     * Set a hint for the renderer responsible for drawing this bitmap
1418     * indicating that it should attempt to use mipmaps when this bitmap
1419     * is drawn scaled down.
1420     *
1421     * If you know that you are going to draw this bitmap at less than
1422     * 50% of its original size, you may be able to obtain a higher
1423     * quality by turning this property on.
1424     *
1425     * Note that if the renderer respects this hint it might have to
1426     * allocate extra memory to hold the mipmap levels for this bitmap.
1427     *
1428     * This property is only a suggestion that can be ignored by the
1429     * renderer. It is not guaranteed to have any effect.
1430     *
1431     * @param hasMipMap indicates whether the renderer should attempt
1432     *                  to use mipmaps
1433     *
1434     * @see #hasMipMap()
1435     */
1436    public final void setHasMipMap(boolean hasMipMap) {
1437        checkRecycled("setHasMipMap called on a recycled bitmap");
1438        nativeSetHasMipMap(mNativePtr, hasMipMap);
1439    }
1440
1441    /**
1442     * Returns the color space associated with this bitmap. If the color
1443     * space is unknown, this method returns null.
1444     */
1445    @Nullable
1446    public final ColorSpace getColorSpace() {
1447        // A reconfigure can change the configuration and rgba16f is
1448        // always linear scRGB at this time
1449        if (getConfig() == Config.RGBA_F16) {
1450            // Reset the color space for potential future reconfigurations
1451            mColorSpace = null;
1452            return ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB);
1453        }
1454
1455        // Cache the color space retrieval since it can be fairly expensive
1456        if (mColorSpace == null) {
1457            if (nativeIsSRGB(mNativePtr)) {
1458                mColorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
1459            } else {
1460                float[] xyz = new float[9];
1461                float[] params = new float[7];
1462
1463                boolean hasColorSpace = nativeGetColorSpace(mNativePtr, xyz, params);
1464                if (hasColorSpace) {
1465                    ColorSpace.Rgb.TransferParameters parameters =
1466                            new ColorSpace.Rgb.TransferParameters(
1467                                    params[0], params[1], params[2],
1468                                    params[3], params[4], params[5], params[6]);
1469                    ColorSpace cs = ColorSpace.match(xyz, parameters);
1470                    if (cs != null) {
1471                        mColorSpace = cs;
1472                    } else {
1473                        mColorSpace = new ColorSpace.Rgb("Unknown", xyz, parameters);
1474                    }
1475                }
1476            }
1477        }
1478
1479        return mColorSpace;
1480    }
1481
1482    /**
1483     * Fills the bitmap's pixels with the specified {@link Color}.
1484     *
1485     * @throws IllegalStateException if the bitmap is not mutable.
1486     */
1487    public void eraseColor(@ColorInt int c) {
1488        checkRecycled("Can't erase a recycled bitmap");
1489        if (!isMutable()) {
1490            throw new IllegalStateException("cannot erase immutable bitmaps");
1491        }
1492        nativeErase(mNativePtr, c);
1493    }
1494
1495    /**
1496     * Returns the {@link Color} at the specified location. Throws an exception
1497     * if x or y are out of bounds (negative or >= to the width or height
1498     * respectively). The returned color is a non-premultiplied ARGB value.
1499     *
1500     * @param x    The x coordinate (0...width-1) of the pixel to return
1501     * @param y    The y coordinate (0...height-1) of the pixel to return
1502     * @return     The argb {@link Color} at the specified coordinate
1503     * @throws IllegalArgumentException if x, y exceed the bitmap's bounds
1504     * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE}
1505     */
1506    @ColorInt
1507    public int getPixel(int x, int y) {
1508        checkRecycled("Can't call getPixel() on a recycled bitmap");
1509        checkHardware("unable to getPixel(), "
1510                + "pixel access is not supported on Config#HARDWARE bitmaps");
1511        checkPixelAccess(x, y);
1512        return nativeGetPixel(mNativePtr, x, y);
1513    }
1514
1515    /**
1516     * Returns in pixels[] a copy of the data in the bitmap. Each value is
1517     * a packed int representing a {@link Color}. The stride parameter allows
1518     * the caller to allow for gaps in the returned pixels array between
1519     * rows. For normal packed results, just pass width for the stride value.
1520     * The returned colors are non-premultiplied ARGB values.
1521     *
1522     * @param pixels   The array to receive the bitmap's colors
1523     * @param offset   The first index to write into pixels[]
1524     * @param stride   The number of entries in pixels[] to skip between
1525     *                 rows (must be >= bitmap's width). Can be negative.
1526     * @param x        The x coordinate of the first pixel to read from
1527     *                 the bitmap
1528     * @param y        The y coordinate of the first pixel to read from
1529     *                 the bitmap
1530     * @param width    The number of pixels to read from each row
1531     * @param height   The number of rows to read
1532     *
1533     * @throws IllegalArgumentException if x, y, width, height exceed the
1534     *         bounds of the bitmap, or if abs(stride) < width.
1535     * @throws ArrayIndexOutOfBoundsException if the pixels array is too small
1536     *         to receive the specified number of pixels.
1537     * @throws IllegalStateException if the bitmap's config is {@link Config#HARDWARE}
1538     */
1539    public void getPixels(@ColorInt int[] pixels, int offset, int stride,
1540                          int x, int y, int width, int height) {
1541        checkRecycled("Can't call getPixels() on a recycled bitmap");
1542        checkHardware("unable to getPixels(), "
1543                + "pixel access is not supported on Config#HARDWARE bitmaps");
1544        if (width == 0 || height == 0) {
1545            return; // nothing to do
1546        }
1547        checkPixelsAccess(x, y, width, height, offset, stride, pixels);
1548        nativeGetPixels(mNativePtr, pixels, offset, stride,
1549                        x, y, width, height);
1550    }
1551
1552    /**
1553     * Shared code to check for illegal arguments passed to getPixel()
1554     * or setPixel()
1555     *
1556     * @param x x coordinate of the pixel
1557     * @param y y coordinate of the pixel
1558     */
1559    private void checkPixelAccess(int x, int y) {
1560        checkXYSign(x, y);
1561        if (x >= getWidth()) {
1562            throw new IllegalArgumentException("x must be < bitmap.width()");
1563        }
1564        if (y >= getHeight()) {
1565            throw new IllegalArgumentException("y must be < bitmap.height()");
1566        }
1567    }
1568
1569    /**
1570     * Shared code to check for illegal arguments passed to getPixels()
1571     * or setPixels()
1572     *
1573     * @param x left edge of the area of pixels to access
1574     * @param y top edge of the area of pixels to access
1575     * @param width width of the area of pixels to access
1576     * @param height height of the area of pixels to access
1577     * @param offset offset into pixels[] array
1578     * @param stride number of elements in pixels[] between each logical row
1579     * @param pixels array to hold the area of pixels being accessed
1580    */
1581    private void checkPixelsAccess(int x, int y, int width, int height,
1582                                   int offset, int stride, int pixels[]) {
1583        checkXYSign(x, y);
1584        if (width < 0) {
1585            throw new IllegalArgumentException("width must be >= 0");
1586        }
1587        if (height < 0) {
1588            throw new IllegalArgumentException("height must be >= 0");
1589        }
1590        if (x + width > getWidth()) {
1591            throw new IllegalArgumentException(
1592                    "x + width must be <= bitmap.width()");
1593        }
1594        if (y + height > getHeight()) {
1595            throw new IllegalArgumentException(
1596                    "y + height must be <= bitmap.height()");
1597        }
1598        if (Math.abs(stride) < width) {
1599            throw new IllegalArgumentException("abs(stride) must be >= width");
1600        }
1601        int lastScanline = offset + (height - 1) * stride;
1602        int length = pixels.length;
1603        if (offset < 0 || (offset + width > length)
1604                || lastScanline < 0
1605                || (lastScanline + width > length)) {
1606            throw new ArrayIndexOutOfBoundsException();
1607        }
1608    }
1609
1610    /**
1611     * <p>Write the specified {@link Color} into the bitmap (assuming it is
1612     * mutable) at the x,y coordinate. The color must be a
1613     * non-premultiplied ARGB value.</p>
1614     *
1615     * @param x     The x coordinate of the pixel to replace (0...width-1)
1616     * @param y     The y coordinate of the pixel to replace (0...height-1)
1617     * @param color The ARGB color to write into the bitmap
1618     *
1619     * @throws IllegalStateException if the bitmap is not mutable
1620     * @throws IllegalArgumentException if x, y are outside of the bitmap's
1621     *         bounds.
1622     */
1623    public void setPixel(int x, int y, @ColorInt int color) {
1624        checkRecycled("Can't call setPixel() on a recycled bitmap");
1625        if (!isMutable()) {
1626            throw new IllegalStateException();
1627        }
1628        checkPixelAccess(x, y);
1629        nativeSetPixel(mNativePtr, x, y, color);
1630    }
1631
1632    /**
1633     * <p>Replace pixels in the bitmap with the colors in the array. Each element
1634     * in the array is a packed int representing a non-premultiplied ARGB
1635     * {@link Color}.</p>
1636     *
1637     * @param pixels   The colors to write to the bitmap
1638     * @param offset   The index of the first color to read from pixels[]
1639     * @param stride   The number of colors in pixels[] to skip between rows.
1640     *                 Normally this value will be the same as the width of
1641     *                 the bitmap, but it can be larger (or negative).
1642     * @param x        The x coordinate of the first pixel to write to in
1643     *                 the bitmap.
1644     * @param y        The y coordinate of the first pixel to write to in
1645     *                 the bitmap.
1646     * @param width    The number of colors to copy from pixels[] per row
1647     * @param height   The number of rows to write to the bitmap
1648     *
1649     * @throws IllegalStateException if the bitmap is not mutable
1650     * @throws IllegalArgumentException if x, y, width, height are outside of
1651     *         the bitmap's bounds.
1652     * @throws ArrayIndexOutOfBoundsException if the pixels array is too small
1653     *         to receive the specified number of pixels.
1654     */
1655    public void setPixels(@ColorInt int[] pixels, int offset, int stride,
1656            int x, int y, int width, int height) {
1657        checkRecycled("Can't call setPixels() on a recycled bitmap");
1658        if (!isMutable()) {
1659            throw new IllegalStateException();
1660        }
1661        if (width == 0 || height == 0) {
1662            return; // nothing to do
1663        }
1664        checkPixelsAccess(x, y, width, height, offset, stride, pixels);
1665        nativeSetPixels(mNativePtr, pixels, offset, stride,
1666                        x, y, width, height);
1667    }
1668
1669    public static final Parcelable.Creator<Bitmap> CREATOR
1670            = new Parcelable.Creator<Bitmap>() {
1671        /**
1672         * Rebuilds a bitmap previously stored with writeToParcel().
1673         *
1674         * @param p    Parcel object to read the bitmap from
1675         * @return a new bitmap created from the data in the parcel
1676         */
1677        public Bitmap createFromParcel(Parcel p) {
1678            Bitmap bm = nativeCreateFromParcel(p);
1679            if (bm == null) {
1680                throw new RuntimeException("Failed to unparcel Bitmap");
1681            }
1682            return bm;
1683        }
1684        public Bitmap[] newArray(int size) {
1685            return new Bitmap[size];
1686        }
1687    };
1688
1689    /**
1690     * No special parcel contents.
1691     */
1692    public int describeContents() {
1693        return 0;
1694    }
1695
1696    /**
1697     * Write the bitmap and its pixels to the parcel. The bitmap can be
1698     * rebuilt from the parcel by calling CREATOR.createFromParcel().
1699     *
1700     * If this bitmap is {@link Config#HARDWARE}, it may be unparceled with a different pixel
1701     * format (e.g. 565, 8888), but the content will be preserved to the best quality permitted
1702     * by the final pixel format
1703     * @param p    Parcel object to write the bitmap data into
1704     */
1705    public void writeToParcel(Parcel p, int flags) {
1706        checkRecycled("Can't parcel a recycled bitmap");
1707        if (!nativeWriteToParcel(mNativePtr, mIsMutable, mDensity, p)) {
1708            throw new RuntimeException("native writeToParcel failed");
1709        }
1710    }
1711
1712    /**
1713     * Returns a new bitmap that captures the alpha values of the original.
1714     * This may be drawn with Canvas.drawBitmap(), where the color(s) will be
1715     * taken from the paint that is passed to the draw call.
1716     *
1717     * @return new bitmap containing the alpha channel of the original bitmap.
1718     */
1719    @CheckResult
1720    public Bitmap extractAlpha() {
1721        return extractAlpha(null, null);
1722    }
1723
1724    /**
1725     * Returns a new bitmap that captures the alpha values of the original.
1726     * These values may be affected by the optional Paint parameter, which
1727     * can contain its own alpha, and may also contain a MaskFilter which
1728     * could change the actual dimensions of the resulting bitmap (e.g.
1729     * a blur maskfilter might enlarge the resulting bitmap). If offsetXY
1730     * is not null, it returns the amount to offset the returned bitmap so
1731     * that it will logically align with the original. For example, if the
1732     * paint contains a blur of radius 2, then offsetXY[] would contains
1733     * -2, -2, so that drawing the alpha bitmap offset by (-2, -2) and then
1734     * drawing the original would result in the blur visually aligning with
1735     * the original.
1736     *
1737     * <p>The initial density of the returned bitmap is the same as the original's.
1738     *
1739     * @param paint Optional paint used to modify the alpha values in the
1740     *              resulting bitmap. Pass null for default behavior.
1741     * @param offsetXY Optional array that returns the X (index 0) and Y
1742     *                 (index 1) offset needed to position the returned bitmap
1743     *                 so that it visually lines up with the original.
1744     * @return new bitmap containing the (optionally modified by paint) alpha
1745     *         channel of the original bitmap. This may be drawn with
1746     *         Canvas.drawBitmap(), where the color(s) will be taken from the
1747     *         paint that is passed to the draw call.
1748     */
1749    @CheckResult
1750    public Bitmap extractAlpha(Paint paint, int[] offsetXY) {
1751        checkRecycled("Can't extractAlpha on a recycled bitmap");
1752        long nativePaint = paint != null ? paint.getNativeInstance() : 0;
1753        Bitmap bm = nativeExtractAlpha(mNativePtr, nativePaint, offsetXY);
1754        if (bm == null) {
1755            throw new RuntimeException("Failed to extractAlpha on Bitmap");
1756        }
1757        bm.mDensity = mDensity;
1758        return bm;
1759    }
1760
1761    /**
1762     *  Given another bitmap, return true if it has the same dimensions, config,
1763     *  and pixel data as this bitmap. If any of those differ, return false.
1764     *  If other is null, return false.
1765     */
1766    public boolean sameAs(Bitmap other) {
1767        checkRecycled("Can't call sameAs on a recycled bitmap!");
1768        if (this == other) return true;
1769        if (other == null) return false;
1770        if (other.isRecycled()) {
1771            throw new IllegalArgumentException("Can't compare to a recycled bitmap!");
1772        }
1773        return nativeSameAs(mNativePtr, other.mNativePtr);
1774    }
1775
1776    /**
1777     * Rebuilds any caches associated with the bitmap that are used for
1778     * drawing it. In the case of purgeable bitmaps, this call will attempt to
1779     * ensure that the pixels have been decoded.
1780     * If this is called on more than one bitmap in sequence, the priority is
1781     * given in LRU order (i.e. the last bitmap called will be given highest
1782     * priority).
1783     *
1784     * For bitmaps with no associated caches, this call is effectively a no-op,
1785     * and therefore is harmless.
1786     */
1787    public void prepareToDraw() {
1788        checkRecycled("Can't prepareToDraw on a recycled bitmap!");
1789        // Kick off an update/upload of the bitmap outside of the normal
1790        // draw path.
1791        nativePrepareToDraw(mNativePtr);
1792    }
1793
1794    /**
1795     *
1796     * @return {@link GraphicBuffer} which is internally used by hardware bitmap
1797     * @hide
1798     */
1799    public GraphicBuffer createGraphicBufferHandle() {
1800        return nativeCreateGraphicBufferHandle(mNativePtr);
1801    }
1802
1803    //////////// native methods
1804
1805    private static native Bitmap nativeCreate(int[] colors, int offset,
1806                                              int stride, int width, int height,
1807                                              int nativeConfig, boolean mutable);
1808    private static native Bitmap nativeCopy(long nativeSrcBitmap, int nativeConfig,
1809                                            boolean isMutable);
1810    private static native Bitmap nativeCopyAshmem(long nativeSrcBitmap);
1811    private static native Bitmap nativeCopyAshmemConfig(long nativeSrcBitmap, int nativeConfig);
1812    private static native long nativeGetNativeFinalizer();
1813    private static native boolean nativeRecycle(long nativeBitmap);
1814    private static native void nativeReconfigure(long nativeBitmap, int width, int height,
1815                                                 int config, boolean isPremultiplied);
1816
1817    private static native boolean nativeCompress(long nativeBitmap, int format,
1818                                            int quality, OutputStream stream,
1819                                            byte[] tempStorage);
1820    private static native void nativeErase(long nativeBitmap, int color);
1821    private static native int nativeRowBytes(long nativeBitmap);
1822    private static native int nativeConfig(long nativeBitmap);
1823
1824    private static native int nativeGetPixel(long nativeBitmap, int x, int y);
1825    private static native void nativeGetPixels(long nativeBitmap, int[] pixels,
1826                                               int offset, int stride, int x, int y,
1827                                               int width, int height);
1828
1829    private static native void nativeSetPixel(long nativeBitmap, int x, int y, int color);
1830    private static native void nativeSetPixels(long nativeBitmap, int[] colors,
1831                                               int offset, int stride, int x, int y,
1832                                               int width, int height);
1833    private static native void nativeCopyPixelsToBuffer(long nativeBitmap,
1834                                                        Buffer dst);
1835    private static native void nativeCopyPixelsFromBuffer(long nativeBitmap, Buffer src);
1836    private static native int nativeGenerationId(long nativeBitmap);
1837
1838    private static native Bitmap nativeCreateFromParcel(Parcel p);
1839    // returns true on success
1840    private static native boolean nativeWriteToParcel(long nativeBitmap,
1841                                                      boolean isMutable,
1842                                                      int density,
1843                                                      Parcel p);
1844    // returns a new bitmap built from the native bitmap's alpha, and the paint
1845    private static native Bitmap nativeExtractAlpha(long nativeBitmap,
1846                                                    long nativePaint,
1847                                                    int[] offsetXY);
1848
1849    private static native boolean nativeHasAlpha(long nativeBitmap);
1850    private static native boolean nativeIsPremultiplied(long nativeBitmap);
1851    private static native void nativeSetPremultiplied(long nativeBitmap,
1852                                                      boolean isPremul);
1853    private static native void nativeSetHasAlpha(long nativeBitmap,
1854                                                 boolean hasAlpha,
1855                                                 boolean requestPremul);
1856    private static native boolean nativeHasMipMap(long nativeBitmap);
1857    private static native void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap);
1858    private static native boolean nativeSameAs(long nativeBitmap0, long nativeBitmap1);
1859    private static native void nativePrepareToDraw(long nativeBitmap);
1860    private static native int nativeGetAllocationByteCount(long nativeBitmap);
1861    private static native Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap);
1862    private static native Bitmap nativeCreateHardwareBitmap(GraphicBuffer buffer);
1863    private static native GraphicBuffer nativeCreateGraphicBufferHandle(long nativeBitmap);
1864    private static native boolean nativeGetColorSpace(long nativePtr, float[] xyz, float[] params);
1865    private static native boolean nativeIsSRGB(long nativePtr);
1866}
1867