Subversion Repositories filter_foundry

Rev

Rev 154 | Rev 176 | 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
171 dmarschall 3
    Copyright (C) 2003-2019 Toby Thain, toby@telegraphics.com.au
2 toby 4
 
5
    This program is free software; you can redistribute it and/or modify
131 dmarschall 6
    it under the terms of the GNU General Public License as published by
2 toby 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
 
131 dmarschall 15
    You should have received a copy of the GNU General Public License
2 toby 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
 
22
#include "file_compat.h"
23
 
149 dmarschall 24
#ifdef MAC_ENV
25
#include <Endian.h>
152 dmarschall 26
#else
27
int EndianS32_LtoN(int num) {
28
        return ((num>>24)&0xff) | // move byte 3 to byte 0
29
               ((num<<8)&0xff0000) | // move byte 1 to byte 2
30
               ((num>>8)&0xff00) | // move byte 2 to byte 1
31
               ((num<<24)&0xff000000); // byte 0 to byte 3
32
}
149 dmarschall 33
#endif
34
 
2 toby 35
enum{
85 toby 36
        BUFSIZE = 4L<<10,
2 toby 37
        MAXLINE = 0x200,
38
};
39
 
40
Boolean readparams(Handle h,Boolean alerts,char **reason){
41
        Boolean res = false;
42
        char linebuf[MAXLINE+1],curexpr[MAXEXPR+1],*p,*dataend,*q;
43
        int c,linecnt,lineptr,exprcnt;
44
 
15 toby 45
        if(!h){
46
                *reason = "readparams: Null parameter handle.";
47
                return false;
48
        }
49
 
2 toby 50
        p = PILOCKHANDLE(h,false);
51
        dataend = p + PIGETHANDLESIZE(h);
131 dmarschall 52
 
2 toby 53
        q = curexpr;
54
        linecnt = exprcnt = lineptr = 0;
55
 
56
        *reason = "File was too short.";
85 toby 57
        while(p < dataend){
2 toby 58
 
59
                c = *p++;
60
 
61
                if(c==CR || c==LF){ /* detected end of line */
131 dmarschall 62
 
2 toby 63
                        /* look ahead to see if we need to skip a line feed (DOS EOL convention) */
131 dmarschall 64
                        if(c == CR && *p == LF && p < dataend)
2 toby 65
                                ++p;
131 dmarschall 66
 
2 toby 67
                        linebuf[lineptr] = 0; /* add terminating NUL to line buffer */
68
 
69
                        /* process complete line */
70
                        if(linecnt==0){
71
                                if(strcmp(linebuf,"%RGB-1.0")){
72
                                        if(alerts)
85 toby 73
                                                *reason = "This doesn't look like a Filter Factory file (first line is not \"%RGB-1.0\").";
2 toby 74
                                        break;
75
                                }
76
                        }else if(linecnt<=8){
77
                                slider[linecnt-1] = atoi(linebuf);
78
                        }else{
131 dmarschall 79
                                if(lineptr){
2 toby 80
                                        /* it's not an empty line; append it to current expr string */
81
                                        if( q+lineptr > curexpr+MAXEXPR ){
85 toby 82
                                                *reason = "Found an expression longer than 1024 characters.";
2 toby 83
                                                break;
84
                                        }
85
                                        q = cat(q,linebuf);
86
                                }else{
87
                                        /* it's an empty line: we've completed the expr string */
131 dmarschall 88
                                        if(expr[exprcnt])
2 toby 89
                                                free(expr[exprcnt]);
90
                                        *q = 0;
91
                                        if(!(expr[exprcnt] = my_strdup(curexpr))){
85 toby 92
                                                *reason = "Could not get memory for expression.";
2 toby 93
                                                break;
94
                                        }
95
 
96
                                        if(++exprcnt == 4){
97
                                                res = true;
98
                                                break; /* got everything we want */
99
                                        }
100
 
101
                                        q = curexpr; /* empty current expr, ready for next one */
102
                                }
103
                        }
131 dmarschall 104
 
2 toby 105
                        ++linecnt;
106
                        lineptr = 0;
107
                }else{
108
                        /* store character */
109
                        if(c=='\\'){ /* escape sequence */
110
                                if(p < dataend){
111
                                        c = *p++;
112
                                        switch(c){
113
                                        case 'r': c = CR;
114
                                        case '\\': break;
131 dmarschall 115
                                        default:
2 toby 116
                                                if(alerts) alertuser("Warning:","Unknown escape sequence in input.");
117
                                        }
131 dmarschall 118
                                }//else if(alerts) alertuser("Warning:","truncated escape sequence ends input");
2 toby 119
                        }
120
 
121
                        if(lineptr < MAXLINE)
122
                                linebuf[lineptr++] = c;
123
                }
124
        }
131 dmarschall 125
 
2 toby 126
        PIUNLOCKHANDLE(h);
127
 
128
        return res;
129
}
130
 
145 dmarschall 131
void convert_premiere_to_photoshop(PARM_T* photoshop, PARM_T_PREMIERE* premiere) {
132
        int i;
133
 
134
        photoshop->cbSize = sizeof(PARM_T);
135
        photoshop->standalone = premiere->standalone;
136
        for (i=0;i<8;++i)
137
          photoshop->val[i] = premiere->val[i];
138
        photoshop->popDialog = premiere->popDialog;
139
        photoshop->unknown1 = premiere->unknown1;
140
        photoshop->unknown2 = premiere->unknown2;
141
        photoshop->unknown3 = premiere->unknown3;
142
        for (i=0;i<4;++i)
143
          photoshop->map_used[i] = premiere->map_used[i];
144
        for (i=0;i<8;++i)
145
          photoshop->ctl_used[i] = premiere->ctl_used[i];
146
        memcpy((void*)photoshop->category, (void*)premiere->category, sizeof(photoshop->category));
147
        photoshop->iProtected = premiere->iProtected;
146 dmarschall 148
        memcpy((void*)photoshop->title, (void*)premiere->title, sizeof(photoshop->title));
149
        memcpy((void*)photoshop->copyright, (void*)premiere->copyright, sizeof(photoshop->copyright));
150
        memcpy((void*)photoshop->author, (void*)premiere->author, sizeof(photoshop->author));
145 dmarschall 151
        for (i=0;i<4;++i)
152
          memcpy((void*)photoshop->map[i], (void*)premiere->map[i], sizeof(photoshop->map[i]));
153
        for (i=0;i<8;++i)
154
          memcpy((void*)photoshop->ctl[i], (void*)premiere->ctl[i], sizeof(photoshop->ctl[i]));
155
 
156
        if (premiere->singleExpression) {
157
                memcpy((void*)photoshop->formula[0], (void*)premiere->formula[3], sizeof(photoshop->formula[3]));
158
                memcpy((void*)photoshop->formula[1], (void*)premiere->formula[3], sizeof(photoshop->formula[3]));
159
                memcpy((void*)photoshop->formula[2], (void*)premiere->formula[3], sizeof(photoshop->formula[3]));
146 dmarschall 160
                memcpy((void*)photoshop->formula[3], (void*)premiere->formula[3], sizeof(photoshop->formula[3]));
145 dmarschall 161
        } else {
162
                memcpy((void*)photoshop->formula[0], (void*)premiere->formula[2], sizeof(photoshop->formula[2]));
163
                memcpy((void*)photoshop->formula[1], (void*)premiere->formula[1], sizeof(photoshop->formula[1]));
164
                memcpy((void*)photoshop->formula[2], (void*)premiere->formula[0], sizeof(photoshop->formula[0]));
165
                memcpy((void*)photoshop->formula[3], (void*)premiere->formula[3], sizeof(photoshop->formula[3]));
166
        }
167
}
168
 
149 dmarschall 169
Boolean read8bfplugin(StandardFileReply *sfr,char **reason){
170
        unsigned char magic[2];
171
        long count;
172
        Handle h;
173
        Boolean res = false;
174
        FILEREF refnum;
175
        int i;
176
 
177
        if(!FSpOpenDF(&sfr->sfFile,fsRdPerm,&refnum)){
178
                // check DOS EXE magic number
179
                count = 2;
152 dmarschall 180
                if(!FSRead(refnum,&count,magic) /*&& magic[0]=='M' && magic[1]=='Z'*/){
149 dmarschall 181
                        if(!GetEOF(refnum,&count) && count < 256L<<10){ // sanity check file size < 256K
182
                                if( (h = readfileintohandle(refnum)) ){
183
                                        long *q = (long*)PILOCKHANDLE(h,false);
184
 
185
                                        // look for signature at start of valid PARM resource
186
                                        // This signature is observed in Filter Factory standalones.
187
                                        for( count /= 4 ; count >= PARM_SIZE/4 ; --count, ++q )
152 dmarschall 188
                                        {
149 dmarschall 189
 
190
#ifdef MAC_ENV
152 dmarschall 191
                                                // Case #1: Mac is reading Windows (Win16/32) plugin
149 dmarschall 192
                                                if( ((EndianS32_LtoN(q[0]) == PARM_SIZE) ||
193
                                                     (EndianS32_LtoN(q[0]) == PARM_SIZE_PREMIERE) ||
152 dmarschall 194
                                                     (EndianS32_LtoN(q[0]) == PARM_SIG_MAC)) && EndianS32_LtoN(q[1]) == 1
149 dmarschall 195
                                                        && (res = readPARM((char*)q, &gdata->parm, reason, 1 /*Windows format resource*/)) )
196
                                                {
197
                                                        // these are the only numeric fields we *have* to swap
198
                                                        // all the rest are flags which (if we're careful) will work in either ordering
199
                                                        for(i = 0; i < 8; ++i)
200
                                                                slider[i] = EndianS32_LtoN(slider[i]);
201
                                                }
202
#else
152 dmarschall 203
                                                // Case #2: Windows is reading a Windows plugin (if Resource API failed, i.e. Win64 tries to open NE file)
149 dmarschall 204
                                                if( ((q[0] == PARM_SIZE) ||
205
                                                     (q[0] == PARM_SIZE_PREMIERE) ||
152 dmarschall 206
                                                     (q[0] == PARM_SIG_MAC)) && q[1] == 1
207
                                                        && (res = readPARM((char*)q, &gdata->parm, reason, 1)) )
149 dmarschall 208
                                                {
209
                                                }
152 dmarschall 210
 
211
                                                // Case #3: Windows is reading an old FilterFactory Mac file (.bin)
212
                                                else if( ((EndianS32_LtoN(q[0]) == PARM_SIZE) ||
213
                                                     (EndianS32_LtoN(q[0]) == PARM_SIZE_PREMIERE) ||
214
                                                     (EndianS32_LtoN(q[0]) == PARM_SIG_MAC)) && EndianS32_LtoN(q[1]) == 1
215
                                                        && (res = readPARM((char*)q, &gdata->parm, reason, 0 /*Strings are already PStrings*/)) )
216
                                                {
217
                                                        // these are the only numeric fields we *have* to swap
218
                                                        // all the rest are flags which (if we're careful) will work in either ordering
219
                                                        for(i = 0; i < 8; ++i)
220
                                                                slider[i] = EndianS32_LtoN(slider[i]);
221
                                                }
149 dmarschall 222
#endif
223
 
152 dmarschall 224
                                                if (res) break;
225
                                        }
149 dmarschall 226
                                        PIDISPOSEHANDLE(h);
227
                                }
228
                        }
229
                } // else no point in proceeding
230
                FSClose(refnum);
231
        }else
232
                *reason = "Could not open file.";
233
        return res;
234
}
235
 
45 toby 236
Boolean readPARM(Ptr p,PARM_T *pparm,char **reasonstr,int fromwin){
2 toby 237
        int i;
238
 
145 dmarschall 239
        if (*((unsigned int*)p) == PARM_SIZE_PREMIERE) {
240
                convert_premiere_to_photoshop(pparm, (PARM_T_PREMIERE*)p);
241
        } else {
242
                // Assume it is Photoshop. Signature either PARM_SIZE (0x2068) or 0x1C68
243
                memcpy(pparm,p,sizeof(PARM_T));
244
        }
2 toby 245
 
45 toby 246
        if(fromwin){
247
                /* Windows PARM resource stores C strings - convert to Pascal strings  */
248
                myc2pstr((char*)pparm->category);
249
                myc2pstr((char*)pparm->title);
250
                myc2pstr((char*)pparm->copyright);
251
                myc2pstr((char*)pparm->author);
85 toby 252
                for(i = 0; i < 4; ++i)
45 toby 253
                        myc2pstr((char*)pparm->map[i]);
85 toby 254
                for(i = 0; i < 8; ++i)
45 toby 255
                        myc2pstr((char*)pparm->ctl[i]);
256
        }
257
 
85 toby 258
        for(i = 0; i < 4; ++i){
2 toby 259
                if(expr[i]) free(expr[i]);
260
                expr[i] = my_strdup(pparm->formula[i]);
261
        }
262
 
85 toby 263
        for(i = 0; i < 8; ++i)
2 toby 264
                slider[i] = pparm->val[i];
265
 
45 toby 266
        return true;
2 toby 267
}
268
 
269
Handle readfileintohandle(FILEREF r){
270
        long n;
271
        Handle h;
272
        Ptr p;
273
 
274
        if( !GetEOF(r,&n) && (h = PINEWHANDLE(n)) ){
275
                p = PILOCKHANDLE(h,false);
45 toby 276
                if(!SetFPos(r,fsFromStart,0) && !FSRead(r,&n,p)){
2 toby 277
                        PIUNLOCKHANDLE(h);
278
                        return h;
279
                }
280
                PIDISPOSEHANDLE(h);
281
        }
282
        return NULL;
283
}
284
 
285
Boolean readfile(StandardFileReply *sfr,char **reason){
286
        FILEREF r;
287
        Handle h;
288
        Boolean res = false;
289
 
290
        if(!FSpOpenDF(&sfr->sfFile,fsRdPerm,&r)){
23 toby 291
                if( (h = readfileintohandle(r)) ){
153 dmarschall 292
                        if( (res = readparams(h,true,reason)) ) {
2 toby 293
                                gdata->standalone = false; // so metadata fields will default, if user chooses Make...
145 dmarschall 294
 
154 dmarschall 295
                                if (sfr->nFileExtension && !strcasecmp((char*)sfr->sfFile.name + sfr->nFileExtension,".pff")) {
153 dmarschall 296
                                        // If it is a Premiere settings file, we need to swap the channels red and blue
297
                                        char* tmp;
298
                                        tmp = my_strdup(expr[0]);
299
                                        memcpy((void*)expr[0], (void*)expr[2], sizeof(expr[0]));
300
                                        memcpy((void*)expr[2], (void*)tmp, sizeof(expr[2]));
301
                                        free(tmp);
302
                                }
145 dmarschall 303
                        }
304
 
2 toby 305
                        PIDISPOSEHANDLE(h);
306
                }
307
                FSClose(r);
308
        }else
85 toby 309
                *reason = "Could not open the file.";
2 toby 310
 
311
        return res;
312
}