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