Subversion Repositories filter_foundry

Compare Revisions

Regard whitespace Rev 536 → Rev 537

/trunk/README.md
58,11 → 58,14
|PRM |Adobe Premiere plugin created by Filter/Transaction Factory for Adobe Premiere. | | |Yes |
|FFX |"Filters Unlimited" file. | | |Yes(2)|
|TXT |A text file created by "Plugin Commander" or "FFDecomp". | |Yes(3)|Yes |
|GUF |A filter file created by "GIMP UserFilter" | |TODO |TODO(2)|
|BIN or RSRC |Standalone filter created by Filter Factory/Foundry for Mac. | | |Yes |
 
Currently not supported are FFL (Filter Library) files.
 
(1) Loading is only possible if the 8BF file was created by Filter Factory, or by Filter Foundry without protection.
 
(2) Note that Filter Foundry only implements the basic Filter Factory commands. Therefore, most "Filters Unlimited" filters will not work with Filter Foundry.
(2) Note that Filter Foundry only implements the basic Filter Factory commands. Therefore, most "Filters Unlimited" filters as well as some "GIMP UserFilter" filters will not work with Filter Foundry.
 
(3) Title, Category, Author, Copyright, and Slider/Map names are left empty and must be added using a text editor.
 
/trunk/TODO.md
5,8 → 5,12
ToDo for the next release
-------------------------
 
(None)
* Finish implementation of GUF format ( http://gimpuserfilter.sourceforge.net/ )
 
saveparams_guf()
_gufReadProperty()
README.md
Documentation (DOCX, PDF)
 
Known problems
--------------
30,8 → 34,6
 
* Import FFL format (but which filter to select?)
 
* Import GUF format ( http://gimpuserfilter.sourceforge.net/ )
 
* If controls are ambigous e.g. ctl(3+c), then you should be able to disable control in the "Make" dialog. Like in Filter Factory.
 
* When you open a file, e.g. "Test.8bf" and you want to save it again, it would be good, if the default output filename is "Test".
/trunk/ff.h
144,7 → 144,8
Handle readfileintohandle(FILEREF r);
Boolean readfile_afs_pff(StandardFileReply* sfr, TCHAR** reason);
Boolean readfile_ffx(StandardFileReply* sfr, TCHAR** reason);
Boolean readfile_picotxt(StandardFileReply* sfr, TCHAR** reason);
Boolean readfile_picotxt_or_ffdecomp(StandardFileReply* sfr, TCHAR** reason);
Boolean readfile_guf(StandardFileReply* sfr, TCHAR** reason);
Boolean readPARM(PARM_T* parm,Ptr h);
 
// from save.c
151,7 → 152,7
OSErr saveparams_afs_pff(Handle h);
OSErr saveparams_picotxt(Handle h, Boolean useparm);
OSErr savehandleintofile(Handle h,FILEREF r);
Boolean savefile_afs_pff_picotxt(StandardFileReply *sfr);
Boolean savefile_afs_pff_picotxt_guf(StandardFileReply *sfr);
 
// from make_*.c
OSErr make_standalone(StandardFileReply *sfr);
/trunk/language.h
18,11 → 18,12
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
 
// Attention: Please save this file as UTF-8 without BOM!
 
#ifndef LANGUAGE_H_
#define LANGUAGE_H_
 
// Attention: Please save this file as UTF-8 without BOM!
// Also, if you extend this, please also extend language_win.rc!
 
#define MSG_PREMIERE_COMPAT_ID 1
#define MSG_PREMIERE_COMPAT_ENUS "This version of Filter Foundry is not compatible with Adobe Premiere!";
#define MSG_PREMIERE_COMPAT_DEDE "Diese Version von Filter Foundry ist mit Adobe Premiere nicht kompatibel!"
251,7 → 252,18
#define MSG_ABOUT_CONTACT_AUTHOR_ENUS "Please contact the author with any bug reports,\nsuggestions or comments.\nIf you use this program and like it, please consider\nmaking a donation."
#define MSG_ABOUT_CONTACT_AUTHOR_DEDE "Bitte kontaktieren Sie den Autor für Fehlerberichte,\nAnregungen und Kommentare.\nWenn Sie dieses Programm mögen,\nerwägen Sie bitte eine kleine Spende."
 
#define MSG_OPEN_GUF_ID 58
#define MSG_OPEN_GUF_ENUS """GIMP UserFilter"" filter"
#define MSG_OPEN_GUF_DEDE """GIMP UserFilter"" Filter"
 
#define MSG_SAVE_GUF_ID 59
#define MSG_SAVE_GUF_ENUS """GIMP UserFilter"" filter"
#define MSG_SAVE_GUF_DEDE """GIMP UserFilter"" Filter"
 
#define MSG_INCOMPATIBLE_GUF_FILE_ID 60
#define MSG_INCOMPATIBLE_GUF_FILE_ENUS "Incompatible GIMP UserFilter File"
#define MSG_INCOMPATIBLE_GUF_FILE_DEDE "Inkompatible GIMP UserFilter Datei"
 
void strcpy_advance_id(TCHAR** str, int msgid);
int FF_GetMsg(TCHAR* ret, int MsgId);
TCHAR* FF_GetMsg_Cpy(int MsgId);
/trunk/language_win.rc
82,6 → 82,9
MSG_ABOUT_BUILT_USING_ID, MSG_ABOUT_BUILT_USING_ENUS
MSG_ABOUT_LATEST_VERSION_FROM_ID, MSG_ABOUT_LATEST_VERSION_FROM_ENUS
MSG_ABOUT_CONTACT_AUTHOR_ID, MSG_ABOUT_CONTACT_AUTHOR_ENUS
MSG_OPEN_GUF_ID, MSG_OPEN_GUF_ENUS
MSG_SAVE_GUF_ID, MSG_SAVE_GUF_ENUS
MSG_INCOMPATIBLE_GUF_FILE_ID, MSG_INCOMPATIBLE_GUF_FILE_ENUS
}
 
LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
146,5 → 149,8
MSG_ABOUT_BUILT_USING_ID, MSG_ABOUT_BUILT_USING_DEDE
MSG_ABOUT_LATEST_VERSION_FROM_ID, MSG_ABOUT_LATEST_VERSION_FROM_DEDE
MSG_ABOUT_CONTACT_AUTHOR_ID, MSG_ABOUT_CONTACT_AUTHOR_DEDE
MSG_OPEN_GUF_ID, MSG_OPEN_GUF_DEDE
MSG_SAVE_GUF_ID, MSG_SAVE_GUF_DEDE
MSG_INCOMPATIBLE_GUF_FILE_ID, MSG_INCOMPATIBLE_GUF_FILE_DEDE
 
}
/trunk/load_win.c
131,12 → 131,20
 
// Is it a "Filters Unlimited" filter? (Only partially compatible with Filter Factory!!!)
if (reasonstr == NULL) {
if (readfile_picotxt(sfr, &reasonstr)) {
if (readfile_picotxt_or_ffdecomp(sfr, &reasonstr)) {
gdata->parmloaded = true;
return true;
}
}
 
// Is it a "GIMP UserFilter (GUF)" file? (Only partially compatible with Filter Factory!!!)
if (reasonstr == NULL) {
if (readfile_guf(sfr, &reasonstr)) {
gdata->parmloaded = true;
return true;
}
}
 
// If nothing worked, we will try to find a PARM resource (MacOS plugin, or 64 bit 8BF on Win32 OS)
// Note that we cannot detect obfuscated filters here!
if (reasonstr == NULL) {
/trunk/main.c
421,7 → 421,7
expr[3] = _strdup("a");
}
 
savefile_afs_pff_picotxt(&sfr);
savefile_afs_pff_picotxt_guf(&sfr);
 
if (gdata->standalone) {
for (i = 0; i < 4; i++) {
/trunk/read.c
700,7 → 700,7
return true;
}
 
Boolean readfile_picotxt(StandardFileReply* sfr, TCHAR** reason) {
Boolean readfile_picotxt_or_ffdecomp(StandardFileReply* sfr, TCHAR** reason) {
extern int ctls[], maps[];
 
Handle h;
741,17 → 741,15
expr[i] = my_strdup(gdata->parm.szFormula[i]);
}
 
for (i = 0; i < 8; i++) {
int v;
char keyname[7+1], tmp[5];
 
// Slider names
for (i = 0; i < 8; i++) {
char keyname[7];
sprintf(keyname, "ctl[%d]", i);
_picoReadProperty(q, count, keyname, gdata->parm.szCtl[i], sizeof(gdata->parm.szCtl[i]), false);
}
 
// Slider values
for (i = 0; i < 8; i++) {
char keyname[7], tmp[5];
int v;
sprintf(keyname, "val[%d]", i);
if (!_picoReadProperty(q, count, keyname, tmp, sizeof(tmp), false)) {
sprintf(keyname, "def[%d]", i);
767,7 → 765,7
 
// Map names
for (i = 0; i < 4; i++) {
char keyname[7];
char keyname[7+1];
sprintf(keyname, "map[%d]", i);
_picoReadProperty(q, count, keyname, gdata->parm.szMap[i], sizeof(gdata->parm.szMap[i]), false);
}
789,6 → 787,102
return res;
}
 
Boolean _gufReadProperty(char* inputFile, size_t maxInput, const char* section, const char* property, char* outputFile, size_t maxOutput) {
// TODO: Implement
return false;
}
 
Boolean readfile_guf(StandardFileReply* sfr, TCHAR** reason) {
extern int ctls[], maps[];
 
Handle h;
Boolean res = false;
FILEREF refnum;
 
if (!fileHasExtension(sfr, TEXT(".guf"))) return false;
 
if (FSpOpenDF(&sfr->sfFile, fsRdPerm, &refnum) == noErr) {
if ((h = readfileintohandle(refnum))) {
FILECOUNT count = (FILECOUNT)PIGETHANDLESIZE(h);
char* q = PILOCKHANDLE(h, false);
 
char out[256];
if (_gufReadProperty(q, count, "GUF", "Protocol", out, sizeof(out))) {
if (!strcmp(out, "1")) {
if (reason) *reason = FF_GetMsg_Cpy(MSG_INCOMPATIBLE_GUF_FILE_ID);
return false;
}
}
else {
if (reason) *reason = FF_GetMsg_Cpy(MSG_INCOMPATIBLE_GUF_FILE_ID);
return false;
}
if (_gufReadProperty(q, count, "Info", "Title", out, sizeof(out))) {
int i;
 
// Plugin infos
_gufReadProperty(q, count, "Info", "Title", gdata->parm.szTitle, sizeof(gdata->parm.szTitle));
_gufReadProperty(q, count, "Info", "Category", gdata->parm.szCategory, sizeof(gdata->parm.szCategory)); // TODO: only last part of "/"
_gufReadProperty(q, count, "Info", "Author", gdata->parm.szAuthor, sizeof(gdata->parm.szAuthor));
_gufReadProperty(q, count, "Info", "Copyright", gdata->parm.szCopyright, sizeof(gdata->parm.szCopyright));
//_gufReadProperty(q, count, "Filter Factory", "8bf", gdata->parm.xxx, sizeof(gdata->parm.xxx));
 
// Expressions
if (!_gufReadProperty(q, count, "Code", "R", gdata->parm.szFormula[0], sizeof(gdata->parm.szFormula[0])))
strcpy(gdata->parm.szFormula[0], "r");
if (!_gufReadProperty(q, count, "Code", "G", gdata->parm.szFormula[1], sizeof(gdata->parm.szFormula[1])))
strcpy(gdata->parm.szFormula[1], "g");
if (!_gufReadProperty(q, count, "Code", "B", gdata->parm.szFormula[2], sizeof(gdata->parm.szFormula[2])))
strcpy(gdata->parm.szFormula[2], "b");
if (!_gufReadProperty(q, count, "Code", "A", gdata->parm.szFormula[3], sizeof(gdata->parm.szFormula[3])))
strcpy(gdata->parm.szFormula[3], "a");
for (i = 0; i < 4; i++) {
if (expr[i]) free(expr[i]);
expr[i] = my_strdup(gdata->parm.szFormula[i]);
}
 
for (i = 0; i < 8; i++) {
int v;
char keyname[10 + 1], tmp[5];
sprintf(keyname, "Control %d", i);
 
// Slider names
_gufReadProperty(q, count, keyname, "Label", gdata->parm.szCtl[i], sizeof(gdata->parm.szCtl[i]));
 
// Slider values
if (!_gufReadProperty(q, count, keyname, "Preset", tmp, sizeof(tmp))) {
strcpy(tmp, "0");
}
v = atoi(tmp);
if (v < 0) v = 0;
else if (v > 255) v = 255;
gdata->parm.val[i] = slider[i] = (uint8_t)v;
}
 
// Map names
for (i = 0; i < 4; i++) {
char keyname[6 + 1];
sprintf(keyname, "Map %d", i);
_gufReadProperty(q, count, keyname, "Label", gdata->parm.szMap[i], sizeof(gdata->parm.szMap[i]));
}
 
//These will be set when the expressions are evaluated anyway. So this part is optional:
checksliders(4, ctls, maps);
for (i = 0; i < 8; i++) gdata->parm.ctl_used[i] = ctls[i];
for (i = 0; i < 4; i++) gdata->parm.map_used[i] = maps[i];
 
res = true;
}
 
PIUNLOCKHANDLE(h);
PIDISPOSEHANDLE(h);
}
FSClose(refnum);
}
 
return res;
}
 
Boolean readfile_afs_pff(StandardFileReply *sfr, TCHAR**reason){
FILEREF r;
Handle h;
/trunk/save.c
201,6 → 201,11
return e;
}
 
OSErr saveparams_guf(Handle h, Boolean useparm) {
// TODO: implement
return NULL;
}
 
OSErr savehandleintofile(Handle h,FILEREF r){
Ptr p;
FILECOUNT n;
214,7 → 219,7
return e;
}
 
Boolean savefile_afs_pff_picotxt(StandardFileReply *sfr){
Boolean savefile_afs_pff_picotxt_guf(StandardFileReply *sfr){
FILEREF r;
Handle h;
Boolean res = false;
232,6 → 237,14
}
}
 
if (fileHasExtension(sfr, TEXT(".guf"))) {
// GIMP UserFilter file
if ((h = PINEWHANDLE(1))) { // don't set initial size to 0, since some hosts (e.g. GIMP/PSPI) are incompatible with that.
res = !(saveparams_guf(h, false) || savehandleintofile(h, r));
PIDISPOSEHANDLE(h);
}
}
 
if ((fileHasExtension(sfr, TEXT(".afs"))) || (fileHasExtension(sfr, TEXT(".pff")))) {
if (fileHasExtension(sfr, TEXT(".pff"))) {
// If it is a Premiere settings file, we need to swap the channels red and blue
/trunk/testcases/import/gimp_userfilter.guf
0,0 → 1,91
# Created with User Filter v0.9.7.
 
[GUF]
Protocol=1
 
[Info]
Category=<Image>/UserFilter/Alf's Filter Factory
Title=Color Grid...
Copyright=Copyright © 1995 Alfredo MateusAll Rights Reserved.
Author=Alfredo Mateus
 
[Version]
Major=1
Minor=0
Micro=0
 
[Filter Factory]
8bf=11 COLGRID.8bf
 
[Gimp]
Registered=false
Description=Imported 8BF filter.
EdgeMode=2
Date=1995-01-01
 
[Control 0]
Enabled=true
Label=Horizontal Divisions
Preset=5
Step=1
 
[Control 1]
Enabled=true
Label=Vertical Divisions
Preset=5
Step=1
 
[Control 2]
Enabled=false
Preset=0
Step=1
Label=Control 2
 
[Control 3]
Enabled=true
Label=Red
Preset=0
Step=1
 
[Control 4]
Enabled=true
Label=Green
Preset=0
Step=1
 
[Control 5]
Enabled=true
Label=Blue
Preset=0
Step=1
 
[Control 6]
Enabled=false
Preset=0
Step=1
 
[Control 7]
Enabled=false
Preset=0
Step=1
 
[Map 0]
Enabled=true
Label=Map 0:
 
[Map 1]
Enabled=false
Label=Map 1
 
[Map 2]
Enabled=true
Label=Map 2:
 
[Map 3]
Enabled=false
 
[Code]
R=(y>0)&&(x>0)&(x%(X/ctl(0))==0)|(y%(Y/ctl(1))==0)?ctl(3):c
G=(y>0)&&(x>0)&(x%(X/ctl(0))==0)|(y%(Y/ctl(1))==0)?ctl(4):c
B=(y>0)&&(x>0)&(x%(X/ctl(0))==0)|(y%(Y/ctl(1))==0)?ctl(5):c
A=a
/trunk/ui.c
378,8 → 378,8
FF_GetMsg(title, MSG_LOAD_FILTER_SETTINGS_TITLE_ID);
 
strcpy_advance_id(&tmp1, MSG_ALL_SUPPORTED_FILES_ID);
strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.afs, *.8bf, *.pff, *.prm, *.bin, *.rsrc, *.txt, *.ffx)")); tmp1++;
strcpy_advance(&tmp1, (TCHAR*)TEXT("*.afs;*.8bf;*.pff;*.prm;*.bin;*.rsrc;*.txt;*.ffx")); tmp1++;
strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.afs, *.8bf, *.pff, *.prm, *.bin, *.rsrc, *.txt, *.ffx, *.guf)")); tmp1++;
strcpy_advance(&tmp1, (TCHAR*)TEXT("*.afs;*.8bf;*.pff;*.prm;*.bin;*.rsrc;*.txt;*.ffx;*.guf")); tmp1++;
 
strcpy_advance_id(&tmp1, MSG_OPEN_AFS_ID);
strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.afs)")); tmp1++;
409,6 → 409,10
strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.ffx)")); tmp1++;
strcpy_advance(&tmp1, (TCHAR*)TEXT("*.ffx")); tmp1++;
 
strcpy_advance_id(&tmp1, MSG_OPEN_GUF_ID);
strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.guf)")); tmp1++;
strcpy_advance(&tmp1, (TCHAR*)TEXT("*.guf")); tmp1++;
 
strcpy_advance_id(&tmp1, MSG_ALL_FILES_ID);
strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.*)")); tmp1++;
strcpy_advance(&tmp1, (TCHAR*)TEXT("*.*")); tmp1++;
462,8 → 466,8
FF_GetMsg(title, MSG_SAVE_FILTER_SETTINGS_TITLE_ID);
 
strcpy_advance_id(&tmp1, MSG_ALL_SUPPORTED_FILES_ID);
strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.afs, *.pff, *.txt)")); tmp1++;
strcpy_advance(&tmp1, (TCHAR*)TEXT("*.afs;*.pff;*.txt")); tmp1++;
strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.afs, *.pff, *.txt, *.guf)")); tmp1++;
strcpy_advance(&tmp1, (TCHAR*)TEXT("*.afs;*.pff;*.txt;*.guf")); tmp1++;
 
strcpy_advance_id(&tmp1, MSG_SAVE_AFS_ID);
strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.afs)")); tmp1++;
477,6 → 481,10
strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.txt)")); tmp1++;
strcpy_advance(&tmp1, (TCHAR*)TEXT("*.txt")); tmp1++;
 
strcpy_advance_id(&tmp1, MSG_SAVE_GUF_ID);
strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.guf)")); tmp1++;
strcpy_advance(&tmp1, (TCHAR*)TEXT("*.guf")); tmp1++;
 
strcpy_advance_id(&tmp1, MSG_ALL_FILES_ID);
strcpy_advance(&tmp1, (TCHAR*)TEXT(" (*.*)")); tmp1++;
strcpy_advance(&tmp1, (TCHAR*)TEXT("*.*")); tmp1++;
501,7 → 509,7
free(title);
 
if (saveDlgRet) {
if (savefile_afs_pff_picotxt(&sfr)) {
if (savefile_afs_pff_picotxt_guf(&sfr)) {
completesave(&reply);
 
if (fileHasExtension(&sfr, TEXT(".txt"))) {