Rev 2 | Rev 18 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | toby | 1 | /* |
2 | This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop |
||
3 | Copyright (C) 2003-5 Toby Thain, toby@telegraphics.com.au |
||
4 | |||
5 | This program is free software; you can redistribute it and/or modify |
||
6 | it under the terms of the GNU General Public License as published by |
||
7 | the Free Software Foundation; either version 2 of the License, or |
||
8 | (at your option) any later version. |
||
9 | |||
10 | This program is distributed in the hope that it will be useful, |
||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
13 | GNU General Public License for more details. |
||
14 | |||
15 | You should have received a copy of the GNU General Public License |
||
16 | along with this program; if not, write to the Free Software |
||
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||
18 | */ |
||
19 | |||
20 | #include "ff.h" |
||
21 | #include "symtab.h" |
||
22 | #include "node.h" |
||
23 | #include "funcs.h" |
||
8 | toby | 24 | #include "y.tab.h" |
2 | toby | 25 | |
26 | extern value_type var[]; |
||
27 | extern int nplanes,varused[],srcradused; |
||
28 | extern struct node *tree[]; |
||
29 | int needinput; |
||
30 | |||
31 | /* get prepared to evaluate expression trees-- |
||
32 | this assumes that tree[] array is already set up |
||
33 | return TRUE if we're ready to go |
||
34 | */ |
||
35 | |||
36 | Boolean setup(FilterRecordPtr pb){ |
||
37 | int i; |
||
38 | extern int chunksize; |
||
39 | |||
40 | INITRANDSEED(); |
||
41 | var['X'] = pb->imageSize.h; |
||
42 | var['Y'] = pb->imageSize.v; |
||
43 | var['Z'] = nplanes; |
||
44 | var['D'] = 1024; |
||
45 | var['M'] = ff_c2m(var['X'],var['Y'])/2; |
||
46 | |||
47 | /* initialise flags for tracking special variable usage */ |
||
48 | for( i=0 ; i<0x100 ; i++ ) |
||
49 | varused[i] = 0; |
||
50 | srcradused = 0; |
||
51 | for(i=0;i<nplanes;++i){ |
||
52 | //char s[100];sprintf(s,"expr[%d]=%#x",i,expr[i]);dbg(s); |
||
53 | if( tree[i] || ( tree[i] = parseexpr(expr[i]) ) ) |
||
54 | checkvars(tree[i],varused,&srcradused); |
||
55 | else |
||
56 | break; |
||
57 | } |
||
58 | needinput = (srcradused || varused['r'] || varused['g'] || varused['b'] || varused['a'] |
||
59 | || varused['i'] || varused['u'] || varused['v'] || varused['c']) ; |
||
60 | |||
61 | return i==nplanes; /* all required expressions parse OK */ |
||
62 | } |
||
63 | |||
64 | void evalpixel(unsigned char *outp,unsigned char *inp){ |
||
65 | int f,k; |
||
66 | |||
67 | if(needinput){ |
||
68 | var['r'] = inp[0]; |
||
69 | var['g'] = nplanes > 1 ? inp[1] : 0; |
||
70 | var['b'] = nplanes > 2 ? inp[2] : 0; |
||
71 | var['a'] = nplanes > 3 ? inp[3] : 0; |
||
72 | |||
73 | if(varused['i']) var['i'] = (( 76L*var['r'])+(150L*var['g'])+( 29L*var['b']))/256; |
||
74 | if(varused['u']) var['u'] = ((-19L*var['r'])+(-37L*var['g'])+( 56L*var['b']))/256; |
||
75 | if(varused['v']) var['v'] = (( 78L*var['r'])+(-65L*var['g'])+(-13L*var['b']))/256; |
||
76 | } |
||
77 | if(varused['d']) var['d'] = ff_c2d(var['X']/2-var['x'],var['Y']/2-var['y']); |
||
78 | if(varused['m']) var['m'] = ff_c2m(var['X']/2-var['x'],var['Y']/2-var['y']); |
||
79 | |||
80 | for( k=0 ; k<nplanes ; ++k ){ |
||
81 | if(needinput) |
||
82 | var['c'] = inp[k]; |
||
83 | var['z'] = k; |
||
84 | f = eval(tree[k]); |
||
85 | outp[k] = f<0 ? 0 : ( f>255 ? 255 : f ); // clamp channel value to 0-255 |
||
86 | } |
||
87 | } |
||
88 | |||
89 | OSErr process(FilterRecordPtr pb,Boolean progress, |
||
90 | Rect *inRect,Rect *filterRect,Rect *outRect, |
||
91 | void *outData,long outRowBytes){ |
||
92 | unsigned char *inrow,*outrow,*inp,*outp; |
||
93 | int j,i,ncols = filterRect->right - filterRect->left; |
||
94 | long t,ticks = TICKCOUNT(); |
||
95 | |||
96 | long inoffset = (long)pb->inRowBytes*(filterRect->top - inRect->top) |
||
97 | + (long)nplanes*(filterRect->left - inRect->left), |
||
98 | outoffset = (long)outRowBytes*(filterRect->top - outRect->top) |
||
99 | + (long)nplanes*(filterRect->left - outRect->left); |
||
100 | /* |
||
101 | {char s[0x100];sprintf(s,"process: inoffset=%d outoffset=%d inData=%#x inRect=(%d,%d,%d,%d) filterRect=(%d,%d,%d,%d)", |
||
102 | inoffset,outoffset,pb->inData, |
||
103 | inRect->left,inRect->top,inRect->right,inRect->bottom, |
||
104 | filterRect->left,filterRect->top,filterRect->right,filterRect->bottom);dbg(s);} |
||
105 | */ |
||
106 | |||
107 | for( inrow = (unsigned char*)pb->inData + inoffset, outrow = (unsigned char*)outData + outoffset, |
||
108 | j = filterRect->bottom - filterRect->top, var['y'] = filterRect->top |
||
109 | ; j-- ; ++var['y'], inrow += pb->inRowBytes, outrow += outRowBytes ){ |
||
110 | |||
111 | for ( inp=inrow, outp=outrow, i=ncols, var['x']=filterRect->left ; i-- ; ++var['x'], inp+=nplanes, outp+=nplanes ){ |
||
112 | evalpixel(outp,inp); /* var['x'] & var['y'] are implicit parameters */ |
||
113 | } |
||
114 | |||
115 | if(progress && (t = TICKCOUNT()) > ticks){ |
||
116 | ticks = t + TICKS_SEC/4; |
||
117 | if(pb->abortProc()) |
||
118 | return userCanceledErr; |
||
119 | else |
||
120 | pb->progressProc(var['y'] - pb->filterRect.top,pb->filterRect.bottom - pb->filterRect.top); |
||
121 | } |
||
122 | #ifdef MAC_ENV |
||
123 | else{ |
||
124 | /* to reduce annoying delays during typing of expressions, |
||
125 | immediately abort preview calculation if a key or mouse has been pressed. */ |
||
126 | EventRecord event; |
||
127 | if(EventAvail(mDownMask|keyDownMask|autoKeyMask,&event)) |
||
128 | return userCanceledErr; |
||
129 | } |
||
130 | #endif |
||
131 | } |
||
132 | return noErr; |
||
133 | |||
134 | } |
||
135 | |||
136 | OSErr process_scaled(FilterRecordPtr pb,Boolean progress, |
||
137 | Rect *inRect,Rect *filterRect,Rect *outRect, |
||
138 | void *outData,long outRowBytes,double zoom){ |
||
139 | unsigned char *inrow,*outrow,*outp; |
||
140 | int j,i,ncols = filterRect->right - filterRect->left; |
||
141 | long t,ticks = TICKCOUNT(); |
||
142 | double x,y; |
||
143 | /* |
||
144 | {char s[0x100];sprintf(s,"process_scaled: pb->inData=%#x outData=%#x\n\ |
||
145 | inRect=(%d,%d,%d,%d) filterRect=(%d,%d,%d,%d) outRect=(%d,%d,%d,%d)\n\ |
||
146 | pb->filterRect=(%d,%d,%d,%d)\n", |
||
147 | pb->inData,outData, |
||
148 | inRect->left,inRect->top,inRect->right,inRect->bottom, |
||
149 | filterRect->left,filterRect->top,filterRect->right,filterRect->bottom, |
||
150 | outRect->left,outRect->top,outRect->right,outRect->bottom, |
||
151 | pb->filterRect.left,pb->filterRect.top,pb->filterRect.right,pb->filterRect.bottom); dbg(s);} |
||
152 | */ |
||
153 | if(needinput && !pb->inData){ |
||
154 | simplealert("Input error (process_scaled: pb->inData == NULL). This problem is being investigated. Cannot apply the filter; please re-launch Photoshop and try again."); |
||
155 | return userCanceledErr; |
||
156 | }else |
||
157 | for( j = outRect->top, outrow = (unsigned char*)outData, y = filterRect->top |
||
158 | ; j < outRect->bottom ; ++j, outrow += outRowBytes, y += zoom ){ |
||
159 | var['y'] = y; |
||
160 | inrow = (unsigned char*)pb->inData |
||
161 | + (var['y'] - inRect->top)*pb->inRowBytes |
||
162 | - (long)nplanes*inRect->left; |
||
163 | |||
164 | for( outp=outrow, i=outRect->left, x=filterRect->left ; i<outRect->right ; ++i, outp+=nplanes, x+=zoom ){ |
||
165 | var['x'] = x; |
||
166 | evalpixel(outp,inrow + (long)var['x']*nplanes); /* var['x'] & var['y'] are implicit parameters */ |
||
167 | } |
||
168 | |||
169 | if(progress && (t = TICKCOUNT()) > ticks){ |
||
170 | ticks = t + TICKS_SEC/4; |
||
171 | if(pb->abortProc()) |
||
172 | return userCanceledErr; |
||
173 | else |
||
174 | pb->progressProc((int)y - pb->filterRect.top,pb->filterRect.bottom - pb->filterRect.top); |
||
175 | } |
||
176 | #ifdef MAC_ENV |
||
177 | else{ |
||
178 | /* to stop delays during typing of expressions, |
||
179 | immediately abort preview calculation if a key or mouse has been pressed. */ |
||
180 | EventRecord event; |
||
181 | if(EventAvail(mDownMask|keyDownMask|autoKeyMask,&event)) |
||
182 | return userCanceledErr; |
||
183 | } |
||
184 | #endif |
||
185 | } |
||
186 | |||
187 | return noErr; |
||
188 | } |