eb256e3775b0c788b93420b01f09d18ff8af3005
[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 "BLI_math_color.h"
28 #include "BLF_api.h"
29
30 void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, int height, float color[4])
31 {
32         int x, y;
33
34         /* blank image */
35         if(rect_float) {
36                 for(y= 0; y<height; y++) {
37                         for(x= 0; x<width; x++) {
38                                 rect_float[0]= color[0];
39                                 rect_float[1]= color[1];
40                                 rect_float[2]= color[2];
41                                 rect_float[3]= color[3];
42                                 rect_float+= 4;
43                         }
44                 }
45         }
46         
47         if(rect) {
48                 char ccol[4];
49
50                 ccol[0]= (char)(color[0]*255.0f);
51                 ccol[1]= (char)(color[1]*255.0f);
52                 ccol[2]= (char)(color[2]*255.0f);
53                 ccol[3]= (char)(color[3]*255.0f);
54                 for(y= 0; y<height; y++) {
55                         for(x= 0; x<width; x++) {
56                                 
57                                 rect[0]= ccol[0];
58                                 rect[1]= ccol[1];
59                                 rect[2]= ccol[2];
60                                 rect[3]= ccol[3];
61                                 rect+= 4;
62                         }
63                 }
64         }
65 }
66
67
68 void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int width, int height)
69 {
70         /* these two passes could be combined into one, but it's more readable and 
71         * easy to tweak like this, speed isn't really that much of an issue in this situation... */
72  
73         int checkerwidth= 32, dark= 1;
74         int x, y;
75     
76         unsigned char *rect_orig= rect;
77         float *rect_float_orig= rect_float;
78     
79         
80         float h=0.0, hoffs=0.0, hue=0.0, s=0.9, v=0.9, r, g, b;
81
82         /* checkers */
83         for(y= 0; y<height; y++) {
84                 dark= powf(-1.0f, floorf(y / checkerwidth));
85                 
86                 for(x= 0; x<width; x++) {
87                         if (x % checkerwidth == 0) dark= -dark;
88                         
89                         if (rect_float) {
90                                 if (dark > 0) {
91                                         rect_float[0]= rect_float[1]= rect_float[2]= 0.25f;
92                                         rect_float[3]= 1.0f;
93                                 } else {
94                                         rect_float[0]= rect_float[1]= rect_float[2]= 0.58f;
95                                         rect_float[3]= 1.0f;
96                                 }
97                                 rect_float+= 4;
98                         }
99                         else {
100                                 if (dark > 0) {
101                                         rect[0]= rect[1]= rect[2]= 64;
102                                         rect[3]= 255;
103                                 } else {
104                                         rect[0]= rect[1]= rect[2]= 150;
105                                         rect[3]= 255;
106                                 }
107                                 rect+= 4;
108                         }
109                 }
110         }
111
112         rect= rect_orig;
113         rect_float= rect_float_orig;
114
115         /* 2nd pass, colored + */
116         for(y= 0; y<height; y++) {
117                 hoffs= 0.125f * floorf(y / checkerwidth);
118                 
119                 for(x= 0; x<width; x++) {
120                         h= 0.125f * floorf(x / checkerwidth);
121                         
122                         if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 4) &&
123                                 (fabs((y % checkerwidth) - (checkerwidth / 2)) < 4)) {
124                                 
125                                 if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 1) ||
126                                         (fabs((y % checkerwidth) - (checkerwidth / 2)) < 1)) {
127                                         
128                                         hue= fmodf(fabs(h-hoffs), 1.0f);
129                                         hsv_to_rgb(hue, s, v, &r, &g, &b);
130                                         
131                                         if (rect) {
132                                                 rect[0]= (char)(r * 255.0f);
133                                                 rect[1]= (char)(g * 255.0f);
134                                                 rect[2]= (char)(b * 255.0f);
135                                                 rect[3]= 255;
136                                         }
137                                         
138                                         if (rect_float) {
139                                                 rect_float[0]= r;
140                                                 rect_float[1]= g;
141                                                 rect_float[2]= b;
142                                                 rect_float[3]= 1.0f;
143                                         }
144                                 }
145                         }
146
147                         if (rect_float) rect_float+= 4;
148                         if (rect) rect+= 4;
149                 }
150         }
151 }
152
153
154 /* Utility functions for BKE_image_buf_fill_checker_color */
155
156 #define BLEND_FLOAT(real, add)  (real+add <= 1.0) ? (real+add) : 1.0
157 #define BLEND_CHAR(real, add) ((real + (char)(add * 255.0)) <= 255) ? (real + (char)(add * 255.0)) : 255
158
159 static int is_pow2(int n)
160 {
161         return ((n)&(n-1))==0;
162 }
163 static int larger_pow2(int n)
164 {
165         if (is_pow2(n))
166                 return n;
167
168         while(!is_pow2(n))
169                 n= n&(n-1);
170
171         return n*2;
172 }
173
174 static void checker_board_color_fill(unsigned char *rect, float *rect_float, int width, int height)
175 {
176         int hue_step, y, x;
177         float hue, val, sat, r, g, b;
178
179         sat= 1.0;
180
181         hue_step= larger_pow2(width / 8);
182         if(hue_step < 8) hue_step= 8;
183
184         for(y= 0; y < height; y++)
185         {
186         
187                 val= 0.1 + (y * (0.4 / height)); /* use a number lower then 1.0 else its too bright */
188                 for(x= 0; x < width; x++)
189                 {
190                         hue= (float)((double)(x/hue_step) * 1.0 / width * hue_step);
191                         hsv_to_rgb(hue, sat, val, &r, &g, &b);
192
193                         if (rect) {
194                                 rect[0]= (char)(r * 255.0f);
195                                 rect[1]= (char)(g * 255.0f);
196                                 rect[2]= (char)(b * 255.0f);
197                                 rect[3]= 255;
198                                 
199                                 rect += 4;
200                         }
201
202                         if (rect_float) {
203                                 rect_float[0]= r;
204                                 rect_float[1]= g;
205                                 rect_float[2]= b;
206                                 rect_float[3]= 1.0f;
207                                 
208                                 rect_float += 4;
209                         }
210                 }
211         }
212 }
213
214 static void checker_board_color_tint(unsigned char *rect, float *rect_float, int width, int height, int size, float blend)
215 {
216         int x, y;
217         float blend_half= blend * 0.5f;
218
219         for(y= 0; y < height; y++)
220         {
221                 for(x= 0; x < width; x++)
222                 {
223                         if( ( (y/size)%2 == 1 && (x/size)%2 == 1 ) || ( (y/size)%2 == 0 && (x/size)%2 == 0 ) )
224                         {
225                                 if (rect) {
226                                         rect[0]= (char)BLEND_CHAR(rect[0], blend);
227                                         rect[1]= (char)BLEND_CHAR(rect[1], blend);
228                                         rect[2]= (char)BLEND_CHAR(rect[2], blend);
229                                         rect[3]= 255;
230                                 
231                                         rect += 4;
232                                 }
233                                 if (rect_float) {
234                                         rect_float[0]= BLEND_FLOAT(rect_float[0], blend);
235                                         rect_float[1]= BLEND_FLOAT(rect_float[1], blend);
236                                         rect_float[2]= BLEND_FLOAT(rect_float[2], blend);
237                                         rect_float[3]= 1.0f;
238                                 
239                                         rect_float += 4;
240                                 }
241                         }
242                         else {
243                                 if (rect) {
244                                         rect[0]= (char)BLEND_CHAR(rect[0], blend_half);
245                                         rect[1]= (char)BLEND_CHAR(rect[1], blend_half);
246                                         rect[2]= (char)BLEND_CHAR(rect[2], blend_half);
247                                         rect[3]= 255;
248                                 
249                                         rect += 4;
250                                 }
251                                 if (rect_float) {
252                                         rect_float[0]= BLEND_FLOAT(rect_float[0], blend_half);
253                                         rect_float[1]= BLEND_FLOAT(rect_float[1], blend_half);
254                                         rect_float[2]= BLEND_FLOAT(rect_float[2], blend_half);
255                                         rect_float[3]= 1.0f;
256                                 
257                                         rect_float += 4;
258                                 }
259                         }
260                         
261                 }
262         }       
263 }
264
265 static void checker_board_grid_fill(unsigned char *rect, float *rect_float, int width, int height, float blend)
266 {
267         int x, y;
268         for(y= 0; y < height; y++)
269         {
270                 for(x= 0; x < width; x++)
271                 {
272                         if( ((y % 32) == 0) || ((x % 32) == 0)  || x == 0 )
273                         {
274                                 if (rect) {
275                                         rect[0]= BLEND_CHAR(rect[0], blend);
276                                         rect[1]= BLEND_CHAR(rect[1], blend);
277                                         rect[2]= BLEND_CHAR(rect[2], blend);
278                                         rect[3]= 255;
279
280                                         rect += 4;
281                                 }
282                                 if (rect_float) {
283                                         rect_float[0]= BLEND_FLOAT(rect_float[0], blend);
284                                         rect_float[1]= BLEND_FLOAT(rect_float[1], blend);
285                                         rect_float[2]= BLEND_FLOAT(rect_float[2], blend);
286                                         rect_float[3]= 1.0f;
287                                 
288                                         rect_float += 4;
289                                 }
290                         }
291                         else {
292                                 if(rect_float) rect_float += 4;
293                                 if(rect) rect += 4;
294                         }
295                 }
296         }
297 }
298
299 /* defined in image.c */
300 extern void stamp_font_begin(int size);
301
302 static void checker_board_text(unsigned char *rect, float *rect_float, int width, int height, int step, int outline)
303 {
304         int x, y;
305         int pen_x, pen_y;
306         char text[3]= {'A', '1', '\0'};
307
308         /* hard coded size! */
309         stamp_font_begin(54);
310         BLF_buffer(rect_float, rect, width, height, 4);
311     
312         for(y= 0; y < height; y+=step)
313         {
314                 text[1]= '1';
315         
316                 for(x= 0; x < width; x+=step)
317                 {
318                         /* hard coded offset */
319                         pen_x = x + 33;
320                         pen_y = y + 44;
321             
322                         /* terribly crappy outline font! */
323                         BLF_buffer_col(1.0, 1.0, 1.0, 1.0);
324
325                         BLF_position(pen_x-outline, pen_y, 0.0);
326                         BLF_draw_buffer(text);
327                         BLF_position(pen_x+outline, pen_y, 0.0);
328                         BLF_draw_buffer(text);
329                         BLF_position(pen_x, pen_y-outline, 0.0);
330                         BLF_draw_buffer(text);
331                         BLF_position(pen_x, pen_y+outline, 0.0);
332                         BLF_draw_buffer(text);
333             
334                         BLF_position(pen_x-outline, pen_y-outline, 0.0);
335                         BLF_draw_buffer(text);
336                         BLF_position(pen_x+outline, pen_y+outline, 0.0);
337                         BLF_draw_buffer(text);
338                         BLF_position(pen_x-outline, pen_y+outline, 0.0);
339                         BLF_draw_buffer(text);
340                         BLF_position(pen_x+outline, pen_y-outline, 0.0);
341                         BLF_draw_buffer(text);
342
343                         BLF_buffer_col(0.0, 0.0, 0.0, 1.0);
344                         BLF_position(pen_x, pen_y, 0.0);
345                         BLF_draw_buffer(text);
346             
347                         text[1]++;
348                 }
349                 text[0]++;
350         }
351     
352         /* cleanup the buffer. */
353         BLF_buffer(0, 0, 0, 0, 0);
354     
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 }