Blender V2.61 - r43446
|
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 * The Original Code is Copyright (C) 2006 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * The Original Code is: all of this file. 00022 * 00023 * Contributor(s): Alfredo de Greef (eeshlo) 00024 * 00025 * ***** END GPL LICENSE BLOCK ***** 00026 */ 00027 00033 #include "node_composite_util.h" 00034 00035 static bNodeSocketTemplate cmp_node_lensdist_in[]= { 00036 { SOCK_RGBA, 1, "Image", 1.0f, 1.0f, 1.0f, 1.0f}, 00037 { SOCK_FLOAT, 1, "Distort", 0.f, 0.f, 0.f, 0.f, -0.999f, 1.f, PROP_NONE}, 00038 { SOCK_FLOAT, 1, "Dispersion", 0.f, 0.f, 0.f, 0.f, 0.f, 1.f, PROP_NONE}, 00039 { -1, 0, "" } 00040 }; 00041 static bNodeSocketTemplate cmp_node_lensdist_out[]= { 00042 { SOCK_RGBA, 0, "Image"}, 00043 { -1, 0, "" } 00044 }; 00045 00046 /* assumes *dst is type RGBA */ 00047 static void lensDistort(CompBuf *dst, CompBuf *src, float kr, float kg, float kb, int jit, int proj, int fit) 00048 { 00049 int x, y, z; 00050 const float cx = 0.5f*(float)dst->x, cy = 0.5f*(float)dst->y; 00051 00052 if (proj) { 00053 // shift 00054 CompBuf *tsrc = dupalloc_compbuf(src); 00055 00056 for (z=0; z<tsrc->type; ++z) 00057 IIR_gauss(tsrc, (kr+0.5f)*(kr+0.5f), z, 1); 00058 kr *= 20.f; 00059 00060 for (y=0; y<dst->y; y++) { 00061 fRGB *colp = (fRGB*)&dst->rect[y*dst->x*dst->type]; 00062 const float v = (y + 0.5f)/(float)dst->y; 00063 00064 for (x=0; x<dst->x; x++) { 00065 const float u = (x + 0.5f)/(float)dst->x; 00066 00067 qd_getPixelLerpChan(tsrc, (u*dst->x + kr) - 0.5f, v*dst->y - 0.5f, 0, colp[x]); 00068 if (tsrc->type == CB_VAL) 00069 colp[x][1] = tsrc->rect[x + y*tsrc->x]; 00070 else 00071 colp[x][1] = tsrc->rect[(x + y*tsrc->x)*tsrc->type + 1]; 00072 qd_getPixelLerpChan(tsrc, (u*dst->x - kr) - 0.5f, v*dst->y - 0.5f, 2, colp[x]+2); 00073 00074 /* set alpha */ 00075 colp[x][3]= 1.0f; 00076 } 00077 } 00078 free_compbuf(tsrc); 00079 } 00080 else { 00081 // Spherical 00082 // Scale factor to make bottom/top & right/left sides fit in window after deform 00083 // so in the case of pincushion (kn < 0), corners will be outside window. 00084 // Now also optionally scales image such that black areas are not visible when distort factor is positive 00085 // (makes distorted corners match window corners, but really only valid if mk<=0.5) 00086 const float mk = MAX3(kr, kg, kb); 00087 const float sc = (fit && (mk > 0.f)) ? (1.f/(1.f + 2.f*mk)) : (1.f/(1.f + mk)); 00088 const float drg = 4.f*(kg - kr), dgb = 4.f*(kb - kg); 00089 00090 kr *= 4.f, kg *= 4.f, kb *= 4.f; 00091 00092 for (y=0; y<dst->y; y++) { 00093 fRGB *colp = (fRGB*)&dst->rect[y*dst->x*dst->type]; 00094 const float v = sc*((y + 0.5f) - cy)/cy; 00095 00096 for (x=0; x<dst->x; x++) { 00097 int dr = 0, dg = 0, db = 0; 00098 float d, t, ln[6] = {0, 0, 0, 0, 0, 0}; 00099 fRGB c1, tc = {0, 0, 0, 0}; 00100 const float u = sc*((x + 0.5f) - cx)/cx; 00101 int sta = 0, mid = 0, end = 0; 00102 00103 if ((t = 1.f - kr*(u*u + v*v)) >= 0.f) { 00104 d = 1.f/(1.f + sqrtf(t)); 00105 ln[0] = (u*d + 0.5f)*dst->x - 0.5f, ln[1] = (v*d + 0.5f)*dst->y - 0.5f; 00106 sta = 1; 00107 } 00108 if ((t = 1.f - kg*(u*u + v*v)) >= 0.f) { 00109 d = 1.f/(1.f + sqrtf(t)); 00110 ln[2] = (u*d + 0.5f)*dst->x - 0.5f, ln[3] = (v*d + 0.5f)*dst->y - 0.5f; 00111 mid = 1; 00112 } 00113 if ((t = 1.f - kb*(u*u + v*v)) >= 0.f) { 00114 d = 1.f/(1.f + sqrtf(t)); 00115 ln[4] = (u*d + 0.5f)*dst->x - 0.5f, ln[5] = (v*d + 0.5f)*dst->y - 0.5f; 00116 end = 1; 00117 } 00118 00119 if (sta && mid && end) { 00120 // RG 00121 const int dx = ln[2] - ln[0], dy = ln[3] - ln[1]; 00122 const float dsf = sqrtf(dx*dx + dy*dy) + 1.f; 00123 const int ds = (int)(jit ? ((dsf < 4.f) ? 2.f : sqrtf(dsf)) : dsf); 00124 const float sd = 1.f/(float)ds; 00125 00126 for (z=0; z<ds; ++z) { 00127 const float tz = ((float)z + (jit ? BLI_frand() : 0.5f))*sd; 00128 t = 1.f - (kr + tz*drg)*(u*u + v*v); 00129 d = 1.f / (1.f + sqrtf(t)); 00130 qd_getPixelLerp(src, (u*d + 0.5f)*dst->x - 0.5f, (v*d + 0.5f)*dst->y - 0.5f, c1); 00131 if (src->type == CB_VAL) c1[1] = c1[2] = c1[0]; 00132 tc[0] += (1.f-tz)*c1[0], tc[1] += tz*c1[1]; 00133 dr++, dg++; 00134 } 00135 // GB 00136 { 00137 const int dx = ln[4] - ln[2], dy = ln[5] - ln[3]; 00138 const float dsf = sqrtf(dx*dx + dy*dy) + 1.f; 00139 const int ds = (int)(jit ? ((dsf < 4.f) ? 2.f : sqrtf(dsf)) : dsf); 00140 const float sd = 1.f/(float)ds; 00141 00142 for (z=0; z<ds; ++z) { 00143 const float tz = ((float)z + (jit ? BLI_frand() : 0.5f))*sd; 00144 t = 1.f - (kg + tz*dgb)*(u*u + v*v); 00145 d = 1.f / (1.f + sqrtf(t)); 00146 qd_getPixelLerp(src, (u*d + 0.5f)*dst->x - 0.5f, (v*d + 0.5f)*dst->y - 0.5f, c1); 00147 if (src->type == CB_VAL) c1[1] = c1[2] = c1[0]; 00148 tc[1] += (1.f-tz)*c1[1], tc[2] += tz*c1[2]; 00149 dg++, db++; 00150 } 00151 } 00152 } 00153 00154 if (dr) colp[x][0] = 2.f*tc[0] / (float)dr; 00155 if (dg) colp[x][1] = 2.f*tc[1] / (float)dg; 00156 if (db) colp[x][2] = 2.f*tc[2] / (float)db; 00157 00158 /* set alpha */ 00159 colp[x][3]= 1.0f; 00160 } 00161 } 00162 } 00163 } 00164 00165 00166 static void node_composit_exec_lensdist(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) 00167 { 00168 CompBuf *new, *img = in[0]->data; 00169 NodeLensDist *nld = node->storage; 00170 const float k = MAX2(MIN2(in[1]->vec[0], 1.f), -0.999f); 00171 // smaller dispersion range for somewhat more control 00172 const float d = 0.25f*MAX2(MIN2(in[2]->vec[0], 1.f), 0.f); 00173 const float kr = MAX2(MIN2((k+d), 1.f), -0.999f), kb = MAX2(MIN2((k-d), 1.f), -0.999f); 00174 00175 if ((img==NULL) || (out[0]->hasoutput==0)) return; 00176 00177 new = alloc_compbuf(img->x, img->y, CB_RGBA, 1); 00178 00179 lensDistort(new, img, (nld->proj ? d : kr), k, kb, nld->jit, nld->proj, nld->fit); 00180 00181 out[0]->data = new; 00182 } 00183 00184 00185 static void node_composit_init_lensdist(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp)) 00186 { 00187 NodeLensDist *nld = MEM_callocN(sizeof(NodeLensDist), "node lensdist data"); 00188 nld->jit = nld->proj = nld->fit = 0; 00189 node->storage = nld; 00190 } 00191 00192 00193 void register_node_type_cmp_lensdist(bNodeTreeType *ttype) 00194 { 00195 static bNodeType ntype; 00196 00197 node_type_base(ttype, &ntype, CMP_NODE_LENSDIST, "Lens Distortion", NODE_CLASS_DISTORT, NODE_OPTIONS); 00198 node_type_socket_templates(&ntype, cmp_node_lensdist_in, cmp_node_lensdist_out); 00199 node_type_size(&ntype, 150, 120, 200); 00200 node_type_init(&ntype, node_composit_init_lensdist); 00201 node_type_storage(&ntype, "NodeLensDist", node_free_standard_storage, node_copy_standard_storage); 00202 node_type_exec(&ntype, node_composit_exec_lensdist); 00203 00204 nodeRegisterType(ttype, &ntype); 00205 }