Blender  V2.59
CMP_filter.c
Go to the documentation of this file.
00001 /*
00002  * $Id: CMP_filter.c 35237 2011-02-27 20:13:22Z jesterking $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version. 
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2006 Blender Foundation.
00021  * All rights reserved.
00022  *
00023  * The Original Code is: all of this file.
00024  *
00025  * Contributor(s): none yet.
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  */
00029 
00035 #include "../CMP_util.h"
00036 
00037 /* **************** FILTER  ******************** */
00038 static bNodeSocketType cmp_node_filter_in[]= {
00039         {       SOCK_VALUE, 1, "Fac",                   1.0f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
00040         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
00041         {       -1, 0, ""       }
00042 };
00043 static bNodeSocketType cmp_node_filter_out[]= {
00044         {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
00045         {       -1, 0, ""       }
00046 };
00047 
00048 static void do_filter_edge(CompBuf *out, CompBuf *in, float *filter, float fac)
00049 {
00050         float *row1, *row2, *row3;
00051         float *fp, f1, f2, mfac= 1.0f-fac;
00052         int rowlen, x, y, c, pix= in->type;
00053         
00054         rowlen= in->x;
00055         
00056         for(y=0; y<in->y; y++) {
00057                 /* setup rows */
00058                 if(y==0) row1= in->rect;
00059                 else row1= in->rect + pix*(y-1)*rowlen;
00060                 
00061                 row2= in->rect + y*pix*rowlen;
00062                 
00063                 if(y==in->y-1) row3= row2;
00064                 else row3= row2 + pix*rowlen;
00065                 
00066                 fp= out->rect + pix*y*rowlen;
00067                 
00068                 if(pix==CB_RGBA) {
00069                         QUATCOPY(fp, row2);
00070                         fp+= pix;
00071                         
00072                         for(x=2; x<rowlen; x++) {
00073                                 for(c=0; c<3; c++) {
00074                                         f1= filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8];
00075                                         f2= filter[0]*row1[0] + filter[3]*row1[4] + filter[6]*row1[8] + filter[1]*row2[0] + filter[4]*row2[4] + filter[7]*row2[8] + filter[2]*row3[0] + filter[5]*row3[4] + filter[8]*row3[8];
00076                                         fp[0]= mfac*row2[4] + fac*sqrt(f1*f1 + f2*f2);
00077                                         fp++; row1++; row2++; row3++;
00078                                 }
00079                                 fp[0]= row2[4];
00080                                 /* no alpha... will clear it completely */
00081                                 fp++; row1++; row2++; row3++;
00082                         }
00083                         QUATCOPY(fp, row2+4);
00084                 }
00085                 else if(pix==CB_VAL) {
00086                         fp+= pix;
00087                         for(x=2; x<rowlen; x++) {
00088                                 f1= filter[0]*row1[0] + filter[1]*row1[1] + filter[2]*row1[2] + filter[3]*row2[0] + filter[4]*row2[1] + filter[5]*row2[2] + filter[6]*row3[0] + filter[7]*row3[1] + filter[8]*row3[2];
00089                                 f2= filter[0]*row1[0] + filter[3]*row1[1] + filter[6]*row1[2] + filter[1]*row2[0] + filter[4]*row2[1] + filter[7]*row2[2] + filter[2]*row3[0] + filter[5]*row3[1] + filter[8]*row3[2];
00090                                 fp[0]= mfac*row2[1] + fac*sqrt(f1*f1 + f2*f2);
00091                                 fp++; row1++; row2++; row3++;
00092                         }
00093                 }
00094         }
00095 }
00096 
00097 static void do_filter3(CompBuf *out, CompBuf *in, float *filter, float fac)
00098 {
00099         float *row1, *row2, *row3;
00100         float *fp, mfac= 1.0f-fac;
00101         int rowlen, x, y, c;
00102         int pixlen= in->type;
00103         
00104         rowlen= in->x;
00105         
00106         for(y=0; y<in->y; y++) {
00107                 /* setup rows */
00108                 if(y==0) row1= in->rect;
00109                 else row1= in->rect + pixlen*(y-1)*rowlen;
00110                 
00111                 row2= in->rect + y*pixlen*rowlen;
00112                 
00113                 if(y==in->y-1) row3= row2;
00114                 else row3= row2 + pixlen*rowlen;
00115                 
00116                 fp= out->rect + pixlen*(y)*rowlen;
00117                 
00118                 if(pixlen==1) {
00119                         fp[0]= row2[0];
00120                         fp+= 1;
00121                         
00122                         for(x=2; x<rowlen; x++) {
00123                                 fp[0]= mfac*row2[1] + fac*(filter[0]*row1[0] + filter[1]*row1[1] + filter[2]*row1[2] + filter[3]*row2[0] + filter[4]*row2[1] + filter[5]*row2[2] + filter[6]*row3[0] + filter[7]*row3[1] + filter[8]*row3[2]);
00124                                 fp++; row1++; row2++; row3++;
00125                         }
00126                         fp[0]= row2[1];
00127                 }
00128                 else if(pixlen==2) {
00129                         fp[0]= row2[0];
00130                         fp[1]= row2[1];
00131                         fp+= 2;
00132                         
00133                         for(x=2; x<rowlen; x++) {
00134                                 for(c=0; c<2; c++) {
00135                                         fp[0]= mfac*row2[2] + fac*(filter[0]*row1[0] + filter[1]*row1[2] + filter[2]*row1[4] + filter[3]*row2[0] + filter[4]*row2[2] + filter[5]*row2[4] + filter[6]*row3[0] + filter[7]*row3[2] + filter[8]*row3[4]);
00136                                         fp++; row1++; row2++; row3++;
00137                                 }
00138                         }
00139                         fp[0]= row2[2];
00140                         fp[1]= row2[3];
00141                 }
00142                 else if(pixlen==3) {
00143                         VECCOPY(fp, row2);
00144                         fp+= 3;
00145                         
00146                         for(x=2; x<rowlen; x++) {
00147                                 for(c=0; c<3; c++) {
00148                                         fp[0]= mfac*row2[3] + fac*(filter[0]*row1[0] + filter[1]*row1[3] + filter[2]*row1[6] + filter[3]*row2[0] + filter[4]*row2[3] + filter[5]*row2[6] + filter[6]*row3[0] + filter[7]*row3[3] + filter[8]*row3[6]);
00149                                         fp++; row1++; row2++; row3++;
00150                                 }
00151                         }
00152                         VECCOPY(fp, row2+3);
00153                 }
00154                 else {
00155                         QUATCOPY(fp, row2);
00156                         fp+= 4;
00157                         
00158                         for(x=2; x<rowlen; x++) {
00159                                 for(c=0; c<4; c++) {
00160                                         fp[0]= mfac*row2[4] + fac*(filter[0]*row1[0] + filter[1]*row1[4] + filter[2]*row1[8] + filter[3]*row2[0] + filter[4]*row2[4] + filter[5]*row2[8] + filter[6]*row3[0] + filter[7]*row3[4] + filter[8]*row3[8]);
00161                                         fp++; row1++; row2++; row3++;
00162                                 }
00163                         }
00164                         QUATCOPY(fp, row2+4);
00165                 }
00166         }
00167 }
00168 
00169 
00170 static void node_composit_exec_filter(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
00171 {
00172         static float soft[9]= {1/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 4/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 1/16.0f};
00173         float sharp[9]= {-1,-1,-1,-1,9,-1,-1,-1,-1};
00174         float laplace[9]= {-1/8.0f, -1/8.0f, -1/8.0f, -1/8.0f, 1.0f, -1/8.0f, -1/8.0f, -1/8.0f, -1/8.0f};
00175         float sobel[9]= {1,2,1,0,0,0,-1,-2,-1};
00176         float prewitt[9]= {1,1,1,0,0,0,-1,-1,-1};
00177         float kirsch[9]= {5,5,5,-3,-3,-3,-2,-2,-2};
00178         float shadow[9]= {1,2,1,0,1,0,-1,-2,-1};
00179         
00180         if(out[0]->hasoutput==0) return;
00181         
00182         /* stack order in: Image */
00183         /* stack order out: Image */
00184         
00185         if(in[1]->data) {
00186                 /* make output size of first available input image */
00187                 CompBuf *cbuf= in[1]->data;
00188                 CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, cbuf->type, 1); /* allocs */
00189                 
00190                 /* warning note: xof and yof are applied in pixelprocessor, but should be copied otherwise? */
00191                 stackbuf->xof= cbuf->xof;
00192                 stackbuf->yof= cbuf->yof;
00193                 
00194                 switch(node->custom1) {
00195                         case CMP_FILT_SOFT:
00196                                 do_filter3(stackbuf, cbuf, soft, in[0]->vec[0]);
00197                                 break;
00198                         case CMP_FILT_SHARP:
00199                                 do_filter3(stackbuf, cbuf, sharp, in[0]->vec[0]);
00200                                 break;
00201                         case CMP_FILT_LAPLACE:
00202                                 do_filter3(stackbuf, cbuf, laplace, in[0]->vec[0]);
00203                                 break;
00204                         case CMP_FILT_SOBEL:
00205                                 do_filter_edge(stackbuf, cbuf, sobel, in[0]->vec[0]);
00206                                 break;
00207                         case CMP_FILT_PREWITT:
00208                                 do_filter_edge(stackbuf, cbuf, prewitt, in[0]->vec[0]);
00209                                 break;
00210                         case CMP_FILT_KIRSCH:
00211                                 do_filter_edge(stackbuf, cbuf, kirsch, in[0]->vec[0]);
00212                                 break;
00213                         case CMP_FILT_SHADOW:
00214                                 do_filter3(stackbuf, cbuf, shadow, in[0]->vec[0]);
00215                                 break;
00216                 }
00217                         
00218                 out[0]->data= stackbuf;
00219                 
00220                 generate_preview(data, node, out[0]->data);
00221         }
00222 }
00223 
00224 
00225 void register_node_type_cmp_filter(ListBase *lb)
00226 {
00227         static bNodeType ntype;
00228 
00229         node_type_base(&ntype, CMP_NODE_FILTER, "Filter", NODE_CLASS_OP_FILTER, NODE_PREVIEW|NODE_OPTIONS,
00230                 cmp_node_filter_in, cmp_node_filter_out);
00231         node_type_size(&ntype, 80, 40, 120);
00232         node_type_label(&ntype, node_filter_label);
00233         node_type_exec(&ntype, node_composit_exec_filter);
00234 
00235         nodeRegisterType(lb, &ntype);
00236 }
00237 
00238 
00239