Subversion Repositories filter_foundry

Rev

Rev 154 | Rev 176 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.     This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
  3.     Copyright (C) 2003-2019 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.  
  22. #include "file_compat.h"
  23.  
  24. #ifdef MAC_ENV
  25. #include <Endian.h>
  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. }
  33. #endif
  34.  
  35. enum{
  36.         BUFSIZE = 4L<<10,
  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.  
  45.         if(!h){
  46.                 *reason = "readparams: Null parameter handle.";
  47.                 return false;
  48.         }
  49.  
  50.         p = PILOCKHANDLE(h,false);
  51.         dataend = p + PIGETHANDLESIZE(h);
  52.  
  53.         q = curexpr;
  54.         linecnt = exprcnt = lineptr = 0;
  55.  
  56.         *reason = "File was too short.";
  57.         while(p < dataend){
  58.  
  59.                 c = *p++;
  60.  
  61.                 if(c==CR || c==LF){ /* detected end of line */
  62.  
  63.                         /* look ahead to see if we need to skip a line feed (DOS EOL convention) */
  64.                         if(c == CR && *p == LF && p < dataend)
  65.                                 ++p;
  66.  
  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)
  73.                                                 *reason = "This doesn't look like a Filter Factory file (first line is not \"%RGB-1.0\").";
  74.                                         break;
  75.                                 }
  76.                         }else if(linecnt<=8){
  77.                                 slider[linecnt-1] = atoi(linebuf);
  78.                         }else{
  79.                                 if(lineptr){
  80.                                         /* it's not an empty line; append it to current expr string */
  81.                                         if( q+lineptr > curexpr+MAXEXPR ){
  82.                                                 *reason = "Found an expression longer than 1024 characters.";
  83.                                                 break;
  84.                                         }
  85.                                         q = cat(q,linebuf);
  86.                                 }else{
  87.                                         /* it's an empty line: we've completed the expr string */
  88.                                         if(expr[exprcnt])
  89.                                                 free(expr[exprcnt]);
  90.                                         *q = 0;
  91.                                         if(!(expr[exprcnt] = my_strdup(curexpr))){
  92.                                                 *reason = "Could not get memory for expression.";
  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.                         }
  104.  
  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;
  115.                                         default:
  116.                                                 if(alerts) alertuser("Warning:","Unknown escape sequence in input.");
  117.                                         }
  118.                                 }//else if(alerts) alertuser("Warning:","truncated escape sequence ends input");
  119.                         }
  120.  
  121.                         if(lineptr < MAXLINE)
  122.                                 linebuf[lineptr++] = c;
  123.                 }
  124.         }
  125.  
  126.         PIUNLOCKHANDLE(h);
  127.  
  128.         return res;
  129. }
  130.  
  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;
  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));
  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]));
  160.                 memcpy((void*)photoshop->formula[3], (void*)premiere->formula[3], sizeof(photoshop->formula[3]));
  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.  
  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;
  180.                 if(!FSRead(refnum,&count,magic) /*&& magic[0]=='M' && magic[1]=='Z'*/){
  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 )
  188.                                         {
  189.  
  190. #ifdef MAC_ENV
  191.                                                 // Case #1: Mac is reading Windows (Win16/32) plugin
  192.                                                 if( ((EndianS32_LtoN(q[0]) == PARM_SIZE) ||
  193.                                                      (EndianS32_LtoN(q[0]) == PARM_SIZE_PREMIERE) ||
  194.                                                      (EndianS32_LtoN(q[0]) == PARM_SIG_MAC)) && EndianS32_LtoN(q[1]) == 1
  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
  203.                                                 // Case #2: Windows is reading a Windows plugin (if Resource API failed, i.e. Win64 tries to open NE file)
  204.                                                 if( ((q[0] == PARM_SIZE) ||
  205.                                                      (q[0] == PARM_SIZE_PREMIERE) ||
  206.                                                      (q[0] == PARM_SIG_MAC)) && q[1] == 1
  207.                                                         && (res = readPARM((char*)q, &gdata->parm, reason, 1)) )
  208.                                                 {
  209.                                                 }
  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.                                                 }
  222. #endif
  223.  
  224.                                                 if (res) break;
  225.                                         }
  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.  
  236. Boolean readPARM(Ptr p,PARM_T *pparm,char **reasonstr,int fromwin){
  237.         int i;
  238.  
  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.         }
  245.  
  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);
  252.                 for(i = 0; i < 4; ++i)
  253.                         myc2pstr((char*)pparm->map[i]);
  254.                 for(i = 0; i < 8; ++i)
  255.                         myc2pstr((char*)pparm->ctl[i]);
  256.         }
  257.  
  258.         for(i = 0; i < 4; ++i){
  259.                 if(expr[i]) free(expr[i]);
  260.                 expr[i] = my_strdup(pparm->formula[i]);
  261.         }
  262.  
  263.         for(i = 0; i < 8; ++i)
  264.                 slider[i] = pparm->val[i];
  265.  
  266.         return true;
  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);
  276.                 if(!SetFPos(r,fsFromStart,0) && !FSRead(r,&n,p)){
  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)){
  291.                 if( (h = readfileintohandle(r)) ){
  292.                         if( (res = readparams(h,true,reason)) ) {
  293.                                 gdata->standalone = false; // so metadata fields will default, if user chooses Make...
  294.  
  295.                                 if (sfr->nFileExtension && !strcasecmp((char*)sfr->sfFile.name + sfr->nFileExtension,".pff")) {
  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.                                 }
  303.                         }
  304.  
  305.                         PIDISPOSEHANDLE(h);
  306.                 }
  307.                 FSClose(r);
  308.         }else
  309.                 *reason = "Could not open the file.";
  310.  
  311.         return res;
  312. }
  313.