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