diff options
| author | Joseph Wen <josephwen@google.com> | 2010-07-19 16:59:51 +0800 |
|---|---|---|
| committer | Joseph Wen <josephwen@google.com> | 2010-08-17 14:34:02 +0800 |
| commit | f1f48bc7f200f54c76b22d845d8ba8419879b375 (patch) | |
| tree | f62d231d5a0ed1d8a5628ff03215188638838c4b /graphics | |
| parent | 1ce4394c779be5e67e37bbb995da13865b36c573 (diff) | |
| download | frameworks_base-f1f48bc7f200f54c76b22d845d8ba8419879b375.zip frameworks_base-f1f48bc7f200f54c76b22d845d8ba8419879b375.tar.gz frameworks_base-f1f48bc7f200f54c76b22d845d8ba8419879b375.tar.bz2 | |
Do JPEG tile-based decoding.
Change-Id: I5c1b4ac3c02eb4350ef0ba9a7877b22cfd730cfb
Diffstat (limited to 'graphics')
| -rw-r--r-- | graphics/java/android/graphics/BitmapFactory.java | 143 | ||||
| -rw-r--r-- | graphics/java/android/graphics/LargeBitmap.java | 128 |
2 files changed, 271 insertions, 0 deletions
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java index 2313f4c..8982388 100644 --- a/graphics/java/android/graphics/BitmapFactory.java +++ b/graphics/java/android/graphics/BitmapFactory.java @@ -27,6 +27,7 @@ import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.FileNotFoundException; /** * Creates Bitmap objects from various sources, including files, streams, @@ -581,6 +582,139 @@ public class BitmapFactory { nativeSetDefaultConfig(config.nativeInt); } + /** + * Create a LargeBitmap from the specified byte array. + * Currently only the Jpeg format is supported. + * + * @param data byte array of compressed image data. + * @param offset offset into data for where the decoder should begin + * parsing. + * @param length the number of bytes, beginning at offset, to parse + * @param isShareable If this is true, then the LargeBitmap may keep a + * shallow reference to the input. If this is false, + * then the LargeBitmap will explicitly make a copy of the + * input data, and keep that. Even if sharing is allowed, + * the implementation may still decide to make a deep + * copy of the input data. If an image is progressively encoded, + * allowing sharing may degrade the decoding speed. + * @return LargeBitmap, or null if the image data could not be decoded. + * @throws IOException if the image format is not supported or can not be decoded. + * @hide + */ + public static LargeBitmap createLargeBitmap(byte[] data, + int offset, int length, boolean isShareable) throws IOException { + if ((offset | length) < 0 || data.length < offset + length) { + throw new ArrayIndexOutOfBoundsException(); + } + return nativeCreateLargeBitmap(data, offset, length, isShareable); + } + + /** + * Create a LargeBitmap from the file descriptor. + * The position within the descriptor will not be changed when + * this returns, so the descriptor can be used again as is. + * Currently only the Jpeg format is supported. + * + * @param fd The file descriptor containing the data to decode + * @param isShareable If this is true, then the LargeBitmap may keep a + * shallow reference to the input. If this is false, + * then the LargeBitmap will explicitly make a copy of the + * input data, and keep that. Even if sharing is allowed, + * the implementation may still decide to make a deep + * copy of the input data. If an image is progressively encoded, + * allowing sharing may degrade the decoding speed. + * @return LargeBitmap, or null if the image data could not be decoded. + * @throws IOException if the image format is not supported or can not be decoded. + * @hide + */ + public static LargeBitmap createLargeBitmap( + FileDescriptor fd, boolean isShareable) throws IOException { + if (MemoryFile.isMemoryFile(fd)) { + int mappedlength = MemoryFile.getSize(fd); + MemoryFile file = new MemoryFile(fd, mappedlength, "r"); + InputStream is = file.getInputStream(); + return createLargeBitmap(is, isShareable); + } + return nativeCreateLargeBitmap(fd, isShareable); + } + + /** + * Create a LargeBitmap from an input stream. + * The stream's position will be where ever it was after the encoded data + * was read. + * Currently only the Jpeg format is supported. + * + * @param is The input stream that holds the raw data to be decoded into a + * LargeBitmap. + * @param isShareable If this is true, then the LargeBitmap may keep a + * shallow reference to the input. If this is false, + * then the LargeBitmap will explicitly make a copy of the + * input data, and keep that. Even if sharing is allowed, + * the implementation may still decide to make a deep + * copy of the input data. If an image is progressively encoded, + * allowing sharing may degrade the decoding speed. + * @return LargeBitmap, or null if the image data could not be decoded. + * @throws IOException if the image format is not supported or can not be decoded. + * @hide + */ + public static LargeBitmap createLargeBitmap(InputStream is, + boolean isShareable) throws IOException { + // we need mark/reset to work properly in JNI + + if (!is.markSupported()) { + is = new BufferedInputStream(is, 16 * 1024); + } + + if (is instanceof AssetManager.AssetInputStream) { + return nativeCreateLargeBitmap( + ((AssetManager.AssetInputStream) is).getAssetInt(), + isShareable); + } else { + // pass some temp storage down to the native code. 1024 is made up, + // but should be large enough to avoid too many small calls back + // into is.read(...). + byte [] tempStorage = null; + tempStorage = new byte[16 * 1024]; + return nativeCreateLargeBitmap(is, tempStorage, isShareable); + } + } + + /** + * Create a LargeBitmap from a file path. + * Currently only the Jpeg format is supported. + * + * @param pathName complete path name for the file to be decoded. + * @param isShareable If this is true, then the LargeBitmap may keep a + * shallow reference to the input. If this is false, + * then the LargeBitmap will explicitly make a copy of the + * input data, and keep that. Even if sharing is allowed, + * the implementation may still decide to make a deep + * copy of the input data. If an image is progressively encoded, + * allowing sharing may degrade the decoding speed. + * @return LargeBitmap, or null if the image data could not be decoded. + * @throws IOException if the image format is not supported or can not be decoded. + * @hide + */ + public static LargeBitmap createLargeBitmap(String pathName, + boolean isShareable) throws FileNotFoundException, IOException { + LargeBitmap bm = null; + InputStream stream = null; + + try { + stream = new FileInputStream(pathName); + bm = createLargeBitmap(stream, isShareable); + } finally { + if (stream != null) { + try { + stream.close(); + } catch (IOException e) { + // do nothing here + } + } + } + return bm; + } + private static native void nativeSetDefaultConfig(int nativeConfig); private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage, Rect padding, Options opts); @@ -590,5 +724,14 @@ public class BitmapFactory { private static native Bitmap nativeDecodeByteArray(byte[] data, int offset, int length, Options opts); private static native byte[] nativeScaleNinePatch(byte[] chunk, float scale, Rect pad); + + private static native LargeBitmap nativeCreateLargeBitmap( + byte[] data, int offset, int length, boolean isShareable); + private static native LargeBitmap nativeCreateLargeBitmap( + FileDescriptor fd, boolean isShareable); + private static native LargeBitmap nativeCreateLargeBitmap( + InputStream is, byte[] storage, boolean isShareable); + private static native LargeBitmap nativeCreateLargeBitmap( + int asset, boolean isShareable); } diff --git a/graphics/java/android/graphics/LargeBitmap.java b/graphics/java/android/graphics/LargeBitmap.java new file mode 100644 index 0000000..6656b17 --- /dev/null +++ b/graphics/java/android/graphics/LargeBitmap.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.graphics; + +import android.os.Parcel; +import android.os.Parcelable; +import android.util.DisplayMetrics; + +import java.io.OutputStream; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import java.nio.ShortBuffer; + +/** + * LargeBitmap can be used to decode a rectangle region from an image. + * LargeBimap is particularly useful when an original image is large and + * you only need parts of the image. + * + * To create a LargeBitmap, call BitmapFactory.createLargeBitmap(). + * Given a LargeBitmap, users can call decodeRegion() repeatedly + * to get a decoded Bitmap of the specified region. + * @hide + */ +public final class LargeBitmap { + private int mNativeLargeBitmap; + private boolean mRecycled; + + /* Private constructor that must received an already allocated native + large bitmap int (pointer). + + This can be called from JNI code. + */ + private LargeBitmap(int lbm) { + mNativeLargeBitmap = lbm; + mRecycled = false; + } + + /** + * Decodes a rectangle region in the image specified by rect. + * + * @param rect The rectangle that specified the region to be decode. + * @param opts null-ok; Options that control downsampling. + * inPurgeable is not supported. + * @return The decoded bitmap, or null if the image data could not be + * decoded. + */ + public Bitmap decodeRegion(Rect rect, BitmapFactory.Options options) { + checkRecycled("decodeRegion called on recycled large bitmap"); + if (rect.left < 0 || rect.top < 0 || rect.right > getWidth() || rect.bottom > getHeight()) + throw new IllegalArgumentException("rectangle is not inside the image"); + return nativeDecodeRegion(mNativeLargeBitmap, rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top, options); + } + + /** Returns the original image's width */ + public int getWidth() { + checkRecycled("getWidth called on recycled large bitmap"); + return nativeGetWidth(mNativeLargeBitmap); + } + + /** Returns the original image's height */ + public int getHeight() { + checkRecycled("getHeight called on recycled large bitmap"); + return nativeGetHeight(mNativeLargeBitmap); + } + + /** + * Frees up the memory associated with this large bitmap, and mark the + * large bitmap as "dead", meaning it will throw an exception if decodeRegion(), + * getWidth() or getHeight() is called. + * This operation cannot be reversed, so it should only be called if you are + * sure there are no further uses for the large bitmap. This is an advanced call, + * and normally need not be called, since the normal GC process will free up this + * memory when there are no more references to this bitmap. + */ + public void recycle() { + if (!mRecycled) { + nativeClean(mNativeLargeBitmap); + mRecycled = true; + } + } + + /** + * Returns true if this large bitmap has been recycled. + * If so, then it is an error to try use its method. + * + * @return true if the large bitmap has been recycled + */ + public final boolean isRecycled() { + return mRecycled; + } + + /** + * Called by methods that want to throw an exception if the bitmap + * has already been recycled. + */ + private void checkRecycled(String errorMessage) { + if (mRecycled) { + throw new IllegalStateException(errorMessage); + } + } + + protected void finalize() { + recycle(); + } + + private static native Bitmap nativeDecodeRegion(int lbm, + int start_x, int start_y, int width, int height, + BitmapFactory.Options options); + private static native int nativeGetWidth(int lbm); + private static native int nativeGetHeight(int lbm); + private static native void nativeClean(int lbm); +} |
