implemented image format registry

This commit is contained in:
aap 2020-05-01 21:02:37 +02:00
parent fd191856c4
commit 02921ff848
6 changed files with 1630 additions and 27 deletions

File diff suppressed because it is too large Load Diff

View File

@ -182,6 +182,7 @@ Engine::init(void)
// core plugin attach here // core plugin attach here
Frame::registerModule(); Frame::registerModule();
Image::registerModule();
Raster::registerModule(); Raster::registerModule();
Texture::registerModule(); Texture::registerModule();
@ -279,6 +280,10 @@ Engine::start(void)
engine->device.system(DEVICEFINALIZE, nil, 0); engine->device.system(DEVICEFINALIZE, nil, 0);
// Register some image formats. Or should we leave that to the user?
Image::registerFileFormat("tga", readTGA, writeTGA);
Image::registerFileFormat("bmp", readBMP, writeBMP);
Engine::state = Started; Engine::state = Started;
return 1; return 1;
} }

View File

@ -21,6 +21,24 @@ namespace rw {
int32 Image::numAllocated; int32 Image::numAllocated;
struct FileAssociation
{
char *extension;
Image *(*read)(const char *afilename);
void (*write)(Image *image, const char *filename);
};
struct ImageGlobals
{
char *searchPaths;
int numSearchPaths;
FileAssociation fileFormats[10];
int numFileFormats;
};
int32 imageModuleOffset;
#define IMAGEGLOBAL(v) (PLUGINOFFSET(ImageGlobals, engine, imageModuleOffset)->v)
// Image formats are as follows: // Image formats are as follows:
// 32 bit has 4 bytes: 8888 RGBA // 32 bit has 4 bytes: 8888 RGBA
// 24 bit has 3 bytes: 888 RGB // 24 bit has 3 bytes: 888 RGB
@ -474,9 +492,6 @@ Image::extractMask(void)
return img; return img;
} }
static char *searchPaths = nil;
int numSearchPaths = 0;
static char* static char*
rwstrdup(const char *s) rwstrdup(const char *s)
{ {
@ -492,19 +507,20 @@ void
Image::setSearchPath(const char *path) Image::setSearchPath(const char *path)
{ {
char *p, *end; char *p, *end;
rwFree(searchPaths); ImageGlobals *g = PLUGINOFFSET(ImageGlobals, engine, imageModuleOffset);
numSearchPaths = 0; rwFree(g->searchPaths);
g->numSearchPaths = 0;
if(path) if(path)
searchPaths = p = rwstrdup(path); g->searchPaths = p = rwstrdup(path);
else{ else{
searchPaths = nil; g->searchPaths = nil;
return; return;
} }
while(p && *p){ while(p && *p){
end = strchr(p, ';'); end = strchr(p, ';');
if(end) if(end)
*end++ = '\0'; *end++ = '\0';
numSearchPaths++; g->numSearchPaths++;
p = end; p = end;
} }
} }
@ -512,8 +528,9 @@ Image::setSearchPath(const char *path)
void void
Image::printSearchPath(void) Image::printSearchPath(void)
{ {
char *p = searchPaths; ImageGlobals *g = PLUGINOFFSET(ImageGlobals, engine, imageModuleOffset);
for(int i = 0; i < numSearchPaths; i++){ char *p = g->searchPaths;
for(int i = 0; i < g->numSearchPaths; i++){
printf("%s\n", p); printf("%s\n", p);
p += strlen(p) + 1; p += strlen(p) + 1;
} }
@ -522,19 +539,23 @@ Image::printSearchPath(void)
char* char*
Image::getFilename(const char *name) Image::getFilename(const char *name)
{ {
ImageGlobals *g = PLUGINOFFSET(ImageGlobals, engine, imageModuleOffset);
FILE *f; FILE *f;
char *s, *p = searchPaths; char *s, *p = g->searchPaths;
size_t len = strlen(name)+1; size_t len = strlen(name)+1;
if(numSearchPaths == 0){ if(g->numSearchPaths == 0){
f = fopen(name, "rb"); s = rwstrdup(name);
makePath(s);
f = fopen(s, "rb");
if(f){ if(f){
fclose(f); fclose(f);
printf("found %s\n", name); printf("found %s\n", s);
return rwstrdup(name); return s;
} }
rwFree(s);
return nil; return nil;
}else }else
for(int i = 0; i < numSearchPaths; i++){ for(int i = 0; i < g->numSearchPaths; i++){
s = (char*)rwMalloc(strlen(p)+len, MEMDUR_EVENT | ID_IMAGE); s = (char*)rwMalloc(strlen(p)+len, MEMDUR_EVENT | ID_IMAGE);
if(s == nil){ if(s == nil){
RWERROR((ERR_ALLOC, strlen(p)+len)); RWERROR((ERR_ALLOC, strlen(p)+len));
@ -542,6 +563,7 @@ Image::getFilename(const char *name)
} }
strcpy(s, p); strcpy(s, p);
strcat(s, name); strcat(s, name);
makePath(s);
f = fopen(s, "r"); f = fopen(s, "r");
if(f){ if(f){
fclose(f); fclose(f);
@ -554,4 +576,80 @@ Image::getFilename(const char *name)
return nil; return nil;
} }
Image*
Image::read(const char *imageName)
{
int i;
char *filename, *ext, *found;
Image *img;
filename = rwNewT(char, strlen(imageName) + 20, MEMDUR_FUNCTION | ID_TEXTURE);
strcpy(filename, imageName);
ext = filename + strlen(filename);
*ext++ = '.';
// Try all supported extensions
for(i = 0; i < IMAGEGLOBAL(numFileFormats); i++){
if(IMAGEGLOBAL(fileFormats)[i].read == nil)
continue;
strncpy(ext, IMAGEGLOBAL(fileFormats)[i].extension, 19);
found = getFilename(filename);
// Found a file
if(found){
img = IMAGEGLOBAL(fileFormats)[i].read(found);
rwFree(found);
// It was a valid image of that format
if(img){
rwFree(filename);
return img;
}
}
}
rwFree(filename);
return nil;
}
bool32
Image::registerFileFormat(const char *ext, fileRead read, fileWrite write)
{
ImageGlobals *g = PLUGINOFFSET(ImageGlobals, engine, imageModuleOffset);
if(g->numFileFormats >= nelem(g->fileFormats))
return 0;
g->fileFormats[g->numFileFormats].extension = rwstrdup(ext);
g->fileFormats[g->numFileFormats].read = read;
g->fileFormats[g->numFileFormats].write = write;
g->numFileFormats++;
return 1;
}
static void*
imageOpen(void *object, int32 offset, int32 size)
{
imageModuleOffset = offset;
ImageGlobals *g = PLUGINOFFSET(ImageGlobals, engine, imageModuleOffset);
g->searchPaths = nil;
g->numSearchPaths = 0;
g->numFileFormats = 0;
return object;
}
static void*
imageClose(void *object, int32 offset, int32 size)
{
ImageGlobals *g = PLUGINOFFSET(ImageGlobals, engine, imageModuleOffset);
int i;
rwFree(g->searchPaths);
g->searchPaths = nil;
g->numSearchPaths = 0;
for(i = 0; i < g->numFileFormats; i++)
rwFree(g->fileFormats[i].extension);
g->numFileFormats = 0;
return object;
}
void
Image::registerModule(void)
{
Engine::registerPlugin(sizeof(ImageGlobals), ID_IMAGEMODULE, imageOpen, imageClose);
}
} }

View File

@ -596,9 +596,24 @@ enum PluginID
enum CoreModuleID enum CoreModuleID
{ {
ID_NAMODULE = MAKEPLUGINID(VEND_CRITERIONINT, 0x00), ID_NAMODULE = MAKEPLUGINID(VEND_CRITERIONINT, 0x00),
// vector
// matrix
ID_FRAMEMODULE = MAKEPLUGINID(VEND_CRITERIONINT, 0x03), ID_FRAMEMODULE = MAKEPLUGINID(VEND_CRITERIONINT, 0x03),
// stream
// camera
ID_IMAGEMODULE = MAKEPLUGINID(VEND_CRITERIONINT, 0x06),
ID_RASTERMODULE = MAKEPLUGINID(VEND_CRITERIONINT, 0x07), ID_RASTERMODULE = MAKEPLUGINID(VEND_CRITERIONINT, 0x07),
ID_TEXTUREMODULE = MAKEPLUGINID(VEND_CRITERIONINT, 0x08) ID_TEXTUREMODULE = MAKEPLUGINID(VEND_CRITERIONINT, 0x08)
// pip
// immediate
// resources
// device
// color
// unused
// error
// metrics
// driver
// chunk group
}; };
#define ECODE(c, s) c #define ECODE(c, s) c

View File

@ -149,6 +149,16 @@ struct Image
static void setSearchPath(const char*); static void setSearchPath(const char*);
static void printSearchPath(void); static void printSearchPath(void);
static char *getFilename(const char*); static char *getFilename(const char*);
static Image *read(const char *imageName);
typedef Image *(*fileRead)(const char *afilename);
typedef void (*fileWrite)(Image *image, const char *filename);
static bool32 registerFileFormat(const char *ext, fileRead read, fileWrite write);
#ifndef RWPUBLIC
static void registerModule(void);
#endif
}; };
Image *readTGA(const char *filename); Image *readTGA(const char *filename);

View File

@ -299,23 +299,14 @@ defaultFindCB(const char *name)
} }
// TODO: no hardcoded file endings
// TODO: actually read the mask! // TODO: actually read the mask!
static Texture* static Texture*
defaultReadCB(const char *name, const char *mask) defaultReadCB(const char *name, const char *mask)
{ {
Texture *tex; Texture *tex;
Image *img; Image *img;
char *n = (char*)rwMalloc(strlen(name) + 5, MEMDUR_FUNCTION | ID_TEXTURE);
strcpy(n, name); img = Image::read(name);
strcat(n, ".tga");
img = readTGA(n);
if(img == nil){
strcpy(n, name);
strcat(n, ".bmp");
img = readBMP(n);
}
rwFree(n);
if(img){ if(img){
tex = Texture::create(Raster::createFromImage(img)); tex = Texture::create(Raster::createFromImage(img));
strncpy(tex->name, name, 32); strncpy(tex->name, name, 32);