/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ /* * $Header: /home/gda/dxcvs/dx/src/exec/dxmods/_rw_image.c,v 1.3 1999/05/10 15:45:21 gda Exp $ */ #include #include #include #include #include #include <_helper_jea.h> #include <_rw_image.h> #include #include #include static int SearchStringList(char *str, char *extension); static int NthImageExtension(char *extensions, int n, char *buf, int bufl); #define MAX_EXTENSION_LEN 10 /* * This is the table of supported images (currently, only WriteImage * uses this table to find the write functions). The table will be * searched sequentially for both format specifiers and extensions. * This means there should not be any overlap between format specifiers * or extensions. If there is a clash, then the first matching format * or extension is the one that is used as a matched. Note the two * "ps" extensions for example. When a filename extension of "ps" is * given it will be assumed to be a 'ps color' image. * * NOTE: although ReadImage is not currently table driven, we set the * read field to be none NULL for read supported formats. */ static Error nullread(RWImageArgs *dummy) { DXSetError(ERROR_UNEXPECTED,"unexpected format" ); return ERROR; } static ImageInfo ImageTable[] = { { img_typ_rgb, 1, "rgb", "rgb", APPENDABLE_FILES, _dxf_write_rgb, nullread}, { img_typ_fb, 1, "fb", "fb", APPENDABLE_FILES|ADASD_OK|ADASD_ONLY, _dxf_write_fb, nullread}, { img_typ_r_g_b, 3, "r+g+b", "r:g:b", APPENDABLE_FILES, _dxf_write_r_g_b, nullread}, { img_typ_tiff, 1, "tiff", "tiff:tif", /* Preferred. */ 0, _dxf_write_tiff, NULL}, #if 0 { img_typ_tiff, 1, "tiff", "tif", /* This is not the preferred writing format. 2nd in list.*/ 0, _dxf_write_tiff, NULL}, #endif { img_typ_ps_color, 1, "ps color:ps", "ps", PIPEABLE_OUTPUT, _dxf_write_ps_color, NULL}, { img_typ_eps_color, 1, "eps color:eps", "epsf", PIPEABLE_OUTPUT, _dxf_write_eps_color, NULL}, { img_typ_ps_gray, 1, "ps gray:ps grey", "ps", PIPEABLE_OUTPUT, _dxf_write_ps_gray, NULL}, { img_typ_eps_gray, 1, "eps gray:eps grey", "epsf", PIPEABLE_OUTPUT, _dxf_write_eps_gray, NULL}, { img_typ_gif, 1, "gif", "gif:giff", /* Preferred. */ 0, _dxf_write_gif, NULL}, { img_typ_yuv, 1, "yuv", "yuv", APPENDABLE_FILES, _dxf_write_yuv, nullread}, { img_typ_miff, 1, "miff", "miff:mif", APPENDABLE_FILES, _dxf_write_miff, NULL}, { img_typ_illegal } }; /* Must be last entry */ /* * Given the type of an image, return a pointer to its ImageInfo * structure if it exists. */ ImageInfo * _dxf_ImageInfoFromType(ImageType type) { int i; for ( i = 0; ImageTable[i].type != img_typ_illegal ; i++ ) if ( type == ImageTable[i].type ) return (&ImageTable[i]); return(NULL); } /* * Given the format of an image, return a pointer to its ImageInfo * structure if it exists. */ ImageInfo * _dxf_ImageInfoFromFormat(char *format) { int i; int matches = 0; ImageInfo *r = NULL; if ( format ) { for ( i = 0; ImageTable[i].type != img_typ_illegal ; i++ ) { int tmp = SearchStringList(ImageTable[i].formats,format); if (tmp > matches) { r = &ImageTable[i]; matches = tmp; } } } return r; } extern char * _dxf_RemoveExtension ( char *extended ) { int i; for ( i = strlen ( extended ) - 1; i >= 0; i-- ) if ( extended[i] == '.' ) { extended[i] = '\0'; return extended; } return ERROR; } /* * Determine the image file type from the name of the file and the * extension there within. If there is no extension or we can't match * the extension, then return NULL. */ ImageInfo * _dxf_ImageInfoFromFileName ( char *basename) { int i; char *ep; int matches = 0; ImageInfo *r = NULL; /* * Find the last '.' in the file name after the last '/', if any. * ep represents the extension pointer, if any. */ ep = NULL; for ( i = strlen ( basename ) - 1; i >= 0; i-- ) if ( basename[i] == '.' ) { ep = &basename[i+1]; break; } else if ( basename[i] == '/' ) break; /* * If a file extension was found, attempt to find match in table. */ if ( ep ) { for ( i=0 ; ImageTable[i].type != img_typ_illegal ; i++ ) { int tmp = SearchStringList(ImageTable[i].extensions,ep); if (tmp > matches) { r = &ImageTable[i]; matches = tmp; } } } return r; } /* * Find the Nth field in a string of characters where fields are seperated * by ':'. * * Return 1 if found, 0 if not. * */ static int NthImageExtension(char *extensions, int n, char *buf, int bufl) { char *s = extensions; buf[0] = '\0'; if (s) { while (*s && n--) { while (*s && *s != ':') s++; if (*s == ':') s++; } if (*s) /* We found the nth extension */ { n = 0; while (*s && (*s != ':') && (n < bufl) ) { buf[n++] = *s; s++; } buf[n] = '\0'; return 1; } } return 0; } /* * Search a string "abcd:efgh:xyz" for a pattern that is separated by ':' * The input 'str' is assumed to be in lower case, the 'pattern' is * copied to lower case so that a case insensitive search is done. * * The following should return > 0. * SearchStringList("abcd:efgh:xyz","efgh") * SearchStringList("abcd:efgh:xyz","XYZ") * SearchStringList("abcd:efgh:xyz","XYZ asdf") * and the following 0 * SearchStringList("abcd:efgh:xyz","ef") * SearchStringList("abcd:efgh:xyz","abcd:ef") * SearchStringList("abcd:efgh:xyz","XYZasdf") * * Return number of characters matched if found, 0 if not. * */ static int SearchStringList(char *str, char *pattern) { int i, patlen; char cpy[256], buf[256], *p1, *p2; int matches = 0; if (str && pattern) { /* * Assume we we don't have any strings in the ImageTable[] that are * larger than 31 characters. */ patlen = strlen(pattern); if (patlen > 255 || strlen(str) > 255) return(0); /* Copy the pattern into a lower case buffer */ for (i=0 ; i matches)) { c = buf[len]; switch (c) { /* Token in buf must be delimited by white space */ case ' ': case '\0': case '\n': case '\t': if (!strncmp(buf,p1,len)) matches = len; break; default: break; } } p1 = p2 ? p2+1 : p2; } } return matches; } static int /* 0/1 on failure/success */ ValidImageExtension(char *ext, ImageType type) { int i; for ( i = 0; ImageTable[i].type != img_typ_illegal; i++ ) { if ((ImageTable[i].type == type ) && SearchStringList(ImageTable[i].extensions,ext)) return 1; } return 0; } /* * Given a file name, remove an extension (after last '.' before last * '/') if it matches the given image type. */ void _dxf_RemoveImageExtension(char *name, ImageType type) { int i; /* * Find the last '.' in the file name before '/', if any. * DXRemove the extension in name if it is recognized. */ for ( i = strlen (name) - 1; i >= 0; i-- ) { if (name[i] == '.') { if (ValidImageExtension(&name[i+1],type)) name[i] = '\0'; return; } else if ( name[i] == '/' ) return; } } char * _dxf_BuildImageFileName ( char *buf, int bufl, char *basename, /* Does not have an extension */ ImageType type, int framenum, /* First frame in image file to write */ int selection) { int i; char extension[MAX_EXTENSION_LEN], framestr[16]; int found; /* * Find and append the requested extension. */ found = 0; for ( i = 0; ImageTable[i].type != img_typ_illegal; i++) { if ( (type == ImageTable[i].type) && NthImageExtension(ImageTable[i].extensions,selection, extension,MAX_EXTENSION_LEN) ) { found = 1; break; } } if ( ! found) { DXSetError ( ERROR_INTERNAL, "Can't match type %d, selection %d in image table", type, selection); return ERROR; } if ((framenum >= 0) && (ImageTable[i].flags & APPENDABLE_FILES) == 0) { sprintf(framestr,".%d",framenum); } else { framestr[0] = '\0'; } /* Make sure buffer is big enough, 2 for NULL and '.' */ if ((strlen(basename) + strlen(framestr) + strlen (extension) + 2) > bufl) DXErrorReturn(ERROR_INTERNAL,"Insufficient storage space for filename"); /* * Move the basename into the output buffer, * skipping the extension if appropriate. */ if ( !strcpy ( buf, basename) ) DXErrorReturn ( ERROR_UNEXPECTED, "strncpy" ); if ( !strcat ( buf, framestr) || !strcat(buf,".") ) DXErrorReturn ( ERROR_UNEXPECTED, "strcat:framestr" ); if ( !strcat ( buf, extension) ) DXErrorReturn ( ERROR_UNEXPECTED, "strcat:extension" ); return buf; } /* * DXExtract the 'member'th image of the given series, check that * the dimensions of the given member match those provided, and if * the member is a composite field, flatten the field into a * non-partitioned image. * * If the member is a composite field and we return successfully, * then a new field has been created and '*created' is set to 1 to * indicate that the field was created. If not created then, '*created' * is set to 0. * * On success, returns an un-partitioned image Field. * On failure, returns NULL and sets the error code. */ extern Field _dxf_GetFlatSeriesImage(Series image, int member, int width, int height, int *created) { Field img = NULL, m; SizeData image_sizes; /* Values as found in the image object itself */ int was_created = 0; if ( NULL == ( m = (Field)DXGetSeriesMember(image, member, NULL))) DXErrorGoto ( ERROR_BAD_PARAMETER, "#10901" ); /* start and end cannot be greater than numbert of series elements */ switch (DXGetGroupClass((Group)m)) { default: DXErrorGoto(ERROR_INTERNAL,"Encountered a non-series object"); case CLASS_COMPOSITEFIELD: if (!(img = _dxf_SimplifyCompositeImage((CompositeField)m))) goto error; was_created = 1; break; case CLASS_FIELD: img = m; break; } /* Check to be sure the image dimensions match */ if (!_dxf_GetImageAttributes((Object)img, &image_sizes ) ) goto error; if ((image_sizes.width != width) || (image_sizes.height != height)) DXErrorGoto(ERROR_BAD_PARAMETER, "Series member does not have matching height and width"); if (created) *created = was_created; return img; error: if (img && was_created) DXDelete((Object)img); if (created) *created = 0; return NULL; } Error _dxf_make_gamma_table(ubyte *gamma_table, float gamma) { int i; float f, g; if (fabs(gamma)>1.0e-6) g = 1.0/gamma; else g = 1.0e+6; if (g>0) { gamma_table[0] = 0; gamma_table[255] = 255; for (i=1; i<255; i++) { f = i/255.0; gamma_table[i] = (ubyte)(255.0*pow(f, g)); } } else { gamma_table[0] = 255; gamma_table[255] = 0; g = -g; for (i=1; i<255; i++) { f = i/255.0; gamma_table[255-i] = (ubyte)(255.0*pow(f, g)); } } return OK; }