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 #include <stdio.h> 18 #include <stdlib.h> 19 20 #include "filters.h" 21 22 static __inline__ void flipVertical(char * source, int srcWidth, int srcHeight, char * destination, 23 int dstWidth __unused, int dstHeight __unused) { 24 //Vertical 25 size_t cpy_bytes = sizeof(char) * 4; 26 int width = cpy_bytes * srcWidth; 27 int length = srcHeight; 28 int total = length * width; 29 size_t bytes_to_copy = sizeof(char) * width; 30 int i = 0; 31 int temp = total - width; 32 for (i = 0; i < total; i += width) { 33 memcpy(destination + temp - i, source + i, bytes_to_copy); 34 } 35 } 36 37 static __inline__ void flipHorizontal(char * source, int srcWidth, int srcHeight, 38 char * destination, int dstWidth __unused, int dstHeight __unused) { 39 //Horizontal 40 size_t cpy_bytes = sizeof(char) * 4; 41 int width = cpy_bytes * srcWidth; 42 int length = srcHeight; 43 int total = length * width; 44 int i = 0; 45 int j = 0; 46 int temp = 0; 47 for (i = 0; i < total; i+= width) { 48 temp = width + i - cpy_bytes; 49 for (j = 0; j < width; j+=cpy_bytes) { 50 memcpy(destination + temp - j, source + i + j, cpy_bytes); 51 } 52 } 53 } 54 55 static __inline__ void flip_fun(int flip, char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight){ 56 int horiz = (flip & 1) != 0; 57 int vert = (flip & 2) != 0; 58 if (horiz && vert){ 59 int arr_len = dstWidth * dstHeight * sizeof(char) * 4; 60 char* temp = (char *) malloc(arr_len); 61 flipHorizontal(source, srcWidth, srcHeight, temp, dstWidth, dstHeight); 62 flipVertical(temp, dstWidth, dstHeight, destination, dstWidth, dstHeight); 63 free(temp); 64 return; 65 } 66 if (horiz){ 67 flipHorizontal(source, srcWidth, srcHeight, destination, dstWidth, dstHeight); 68 return; 69 } 70 if (vert){ 71 flipVertical(source, srcWidth, srcHeight, destination, dstWidth, dstHeight); 72 return; 73 } 74 } 75 76 //90 CCW (opposite of what's used in UI?) 77 static __inline__ void rotate90(char * source, int srcWidth, int srcHeight, char * destination, 78 int dstWidth __unused, int dstHeight __unused) { 79 size_t cpy_bytes = sizeof(char) * 4; 80 int width = cpy_bytes * srcWidth; 81 int length = srcHeight; 82 for (size_t j = 0; j < length * cpy_bytes; j+= cpy_bytes){ 83 for (int i = 0; i < width; i+=cpy_bytes){ 84 int column_disp = (width - cpy_bytes - i) * length; 85 int row_disp = j; 86 memcpy(destination + column_disp + row_disp , source + j * srcWidth + i, cpy_bytes); 87 } 88 } 89 } 90 91 static __inline__ void rotate180(char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight){ 92 flip_fun(3, source, srcWidth, srcHeight, destination, dstWidth, dstHeight); 93 } 94 95 static __inline__ void rotate270(char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight){ 96 rotate90(source, srcWidth, srcHeight, destination, dstWidth, dstHeight); 97 flip_fun(3, destination, dstWidth, dstHeight, destination, dstWidth, dstHeight); 98 } 99 100 // rotate == 1 is 90 degrees, 2 is 180, 3 is 270 (positive is CCW). 101 static __inline__ void rotate_fun(int rotate, char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight){ 102 switch( rotate ) 103 { 104 case 1: 105 rotate90(source, srcWidth, srcHeight, destination, dstWidth, dstHeight); 106 break; 107 case 2: 108 rotate180(source, srcWidth, srcHeight, destination, dstWidth, dstHeight); 109 break; 110 case 3: 111 rotate270(source, srcWidth, srcHeight, destination, dstWidth, dstHeight); 112 break; 113 default: 114 break; 115 } 116 } 117 118 static __inline__ void crop(char * source, int srcWidth, int srcHeight, char * destination, int dstWidth, int dstHeight, int offsetWidth, int offsetHeight){ 119 size_t cpy_bytes = sizeof(char) * 4; 120 int row_width = cpy_bytes * srcWidth; 121 int new_row_width = cpy_bytes * dstWidth; 122 if ((srcWidth > dstWidth + offsetWidth) || (srcHeight > dstHeight + offsetHeight)){ 123 return; 124 } 125 int j = 0; 126 for (j = offsetHeight; j < offsetHeight + dstHeight; j++){ 127 memcpy(destination + (j - offsetHeight) * new_row_width, source + j * row_width + offsetWidth * cpy_bytes, cpy_bytes * dstWidth ); 128 } 129 } 130 131 void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterFlip, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jint flip) { 132 char* destination = 0; 133 char* source = 0; 134 if (srcWidth != dstWidth || srcHeight != dstHeight) { 135 return; 136 } 137 AndroidBitmap_lockPixels(env, src, (void**) &source); 138 AndroidBitmap_lockPixels(env, dst, (void**) &destination); 139 flip_fun(flip, source, srcWidth, srcHeight, destination, dstWidth, dstHeight); 140 AndroidBitmap_unlockPixels(env, dst); 141 AndroidBitmap_unlockPixels(env, src); 142 } 143 144 void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterRotate, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jint rotate) { 145 char* destination = 0; 146 char* source = 0; 147 AndroidBitmap_lockPixels(env, src, (void**) &source); 148 AndroidBitmap_lockPixels(env, dst, (void**) &destination); 149 rotate_fun(rotate, source, srcWidth, srcHeight, destination, dstWidth, dstHeight); 150 AndroidBitmap_unlockPixels(env, dst); 151 AndroidBitmap_unlockPixels(env, src); 152 } 153 154 void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterCrop, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jint offsetWidth, jint offsetHeight) { 155 char* destination = 0; 156 char* source = 0; 157 AndroidBitmap_lockPixels(env, src, (void**) &source); 158 AndroidBitmap_lockPixels(env, dst, (void**) &destination); 159 crop(source, srcWidth, srcHeight, destination, dstWidth, dstHeight, offsetWidth, offsetHeight); 160 AndroidBitmap_unlockPixels(env, dst); 161 AndroidBitmap_unlockPixels(env, src); 162 } 163 164 void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterStraighten, jobject src, jint srcWidth __unused, 165 jint srcHeight __unused, jobject dst, jint dstWidth, jint dstHeight, 166 jfloat straightenAngle __unused) { 167 char* destination = 0; 168 char* source = 0; 169 int len = dstWidth * dstHeight * 4; 170 AndroidBitmap_lockPixels(env, src, (void**) &source); 171 AndroidBitmap_lockPixels(env, dst, (void**) &destination); 172 // TODO: implement straighten 173 int i = 0; 174 for (; i < len; i += 4) { 175 destination[RED] = 128; 176 destination[GREEN] = source[GREEN]; 177 destination[BLUE] = 128; 178 } 179 AndroidBitmap_unlockPixels(env, dst); 180 AndroidBitmap_unlockPixels(env, src); 181 } 182 183