From a66df0c9e8106ef6a275e20ab2a47286e054fe7c Mon Sep 17 00:00:00 2001 From: Ruben Brunk Date: Mon, 8 Oct 2012 16:05:48 -0700 Subject: [PATCH] Added the rest of the Geometryfilter stubs. Bug: 7224232 Bug: 7218935 Change-Id: I9ebbc4a98b5696e1514995e465aa4e145fdfa4f8 --- jni/filters/geometry.c | 68 ++++++++++- .../filtershow/filters/ImageFilterGeometry.java | 126 +++++++++++++++++++-- .../filtershow/imageshow/GeometryMetadata.java | 10 +- .../filtershow/imageshow/ImageGeometry.java | 18 +-- .../gallery3d/filtershow/imageshow/ImageShow.java | 5 +- 5 files changed, 206 insertions(+), 21 deletions(-) diff --git a/jni/filters/geometry.c b/jni/filters/geometry.c index f2f5b27bc..8550dd778 100644 --- a/jni/filters/geometry.c +++ b/jni/filters/geometry.c @@ -19,14 +19,18 @@ void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterFlip, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jint flip) { char* destination = 0; char* source = 0; + int len = dstWidth * dstHeight * 4; + if (srcWidth != dstWidth || srcHeight != dstHeight) { + return; + } AndroidBitmap_lockPixels(env, src, (void**) &source); AndroidBitmap_lockPixels(env, dst, (void**) &destination); int i = 0; - for (; i < dstWidth * dstHeight * 4; i+=4) { + for (; i < len; i += 4) { int r = source[RED]; int g = source[GREEN]; int b = source[BLUE]; - + // TODO: implement flip destination[RED] = 255; destination[GREEN] = g; destination[BLUE] = b; @@ -34,3 +38,63 @@ void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterFlip, jobject src, jint srcW AndroidBitmap_unlockPixels(env, dst); AndroidBitmap_unlockPixels(env, src); } + +void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterRotate, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jfloat rotate) { + char* destination = 0; + char* source = 0; + int len = dstWidth * dstHeight * 4; + AndroidBitmap_lockPixels(env, src, (void**) &source); + AndroidBitmap_lockPixels(env, dst, (void**) &destination); + // TODO: implement rotate + int i = 0; + for (; i < len; i += 4) { + int r = source[RED]; + int g = source[GREEN]; + int b = source[BLUE]; + destination[RED] = r; + destination[GREEN] = 255; + destination[BLUE] = b; + } + AndroidBitmap_unlockPixels(env, dst); + AndroidBitmap_unlockPixels(env, src); +} + +void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterCrop, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jint offsetWidth, jint offsetHeight) { + char* destination = 0; + char* source = 0; + int len = dstWidth * dstHeight * 4; + AndroidBitmap_lockPixels(env, src, (void**) &source); + AndroidBitmap_lockPixels(env, dst, (void**) &destination); + // TODO: implement crop + int i = 0; + for (; i < len; i += 4) { + int r = source[RED]; + int g = source[GREEN]; + int b = source[BLUE]; + destination[RED] = r; + destination[GREEN] = g; + destination[BLUE] = 255; + } + AndroidBitmap_unlockPixels(env, dst); + AndroidBitmap_unlockPixels(env, src); +} + +void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterStraighten, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jfloat straightenAngle) { + char* destination = 0; + char* source = 0; + int len = dstWidth * dstHeight * 4; + AndroidBitmap_lockPixels(env, src, (void**) &source); + AndroidBitmap_lockPixels(env, dst, (void**) &destination); + // TODO: implement straighten + int i = 0; + for (; i < len; i += 4) { + int r = source[RED]; + int g = source[GREEN]; + int b = source[BLUE]; + destination[RED] = 128; + destination[GREEN] = g; + destination[BLUE] = 128; + } + AndroidBitmap_unlockPixels(env, dst); + AndroidBitmap_unlockPixels(env, src); +} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java index 69a8f20d8..1368255a6 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2012 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 com.android.gallery3d.filtershow.filters; @@ -5,13 +20,21 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; +import android.graphics.RectF; +import android.util.Log; import com.android.gallery3d.filtershow.imageshow.GeometryMetadata; import com.android.gallery3d.filtershow.imageshow.GeometryMetadata.FLIP; +import com.android.gallery3d.filtershow.imageshow.ImageGeometry; public class ImageFilterGeometry extends ImageFilter { private final Bitmap.Config mConfig = Bitmap.Config.ARGB_8888; private GeometryMetadata mGeometry = null; + private static final String LOGTAG = "ImageFilterGeometry"; + private static final boolean LOGV = false; + private static final int BOTH = 3; + private static final int VERTICAL = 2; + private static final int HORIZONTAL = 1; public ImageFilterGeometry() { mName = "Geometry"; @@ -23,22 +46,109 @@ public class ImageFilterGeometry extends ImageFilter { return filter; } - public void setGeometryMetadata(GeometryMetadata m){ + public void setGeometryMetadata(GeometryMetadata m) { mGeometry = m; } native protected void nativeApplyFilterFlip(Bitmap src, int srcWidth, int srcHeight, Bitmap dst, int dstWidth, int dstHeight, int flip); + native protected void nativeApplyFilterRotate(Bitmap src, int srcWidth, int srcHeight, + Bitmap dst, int dstWidth, int dstHeight, float rotate); + + native protected void nativeApplyFilterCrop(Bitmap src, int srcWidth, int srcHeight, + Bitmap dst, int dstWidth, int dstHeight, int offsetWidth, int offsetHeight); + + native protected void nativeApplyFilterStraighten(Bitmap src, int srcWidth, int srcHeight, + Bitmap dst, int dstWidth, int dstHeight, float straightenAngle); + @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) { - if(mGeometry.getFlipType() == FLIP.NONE){ - return bitmap; + public Bitmap apply(Bitmap originalBitmap, float scaleFactor, boolean highQuality) { + Rect cropBounds = new Rect(); + Rect originalBounds = new Rect(); + FLIP flipType = mGeometry.getFlipType(); + float rAngle = mGeometry.getRotation(); + float sAngle = mGeometry.getStraightenRotation(); + mGeometry.getCropBounds().roundOut(cropBounds); + mGeometry.getPhotoBounds().roundOut(originalBounds); + boolean flip = flipType != FLIP.NONE; + boolean rotate = rAngle != 0; + boolean crop = !cropBounds.equals(originalBounds); + boolean straighten = sAngle != 0; + + int jniFlipType = 0; + switch (flipType) { + case BOTH: + jniFlipType = BOTH; + break; + case VERTICAL: + jniFlipType = VERTICAL; + break; + case HORIZONTAL: + jniFlipType = HORIZONTAL; + break; + default: + jniFlipType = 0; + break; + } + int bmWidth = originalBitmap.getWidth(); + int bmHeight = originalBitmap.getHeight(); + if (!(flip || rotate || crop || straighten)) { + return originalBitmap; + } + if (originalBounds.width() != bmWidth || originalBounds.height() != bmHeight) { + if (LOGV) + Log.v(LOGTAG, "PHOTOBOUNDS WIDTH/HEIGHT NOT SAME AS BITMAP WIDTH/HEIGHT"); + return originalBitmap; + } + Bitmap modBitmap = originalBitmap; + Rect modifiedBounds = new Rect(originalBounds); + if (flip) { + modBitmap = originalBitmap.copy(mConfig, true); + nativeApplyFilterFlip(originalBitmap, bmWidth, bmHeight, modBitmap, + bmWidth, bmHeight, jniFlipType); + } + if (rotate) { + // Fails for non-90 degree rotations + Bitmap modBitmapRotate = null; + if (((int) (sAngle / 90)) % 2 == 0) { + modBitmapRotate = Bitmap.createBitmap(bmWidth, bmHeight, mConfig); + nativeApplyFilterRotate(modBitmap, bmWidth, bmHeight, modBitmapRotate, + bmWidth, bmHeight, mGeometry.getRotation()); + modifiedBounds = new Rect(0, 0, bmWidth, bmHeight); + } else { + modBitmapRotate = Bitmap.createBitmap(bmHeight, bmWidth, mConfig); + nativeApplyFilterRotate(modBitmap, bmWidth, bmHeight, modBitmapRotate, + bmHeight, bmWidth, mGeometry.getRotation()); + modifiedBounds = new Rect(0, 0, bmHeight, bmWidth); + } + modBitmap = modBitmapRotate; + } + if (straighten) { + Rect straightenBounds = new Rect(); + ImageGeometry.getUntranslatedStraightenCropBounds(new RectF(modifiedBounds), sAngle) + .roundOut(straightenBounds); + Bitmap modBitmapStraighten = Bitmap.createBitmap(straightenBounds.width(), + straightenBounds.height(), mConfig); + nativeApplyFilterStraighten(modBitmap, modifiedBounds.width(), modifiedBounds.height(), + modBitmapStraighten, + straightenBounds.width(), straightenBounds.height(), + mGeometry.getStraightenRotation()); + modifiedBounds = straightenBounds; + modBitmap = modBitmapStraighten; + } + if (crop) { + Bitmap modBitmapCrop = Bitmap.createBitmap(cropBounds.width(), cropBounds.height(), + mConfig); + // Force crop bounds to be within straighten bounds. + if (!modifiedBounds.intersect(cropBounds)) { + return modBitmap; + } + nativeApplyFilterCrop(modBitmap, bmWidth, bmHeight, modBitmapCrop, + cropBounds.width(), cropBounds.height(), cropBounds.left, cropBounds.top); + modBitmap = modBitmapCrop; } - Bitmap flipBitmap = bitmap.copy(mConfig, true); - nativeApplyFilterFlip(bitmap, bitmap.getWidth(), bitmap.getHeight(), flipBitmap, - flipBitmap.getWidth(), flipBitmap.getHeight(), 1); - return flipBitmap; + return modBitmap; } } diff --git a/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java b/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java index f3d64a518..4f172285d 100644 --- a/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java +++ b/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java @@ -53,7 +53,15 @@ public class GeometryMetadata { public Bitmap apply(Bitmap original, float scaleFactor, boolean highQuality){ mImageFilter.setGeometryMetadata(this); - return mImageFilter.apply(original, scaleFactor, highQuality); + Bitmap m = mImageFilter.apply(original, scaleFactor, highQuality); + mPhotoBounds.set(0,0, m.getWidth(), m.getHeight()); + mCropBounds.set(mPhotoBounds); + mScaleFactor = 0; + mRotation = 0; + mStraightenRotation = 0; + mFlip = FLIP.NONE; + mSafe = false; + return m; } public GeometryMetadata(float scale, float rotation, float straighten, RectF cropBounds, diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageGeometry.java b/src/com/android/gallery3d/filtershow/imageshow/ImageGeometry.java index c6709e81f..606e4770c 100644 --- a/src/com/android/gallery3d/filtershow/imageshow/ImageGeometry.java +++ b/src/com/android/gallery3d/filtershow/imageshow/ImageGeometry.java @@ -499,6 +499,16 @@ public abstract class ImageGeometry extends ImageSlave { } protected RectF getStraightenCropBounds(RectF imageRect, float straightenAngle) { + RectF boundsRect = getUntranslatedStraightenCropBounds(imageRect, straightenAngle); + RectF nonRotateImage = getLocalPhotoBounds(); + Matrix m1 = new Matrix(); + m1.setTranslate(nonRotateImage.centerX() - boundsRect.centerX(), nonRotateImage.centerY() + - boundsRect.centerY()); + m1.mapRect(boundsRect); + return boundsRect; + } + + public static RectF getUntranslatedStraightenCropBounds(RectF imageRect, float straightenAngle) { float deg = straightenAngle; if (deg < 0) { deg = -deg; @@ -519,13 +529,7 @@ public abstract class ImageGeometry extends ImageSlave { float right = (float) (left + ww); float bottom = (float) (top + hh); - RectF boundsRect = new RectF(left, top, right, bottom); - RectF nonRotateImage = getLocalPhotoBounds(); - Matrix m1 = new Matrix(); - m1.setTranslate(nonRotateImage.centerX() - boundsRect.centerX(), nonRotateImage.centerY() - - boundsRect.centerY()); - m1.mapRect(boundsRect); - return boundsRect; + return new RectF(left, top, right, bottom); } protected void drawShadows(Canvas canvas, RectF innerBounds, RectF outerBounds, Paint p) { diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java index 2c20706a7..185ac2a3a 100644 --- a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java +++ b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java @@ -414,9 +414,8 @@ public class ImageShow extends View implements SliderListener, OnSeekBarChangeLi float w = image.getWidth(); float h = image.getHeight(); RectF r = new RectF(0, 0, w, h); - RectF c = new RectF(w / 4f, h / 4f, w * 3 / 4f, h * 3 / 4f); - getImagePreset().mGeoData.setPhotoBounds(r); - getImagePreset().mGeoData.setCropBounds(c); + mImagePreset.mGeoData.setPhotoBounds(r); + mImagePreset.mGeoData.setCropBounds(r); setDirtyGeometryFlag(); } -- 2.11.0