Rev 89 | Rev 110 | 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 |
94 | toby | 3 | Copyright (C) 2003-7 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 | /* This is PLATFORM INDEPENDENT user interface code - mainly dialog logic */ |
||
21 | |||
94 | toby | 22 | #include "preview.h" |
2 | toby | 23 | |
94 | toby | 24 | #ifdef MAC_ENV |
25 | #include <fp.h> |
||
26 | #endif |
||
27 | #include <math.h> |
||
28 | |||
29 | toby | 29 | #include "PIProperties.h" |
2 | toby | 30 | |
94 | toby | 31 | extern FilterRecordPtr gpb; |
2 | toby | 32 | |
33 | PSPixelMap preview_pmap; |
||
34 | PSPixelMask preview_pmask; |
||
35 | Handle preview_handle; |
||
36 | UIRECT preview_rect; |
||
94 | toby | 37 | int preview_w,preview_h,previewerr = false,needall = false,needinput = true; |
2 | toby | 38 | Point preview_scroll; |
39 | Boolean preview_complete = false; |
||
94 | toby | 40 | double zoomfactor,fitzoom; |
2 | toby | 41 | |
94 | toby | 42 | Boolean setup_preview(FilterRecordPtr pb, int nplanes){ |
43 | double zh,zv; |
||
44 | |||
2 | toby | 45 | if(pb->displayPixels && pb->advanceState){ |
89 | toby | 46 | preview_w = MIN(preview_rect.right - preview_rect.left - 2, |
47 | pb->filterRect.right - pb->filterRect.left); |
||
48 | preview_h = MIN(preview_rect.bottom - preview_rect.top - 2, |
||
49 | pb->filterRect.bottom - pb->filterRect.top); |
||
94 | toby | 50 | zh = (pb->filterRect.right - pb->filterRect.left)/(double)preview_w; |
51 | zv = (pb->filterRect.bottom - pb->filterRect.top)/(double)preview_h; |
||
52 | fitzoom = zh > zv ? zh : zv; |
||
2 | toby | 53 | |
54 | preview_pmap.version = 1; |
||
55 | preview_pmap.bounds.left = preview_pmap.bounds.top = 0; |
||
56 | preview_pmap.bounds.right = preview_w; |
||
57 | preview_pmap.bounds.bottom = preview_h; |
||
94 | toby | 58 | preview_pmap.imageMode = pb->imageMode; |
2 | toby | 59 | preview_pmap.rowBytes = nplanes*preview_w; |
60 | preview_pmap.colBytes = nplanes; |
||
61 | preview_pmap.planeBytes = 1; /*interleaved*/ |
||
62 | // preview_pmap.baseAddr = preview_data; |
||
63 | /* baseAddr must be set before using pixelmap */ |
||
64 | |||
65 | //--------------------------------------------------------------------------- |
||
66 | // Fields new in version 1: |
||
67 | //--------------------------------------------------------------------------- |
||
68 | preview_pmap.mat = NULL; |
||
69 | |||
94 | toby | 70 | if( (pb->imageMode == plugInModeRGBColor && nplanes == 4) |
71 | || (pb->imageMode == plugInModeLabColor && nplanes == 4) |
||
72 | || (pb->imageMode == plugInModeGrayScale && nplanes == 2) |
||
73 | || (pb->imageMode == plugInModeDuotone && nplanes == 2) ) |
||
89 | toby | 74 | { |
2 | toby | 75 | preview_pmask.next = NULL; |
76 | // preview_pmask.maskData = preview_data+3; |
||
77 | preview_pmask.rowBytes = preview_pmap.rowBytes; |
||
78 | preview_pmask.colBytes = nplanes; |
||
79 | preview_pmask.maskDescription = kSimplePSMask; |
||
80 | preview_pmap.masks = &preview_pmask; |
||
81 | }else |
||
82 | preview_pmap.masks = NULL; |
||
83 | |||
84 | preview_handle = PINEWHANDLE((long)preview_h * preview_pmap.rowBytes); |
||
85 | }else |
||
86 | preview_handle = NULL; |
||
87 | return preview_handle != NULL; |
||
88 | |||
89 | //--------------------------------------------------------------------------- |
||
90 | // Fields new in version 2: |
||
91 | //--------------------------------------------------------------------------- |
||
92 | // preview_pmap.pixelOverlays; |
||
93 | // preview_pmap.colorManagementOptions; |
||
94 | } |
||
95 | |||
96 | void dispose_preview(){ |
||
97 | if(preview_handle){ |
||
98 | PIDISPOSEHANDLE(preview_handle); |
||
99 | preview_handle = NULL; |
||
100 | } |
||
101 | } |
||
102 | |||
103 | void recalc_preview(FilterRecordPtr pb,DIALOGREF dp){ |
||
104 | OSErr e; |
||
45 | toby | 105 | int j,n,scaledw,scaledh,imgw,imgh; |
2 | toby | 106 | Rect r,outRect; |
107 | Ptr outrow; |
||
108 | |||
37 | toby | 109 | preview_complete = false; |
110 | |||
2 | toby | 111 | if(preview_handle){ |
112 | /* size of previewed area, of source image; but no larger than filtered area (selection) */ |
||
113 | scaledw = zoomfactor*preview_w; |
||
114 | if(scaledw > (pb->filterRect.right - pb->filterRect.left)) |
||
89 | toby | 115 | scaledw = pb->filterRect.right - pb->filterRect.left; |
2 | toby | 116 | scaledh = zoomfactor*preview_h; |
117 | if(scaledh > (pb->filterRect.bottom - pb->filterRect.top)) |
||
89 | toby | 118 | scaledh = pb->filterRect.bottom - pb->filterRect.top; |
2 | toby | 119 | |
120 | /* scale clipped preview area down again - this becomes the pixel size of preview */ |
||
121 | imgw = scaledw/zoomfactor; |
||
122 | if(imgw > preview_w) |
||
123 | imgw = preview_w; |
||
124 | imgh = scaledh/zoomfactor; |
||
125 | if(imgh > preview_h) |
||
126 | imgh = preview_h; |
||
127 | |||
128 | // Use to set the phase of the checkerboard: |
||
129 | preview_pmap.maskPhaseRow = preview_scroll.v/zoomfactor; |
||
130 | preview_pmap.maskPhaseCol = preview_scroll.h/zoomfactor; |
||
131 | |||
132 | /* compute source data rectangle (inRect) */ |
||
133 | |||
134 | /* centre preview on filtered part of input image, adding scroll offset */ |
||
53 | toby | 135 | r.left = (pb->filterRect.left + pb->filterRect.right - scaledw)/2 + preview_scroll.h; |
2 | toby | 136 | /* make sure it does not go outside the input area */ |
137 | if(r.left < pb->filterRect.left) |
||
138 | r.left = pb->filterRect.left; |
||
139 | else if(r.left > pb->filterRect.right-scaledw) |
||
53 | toby | 140 | r.left = pb->filterRect.right - scaledw; |
2 | toby | 141 | r.right = r.left + scaledw; |
142 | |||
143 | /* now compute for vertical */ |
||
94 | toby | 144 | r.top = (pb->filterRect.top + pb->filterRect.bottom - scaledh)/2 + preview_scroll.v; |
2 | toby | 145 | if(r.top < pb->filterRect.top) |
146 | r.top = pb->filterRect.top; |
||
147 | else if(r.top > pb->filterRect.bottom-scaledh) |
||
53 | toby | 148 | r.top = pb->filterRect.bottom - scaledh; |
2 | toby | 149 | r.bottom = r.top + scaledh; |
150 | |||
151 | /* if formulae need random access to image - src(), rad() - we must request entire area: */ |
||
94 | toby | 152 | if(needall) |
2 | toby | 153 | SETRECT(pb->inRect,0,0,pb->imageSize.h,pb->imageSize.v); |
94 | toby | 154 | else |
2 | toby | 155 | pb->inRect = r; |
156 | |||
157 | pb->outRect = pb->inRect; |
||
158 | SETRECT(pb->maskRect,0,0,0,0); |
||
159 | pb->inLoPlane = pb->outLoPlane = 0; |
||
160 | pb->inHiPlane = pb->outHiPlane = nplanes-1; |
||
37 | toby | 161 | |
2 | toby | 162 | if( !needinput || !(e = pb->advanceState()) ){ |
163 | Ptr outptr = PILOCKHANDLE(preview_handle,false); |
||
53 | toby | 164 | int blankrows = (preview_h - imgh)/2, |
89 | toby | 165 | blankcols = (preview_w - imgw)/2, |
166 | pmrb = preview_pmap.rowBytes; |
||
2 | toby | 167 | |
94 | toby | 168 | evalinit(); |
2 | toby | 169 | |
170 | SETRECT(outRect,0,0,imgw,imgh); |
||
171 | |||
53 | toby | 172 | e = process_scaled(pb, false, &r, &outRect, |
173 | outptr + pmrb*blankrows + nplanes*blankcols, pmrb, zoomfactor); |
||
2 | toby | 174 | if(blankrows){ |
53 | toby | 175 | memset(outptr, 0xff, pmrb*blankrows); |
2 | toby | 176 | n = preview_h - blankrows - imgh; /* blank rows below preview */ |
53 | toby | 177 | memset(outptr + pmrb*(blankrows+imgh), 0xff, pmrb*n); |
2 | toby | 178 | } |
179 | if(blankcols){ |
||
180 | n = preview_w - blankcols - imgw; /* blank columns on right side of preview */ |
||
53 | toby | 181 | outrow = outptr + pmrb*blankrows; |
94 | toby | 182 | for(j = blankrows; j < preview_h - blankrows; ++j){ |
53 | toby | 183 | memset(outrow, 0xff, nplanes*blankcols); |
184 | memset(outrow + nplanes*(blankcols+imgw), 0xff, nplanes*n); |
||
185 | outrow += pmrb; |
||
2 | toby | 186 | } |
187 | } |
||
188 | |||
189 | if(!e){ |
||
190 | preview_complete = true; |
||
191 | |||
192 | #ifdef WIN_ENV |
||
193 | { |
||
194 | extern HWND preview_hwnd; |
||
195 | HDC hdc = GetDC(preview_hwnd); |
||
89 | toby | 196 | |
2 | toby | 197 | drawpreview(dp,hdc,outptr); |
198 | |||
199 | ReleaseDC(preview_hwnd,hdc); |
||
200 | } |
||
201 | #else |
||
202 | { |
||
203 | GrafPtr saveport; |
||
204 | |||
205 | GetPort(&saveport); |
||
206 | SetPortDialogPort(dp); |
||
207 | |||
208 | drawpreview(dp,NULL,outptr); |
||
209 | |||
210 | SetPort(saveport); |
||
211 | } |
||
212 | #endif |
||
213 | } |
||
214 | |||
215 | PIUNLOCKHANDLE(preview_handle); |
||
94 | toby | 216 | } |
2 | toby | 217 | |
37 | toby | 218 | if(e && !previewerr){ |
39 | toby | 219 | alertuser("Could not build preview at chosen zoom level.", |
94 | toby | 220 | e == memFullErr && !needall ? "The image is too large for available memory. Try zooming in.\nIf that does not help, Cancel and retry the filter." : ""); |
37 | toby | 221 | previewerr = true; |
2 | toby | 222 | } |
37 | toby | 223 | |
2 | toby | 224 | } |
225 | } |
||
226 | |||
227 | OSErr drawpreview(DIALOGREF dp,void *hdc,Ptr imageptr){ |
||
228 | int32 watchsusp; |
||
229 | OSErr e = noErr; |
||
230 | VRect srcRect; |
||
231 | UIRECT imagebounds; |
||
232 | |||
233 | if(preview_handle && preview_complete){ |
||
234 | |||
235 | srcRect = preview_pmap.bounds; |
||
236 | |||
53 | toby | 237 | imagebounds.left = (preview_rect.left + preview_rect.right - preview_w)/2; |
238 | imagebounds.top = (preview_rect.top + preview_rect.bottom - preview_h)/2; |
||
2 | toby | 239 | imagebounds.right = imagebounds.left + preview_w; |
240 | imagebounds.bottom = imagebounds.top + preview_h; |
||
241 | |||
89 | toby | 242 | preview_pmap.baseAddr = imageptr; |
94 | toby | 243 | preview_pmask.maskData = imageptr+3; // FIXME: is this offset correct for all modes?! |
2 | toby | 244 | |
245 | if(gpb->propertyProcs->getPropertyProc){ |
||
246 | gpb->propertyProcs->getPropertyProc(kPhotoshopSignature,propWatchSuspension,0,&watchsusp,NULL); |
||
247 | gpb->propertyProcs->setPropertyProc(kPhotoshopSignature,propWatchSuspension,0,watchsusp+1,NULL); |
||
248 | } |
||
89 | toby | 249 | |
2 | toby | 250 | e = gpb->displayPixels(&preview_pmap,&srcRect,imagebounds.top,imagebounds.left,hdc); |
251 | |||
252 | if(gpb->propertyProcs->getPropertyProc) |
||
253 | gpb->propertyProcs->setPropertyProc(kPhotoshopSignature,propWatchSuspension,0,watchsusp,NULL); |
||
254 | } |
||
255 | return e; |
||
256 | } |