1 /*-----------------------------------------------------------------------
2     This file is part of aaphoto.
3 
4     aaphoto is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 3 of the License, or
7     (at your option) any later version.
8 
9     aaphoto is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 ------------------------------------------------------------------------*/
17 
18 
RESIZE(unsigned char ** image_buffer,unsigned long * image_width,unsigned long * image_height,unsigned long new_width,unsigned long new_height,int alpha_flag)19 int RESIZE(
20     unsigned char **image_buffer,
21     unsigned long *image_width,
22     unsigned long *image_height,
23     unsigned long new_width,
24     unsigned long new_height,
25     int alpha_flag)
26 {
27 	unsigned int startx, endx;
28 	unsigned int starty, endy;
29 	unsigned int i, j, x, y;
30 
31 	unsigned char *bitmap_buffer2;
32 	/* if there is an Alpha channel beside the RGB too */
33 	/* then i need to allocate more memory for Alpha channel */
34 	/* not 3x but 5x more than the number of pixels in image */
35 	if (alpha_flag) { alpha_flag = 2; }
36 	/*allocate memory */
37 	/* print info */ STRING_PRINTV("allocating memory for uncompressed bitmap image\n");
38 	bitmap_buffer2 = malloc(new_width * new_height * (3 + alpha_flag) * sizeof (*bitmap_buffer2));
39 	if (bitmap_buffer2 == 0) return 1;
40 
41 	/* print info */ STRING_PRINTV("resizing image\n");
42 
43 	#ifdef __OPENMP__
44 	#pragma omp parallel for private(i, j, x, y, startx, starty, endx, endy) num_threads(max_threads)
45 	#endif
46 	for (j=0; j<new_height; j++){
47 
48 		for (i=0; i<new_width; i++){
49 
50 			long addr = 0;
51 			long rgb_avg_r = 0;
52 			long rgb_avg_g = 0;
53 			long rgb_avg_b = 0;
54 			long rgb_avg_a = 0;
55 			long rgb_counter = 0;
56 
57 			startx = *image_width  * i     / new_width;
58 			endx   = *image_width  * (i+1) / new_width;
59 			starty = *image_height * j     / new_height;
60 			endy   = *image_height * (j+1) / new_height;
61 
62 			for (y=starty; y<endy; y++){
63 				for (x=startx; x<endx; x++){
64 
65 					addr = (x + y * *image_width);
66 					rgb_avg_r += (*image_buffer)[3 * addr + 0];
67 					rgb_avg_g += (*image_buffer)[3 * addr + 1];
68 					rgb_avg_b += (*image_buffer)[3 * addr + 2];
69 					if (alpha_flag) {
70 						rgb_avg_a += (*image_buffer)[(*image_width) * (*image_height) * 3 + addr + 0];
71 					}
72 					rgb_counter++;
73 
74 				}
75 			}
76 			if (rgb_counter > 0){
77 				rgb_avg_r = rgb_avg_r / rgb_counter;
78 				rgb_avg_g = rgb_avg_g / rgb_counter;
79 				rgb_avg_b = rgb_avg_b / rgb_counter;
80 				if (alpha_flag) { rgb_avg_a = rgb_avg_a / rgb_counter; }
81 			}
82 
83 			addr = (i + j * new_width);
84 			bitmap_buffer2[3 * addr + 0] = rgb_avg_r;
85 			bitmap_buffer2[3 * addr + 1] = rgb_avg_g;
86 			bitmap_buffer2[3 * addr + 2] = rgb_avg_b;
87 			if (alpha_flag) {
88 				bitmap_buffer2[new_width * new_height * 3 + addr + 0] = rgb_avg_a;
89 			}
90 
91 		}
92 	}
93 
94 	/* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
95 	free(*image_buffer);
96 	*image_buffer = bitmap_buffer2;
97 	*image_width = new_width;
98 	*image_height = new_height;
99 
100 	return 0;
101 }
102 
103 
104 
ROTATE90(unsigned char ** image_buffer,unsigned long * image_width,unsigned long * image_height,int alpha_flag)105 int ROTATE90(
106     unsigned char **image_buffer,
107     unsigned long *image_width,
108     unsigned long *image_height,
109     int alpha_flag)
110 {
111 	unsigned char *bitmap_buffer2;
112 	unsigned int x, y;
113 
114 	unsigned long new_width;
115     	unsigned long new_height;
116 	new_width = *image_width;
117 	new_height = *image_height;
118 
119 	/*allocate memory */
120 	if (alpha_flag) { alpha_flag = 2; }
121 	/* print info */ STRING_PRINTV("allocating memory for uncompressed bitmap image\n");
122 	bitmap_buffer2 = malloc(new_width * new_height * (3 + alpha_flag) * sizeof (*bitmap_buffer2));
123 	if (bitmap_buffer2 == 0) return 1;
124 
125 	/* print info */ STRING_PRINTV("rotating image with 90\n");
126 
127 	#ifdef __OPENMP__
128 	#pragma omp parallel for private(x, y) num_threads(max_threads)
129 	#endif
130 	for (y=0; y<new_height; y++){
131 
132 		for (x=0; x<new_width; x++){
133 
134 			long addr = 0;
135 			long rgb_avg_r = 0;
136 			long rgb_avg_g = 0;
137 			long rgb_avg_b = 0;
138 			long rgb_avg_a = 0;
139 
140 			addr = (x + y * new_width);
141 			rgb_avg_r += (*image_buffer)[3 * addr + 0];
142 			rgb_avg_g += (*image_buffer)[3 * addr + 1];
143 			rgb_avg_b += (*image_buffer)[3 * addr + 2];
144 			if (alpha_flag){ rgb_avg_a += (*image_buffer)[(*image_width) * (*image_height) * 3 + addr + 0]; }
145 
146 			addr = ((new_height - 1 - y) + x * new_height);
147 			bitmap_buffer2[3 * addr + 0] = rgb_avg_r;
148 			bitmap_buffer2[3 * addr + 1] = rgb_avg_g;
149 			bitmap_buffer2[3 * addr + 2] = rgb_avg_b;
150 			if (alpha_flag){ bitmap_buffer2[new_width * new_height * 3 + addr + 2] = rgb_avg_a; }
151 		}
152 	}
153 
154 	/* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
155 	free(*image_buffer);
156 	*image_buffer = bitmap_buffer2;
157 	*image_width = new_height;
158 	*image_height = new_width;
159 
160 	return 0;
161 }
162 
163 
164 
ROTATE180(unsigned char ** image_buffer,unsigned long * image_width,unsigned long * image_height,int alpha_flag)165 int ROTATE180(
166     unsigned char **image_buffer,
167     unsigned long *image_width,
168     unsigned long *image_height,
169     int alpha_flag)
170 {
171 	int x, y, x_max, y_max, y_odd;
172 
173 	unsigned long new_width;
174 	unsigned long new_height;
175 	new_width = *image_width;
176 	new_height = *image_height;
177 
178 	/* print info */ STRING_PRINTV("rotating image with 180\n");
179 
180 	/* is the number of lines an odd number? */
181 	y_odd = new_height & 1;
182 	y_max = new_height/2 + y_odd;
183 
184 	#ifdef __OPENMP__
185 	#pragma omp parallel for private(x, y, x_max) num_threads(max_threads)
186 	#endif
187 	for (y=0; y<y_max; y++){
188 
189 		x_max = new_width;
190 		/* if the height is an odd number, then the flipping should go only to the middle of the width */
191 		/* in the middle line */
192 		if ((y_odd) && (y == y_max-1)){ x_max = new_width/2; }
193 
194 		for (x=0; x<x_max; x++){
195 
196 			long addr1 = 0;
197 			long addr2 = 0;
198 			long rgb_avg_r1 = 0;
199 			long rgb_avg_g1 = 0;
200 			long rgb_avg_b1 = 0;
201 			long rgb_avg_a1 = 0;
202 			long rgb_avg_r2 = 0;
203 			long rgb_avg_g2 = 0;
204 			long rgb_avg_b2 = 0;
205 			long rgb_avg_a2 = 0;
206 
207 			addr1 = (x + y * new_width);
208 			addr2 = ((new_width - 1 - x) + (new_height - 1 - y) * new_width);
209 
210 			rgb_avg_r1 += (*image_buffer)[3 * addr1 + 0];
211 			rgb_avg_g1 += (*image_buffer)[3 * addr1 + 1];
212 			rgb_avg_b1 += (*image_buffer)[3 * addr1 + 2];
213 			if (alpha_flag){ rgb_avg_a1 += (*image_buffer)[(*image_width) * (*image_height) * 3 + addr1 + 0]; }
214 			rgb_avg_r2 += (*image_buffer)[3 * addr2 + 0];
215 			rgb_avg_g2 += (*image_buffer)[3 * addr2 + 1];
216 			rgb_avg_b2 += (*image_buffer)[3 * addr2 + 2];
217 			if (alpha_flag){ rgb_avg_a2 += (*image_buffer)[(*image_width) * (*image_height) * 3 + addr2 + 0]; }
218 
219 			(*image_buffer)[3 * addr1 + 0] = rgb_avg_r2;
220 			(*image_buffer)[3 * addr1 + 1] = rgb_avg_g2;
221 			(*image_buffer)[3 * addr1 + 2] = rgb_avg_b2;
222 			if (alpha_flag){ (*image_buffer)[(*image_width) * (*image_height) * 3 + addr1 + 0] = rgb_avg_a2; }
223 			(*image_buffer)[3 * addr2 + 0] = rgb_avg_r1;
224 			(*image_buffer)[3 * addr2 + 1] = rgb_avg_g1;
225 			(*image_buffer)[3 * addr2 + 2] = rgb_avg_b1;
226 			if (alpha_flag){ (*image_buffer)[(*image_width) * (*image_height) * 3 + addr2 + 0] = rgb_avg_a1; }
227 		}
228 	}
229 
230 	return 0;
231 }
232 
233 
234 
ROTATE270(unsigned char ** image_buffer,unsigned long * image_width,unsigned long * image_height,int alpha_flag)235 int ROTATE270(
236     unsigned char **image_buffer,
237     unsigned long *image_width,
238     unsigned long *image_height,
239     int alpha_flag)
240 {
241 	unsigned char *bitmap_buffer2;
242 	unsigned int x, y;
243 
244 	unsigned long new_width;
245     	unsigned long new_height;
246 	new_width = *image_width;
247 	new_height = *image_height;
248 
249 	/*allocate memory */
250 	if (alpha_flag) { alpha_flag = 2; }
251 	/* print info */ STRING_PRINTV("allocating memory for uncompressed bitmap image\n");
252 	bitmap_buffer2 = malloc(new_width * new_height * (3 + alpha_flag) * sizeof (*bitmap_buffer2));
253 	if (bitmap_buffer2 == 0) return 1;
254 
255 	/* print info */ STRING_PRINTV("rotating image with 270\n");
256 
257 	#ifdef __OPENMP__
258 	#pragma omp parallel for private(x, y) num_threads(max_threads)
259 	#endif
260 	for (y=0; y<new_height; y++){
261 
262 		for (x=0; x<new_width; x++){
263 
264 			long addr = 0;
265 			long rgb_avg_r = 0;
266 			long rgb_avg_g = 0;
267 			long rgb_avg_b = 0;
268 			long rgb_avg_a = 0;
269 
270 			addr = (x + y * new_width);
271 			rgb_avg_r += (*image_buffer)[3 * addr + 0];
272 			rgb_avg_g += (*image_buffer)[3 * addr + 1];
273 			rgb_avg_b += (*image_buffer)[3 * addr + 2];
274 			if (alpha_flag){ rgb_avg_a += (*image_buffer)[(*image_width) * (*image_height) * 3 + addr + 0]; }
275 
276 			addr = (y + (new_width - 1 - x) * new_height);
277 			bitmap_buffer2[3 * addr + 0] = rgb_avg_r;
278 			bitmap_buffer2[3 * addr + 1] = rgb_avg_g;
279 			bitmap_buffer2[3 * addr + 2] = rgb_avg_b;
280 			if (alpha_flag){ bitmap_buffer2[(*image_width) * (*image_height) * 3 + addr + 0] = rgb_avg_a; }
281 		}
282 	}
283 
284 	/* print info */ STRING_PRINTV("freeing uncompressed bitmap buffer\n");
285 	free(*image_buffer);
286 	*image_buffer = bitmap_buffer2;
287 	*image_width = new_height;
288 	*image_height = new_width;
289 
290 	return 0;
291 }
292 
293 
294 
FLIPX(unsigned char ** image_buffer,unsigned long * image_width,unsigned long * image_height,int alpha_flag)295 int FLIPX(
296     unsigned char **image_buffer,
297     unsigned long *image_width,
298     unsigned long *image_height,
299     int alpha_flag)
300 {
301 	unsigned int x, y;
302 
303 	unsigned long new_width;
304     	unsigned long new_height;
305 	new_width = *image_width;
306 	new_height = *image_height;
307 
308 	/* print info */ STRING_PRINTV("flipping image horizontally\n");
309 
310 	#ifdef __OPENMP__
311 	#pragma omp parallel for private(x, y) num_threads(max_threads)
312 	#endif
313 	for (y=0; y<new_height; y++){
314 
315 		for (x=0; x<(new_width/2); x++){
316 
317 			long addr1 = 0;
318 			long addr2 = 0;
319 			long rgb_avg_r1 = 0;
320 			long rgb_avg_g1 = 0;
321 			long rgb_avg_b1 = 0;
322 			long rgb_avg_a1 = 0;
323 			long rgb_avg_r2 = 0;
324 			long rgb_avg_g2 = 0;
325 			long rgb_avg_b2 = 0;
326 			long rgb_avg_a2 = 0;
327 
328 			addr1 = (x + y * new_width);
329 			addr2 = ((new_width - 1 - x) + y * new_width);
330 
331 			rgb_avg_r1 += (*image_buffer)[3 * addr1 + 0];
332 			rgb_avg_g1 += (*image_buffer)[3 * addr1 + 1];
333 			rgb_avg_b1 += (*image_buffer)[3 * addr1 + 2];
334                         if (alpha_flag){ rgb_avg_a1 += (*image_buffer)[(*image_width) * (*image_height) * 3 + addr1 + 0]; }
335 			rgb_avg_r2 += (*image_buffer)[3 * addr2 + 0];
336 			rgb_avg_g2 += (*image_buffer)[3 * addr2 + 1];
337 			rgb_avg_b2 += (*image_buffer)[3 * addr2 + 2];
338                         if (alpha_flag){ rgb_avg_a2 += (*image_buffer)[(*image_width) * (*image_height) * 3 + addr2 + 0]; }
339 
340 			(*image_buffer)[3 * addr1 + 0] = rgb_avg_r2;
341 			(*image_buffer)[3 * addr1 + 1] = rgb_avg_g2;
342 			(*image_buffer)[3 * addr1 + 2] = rgb_avg_b2;
343 			if (alpha_flag){ (*image_buffer)[(*image_width) * (*image_height) * 3 + addr1 + 0] = rgb_avg_a2; }
344 			(*image_buffer)[3 * addr2 + 0] = rgb_avg_r1;
345 			(*image_buffer)[3 * addr2 + 1] = rgb_avg_g1;
346 			(*image_buffer)[3 * addr2 + 2] = rgb_avg_b1;
347                         if (alpha_flag){ (*image_buffer)[(*image_width) * (*image_height) * 3 + addr2 + 0] = rgb_avg_a1; }
348 		}
349 	}
350 
351 	return 0;
352 }
353 
354 
355 
FLIPY(unsigned char ** image_buffer,unsigned long * image_width,unsigned long * image_height,int alpha_flag)356 int FLIPY(
357     unsigned char **image_buffer,
358     unsigned long *image_width,
359     unsigned long *image_height,
360     int alpha_flag)
361 {
362 	unsigned int x, y;
363 
364 	unsigned long new_width;
365     	unsigned long new_height;
366 	new_width = *image_width;
367 	new_height = *image_height;
368 
369 	/* print info */ STRING_PRINTV("flipping image vertically\n");
370 
371 	#ifdef __OPENMP__
372 	#pragma omp parallel for private(x, y) num_threads(max_threads)
373 	#endif
374 	for (y=0; y<(new_height/2); y++){
375 
376 		for (x=0; x<new_width; x++){
377 
378 			long addr1 = 0;
379 			long addr2 = 0;
380 			long rgb_avg_r1 = 0;
381 			long rgb_avg_g1 = 0;
382 			long rgb_avg_b1 = 0;
383 			long rgb_avg_a1 = 0;
384 			long rgb_avg_r2 = 0;
385 			long rgb_avg_g2 = 0;
386 			long rgb_avg_b2 = 0;
387 			long rgb_avg_a2 = 0;
388 
389 			addr1 = (x + y * new_width);
390 			addr2 = (x + (new_height - 1 - y) * new_width);
391 
392 			rgb_avg_r1 += (*image_buffer)[3 * addr1 + 0];
393 			rgb_avg_g1 += (*image_buffer)[3 * addr1 + 1];
394 			rgb_avg_b1 += (*image_buffer)[3 * addr1 + 2];
395                         if (alpha_flag){ rgb_avg_a1 += (*image_buffer)[(*image_width) * (*image_height) * 3 + addr1 + 0]; }
396 			rgb_avg_r2 += (*image_buffer)[3 * addr2 + 0];
397 			rgb_avg_g2 += (*image_buffer)[3 * addr2 + 1];
398 			rgb_avg_b2 += (*image_buffer)[3 * addr2 + 2];
399                         if (alpha_flag){ rgb_avg_a2 += (*image_buffer)[(*image_width) * (*image_height) * 3 + addr2 + 0]; }
400 
401 			(*image_buffer)[3 * addr1 + 0] = rgb_avg_r2;
402 			(*image_buffer)[3 * addr1 + 1] = rgb_avg_g2;
403 			(*image_buffer)[3 * addr1 + 2] = rgb_avg_b2;
404 			if (alpha_flag){ (*image_buffer)[(*image_width) * (*image_height) * 3 + addr1 + 0] = rgb_avg_a2; }
405 			(*image_buffer)[3 * addr2 + 0] = rgb_avg_r1;
406 			(*image_buffer)[3 * addr2 + 1] = rgb_avg_g1;
407 			(*image_buffer)[3 * addr2 + 2] = rgb_avg_b1;
408                         if (alpha_flag){ (*image_buffer)[(*image_width) * (*image_height) * 3 + addr2 + 0] = rgb_avg_a1; }
409 		}
410 	}
411 
412 	return 0;
413 }
414 
415