/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"))) { |