mirror of https://github.com/aap/librw.git
implemented image format registry
This commit is contained in:
parent
fd191856c4
commit
02921ff848
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
130
src/image.cpp
130
src/image.cpp
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
15
src/rwbase.h
15
src/rwbase.h
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue