Search in sources :

Example 1 with BitmapRegionDecoder

use of android.graphics.BitmapRegionDecoder in project StickerCamera by Skykai521.

the class CameraActivity method decodeRegionCrop.

private Bitmap decodeRegionCrop(byte[] data, Rect rect) {
    InputStream is = null;
    System.gc();
    Bitmap croppedImage = null;
    try {
        is = new ByteArrayInputStream(data);
        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);
        try {
            croppedImage = decoder.decodeRegion(rect, new BitmapFactory.Options());
        } catch (IllegalArgumentException e) {
        }
    } catch (Throwable e) {
        e.printStackTrace();
    } finally {
        IOUtil.closeStream(is);
    }
    Matrix m = new Matrix();
    m.setRotate(90, PHOTO_SIZE / 2, PHOTO_SIZE / 2);
    if (mCurrentCameraId == 1) {
        m.postScale(1, -1);
    }
    Bitmap rotatedImage = Bitmap.createBitmap(croppedImage, 0, 0, PHOTO_SIZE, PHOTO_SIZE, m, true);
    if (rotatedImage != croppedImage)
        croppedImage.recycle();
    return rotatedImage;
}
Also used : Bitmap(android.graphics.Bitmap) Matrix(android.graphics.Matrix) ByteArrayInputStream(java.io.ByteArrayInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) BitmapRegionDecoder(android.graphics.BitmapRegionDecoder)

Example 2 with BitmapRegionDecoder

use of android.graphics.BitmapRegionDecoder in project robolectric by robolectric.

the class ShadowBitmapRegionDecoderTest method getWidthAndGetHeight_shouldReturnCorrectValuesForImage.

@Test
public void getWidthAndGetHeight_shouldReturnCorrectValuesForImage() throws Exception {
    BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(getImageInputStream(), true);
    assertThat(decoder.getWidth()).isEqualTo(297);
    assertThat(decoder.getHeight()).isEqualTo(251);
}
Also used : BitmapRegionDecoder(android.graphics.BitmapRegionDecoder) Test(org.junit.Test)

Example 3 with BitmapRegionDecoder

use of android.graphics.BitmapRegionDecoder in project platform_frameworks_base by android.

the class WallpaperManagerService method generateCrop.

/**
     * Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
     * for display.
     */
private void generateCrop(WallpaperData wallpaper) {
    boolean success = false;
    Rect cropHint = new Rect(wallpaper.cropHint);
    if (DEBUG) {
        Slog.v(TAG, "Generating crop for new wallpaper(s): 0x" + Integer.toHexString(wallpaper.whichPending) + " to " + wallpaper.cropFile.getName() + " crop=(" + cropHint.width() + 'x' + cropHint.height() + ") dim=(" + wallpaper.width + 'x' + wallpaper.height + ')');
    }
    // Analyse the source; needed in multiple cases
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(wallpaper.wallpaperFile.getAbsolutePath(), options);
    if (options.outWidth <= 0 || options.outHeight <= 0) {
        Slog.e(TAG, "Invalid wallpaper data");
        success = false;
    } else {
        boolean needCrop = false;
        boolean needScale = false;
        // Empty crop means use the full image
        if (cropHint.isEmpty()) {
            cropHint.left = cropHint.top = 0;
            cropHint.right = options.outWidth;
            cropHint.bottom = options.outHeight;
        } else {
            // force the crop rect to lie within the measured bounds
            cropHint.offset((cropHint.right > options.outWidth ? options.outWidth - cropHint.right : 0), (cropHint.bottom > options.outHeight ? options.outHeight - cropHint.bottom : 0));
            // If the crop hint was larger than the image we just overshot. Patch things up.
            if (cropHint.left < 0) {
                cropHint.left = 0;
            }
            if (cropHint.top < 0) {
                cropHint.top = 0;
            }
            // Don't bother cropping if what we're left with is identity
            needCrop = (options.outHeight > cropHint.height() || options.outWidth > cropHint.width());
        }
        // scale if the crop height winds up not matching the recommended metrics
        needScale = (wallpaper.height != cropHint.height());
        if (DEBUG) {
            Slog.v(TAG, "crop: w=" + cropHint.width() + " h=" + cropHint.height());
            Slog.v(TAG, "dims: w=" + wallpaper.width + " h=" + wallpaper.height);
            Slog.v(TAG, "meas: w=" + options.outWidth + " h=" + options.outHeight);
            Slog.v(TAG, "crop?=" + needCrop + " scale?=" + needScale);
        }
        if (!needCrop && !needScale) {
            // the whole thing and just copy the image file directly.
            if (DEBUG) {
                Slog.v(TAG, "Null crop of new wallpaper; copying");
            }
            success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
            if (!success) {
                wallpaper.cropFile.delete();
            // TODO: fall back to default wallpaper in this case
            }
        } else {
            // Fancy case: crop and scale.  First, we decode and scale down if appropriate.
            FileOutputStream f = null;
            BufferedOutputStream bos = null;
            try {
                BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(wallpaper.wallpaperFile.getAbsolutePath(), false);
                // This actually downsamples only by powers of two, but that's okay; we do
                // a proper scaling blit later.  This is to minimize transient RAM use.
                // We calculate the largest power-of-two under the actual ratio rather than
                // just let the decode take care of it because we also want to remap where the
                // cropHint rectangle lies in the decoded [super]rect.
                final BitmapFactory.Options scaler;
                final int actualScale = cropHint.height() / wallpaper.height;
                int scale = 1;
                while (2 * scale < actualScale) {
                    scale *= 2;
                }
                if (scale > 1) {
                    scaler = new BitmapFactory.Options();
                    scaler.inSampleSize = scale;
                    if (DEBUG) {
                        Slog.v(TAG, "Downsampling cropped rect with scale " + scale);
                    }
                } else {
                    scaler = null;
                }
                Bitmap cropped = decoder.decodeRegion(cropHint, scaler);
                decoder.recycle();
                if (cropped == null) {
                    Slog.e(TAG, "Could not decode new wallpaper");
                } else {
                    // We've got the extracted crop; now we want to scale it properly to
                    // the desired rectangle.  That's a height-biased operation: make it
                    // fit the hinted height, and accept whatever width we end up with.
                    cropHint.offsetTo(0, 0);
                    // adjust by downsampling factor
                    cropHint.right /= scale;
                    cropHint.bottom /= scale;
                    final float heightR = ((float) wallpaper.height) / ((float) cropHint.height());
                    if (DEBUG) {
                        Slog.v(TAG, "scale " + heightR + ", extracting " + cropHint);
                    }
                    final int destWidth = (int) (cropHint.width() * heightR);
                    final Bitmap finalCrop = Bitmap.createScaledBitmap(cropped, destWidth, wallpaper.height, true);
                    if (DEBUG) {
                        Slog.v(TAG, "Final extract:");
                        Slog.v(TAG, "  dims: w=" + wallpaper.width + " h=" + wallpaper.height);
                        Slog.v(TAG, "   out: w=" + finalCrop.getWidth() + " h=" + finalCrop.getHeight());
                    }
                    f = new FileOutputStream(wallpaper.cropFile);
                    bos = new BufferedOutputStream(f, 32 * 1024);
                    finalCrop.compress(Bitmap.CompressFormat.JPEG, 100, bos);
                    // don't rely on the implicit flush-at-close when noting success
                    bos.flush();
                    success = true;
                }
            } catch (Exception e) {
                if (DEBUG) {
                    Slog.e(TAG, "Error decoding crop", e);
                }
            } finally {
                IoUtils.closeQuietly(bos);
                IoUtils.closeQuietly(f);
            }
        }
    }
    if (!success) {
        Slog.e(TAG, "Unable to apply new wallpaper");
        wallpaper.cropFile.delete();
    }
    if (wallpaper.cropFile.exists()) {
        boolean didRestorecon = SELinux.restorecon(wallpaper.cropFile.getAbsoluteFile());
        if (DEBUG) {
            Slog.v(TAG, "restorecon() of crop file returned " + didRestorecon);
        }
    }
}
Also used : Rect(android.graphics.Rect) Bitmap(android.graphics.Bitmap) FileOutputStream(java.io.FileOutputStream) BitmapRegionDecoder(android.graphics.BitmapRegionDecoder) BitmapFactory(android.graphics.BitmapFactory) BufferedOutputStream(java.io.BufferedOutputStream) Point(android.graphics.Point) ErrnoException(android.system.ErrnoException) FileNotFoundException(java.io.FileNotFoundException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) NameNotFoundException(android.content.pm.PackageManager.NameNotFoundException) RemoteException(android.os.RemoteException) IOException(java.io.IOException)

Example 4 with BitmapRegionDecoder

use of android.graphics.BitmapRegionDecoder in project platform_frameworks_base by android.

the class WallpaperManager method getBuiltInDrawable.

/**
     * Returns a drawable for the built-in static wallpaper of the specified type.  Based on the
     * parameters, the drawable can be cropped and scaled.
     *
     * @param outWidth The width of the returned drawable
     * @param outWidth The height of the returned drawable
     * @param scaleToFit If true, scale the wallpaper down rather than just cropping it
     * @param horizontalAlignment A float value between 0 and 1 specifying where to crop the image;
     *        0 for left-aligned, 0.5 for horizontal center-aligned, and 1 for right-aligned
     * @param verticalAlignment A float value between 0 and 1 specifying where to crop the image;
     *        0 for top-aligned, 0.5 for vertical center-aligned, and 1 for bottom-aligned
     * @param which The {@code FLAG_*} identifier of a valid wallpaper type.  Throws
     *     IllegalArgumentException if an invalid wallpaper is requested.
     * @return A Drawable presenting the built-in default wallpaper image of the given type,
     *        or {@code null} if no default image of that type is defined on this device.
     */
public Drawable getBuiltInDrawable(int outWidth, int outHeight, boolean scaleToFit, float horizontalAlignment, float verticalAlignment, @SetWallpaperFlags int which) {
    if (sGlobals.mService == null) {
        Log.w(TAG, "WallpaperService not running");
        throw new RuntimeException(new DeadSystemException());
    }
    if (which != FLAG_SYSTEM && which != FLAG_LOCK) {
        throw new IllegalArgumentException("Must request exactly one kind of wallpaper");
    }
    Resources resources = mContext.getResources();
    horizontalAlignment = Math.max(0, Math.min(1, horizontalAlignment));
    verticalAlignment = Math.max(0, Math.min(1, verticalAlignment));
    InputStream wpStream = openDefaultWallpaper(mContext, which);
    if (wpStream == null) {
        if (DEBUG) {
            Log.w(TAG, "default wallpaper stream " + which + " is null");
        }
        return null;
    } else {
        InputStream is = new BufferedInputStream(wpStream);
        if (outWidth <= 0 || outHeight <= 0) {
            Bitmap fullSize = BitmapFactory.decodeStream(is, null, null);
            return new BitmapDrawable(resources, fullSize);
        } else {
            int inWidth;
            int inHeight;
            // Just measure this time through...
            {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;
                BitmapFactory.decodeStream(is, null, options);
                if (options.outWidth != 0 && options.outHeight != 0) {
                    inWidth = options.outWidth;
                    inHeight = options.outHeight;
                } else {
                    Log.e(TAG, "default wallpaper dimensions are 0");
                    return null;
                }
            }
            // Reopen the stream to do the full decode.  We know at this point
            // that openDefaultWallpaper() will return non-null.
            is = new BufferedInputStream(openDefaultWallpaper(mContext, which));
            RectF cropRectF;
            outWidth = Math.min(inWidth, outWidth);
            outHeight = Math.min(inHeight, outHeight);
            if (scaleToFit) {
                cropRectF = getMaxCropRect(inWidth, inHeight, outWidth, outHeight, horizontalAlignment, verticalAlignment);
            } else {
                float left = (inWidth - outWidth) * horizontalAlignment;
                float right = left + outWidth;
                float top = (inHeight - outHeight) * verticalAlignment;
                float bottom = top + outHeight;
                cropRectF = new RectF(left, top, right, bottom);
            }
            Rect roundedTrueCrop = new Rect();
            cropRectF.roundOut(roundedTrueCrop);
            if (roundedTrueCrop.width() <= 0 || roundedTrueCrop.height() <= 0) {
                Log.w(TAG, "crop has bad values for full size image");
                return null;
            }
            // See how much we're reducing the size of the image
            int scaleDownSampleSize = Math.min(roundedTrueCrop.width() / outWidth, roundedTrueCrop.height() / outHeight);
            // Attempt to open a region decoder
            BitmapRegionDecoder decoder = null;
            try {
                decoder = BitmapRegionDecoder.newInstance(is, true);
            } catch (IOException e) {
                Log.w(TAG, "cannot open region decoder for default wallpaper");
            }
            Bitmap crop = null;
            if (decoder != null) {
                // Do region decoding to get crop bitmap
                BitmapFactory.Options options = new BitmapFactory.Options();
                if (scaleDownSampleSize > 1) {
                    options.inSampleSize = scaleDownSampleSize;
                }
                crop = decoder.decodeRegion(roundedTrueCrop, options);
                decoder.recycle();
            }
            if (crop == null) {
                // BitmapRegionDecoder has failed, try to crop in-memory. We know at
                // this point that openDefaultWallpaper() will return non-null.
                is = new BufferedInputStream(openDefaultWallpaper(mContext, which));
                Bitmap fullSize = null;
                BitmapFactory.Options options = new BitmapFactory.Options();
                if (scaleDownSampleSize > 1) {
                    options.inSampleSize = scaleDownSampleSize;
                }
                fullSize = BitmapFactory.decodeStream(is, null, options);
                if (fullSize != null) {
                    crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left, roundedTrueCrop.top, roundedTrueCrop.width(), roundedTrueCrop.height());
                }
            }
            if (crop == null) {
                Log.w(TAG, "cannot decode default wallpaper");
                return null;
            }
            // Scale down if necessary
            if (outWidth > 0 && outHeight > 0 && (crop.getWidth() != outWidth || crop.getHeight() != outHeight)) {
                Matrix m = new Matrix();
                RectF cropRect = new RectF(0, 0, crop.getWidth(), crop.getHeight());
                RectF returnRect = new RectF(0, 0, outWidth, outHeight);
                m.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL);
                Bitmap tmp = Bitmap.createBitmap((int) returnRect.width(), (int) returnRect.height(), Bitmap.Config.ARGB_8888);
                if (tmp != null) {
                    Canvas c = new Canvas(tmp);
                    Paint p = new Paint();
                    p.setFilterBitmap(true);
                    c.drawBitmap(crop, m, p);
                    crop = tmp;
                }
            }
            return new BitmapDrawable(resources, crop);
        }
    }
}
Also used : DeadSystemException(android.os.DeadSystemException) Rect(android.graphics.Rect) BufferedInputStream(java.io.BufferedInputStream) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) Canvas(android.graphics.Canvas) BitmapRegionDecoder(android.graphics.BitmapRegionDecoder) BitmapDrawable(android.graphics.drawable.BitmapDrawable) IOException(java.io.IOException) Paint(android.graphics.Paint) Paint(android.graphics.Paint) RectF(android.graphics.RectF) Bitmap(android.graphics.Bitmap) Matrix(android.graphics.Matrix) BufferedInputStream(java.io.BufferedInputStream) Resources(android.content.res.Resources) BitmapFactory(android.graphics.BitmapFactory)

Example 5 with BitmapRegionDecoder

use of android.graphics.BitmapRegionDecoder in project UltimateAndroid by cymcsg.

the class CropImageActivity method decodeRegionCrop.

@TargetApi(10)
private Bitmap decodeRegionCrop(Bitmap croppedImage, Rect rect) {
    // Release memory now
    clearImageView();
    InputStream is = null;
    try {
        is = getContentResolver().openInputStream(sourceUri);
        BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false);
        final int width = decoder.getWidth();
        final int height = decoder.getHeight();
        if (exifRotation != 0) {
            // Adjust crop area to account for image rotation
            Matrix matrix = new Matrix();
            matrix.setRotate(-exifRotation);
            RectF adjusted = new RectF();
            matrix.mapRect(adjusted, new RectF(rect));
            // Adjust to account for origin at 0,0
            adjusted.offset(adjusted.left < 0 ? width : 0, adjusted.top < 0 ? height : 0);
            rect = new Rect((int) adjusted.left, (int) adjusted.top, (int) adjusted.right, (int) adjusted.bottom);
        }
        try {
            croppedImage = decoder.decodeRegion(rect, new BitmapFactory.Options());
        } catch (IllegalArgumentException e) {
            // Rethrow with some extra information
            throw new IllegalArgumentException("Rectangle " + rect + " is outside of the image (" + width + "," + height + "," + exifRotation + ")", e);
        }
    } catch (IOException e) {
        Logs.e("Error cropping image: " + e.getMessage(), e);
        finish();
    } catch (OutOfMemoryError e) {
        Log.e("OOM cropping image: " + e.getMessage(), e);
        setResultException(e);
    } finally {
        CropUtil.closeSilently(is);
    }
    return croppedImage;
}
Also used : RectF(android.graphics.RectF) Rect(android.graphics.Rect) Matrix(android.graphics.Matrix) InputStream(java.io.InputStream) BitmapRegionDecoder(android.graphics.BitmapRegionDecoder) IOException(java.io.IOException) TargetApi(android.annotation.TargetApi)

Aggregations

BitmapRegionDecoder (android.graphics.BitmapRegionDecoder)22 Rect (android.graphics.Rect)19 Bitmap (android.graphics.Bitmap)18 IOException (java.io.IOException)15 BitmapFactory (android.graphics.BitmapFactory)13 InputStream (java.io.InputStream)12 Matrix (android.graphics.Matrix)10 RectF (android.graphics.RectF)10 Paint (android.graphics.Paint)7 FileInputStream (java.io.FileInputStream)6 Resources (android.content.res.Resources)5 Canvas (android.graphics.Canvas)5 Point (android.graphics.Point)5 BitmapDrawable (android.graphics.drawable.BitmapDrawable)5 DeadSystemException (android.os.DeadSystemException)5 BufferedInputStream (java.io.BufferedInputStream)5 FileNotFoundException (java.io.FileNotFoundException)5 NameNotFoundException (android.content.pm.PackageManager.NameNotFoundException)4 RemoteException (android.os.RemoteException)4 ErrnoException (android.system.ErrnoException)4