Blender  V2.59
image_gen.c
Go to the documentation of this file.
00001 /*  image_gen.c 
00002  * 
00003  * $Id: image_gen.c 36271 2011-04-21 13:11:51Z campbellbarton $
00004  *
00005  * ***** BEGIN GPL LICENSE BLOCK *****
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software Foundation,
00019  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  * Contributor(s): Matt Ebb, Campbell Barton, Shuvro Sarker
00022  *
00023  * ***** END GPL LICENSE BLOCK *****
00024  */
00025 
00031 #include <math.h>
00032 #include <stdlib.h>
00033 
00034 #include "BKE_image.h"
00035 #include "BLI_math_color.h"
00036 #include "BLF_api.h"
00037 
00038 void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, int height, float color[4])
00039 {
00040         int x, y;
00041 
00042         /* blank image */
00043         if(rect_float) {
00044                 for(y= 0; y<height; y++) {
00045                         for(x= 0; x<width; x++) {
00046                                 rect_float[0]= color[0];
00047                                 rect_float[1]= color[1];
00048                                 rect_float[2]= color[2];
00049                                 rect_float[3]= color[3];
00050                                 rect_float+= 4;
00051                         }
00052                 }
00053         }
00054         
00055         if(rect) {
00056                 char ccol[4];
00057 
00058                 ccol[0]= (char)(color[0]*255.0f);
00059                 ccol[1]= (char)(color[1]*255.0f);
00060                 ccol[2]= (char)(color[2]*255.0f);
00061                 ccol[3]= (char)(color[3]*255.0f);
00062                 for(y= 0; y<height; y++) {
00063                         for(x= 0; x<width; x++) {
00064                                 
00065                                 rect[0]= ccol[0];
00066                                 rect[1]= ccol[1];
00067                                 rect[2]= ccol[2];
00068                                 rect[3]= ccol[3];
00069                                 rect+= 4;
00070                         }
00071                 }
00072         }
00073 }
00074 
00075 
00076 void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int width, int height)
00077 {
00078         /* these two passes could be combined into one, but it's more readable and 
00079         * easy to tweak like this, speed isn't really that much of an issue in this situation... */
00080  
00081         int checkerwidth= 32, dark= 1;
00082         int x, y;
00083 
00084         unsigned char *rect_orig= rect;
00085         float *rect_float_orig= rect_float;
00086 
00087         
00088         float h=0.0, hoffs=0.0, hue=0.0, s=0.9, v=0.9, r, g, b;
00089 
00090         /* checkers */
00091         for(y= 0; y<height; y++) {
00092                 dark= powf(-1.0f, floorf(y / checkerwidth));
00093                 
00094                 for(x= 0; x<width; x++) {
00095                         if (x % checkerwidth == 0) dark= -dark;
00096                         
00097                         if (rect_float) {
00098                                 if (dark > 0) {
00099                                         rect_float[0]= rect_float[1]= rect_float[2]= 0.25f;
00100                                         rect_float[3]= 1.0f;
00101                                 } else {
00102                                         rect_float[0]= rect_float[1]= rect_float[2]= 0.58f;
00103                                         rect_float[3]= 1.0f;
00104                                 }
00105                                 rect_float+= 4;
00106                         }
00107                         else {
00108                                 if (dark > 0) {
00109                                         rect[0]= rect[1]= rect[2]= 64;
00110                                         rect[3]= 255;
00111                                 } else {
00112                                         rect[0]= rect[1]= rect[2]= 150;
00113                                         rect[3]= 255;
00114                                 }
00115                                 rect+= 4;
00116                         }
00117                 }
00118         }
00119 
00120         rect= rect_orig;
00121         rect_float= rect_float_orig;
00122 
00123         /* 2nd pass, colored + */
00124         for(y= 0; y<height; y++) {
00125                 hoffs= 0.125f * floorf(y / checkerwidth);
00126                 
00127                 for(x= 0; x<width; x++) {
00128                         h= 0.125f * floorf(x / checkerwidth);
00129                         
00130                         if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 4) &&
00131                                 (fabs((y % checkerwidth) - (checkerwidth / 2)) < 4)) {
00132                                 
00133                                 if ((fabs((x % checkerwidth) - (checkerwidth / 2)) < 1) ||
00134                                         (fabs((y % checkerwidth) - (checkerwidth / 2)) < 1)) {
00135                                         
00136                                         hue= fmodf(fabs(h-hoffs), 1.0f);
00137                                         hsv_to_rgb(hue, s, v, &r, &g, &b);
00138                                         
00139                                         if (rect) {
00140                                                 rect[0]= (char)(r * 255.0f);
00141                                                 rect[1]= (char)(g * 255.0f);
00142                                                 rect[2]= (char)(b * 255.0f);
00143                                                 rect[3]= 255;
00144                                         }
00145                                         
00146                                         if (rect_float) {
00147                                                 rect_float[0]= r;
00148                                                 rect_float[1]= g;
00149                                                 rect_float[2]= b;
00150                                                 rect_float[3]= 1.0f;
00151                                         }
00152                                 }
00153                         }
00154 
00155                         if (rect_float) rect_float+= 4;
00156                         if (rect) rect+= 4;
00157                 }
00158         }
00159 }
00160 
00161 
00162 /* Utility functions for BKE_image_buf_fill_checker_color */
00163 
00164 #define BLEND_FLOAT(real, add)  (real+add <= 1.0f) ? (real+add) : 1.0f
00165 #define BLEND_CHAR(real, add) ((real + (char)(add * 255.0f)) <= 255) ? (real + (char)(add * 255.0f)) : 255
00166 
00167 static int is_pow2(int n)
00168 {
00169         return ((n)&(n-1))==0;
00170 }
00171 static int larger_pow2(int n)
00172 {
00173         if (is_pow2(n))
00174                 return n;
00175 
00176         while(!is_pow2(n))
00177                 n= n&(n-1);
00178 
00179         return n*2;
00180 }
00181 
00182 static void checker_board_color_fill(unsigned char *rect, float *rect_float, int width, int height)
00183 {
00184         int hue_step, y, x;
00185         float hue, val, sat, r, g, b;
00186 
00187         sat= 1.0;
00188 
00189         hue_step= larger_pow2(width / 8);
00190         if(hue_step < 8) hue_step= 8;
00191 
00192         for(y= 0; y < height; y++)
00193         {
00194 
00195                 val= 0.1 + (y * (0.4 / height)); /* use a number lower then 1.0 else its too bright */
00196                 for(x= 0; x < width; x++)
00197                 {
00198                         hue= (float)((double)(x/hue_step) * 1.0 / width * hue_step);
00199                         hsv_to_rgb(hue, sat, val, &r, &g, &b);
00200 
00201                         if (rect) {
00202                                 rect[0]= (char)(r * 255.0f);
00203                                 rect[1]= (char)(g * 255.0f);
00204                                 rect[2]= (char)(b * 255.0f);
00205                                 rect[3]= 255;
00206                                 
00207                                 rect += 4;
00208                         }
00209 
00210                         if (rect_float) {
00211                                 rect_float[0]= r;
00212                                 rect_float[1]= g;
00213                                 rect_float[2]= b;
00214                                 rect_float[3]= 1.0f;
00215                                 
00216                                 rect_float += 4;
00217                         }
00218                 }
00219         }
00220 }
00221 
00222 static void checker_board_color_tint(unsigned char *rect, float *rect_float, int width, int height, int size, float blend)
00223 {
00224         int x, y;
00225         float blend_half= blend * 0.5f;
00226 
00227         for(y= 0; y < height; y++)
00228         {
00229                 for(x= 0; x < width; x++)
00230                 {
00231                         if( ( (y/size)%2 == 1 && (x/size)%2 == 1 ) || ( (y/size)%2 == 0 && (x/size)%2 == 0 ) )
00232                         {
00233                                 if (rect) {
00234                                         rect[0]= (char)BLEND_CHAR(rect[0], blend);
00235                                         rect[1]= (char)BLEND_CHAR(rect[1], blend);
00236                                         rect[2]= (char)BLEND_CHAR(rect[2], blend);
00237                                         rect[3]= 255;
00238                                 
00239                                         rect += 4;
00240                                 }
00241                                 if (rect_float) {
00242                                         rect_float[0]= BLEND_FLOAT(rect_float[0], blend);
00243                                         rect_float[1]= BLEND_FLOAT(rect_float[1], blend);
00244                                         rect_float[2]= BLEND_FLOAT(rect_float[2], blend);
00245                                         rect_float[3]= 1.0f;
00246                                 
00247                                         rect_float += 4;
00248                                 }
00249                         }
00250                         else {
00251                                 if (rect) {
00252                                         rect[0]= (char)BLEND_CHAR(rect[0], blend_half);
00253                                         rect[1]= (char)BLEND_CHAR(rect[1], blend_half);
00254                                         rect[2]= (char)BLEND_CHAR(rect[2], blend_half);
00255                                         rect[3]= 255;
00256                                 
00257                                         rect += 4;
00258                                 }
00259                                 if (rect_float) {
00260                                         rect_float[0]= BLEND_FLOAT(rect_float[0], blend_half);
00261                                         rect_float[1]= BLEND_FLOAT(rect_float[1], blend_half);
00262                                         rect_float[2]= BLEND_FLOAT(rect_float[2], blend_half);
00263                                         rect_float[3]= 1.0f;
00264                                 
00265                                         rect_float += 4;
00266                                 }
00267                         }
00268                         
00269                 }
00270         }       
00271 }
00272 
00273 static void checker_board_grid_fill(unsigned char *rect, float *rect_float, int width, int height, float blend)
00274 {
00275         int x, y;
00276         for(y= 0; y < height; y++)
00277         {
00278                 for(x= 0; x < width; x++)
00279                 {
00280                         if( ((y % 32) == 0) || ((x % 32) == 0)  || x == 0 )
00281                         {
00282                                 if (rect) {
00283                                         rect[0]= BLEND_CHAR(rect[0], blend);
00284                                         rect[1]= BLEND_CHAR(rect[1], blend);
00285                                         rect[2]= BLEND_CHAR(rect[2], blend);
00286                                         rect[3]= 255;
00287 
00288                                         rect += 4;
00289                                 }
00290                                 if (rect_float) {
00291                                         rect_float[0]= BLEND_FLOAT(rect_float[0], blend);
00292                                         rect_float[1]= BLEND_FLOAT(rect_float[1], blend);
00293                                         rect_float[2]= BLEND_FLOAT(rect_float[2], blend);
00294                                         rect_float[3]= 1.0f;
00295                                 
00296                                         rect_float += 4;
00297                                 }
00298                         }
00299                         else {
00300                                 if(rect_float) rect_float += 4;
00301                                 if(rect) rect += 4;
00302                         }
00303                 }
00304         }
00305 }
00306 
00307 /* defined in image.c */
00308 
00309 static void checker_board_text(unsigned char *rect, float *rect_float, int width, int height, int step, int outline)
00310 {
00311         int x, y;
00312         int pen_x, pen_y;
00313         char text[3]= {'A', '1', '\0'};
00314         const int mono= blf_mono_font;
00315 
00316         BLF_size(mono, 54, 72); /* hard coded size! */
00317 
00318         BLF_buffer(mono, rect_float, rect, width, height, 4);
00319 
00320         for(y= 0; y < height; y+=step)
00321         {
00322                 text[1]= '1';
00323 
00324                 for(x= 0; x < width; x+=step)
00325                 {
00326                         /* hard coded offset */
00327                         pen_x = x + 33;
00328                         pen_y = y + 44;
00329 
00330                         /* terribly crappy outline font! */
00331                         BLF_buffer_col(mono, 1.0, 1.0, 1.0, 1.0);
00332 
00333                         BLF_position(mono, pen_x-outline, pen_y, 0.0);
00334                         BLF_draw_buffer(mono, text);
00335                         BLF_position(mono, pen_x+outline, pen_y, 0.0);
00336                         BLF_draw_buffer(mono, text);
00337                         BLF_position(mono, pen_x, pen_y-outline, 0.0);
00338                         BLF_draw_buffer(mono, text);
00339                         BLF_position(mono, pen_x, pen_y+outline, 0.0);
00340                         BLF_draw_buffer(mono, text);
00341 
00342                         BLF_position(mono, pen_x-outline, pen_y-outline, 0.0);
00343                         BLF_draw_buffer(mono, text);
00344                         BLF_position(mono, pen_x+outline, pen_y+outline, 0.0);
00345                         BLF_draw_buffer(mono, text);
00346                         BLF_position(mono, pen_x-outline, pen_y+outline, 0.0);
00347                         BLF_draw_buffer(mono, text);
00348                         BLF_position(mono, pen_x+outline, pen_y-outline, 0.0);
00349                         BLF_draw_buffer(mono, text);
00350 
00351                         BLF_buffer_col(mono, 0.0, 0.0, 0.0, 1.0);
00352                         BLF_position(mono, pen_x, pen_y, 0.0);
00353                         BLF_draw_buffer(mono, text);
00354 
00355                         text[1]++;
00356                 }
00357                 text[0]++;
00358         }
00359 
00360         /* cleanup the buffer. */
00361         BLF_buffer(mono, NULL, NULL, 0, 0, 0);
00362 }
00363 
00364 void BKE_image_buf_fill_checker_color(unsigned char *rect, float *rect_float, int width, int height)
00365 {
00366         checker_board_color_fill(rect, rect_float, width, height);
00367         checker_board_color_tint(rect, rect_float, width, height, 1, 0.03f);
00368         checker_board_color_tint(rect, rect_float, width, height, 4, 0.05f);
00369         checker_board_color_tint(rect, rect_float, width, height, 32, 0.07f);
00370         checker_board_color_tint(rect, rect_float, width, height, 128, 0.15f);
00371         checker_board_grid_fill(rect, rect_float, width, height, 1.0f/4.0f);
00372 
00373         checker_board_text(rect, rect_float, width, height, 128, 2);
00374 }