1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.gallery3d.filtershow.filters; 18 19 import android.graphics.Bitmap; 20 import android.graphics.Canvas; 21 import android.graphics.Matrix; 22 import android.graphics.Paint; 23 import android.graphics.Rect; 24 import android.graphics.RectF; 25 import android.util.Log; 26 27 import com.android.gallery3d.filtershow.crop.CropExtras; 28 import com.android.gallery3d.filtershow.imageshow.GeometryMath; 29 import com.android.gallery3d.filtershow.imageshow.GeometryMetadata; 30 31 public class ImageFilterGeometry extends ImageFilter { 32 private final Bitmap.Config mConfig = Bitmap.Config.ARGB_8888; 33 private GeometryMetadata mGeometry = null; 34 private static final String LOGTAG = "ImageFilterGeometry"; 35 private static final boolean LOGV = false; 36 private static final int BOTH = 3; 37 private static final int VERTICAL = 2; 38 private static final int HORIZONTAL = 1; 39 private static final int NINETY = 1; 40 private static final int ONE_EIGHTY = 2; 41 private static final int TWO_SEVENTY = 3; 42 43 public ImageFilterGeometry() { 44 mName = "Geometry"; 45 } 46 47 @Override 48 public ImageFilter clone() throws CloneNotSupportedException { 49 // FIXME: clone() should not be needed. Remove when we fix geometry. 50 ImageFilterGeometry filter = (ImageFilterGeometry) super.clone(); 51 return filter; 52 } 53 54 native protected void nativeApplyFilterFlip(Bitmap src, int srcWidth, int srcHeight, 55 Bitmap dst, int dstWidth, int dstHeight, int flip); 56 57 native protected void nativeApplyFilterRotate(Bitmap src, int srcWidth, int srcHeight, 58 Bitmap dst, int dstWidth, int dstHeight, int rotate); 59 60 native protected void nativeApplyFilterCrop(Bitmap src, int srcWidth, int srcHeight, 61 Bitmap dst, int dstWidth, int dstHeight, int offsetWidth, int offsetHeight); 62 63 native protected void nativeApplyFilterStraighten(Bitmap src, int srcWidth, int srcHeight, 64 Bitmap dst, int dstWidth, int dstHeight, float straightenAngle); 65 66 @Override 67 public void useRepresentation(FilterRepresentation representation) { 68 mGeometry = (GeometryMetadata) representation; 69 } 70 71 @Override 72 public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { 73 // TODO: implement bilinear or bicubic here... for now, just use 74 // canvas to do a simple implementation... 75 // TODO: and be more memory efficient! (do it in native?) 76 RectF cb = mGeometry.getPreviewCropBounds(); 77 RectF pb = mGeometry.getPhotoBounds(); 78 if (cb.width() == 0 || cb.height() == 0 || pb.width() == 0 || pb.height() == 0) { 79 Log.w(LOGTAG, "Cannot apply geometry: geometry metadata has not been initialized"); 80 return bitmap; 81 } 82 CropExtras extras = mGeometry.getCropExtras(); 83 boolean useExtras = mGeometry.getUseCropExtrasFlag(); 84 int outputX = 0; 85 int outputY = 0; 86 boolean s = false; 87 if (extras != null && useExtras){ 88 outputX = extras.getOutputX(); 89 outputY = extras.getOutputY(); 90 s = extras.getScaleUp(); 91 } 92 93 94 Rect cropBounds = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); 95 RectF crop = mGeometry.getCropBounds(bitmap); 96 if (crop.width() > 0 && crop.height() > 0) 97 cropBounds = GeometryMath.roundNearest(crop); 98 99 int width = cropBounds.width(); 100 int height = cropBounds.height(); 101 102 if (mGeometry.hasSwitchedWidthHeight()){ 103 int temp = width; 104 width = height; 105 height = temp; 106 } 107 108 if(outputX <= 0 || outputY <= 0){ 109 outputX = width; 110 outputY = height; 111 } 112 113 float scaleX = 1; 114 float scaleY = 1; 115 if (s){ 116 scaleX = (float) outputX / width; 117 scaleY = (float) outputY / height; 118 } 119 120 Bitmap temp = null; 121 temp = Bitmap.createBitmap(outputX, outputY, mConfig); 122 123 float[] displayCenter = { 124 temp.getWidth() / 2f, temp.getHeight() / 2f 125 }; 126 127 Matrix m1 = mGeometry.buildTotalXform(bitmap.getWidth(), bitmap.getHeight(), displayCenter); 128 129 m1.postScale(scaleX, scaleY, displayCenter[0], displayCenter[1]); 130 131 Canvas canvas = new Canvas(temp); 132 Paint paint = new Paint(); 133 paint.setAntiAlias(true); 134 paint.setFilterBitmap(true); 135 paint.setDither(true); 136 canvas.drawBitmap(bitmap, m1, paint); 137 return temp; 138 } 139 140 } 141