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
flipVertical(uint8_t * source,int srcWidth,int srcHeight,uint8_t * destination,int dstWidth __unused,int dstHeight __unused)22 static __inline__ void flipVertical(uint8_t * source, int srcWidth, int srcHeight, uint8_t * 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
flipHorizontal(uint8_t * source,int srcWidth,int srcHeight,uint8_t * destination,int dstWidth __unused,int dstHeight __unused)37 static __inline__ void flipHorizontal(uint8_t * source, int srcWidth, int srcHeight,
38 uint8_t * 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
flip_fun(int flip,uint8_t * source,int srcWidth,int srcHeight,uint8_t * destination,int dstWidth,int dstHeight)55 static __inline__ void flip_fun(int flip, uint8_t * source, int srcWidth, int srcHeight, uint8_t * 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 uint8_t* temp = (uint8_t *) 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?)
rotate90(uint8_t * source,int srcWidth,int srcHeight,uint8_t * destination,int dstWidth __unused,int dstHeight __unused)77 static __inline__ void rotate90(uint8_t * source, int srcWidth, int srcHeight, uint8_t * 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
rotate180(uint8_t * source,int srcWidth,int srcHeight,uint8_t * destination,int dstWidth,int dstHeight)91 static __inline__ void rotate180(uint8_t * source, int srcWidth, int srcHeight, uint8_t * destination, int dstWidth, int dstHeight){
92 flip_fun(3, source, srcWidth, srcHeight, destination, dstWidth, dstHeight);
93 }
94
rotate270(uint8_t * source,int srcWidth,int srcHeight,uint8_t * destination,int dstWidth,int dstHeight)95 static __inline__ void rotate270(uint8_t * source, int srcWidth, int srcHeight, uint8_t * 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).
rotate_fun(int rotate,uint8_t * source,int srcWidth,int srcHeight,uint8_t * destination,int dstWidth,int dstHeight)101 static __inline__ void rotate_fun(int rotate, uint8_t * source, int srcWidth, int srcHeight, uint8_t * 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
crop(uint8_t * source,int srcWidth,int srcHeight,uint8_t * destination,int dstWidth,int dstHeight,int offsetWidth,int offsetHeight)118 static __inline__ void crop(uint8_t * source, int srcWidth, int srcHeight, uint8_t * 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
JNIFUNCF(ImageFilterGeometry,nativeApplyFilterFlip,jobject src,jint srcWidth,jint srcHeight,jobject dst,jint dstWidth,jint dstHeight,jint flip)131 void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterFlip, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jint flip) {
132 uint8_t* destination = 0;
133 uint8_t* 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
JNIFUNCF(ImageFilterGeometry,nativeApplyFilterRotate,jobject src,jint srcWidth,jint srcHeight,jobject dst,jint dstWidth,jint dstHeight,jint rotate)144 void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterRotate, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jint rotate) {
145 uint8_t* destination = 0;
146 uint8_t* 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
JNIFUNCF(ImageFilterGeometry,nativeApplyFilterCrop,jobject src,jint srcWidth,jint srcHeight,jobject dst,jint dstWidth,jint dstHeight,jint offsetWidth,jint offsetHeight)154 void JNIFUNCF(ImageFilterGeometry, nativeApplyFilterCrop, jobject src, jint srcWidth, jint srcHeight, jobject dst, jint dstWidth, jint dstHeight, jint offsetWidth, jint offsetHeight) {
155 uint8_t* destination = 0;
156 uint8_t* 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
JNIFUNCF(ImageFilterGeometry,nativeApplyFilterStraighten,jobject src,jint srcWidth __unused,jint srcHeight __unused,jobject dst,jint dstWidth,jint dstHeight,jfloat straightenAngle __unused)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 uint8_t* destination = 0;
168 uint8_t* 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