Blender V2.61 - r43446

image_gen.c

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