|
Blender
V2.59
|
00001 /* 00002 * 00003 * ***** BEGIN GPL LICENSE BLOCK ***** 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU General Public License 00007 * as published by the Free Software Foundation; either version 2 00008 * of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software Foundation, 00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00018 * 00019 * The Original Code is Copyright (C) 2006 Blender Foundation. 00020 * All rights reserved. 00021 * 00022 * The Original Code is: all of this file. 00023 * 00024 * Contributor(s): Alfredo de Greef (eeshlo) 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00034 #include "../CMP_util.h" 00035 00036 static bNodeSocketType cmp_node_lensdist_in[]= { 00037 { SOCK_RGBA, 1, "Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, 00038 { SOCK_VALUE, 1, "Distort", 0.f, 0.f, 0.f, 0.f, -0.999f, 1.f}, 00039 { SOCK_VALUE, 1, "Dispersion", 0.f, 0.f, 0.f, 0.f, 0.f, 1.f}, 00040 { -1, 0, "" } 00041 }; 00042 static bNodeSocketType cmp_node_lensdist_out[]= { 00043 { SOCK_RGBA, 0, "Image", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, 00044 { -1, 0, "" } 00045 }; 00046 00047 /* assumes *dst is type RGBA */ 00048 static void lensDistort(CompBuf *dst, CompBuf *src, float kr, float kg, float kb, int jit, int proj, int fit) 00049 { 00050 int x, y, z; 00051 const float cx = 0.5f*(float)dst->x, cy = 0.5f*(float)dst->y; 00052 00053 if (proj) { 00054 // shift 00055 CompBuf *tsrc = dupalloc_compbuf(src); 00056 00057 for (z=0; z<tsrc->type; ++z) 00058 IIR_gauss(tsrc, (kr+0.5f)*(kr+0.5f), z, 1); 00059 kr *= 20.f; 00060 00061 for (y=0; y<dst->y; y++) { 00062 fRGB *colp = (fRGB*)&dst->rect[y*dst->x*dst->type]; 00063 const float v = (y + 0.5f)/(float)dst->y; 00064 00065 for (x=0; x<dst->x; x++) { 00066 const float u = (x + 0.5f)/(float)dst->x; 00067 00068 qd_getPixelLerpChan(tsrc, (u*dst->x + kr) - 0.5f, v*dst->y - 0.5f, 0, colp[x]); 00069 if (tsrc->type == CB_VAL) 00070 colp[x][1] = tsrc->rect[x + y*tsrc->x]; 00071 else 00072 colp[x][1] = tsrc->rect[(x + y*tsrc->x)*tsrc->type + 1]; 00073 qd_getPixelLerpChan(tsrc, (u*dst->x - kr) - 0.5f, v*dst->y - 0.5f, 2, colp[x]+2); 00074 00075 /* set alpha */ 00076 colp[x][3]= 1.0f; 00077 } 00078 } 00079 free_compbuf(tsrc); 00080 } 00081 else { 00082 // Spherical 00083 // Scale factor to make bottom/top & right/left sides fit in window after deform 00084 // so in the case of pincushion (kn < 0), corners will be outside window. 00085 // Now also optionally scales image such that black areas are not visible when distort factor is positive 00086 // (makes distorted corners match window corners, but really only valid if mk<=0.5) 00087 const float mk = MAX3(kr, kg, kb); 00088 const float sc = (fit && (mk > 0.f)) ? (1.f/(1.f + 2.f*mk)) : (1.f/(1.f + mk)); 00089 const float drg = 4.f*(kg - kr), dgb = 4.f*(kb - kg); 00090 00091 kr *= 4.f, kg *= 4.f, kb *= 4.f; 00092 00093 for (y=0; y<dst->y; y++) { 00094 fRGB *colp = (fRGB*)&dst->rect[y*dst->x*dst->type]; 00095 const float v = sc*((y + 0.5f) - cy)/cy; 00096 00097 for (x=0; x<dst->x; x++) { 00098 int dr = 0, dg = 0, db = 0; 00099 float d, t, ln[6] = {0, 0, 0, 0, 0, 0}; 00100 fRGB c1, tc = {0, 0, 0, 0}; 00101 const float u = sc*((x + 0.5f) - cx)/cx; 00102 int sta = 0, mid = 0, end = 0; 00103 00104 if ((t = 1.f - kr*(u*u + v*v)) >= 0.f) { 00105 d = 1.f/(1.f + sqrtf(t)); 00106 ln[0] = (u*d + 0.5f)*dst->x - 0.5f, ln[1] = (v*d + 0.5f)*dst->y - 0.5f; 00107 sta = 1; 00108 } 00109 if ((t = 1.f - kg*(u*u + v*v)) >= 0.f) { 00110 d = 1.f/(1.f + sqrtf(t)); 00111 ln[2] = (u*d + 0.5f)*dst->x - 0.5f, ln[3] = (v*d + 0.5f)*dst->y - 0.5f; 00112 mid = 1; 00113 } 00114 if ((t = 1.f - kb*(u*u + v*v)) >= 0.f) { 00115 d = 1.f/(1.f + sqrtf(t)); 00116 ln[4] = (u*d + 0.5f)*dst->x - 0.5f, ln[5] = (v*d + 0.5f)*dst->y - 0.5f; 00117 end = 1; 00118 } 00119 00120 if (sta && mid && end) { 00121 // RG 00122 const int dx = ln[2] - ln[0], dy = ln[3] - ln[1]; 00123 const float dsf = sqrtf(dx*dx + dy*dy) + 1.f; 00124 const int ds = (int)(jit ? ((dsf < 4.f) ? 2.f : sqrtf(dsf)) : dsf); 00125 const float sd = 1.f/(float)ds; 00126 00127 for (z=0; z<ds; ++z) { 00128 const float tz = ((float)z + (jit ? BLI_frand() : 0.5f))*sd; 00129 t = 1.f - (kr + tz*drg)*(u*u + v*v); 00130 d = 1.f / (1.f + sqrtf(t)); 00131 qd_getPixelLerp(src, (u*d + 0.5f)*dst->x - 0.5f, (v*d + 0.5f)*dst->y - 0.5f, c1); 00132 if (src->type == CB_VAL) c1[1] = c1[2] = c1[0]; 00133 tc[0] += (1.f-tz)*c1[0], tc[1] += tz*c1[1]; 00134 dr++, dg++; 00135 } 00136 // GB 00137 { 00138 const int dx = ln[4] - ln[2], dy = ln[5] - ln[3]; 00139 const float dsf = sqrtf(dx*dx + dy*dy) + 1.f; 00140 const int ds = (int)(jit ? ((dsf < 4.f) ? 2.f : sqrtf(dsf)) : dsf); 00141 const float sd = 1.f/(float)ds; 00142 00143 for (z=0; z<ds; ++z) { 00144 const float tz = ((float)z + (jit ? BLI_frand() : 0.5f))*sd; 00145 t = 1.f - (kg + tz*dgb)*(u*u + v*v); 00146 d = 1.f / (1.f + sqrtf(t)); 00147 qd_getPixelLerp(src, (u*d + 0.5f)*dst->x - 0.5f, (v*d + 0.5f)*dst->y - 0.5f, c1); 00148 if (src->type == CB_VAL) c1[1] = c1[2] = c1[0]; 00149 tc[1] += (1.f-tz)*c1[1], tc[2] += tz*c1[2]; 00150 dg++, db++; 00151 } 00152 } 00153 } 00154 00155 if (dr) colp[x][0] = 2.f*tc[0] / (float)dr; 00156 if (dg) colp[x][1] = 2.f*tc[1] / (float)dg; 00157 if (db) colp[x][2] = 2.f*tc[2] / (float)db; 00158 00159 /* set alpha */ 00160 colp[x][3]= 1.0f; 00161 } 00162 } 00163 } 00164 } 00165 00166 00167 static void node_composit_exec_lensdist(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out) 00168 { 00169 CompBuf *new, *img = in[0]->data; 00170 NodeLensDist *nld = node->storage; 00171 const float k = MAX2(MIN2(in[1]->vec[0], 1.f), -0.999f); 00172 // smaller dispersion range for somewhat more control 00173 const float d = 0.25f*MAX2(MIN2(in[2]->vec[0], 1.f), 0.f); 00174 const float kr = MAX2(MIN2((k+d), 1.f), -0.999f), kb = MAX2(MIN2((k-d), 1.f), -0.999f); 00175 00176 if ((img==NULL) || (out[0]->hasoutput==0)) return; 00177 00178 new = alloc_compbuf(img->x, img->y, CB_RGBA, 1); 00179 00180 lensDistort(new, img, (nld->proj ? d : kr), k, kb, nld->jit, nld->proj, nld->fit); 00181 00182 out[0]->data = new; 00183 } 00184 00185 00186 static void node_composit_init_lensdist(bNode* node) 00187 { 00188 NodeLensDist *nld = MEM_callocN(sizeof(NodeLensDist), "node lensdist data"); 00189 nld->jit = nld->proj = nld->fit = 0; 00190 node->storage = nld; 00191 } 00192 00193 00194 void register_node_type_cmp_lensdist(ListBase *lb) 00195 { 00196 static bNodeType ntype; 00197 00198 node_type_base(&ntype, CMP_NODE_LENSDIST, "Lens Distortion", NODE_CLASS_DISTORT, NODE_OPTIONS, 00199 cmp_node_lensdist_in, cmp_node_lensdist_out); 00200 node_type_size(&ntype, 150, 120, 200); 00201 node_type_init(&ntype, node_composit_init_lensdist); 00202 node_type_storage(&ntype, "NodeLensDist", node_free_standard_storage, node_copy_standard_storage); 00203 node_type_exec(&ntype, node_composit_exec_lensdist); 00204 00205 nodeRegisterType(lb, &ntype); 00206 } 00207