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__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__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__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__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__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__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__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__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
130void 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
143void 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
154void 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
165void 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