2D Graphics Android

/*
 * Copyright (C) 2008 Google Inc.
 *
 * 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 com.google.android.photostream;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import java.util.Random;
/**
 * This class contains various utilities to manipulate Bitmaps. The methods of this class,
 * although static, are not thread safe and cannot be invoked by several threads at the
 * same time. Synchronization is required by the caller.
 */
final class ImageUtilities {
    private static final float PHOTO_BORDER_WIDTH = 3.0f;
    private static final int PHOTO_BORDER_COLOR = 0xffffffff;
    private static final float ROTATION_ANGLE_MIN = 2.5f;
    private static final float ROTATION_ANGLE_EXTRA = 5.5f;
    private static final Random sRandom = new Random();
    private static final Paint sPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
    private static final Paint sStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    static {
        sStrokePaint.setStrokeWidth(PHOTO_BORDER_WIDTH);
        sStrokePaint.setStyle(Paint.Style.STROKE);
        sStrokePaint.setColor(PHOTO_BORDER_COLOR);
    }
    /**
     * Rotate specified Bitmap by a random angle. The angle is either negative or positive,
     * and ranges, in degrees, from 2.5 to 8. After rotation a frame is overlaid on top
     * of the rotated image.
     *
     * This method is not thread safe.
     *
     * @param bitmap The Bitmap to rotate and apply a frame onto.
     *
     * @return A new Bitmap whose dimension are different from the original bitmap.
     */
    static Bitmap rotateAndFrame(Bitmap bitmap) {
        final boolean positive = sRandom.nextFloat() >= 0.5f;
        final float angle = (ROTATION_ANGLE_MIN + sRandom.nextFloat() * ROTATION_ANGLE_EXTRA) *
                (positive ? 1.0f : -1.0f);
        final double radAngle = Math.toRadians(angle);
        final int bitmapWidth = bitmap.getWidth();
        final int bitmapHeight = bitmap.getHeight();
        final double cosAngle = Math.abs(Math.cos(radAngle));
        final double sinAngle = Math.abs(Math.sin(radAngle));
        final int strokedWidth = (int) (bitmapWidth + 2 * PHOTO_BORDER_WIDTH);
        final int strokedHeight = (int) (bitmapHeight + 2 * PHOTO_BORDER_WIDTH);
        final int width = (int) (strokedHeight * sinAngle + strokedWidth * cosAngle);
        final int height = (int) (strokedWidth * sinAngle + strokedHeight * cosAngle);
        final float x = (width - bitmapWidth) / 2.0f;
        final float y = (height - bitmapHeight) / 2.0f;
        final Bitmap decored = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        final Canvas canvas = new Canvas(decored);
        canvas.rotate(angle, width / 2.0f, height / 2.0f);
        canvas.drawBitmap(bitmap, x, y, sPaint);
        canvas.drawRect(x, y, x + bitmapWidth, y + bitmapHeight, sStrokePaint);
        return decored;
    }
    /**
     * Scales the specified Bitmap to fit within the specified dimensions. After scaling,
     * a frame is overlaid on top of the scaled image.
     *
     * This method is not thread safe.
     *
     * @param bitmap The Bitmap to scale to fit the specified dimensions and to apply
     *               a frame onto.
     * @param width The maximum width of the new Bitmap.
     * @param height The maximum height of the new Bitmap.
     *
     * @return A scaled version of the original bitmap, whose dimension are less than or
     *         equal to the specified width and height.
     */
    static Bitmap scaleAndFrame(Bitmap bitmap, int width, int height) {
        final int bitmapWidth = bitmap.getWidth();
        final int bitmapHeight = bitmap.getHeight();
        final float scale = Math.min((float) width / (float) bitmapWidth, 
                (float) height / (float) bitmapHeight);
        final int scaledWidth = (int) (bitmapWidth * scale);
        final int scaledHeight = (int) (bitmapHeight * scale);
        final Bitmap decored = Bitmap.createScaledBitmap(bitmap, scaledWidth, scaledHeight, true);
        final Canvas canvas = new Canvas(decored);
        final int offset = (int) (PHOTO_BORDER_WIDTH / 2);
        sStrokePaint.setAntiAlias(false);
        canvas.drawRect(offset, offset, scaledWidth - offset - 1,
                scaledHeight - offset - 1, sStrokePaint);
        sStrokePaint.setAntiAlias(true);
        return decored;
    }
}