BugFix:
[blender-staging.git] / source / blender / blenkernel / intern / image_gen.c
1 /*  image_gen.c 
2  * 
3  * $Id$
4  *
5  * ***** BEGIN GPL LICENSE BLOCK *****
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  * Contributor(s): Matt Ebb, Campbell Barton, Shuvro Sarker
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 #include <math.h>
27 #include <stdlib.h>
28 #include "BLI_math_color.h"
29 #include "BLF_api.h"
30
31 void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, int height, float color[4])
32 {
33         int x, y;
34
35         /* blank image */
36         if(rect_float) {
37                 for(y= 0; y<height; y++) {
38                         for(x= 0; x<width; x++) {
39                                 rect_float[0]= color[0];
40                                 rect_float[1]= color[1];
41                                 rect_float[2]= color[2];
42                                 rect_float[3]= color[3];
43                                 rect_float+= 4;
44                         }
45                 }
46         }
47         
48         if(rect) {
49                 char ccol[4];
50
51                 ccol[0]= (char)(color[0]*255.0f);
52                 ccol[1]= (char)(color[1]*255.0f);
53                 ccol[2]= (char)(color[2]*255.0f);
54                 ccol[3]= (char)(color[3]*255.0f);
55                 for(y= 0; y<height; y++) {
56                         for(x= 0; x<width; x++) {
57                                 
58                                 rect[0]= ccol[0];
59                                 rect[1]= ccol[1];
60                                 rect[2]= ccol[2];
61                                 rect[3]= ccol[3];
62                                 rect+= 4;
63                         }
64                 }
65         }
66 }
67
68
69 void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int width, int height)
70 {
71         /* these two passes could be combined into one, but it's more readable and 
72         * easy to tweak like this, speed isn't really that much of an issue in this situation... */
73  
74         int checkerwidth= 32, dark= 1;
75         int x, y;
76     
77         unsigned char *rect_orig= rect;
78         float *rect_float_orig= rect_float;
79     
80         
81         float h=0.0, hoffs=0.0, hue=0.0, s=0.9, v=0.9, r, g, b;
82
83         /* checkers */
84         for(y= 0; y<height; y++) {
85                 dark= powf(-1.0f, floorf(y / checkerwidth));
86                 
87                 for(x= 0; x<width; x++) {
88                         if (x % checkerwidth == 0) dark= -dark;
89                         
90                         if (rect_float) {
91                                 if (dark > 0) {
92                                         rect_float[0]= rect_float[1]= rect_float[2]= 0.25f;
93                                         rect_float[3]= 1.0f;
94                                 } else {
95                                         rect_float[0]= rect_float[1]= rect_float[2]= 0.58f;
96                                         rect_float[3]= 1.0f;
97                                 }
98                                 rect_float+= 4;
99                         }
100                         else {
101                                 if (dark > 0) {
102                                         rect[0]= rect[1]= rect[2]= 64;
103                                         rect[3]= 255;
104                                 } else {
105                                         rect[0]= rect[1]= rect[2]= 150;
106                                         rect[3]= 255;
107                                 }
108                                 rect+= 4;
109                         }
110                 }
111         }
112
113         rect= rect_orig;
114         rect_float= rect_float_orig;
115
116         /* 2nd pass, colored + */
117         for(y= 0; y<height; y++) {
118                 hoffs= 0.125f * floorf(y / checkerwidth);
119                 
120                 for(x= 0; x<width; x++) {
121                         h= 0.125f * floorf(x / checkerwidth);
122                         
123                         if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 4) &&
124                                 (fabs((y % checkerwidth) - (checkerwidth / 2)) < 4)) {
125                                 
126                                 if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 1) ||
127                                         (fabs((y % checkerwidth) - (checkerwidth / 2)) < 1)) {
128                                         
129                                         hue= fmodf(fabs(h-hoffs), 1.0f);
130                                         hsv_to_rgb(hue, s, v, &r, &g, &b);
131                                         
132                                         if (rect) {
133                                                 rect[0]= (char)(r * 255.0f);
134                                                 rect[1]= (char)(g * 255.0f);
135                                                 rect[2]= (char)(b * 255.0f);
136                                                 rect[3]= 255;
137                                         }
138                                         
139                                         if (rect_float) {
140                                                 rect_float[0]= r;
141                                                 rect_float[1]= g;
142                                                 rect_float[2]= b;
143                                                 rect_float[3]= 1.0f;
144                                         }
145                                 }
146                         }
147
148                         if (rect_float) rect_float+= 4;
149                         if (rect) rect+= 4;
150                 }
151         }
152 }
153
154
155 /* Utility functions for BKE_image_buf_fill_checker_color */
156
157 #define BLEND_FLOAT(real, add)  (real+add <= 1.0) ? (real+add) : 1.0
158 #define BLEND_CHAR(real, add) ((real + (char)(add * 255.0)) <= 255) ? (real + (char)(add * 255.0)) : 255
159
160 static int is_pow2(int n)
161 {
162         return ((n)&(n-1))==0;
163 }
164 static int larger_pow2(int n)
165 {
166         if (is_pow2(n))
167                 return n;
168
169         while(!is_pow2(n))
170                 n= n&(n-1);
171
172         return n*2;
173 }
174
175 static void checker_board_color_fill(unsigned char *rect, float *rect_float, int width, int height)
176 {
177         int hue_step, y, x;
178         float hue, val, sat, r, g, b;
179
180         sat= 1.0;
181
182         hue_step= larger_pow2(width / 8);
183         if(hue_step < 8) hue_step= 8;
184
185         for(y= 0; y < height; y++)
186         {
187         
188                 val= 0.1 + (y * (0.4 / height)); /* use a number lower then 1.0 else its too bright */
189                 for(x= 0; x < width; x++)
190                 {
191                         hue= (float)((double)(x/hue_step) * 1.0 / width * hue_step);
192                         hsv_to_rgb(hue, sat, val, &r, &g, &b);
193
194                         if (rect) {
195                                 rect[0]= (char)(r * 255.0f);
196                                 rect[1]= (char)(g * 255.0f);
197                                 rect[2]= (char)(b * 255.0f);
198                                 rect[3]= 255;
199                                 
200                                 rect += 4;
201                         }
202
203                         if (rect_float) {
204                                 rect_float[0]= r;
205                                 rect_float[1]= g;
206                                 rect_float[2]= b;
207                                 rect_float[3]= 1.0f;
208                                 
209                                 rect_float += 4;
210                         }
211                 }
212         }
213 }
214
215 static void checker_board_color_tint(unsigned char *rect, float *rect_float, int width, int height, int size, float blend)
216 {
217         int x, y;
218         float blend_half= blend * 0.5f;
219
220         for(y= 0; y < height; y++)
221         {
222                 for(x= 0; x < width; x++)
223                 {
224                         if( ( (y/size)%2 == 1 && (x/size)%2 == 1 ) || ( (y/size)%2 == 0 && (x/size)%2 == 0 ) )
225                         {
226                                 if (rect) {
227                                         rect[0]= (char)BLEND_CHAR(rect[0], blend);
228                                         rect[1]= (char)BLEND_CHAR(rect[1], blend);
229                                         rect[2]= (char)BLEND_CHAR(rect[2], blend);
230                                         rect[3]= 255;
231                                 
232                                         rect += 4;
233                                 }
234                                 if (rect_float) {
235                                         rect_float[0]= BLEND_FLOAT(rect_float[0], blend);
236                                         rect_float[1]= BLEND_FLOAT(rect_float[1], blend);
237                                         rect_float[2]= BLEND_FLOAT(rect_float[2], blend);
238                                         rect_float[3]= 1.0f;
239                                 
240                                         rect_float += 4;
241                                 }
242                         }
243                         else {
244                                 if (rect) {
245                                         rect[0]= (char)BLEND_CHAR(rect[0], blend_half);
246                                         rect[1]= (char)BLEND_CHAR(rect[1], blend_half);
247                                         rect[2]= (char)BLEND_CHAR(rect[2], blend_half);
248                                         rect[3]= 255;
249                                 
250                                         rect += 4;
251                                 }
252                                 if (rect_float) {
253                                         rect_float[0]= BLEND_FLOAT(rect_float[0], blend_half);
254                                         rect_float[1]= BLEND_FLOAT(rect_float[1], blend_half);
255                                         rect_float[2]= BLEND_FLOAT(rect_float[2], blend_half);
256                                         rect_float[3]= 1.0f;
257                                 
258                                         rect_float += 4;
259                                 }
260                         }
261                         
262                 }
263         }       
264 }
265
266 static void checker_board_grid_fill(unsigned char *rect, float *rect_float, int width, int height, float blend)
267 {
268         int x, y;
269         for(y= 0; y < height; y++)
270         {
271                 for(x= 0; x < width; x++)
272                 {
273                         if( ((y % 32) == 0) || ((x % 32) == 0)  || x == 0 )
274                         {
275                                 if (rect) {
276                                         rect[0]= BLEND_CHAR(rect[0], blend);
277                                         rect[1]= BLEND_CHAR(rect[1], blend);
278                                         rect[2]= BLEND_CHAR(rect[2], blend);
279                                         rect[3]= 255;
280
281                                         rect += 4;
282                                 }
283                                 if (rect_float) {
284                                         rect_float[0]= BLEND_FLOAT(rect_float[0], blend);
285                                         rect_float[1]= BLEND_FLOAT(rect_float[1], blend);
286                                         rect_float[2]= BLEND_FLOAT(rect_float[2], blend);
287                                         rect_float[3]= 1.0f;
288                                 
289                                         rect_float += 4;
290                                 }
291                         }
292                         else {
293                                 if(rect_float) rect_float += 4;
294                                 if(rect) rect += 4;
295                         }
296                 }
297         }
298 }
299
300 /* defined in image.c */
301 extern int stamp_font_begin(int size);
302
303 static void checker_board_text(unsigned char *rect, float *rect_float, int width, int height, int step, int outline)
304 {
305         int x, y, mono;
306         int pen_x, pen_y;
307         char text[3]= {'A', '1', '\0'};
308
309         /* hard coded size! */
310         mono= stamp_font_begin(54);
311         BLF_buffer(mono, rect_float, rect, width, height, 4);
312     
313         for(y= 0; y < height; y+=step)
314         {
315                 text[1]= '1';
316         
317                 for(x= 0; x < width; x+=step)
318                 {
319                         /* hard coded offset */
320                         pen_x = x + 33;
321                         pen_y = y + 44;
322             
323                         /* terribly crappy outline font! */
324                         BLF_buffer_col(mono, 1.0, 1.0, 1.0, 1.0);
325
326                         BLF_position(mono, pen_x-outline, pen_y, 0.0);
327                         BLF_draw_buffer(mono, text);
328                         BLF_position(mono, pen_x+outline, pen_y, 0.0);
329                         BLF_draw_buffer(mono, text);
330                         BLF_position(mono, pen_x, pen_y-outline, 0.0);
331                         BLF_draw_buffer(mono, text);
332                         BLF_position(mono, pen_x, pen_y+outline, 0.0);
333                         BLF_draw_buffer(mono, text);
334             
335                         BLF_position(mono, pen_x-outline, pen_y-outline, 0.0);
336                         BLF_draw_buffer(mono, text);
337                         BLF_position(mono, pen_x+outline, pen_y+outline, 0.0);
338                         BLF_draw_buffer(mono, text);
339                         BLF_position(mono, pen_x-outline, pen_y+outline, 0.0);
340                         BLF_draw_buffer(mono, text);
341                         BLF_position(mono, pen_x+outline, pen_y-outline, 0.0);
342                         BLF_draw_buffer(mono, text);
343
344                         BLF_buffer_col(mono, 0.0, 0.0, 0.0, 1.0);
345                         BLF_position(mono, pen_x, pen_y, 0.0);
346                         BLF_draw_buffer(mono, text);
347             
348                         text[1]++;
349                 }
350                 text[0]++;
351         }
352     
353         /* cleanup the buffer. */
354         BLF_buffer(mono, NULL, NULL, 0, 0, 0);
355 }
356
357 void BKE_image_buf_fill_checker_color(unsigned char *rect, float *rect_float, int width, int height)
358 {
359         checker_board_color_fill(rect, rect_float, width, height);
360         checker_board_color_tint(rect, rect_float, width, height, 1, 0.03f);
361         checker_board_color_tint(rect, rect_float, width, height, 4, 0.05f);
362         checker_board_color_tint(rect, rect_float, width, height, 32, 0.07f);
363         checker_board_color_tint(rect, rect_float, width, height, 128, 0.15f);
364         checker_board_grid_fill(rect, rect_float, width, height, 1.0f/4.0f);
365
366         checker_board_text(rect, rect_float, width, height, 128, 2);
367 }