diff options
Diffstat (limited to 'src/im_format.cpp')
-rw-r--r-- | src/im_format.cpp | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/src/im_format.cpp b/src/im_format.cpp new file mode 100644 index 0000000..be9892c --- /dev/null +++ b/src/im_format.cpp @@ -0,0 +1,289 @@ +/** \file + * \brief File Format Access + * + * See Copyright Notice in im_lib.h + * $Id: im_format.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $ + */ + + +#include <stdlib.h> +#include <ctype.h> +#include <memory.h> +#include <string.h> +#include <assert.h> + +#include "im.h" +#include "im_format.h" +#include "im_util.h" + + +static imFormat* iFormatList[50]; +static int iFormatCount = 0; +static int iFormatRegistredAll = 0; + +void imFormatRemoveAll(void) +{ + for (int i = 0; i < iFormatCount; i++) + { + imFormat* iformat = iFormatList[i]; + delete iformat; + iFormatList[i] = NULL; + } + iFormatCount = 0; + iFormatRegistredAll = 0; +} + +void imFormatRegister(imFormat* iformat) +{ + iFormatList[iFormatCount] = iformat; + iFormatCount++; +} + +static imFormat* iFormatFind(const char* format) +{ + assert(format); + + if (!iFormatRegistredAll) + { + imFormatRegisterInternal(); + iFormatRegistredAll = 1; + } + + for (int i = 0; i < iFormatCount; i++) + { + imFormat* iformat = iFormatList[i]; + if (imStrEqual(format, iformat->format)) + return iformat; + } + return NULL; +} + +void imFormatList(char** format_list, int *format_count) +{ + assert(format_list); + assert(format_count); + + if (!iFormatRegistredAll) + { + imFormatRegisterInternal(); + iFormatRegistredAll = 1; + } + + static char format_list_buffer[50][50]; + + *format_count = iFormatCount; + for (int i = 0; i < iFormatCount; i++) + { + imFormat* iformat = iFormatList[i]; + strcpy(format_list_buffer[i], iformat->format); + format_list[i] = format_list_buffer[i]; + } +} + +int imFormatInfo(const char* format, char* desc, char* ext, int *can_sequence) +{ + imFormat* iformat = iFormatFind(format); + if (!iformat) return IM_ERR_FORMAT; + + if (desc) strcpy(desc, iformat->desc); + if (ext) strcpy(ext, iformat->ext); + if (can_sequence) *can_sequence = iformat->can_sequence; + + return IM_ERR_NONE; +} + +int imFormatCompressions(const char* format, char** comp, int *comp_count, int color_mode, int data_type) +{ + imFormat* iformat = iFormatFind(format); + if (!iformat) return IM_ERR_FORMAT; + + int count = 0; + + static char comp_buffer[50][50]; + + for (int i = 0; i < iformat->comp_count; i++) + { + if (color_mode == -1 || data_type == -1 || + iformat->CanWrite(iformat->comp[i], color_mode, data_type) == IM_ERR_NONE) + { + strcpy(comp_buffer[count], iformat->comp[i]); + comp[count] = comp_buffer[count]; + count++; + } + } + + *comp_count = count; + + return IM_ERR_NONE; +} + +int imFormatCanWriteImage(const char* format, const char* compression, int color_mode, int data_type) +{ + assert(format); + + imFormat* iformat = iFormatFind(format); + if (!iformat) return IM_ERR_FORMAT; + + int error = iformat->CanWrite(compression, color_mode, data_type); + return error; +} + +static char* utlFileGetExt(const char *file_name) +{ + int len = strlen(file_name); + + // Starts at the last character + int offset = len - 1; + while (offset != 0) + { + // if found a path separator, no extension found + if (file_name[offset] == '\\' || file_name[offset] == '/') + return NULL; + + if (file_name[offset] == '.') + { + offset++; + break; + } + + offset--; + } + + // if at the first character, no extension found + if (offset == 0) + return NULL; + + int ext_size = len - offset + 1; + char* file_ext = (char*)malloc(ext_size); + + for (int i = 0; i < ext_size-1; i++) + file_ext[i] = (char)tolower(file_name[i+offset]); + file_ext[ext_size-1] = 0; + + return file_ext; +} + +imFormat* imFormatOpen(const char* file_name, int *error) +{ + int i; + + assert(file_name); + assert(error); + + if (!iFormatRegistredAll) + { + imFormatRegisterInternal(); + iFormatRegistredAll = 1; + } + + int* ext_mark = new int [iFormatCount]; + memset(ext_mark, 0, sizeof(int)*iFormatCount); + + // Search for the extension first, this usually is going to speed the search + char* extension = utlFileGetExt(file_name); + if (extension) + { + for(i = 0; i < iFormatCount; i++) + { + imFormat* iformat = iFormatList[i]; + + if (strstr(iformat->ext, extension) != NULL) + { + ext_mark[i] = 1; // Mark this format to avoid testing it again in the next phase + + *error = iformat->Open(file_name); + if (*error != IM_ERR_NONE && *error != IM_ERR_FORMAT) // Error situation that must abort + { // Only IM_ERR_FORMAT is a valid error here + free(extension); + delete [] ext_mark; + return NULL; + } + else if (*error == IM_ERR_NONE) // Sucessfully oppened the file + { + free(extension); + delete [] ext_mark; + return iformat; + } + } + } + + free(extension); + } + + // If the search did not work, try all the formats + // except those already tested. + + for(i = 0; i < iFormatCount; i++) + { + if (!ext_mark[i]) + { + imFormat* iformat = iFormatList[i]; + + *error = iformat->Open(file_name); + if (*error != IM_ERR_NONE && *error != IM_ERR_FORMAT) // Error situation that must abort + { // Only IM_ERR_FORMAT is a valid error here + delete [] ext_mark; + return NULL; + } + else if (*error == IM_ERR_NONE) // Sucessfully oppened the file + { + delete [] ext_mark; + return iformat; + } + } + } + + *error = IM_ERR_FORMAT; + delete [] ext_mark; + return NULL; +} + +imFormat* imFormatOpenAs(const char* file_name, const char* format, int *error) +{ + assert(file_name); + assert(format); + assert(error); + + if (!iFormatRegistredAll) + { + imFormatRegisterInternal(); + iFormatRegistredAll = 1; + } + + imFormat* iformat = iFormatFind(format); + if (!format) + { + *error = IM_ERR_FORMAT; + return NULL; + } + + *error = iformat->Open(file_name); + if (*error != IM_ERR_NONE && *error != IM_ERR_FORMAT) // Error situation that must abort + return NULL; + else if (*error == IM_ERR_NONE) // Sucessfully oppened the file + return iformat; + + *error = IM_ERR_FORMAT; + return NULL; +} + +imFormat* imFormatNew(const char* file_name, const char* format, int *error) +{ + assert(file_name); + assert(format); + assert(error); + + imFormat* iformat = iFormatFind(format); + if (!iformat) + { + *error = IM_ERR_FORMAT; + return NULL; + } + + *error = iformat->New(file_name); + if (*error) + return NULL; + + return iformat; +} + |