Rev 76 | Rev 106 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | toby | 1 | /* |
18 | toby | 2 | This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop |
53 | toby | 3 | Copyright (C) 2003-6 Toby Thain, toby@telegraphics.com.au |
2 | toby | 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" |
||
94 | toby | 21 | |
2 | toby | 22 | #include "symtab.h" |
23 | #include "node.h" |
||
24 | #include "funcs.h" |
||
8 | toby | 25 | #include "y.tab.h" |
2 | toby | 26 | |
27 | extern value_type var[]; |
||
94 | toby | 28 | extern int nplanes,varused[],cnvused; |
2 | toby | 29 | extern struct node *tree[]; |
66 | toby | 30 | |
31 | // points to first row, first column of selection image data |
||
32 | // this is used by src() and cnv() functions to access pixels |
||
33 | unsigned char *image_ptr; |
||
34 | |||
2 | toby | 35 | int needinput; |
36 | |||
37 | /* get prepared to evaluate expression trees-- |
||
38 | this assumes that tree[] array is already set up |
||
39 | return TRUE if we're ready to go |
||
40 | */ |
||
41 | |||
94 | toby | 42 | // minimum setup required when formulae have not changed, |
43 | // and a new preview is to be generated. (Called by recalc_preview()) |
||
44 | void evalinit(){ |
||
45 | INITRANDSEED(); |
||
46 | } |
||
47 | |||
48 | // full setup for evaluation, called when formulae have changed. |
||
2 | toby | 49 | Boolean setup(FilterRecordPtr pb){ |
50 | int i; |
||
51 | |||
53 | toby | 52 | var['X'] = pb->filterRect.right - pb->filterRect.left; |
53 | var['Y'] = pb->filterRect.bottom - pb->filterRect.top; |
||
2 | toby | 54 | var['Z'] = nplanes; |
55 | var['D'] = 1024; |
||
56 | var['M'] = ff_c2m(var['X'],var['Y'])/2; |
||
57 | |||
58 | /* initialise flags for tracking special variable usage */ |
||
71 | toby | 59 | for(i = 0; i < 0x100; i++) |
2 | toby | 60 | varused[i] = 0; |
94 | toby | 61 | needall = cnvused = 0; |
71 | toby | 62 | for(i = 0; i < nplanes; ++i){ |
2 | toby | 63 | //char s[100];sprintf(s,"expr[%d]=%#x",i,expr[i]);dbg(s); |
71 | toby | 64 | if( tree[i] || (tree[i] = parseexpr(expr[i])) ) |
94 | toby | 65 | checkvars(tree[i],varused,&cnvused,&needall); |
2 | toby | 66 | else |
67 | break; |
||
68 | } |
||
94 | toby | 69 | needinput = ( cnvused || needall |
71 | toby | 70 | || varused['r'] || varused['g'] || varused['b'] || varused['a'] |
71 | || varused['i'] || varused['u'] || varused['v'] || varused['c'] ); |
||
94 | toby | 72 | |
73 | evalinit(); |
||
2 | toby | 74 | return i==nplanes; /* all required expressions parse OK */ |
75 | } |
||
76 | |||
77 | void evalpixel(unsigned char *outp,unsigned char *inp){ |
||
78 | int f,k; |
||
79 | |||
80 | if(needinput){ |
||
81 | var['r'] = inp[0]; |
||
82 | var['g'] = nplanes > 1 ? inp[1] : 0; |
||
83 | var['b'] = nplanes > 2 ? inp[2] : 0; |
||
84 | var['a'] = nplanes > 3 ? inp[3] : 0; |
||
85 | |||
86 | if(varused['i']) var['i'] = (( 76L*var['r'])+(150L*var['g'])+( 29L*var['b']))/256; |
||
87 | if(varused['u']) var['u'] = ((-19L*var['r'])+(-37L*var['g'])+( 56L*var['b']))/256; |
||
88 | if(varused['v']) var['v'] = (( 78L*var['r'])+(-65L*var['g'])+(-13L*var['b']))/256; |
||
89 | } |
||
66 | toby | 90 | if(varused['d']) var['d'] = ff_c2d(var['X']/2 - var['x'], var['Y']/2 - var['y']); |
91 | if(varused['m']) var['m'] = ff_c2m(var['X']/2 - var['x'], var['Y']/2 - var['y']); |
||
2 | toby | 92 | |
66 | toby | 93 | for(k = 0; k < nplanes; ++k){ |
2 | toby | 94 | if(needinput) |
95 | var['c'] = inp[k]; |
||
96 | var['z'] = k; |
||
97 | f = eval(tree[k]); |
||
66 | toby | 98 | outp[k] = f<0 ? 0 : (f>255 ? 255 : f); // clamp channel value to 0-255 |
2 | toby | 99 | } |
100 | } |
||
101 | |||
53 | toby | 102 | /* Zoom and filter image. |
66 | toby | 103 | * Parameters: pb - Photoshop Filter parameter block |
104 | * progress - whether to use Photoshop's progress bar |
||
53 | toby | 105 | * (not appropriate during preview) |
66 | toby | 106 | * filterRect - rectangle (within pb->inRect) |
53 | toby | 107 | * of area to be filtered. This may not correspond |
108 | * to pb->filterRect, it may be just a piece. |
||
66 | toby | 109 | * outPiece - rectangle defining scaled output buffer. |
110 | * In case of zoomed preview, this is physically |
||
111 | * scaled FROM filterRect (or equal to filterRect |
||
112 | * for unscaled 1:1 filtering). |
||
53 | toby | 113 | * outData - pointer to output data buffer |
114 | * outRowBytes - row stride of output data buffer |
||
66 | toby | 115 | * zoom - pixel scale factor (both horiz & vert) |
53 | toby | 116 | * e.g. 2.0 means 1 output pixel per 2 input pixels. |
117 | */ |
||
2 | toby | 118 | |
53 | toby | 119 | OSErr process_scaled(FilterRecordPtr pb, Boolean progress, |
66 | toby | 120 | Rect *filterPiece, Rect *outPiece, |
53 | toby | 121 | void *outData, long outRowBytes, double zoom){ |
2 | toby | 122 | unsigned char *inrow,*outrow,*outp; |
23 | toby | 123 | int j,i; |
2 | toby | 124 | long t,ticks = TICKCOUNT(); |
125 | double x,y; |
||
66 | toby | 126 | |
127 | /* char s[0x100];sprintf(s,"process_scaled: pb->inData=%p outData=%p\n\ |
||
128 | pb->inRect=(%d,%d,%d,%d) filterPiece=(%d,%d,%d,%d) outPiece=(%d,%d,%d,%d)\n\ |
||
129 | pb->fRect=(%d,%d,%d,%d)\n\ |
||
130 | top row offset (from inData) = %d\n\ |
||
131 | left row offset = %d\n", |
||
2 | toby | 132 | pb->inData,outData, |
66 | toby | 133 | pb->inRect.left,pb->inRect.top,pb->inRect.right,pb->inRect.bottom, |
134 | filterPiece->left,filterPiece->top,filterPiece->right,filterPiece->bottom, |
||
135 | outPiece->left,outPiece->top,outPiece->right,outPiece->bottom, |
||
136 | pb->filterRect.left,pb->filterRect.top,pb->filterRect.right,pb->filterRect.bottom, |
||
137 | filterPiece->top - pb->filterRect.top + pb->filterRect.top - pb->inRect.top, |
||
138 | filterPiece->left - pb->filterRect.left + pb->filterRect.left - pb->inRect.left); dbg(s); */ |
||
139 | |||
2 | toby | 140 | if(needinput && !pb->inData){ |
53 | toby | 141 | simplealert("Error (process_scaled: pb->inData == NULL)." |
142 | " This problem is being investigated. Cannot apply the filter;" |
||
143 | " please re-launch Photoshop and try again."); |
||
2 | toby | 144 | return userCanceledErr; |
145 | }else |
||
66 | toby | 146 | // find base pointer to selection image data |
76 | toby | 147 | image_ptr = (unsigned char*)pb->inData |
148 | + (long)pb->inRowBytes*(pb->filterRect.top - pb->inRect.top) |
||
66 | toby | 149 | + (long)nplanes*(pb->filterRect.left - pb->inRect.left); |
150 | |||
151 | // j indexes scaled output rows |
||
152 | for( j = outPiece->top, outrow = (unsigned char*)outData, y = filterPiece->top - pb->filterRect.top ; |
||
153 | j < outPiece->bottom ; ++j, outrow += outRowBytes, y += zoom ) |
||
53 | toby | 154 | { |
66 | toby | 155 | var['y'] = y; // index of corresponding *input* row, top of selection == 0 |
76 | toby | 156 | inrow = image_ptr + (long)y*pb->inRowBytes; |
66 | toby | 157 | |
158 | // i indexes scaled output columns |
||
159 | for( outp = outrow, i = outPiece->left, x = filterPiece->left - pb->filterRect.left ; |
||
160 | i < outPiece->right ; ++i, outp += nplanes, x += zoom ) |
||
53 | toby | 161 | { |
66 | toby | 162 | var['x'] = x; // index of corresponding *input* column, left of selection == 0 |
163 | evalpixel(outp,inrow + (long)x*nplanes); /* var['x'] & var['y'] are implicit parameters */ |
||
2 | toby | 164 | } |
165 | |||
66 | toby | 166 | if(progress){ |
167 | if((t = TICKCOUNT()) > ticks){ |
||
168 | ticks = t + TICKS_SEC/4; |
||
169 | if(pb->abortProc()) |
||
170 | return userCanceledErr; |
||
171 | else |
||
172 | pb->progressProc((int)y - pb->filterRect.top,pb->filterRect.bottom - pb->filterRect.top); |
||
173 | } |
||
2 | toby | 174 | } |
175 | #ifdef MAC_ENV |
||
176 | else{ |
||
177 | /* to stop delays during typing of expressions, |
||
178 | immediately abort preview calculation if a key or mouse has been pressed. */ |
||
179 | EventRecord event; |
||
180 | if(EventAvail(mDownMask|keyDownMask|autoKeyMask,&event)) |
||
181 | return userCanceledErr; |
||
182 | } |
||
183 | #endif |
||
184 | } |
||
185 | |||
186 | return noErr; |
||
187 | } |