/***********************************************************************/ /* 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/writeimage.c,v 1.3 1999/05/10 15:45:33 gda Exp $ */ #include /*** MODULE: WriteImage SHORTDESCRIPTION: writes an image to a file. CATEGORY: Import and Export INPUTS: image; image or image series; NULL; the image to write file; string; image.rgb; file name format; string; .rgb; format of file frame; integer; current + 1; frame to write OUTPUTS: BUGS: There is currently no way to overwrite an existing frame in the middle of a file. AUTHOR: nancy s collins END: ***/ #define I_image in[0] #define I_file in[1] #define I_format in[2] #define I_frame in[3] #include #include #include #include #include <_helper_jea.h> #include <_rw_image.h> #include #include /* FIXME: this belongs in the arch.h file */ #if defined(ibmpvs) || defined(os2) || defined(DXD_WIN) # define HAS_POSIX_SIGNALS 0 #else # define HAS_POSIX_SIGNALS 1 #endif #if DXD_POPEN_OK && DXD_HAS_LIBIOP #define popen popen_host #define pclose pclose_host #endif #define HANDLE_SIGPIPE 0 #ifdef DXD_WIN #define SIGPIPE SIGILL #define popen _popen #define pclose _pclose #endif static float GammaFromFormat(char *s); #if HANDLE_SIGPIPE static int pipe_error_happened; static void PipeError() { pipe_error_happened = 1; } #endif /* HANDLE_SIGPIPE */ int m_WriteImage ( Object *in, Object *out ) { char *exclamation=NULL, *filename, *format, basename[MAX_IMAGE_NAMELEN]; int deleteable = 0; int transposed; RWImageArgs iargs; ImageWriteFunction f; /* Function to write the image to disk */ ImageInfo *imginfo; int r; #if HAS_POSIX_SIGNALS struct sigaction action, oaction; #else void (*oaction)(); #endif /* HAS_POSIX_SIGNALS */ #if ( CAN_HAVE_ARRAY_DASD == 1 ) int Output_to_ADASD = 0; #else #define Output_to_ADASD 0 #endif iargs.image = NULL; iargs.pipe = NULL; if ( !I_image ) DXErrorGoto2 ( ERROR_MISSING_DATA, "#10000", "'image'" ) else { switch ( iargs.imgclass = DXGetObjectClass ( I_image ) ) { case CLASS_FIELD: iargs.image = (Field)I_image; /* * Check to be sure the provided image(s) are images. */ if ( !_dxf_ValidImageField ( (Field)iargs.image) ) DXErrorGoto ( ERROR_INVALID_DATA, "'image' Field is not an image" ); break; case CLASS_GROUP: switch ( iargs.imgclass = DXGetGroupClass ( (Group)I_image ) ) { Object o; int i; case CLASS_SERIES: iargs.image = (Field)I_image; i=0; while (o=DXGetEnumeratedMember((Group)I_image,i++,NULL)) if ( !_dxf_ValidImageField ( (Field)o) ) DXErrorGoto ( ERROR_INVALID_DATA, "series 'image' contains non-image" ); break; case CLASS_COMPOSITEFIELD: if ( ( iargs.image = _dxf_SimplifyCompositeImage ( (CompositeField)I_image ) ) ) deleteable = 1; else goto error; break; default: DXErrorGoto ( ERROR_BAD_PARAMETER, "'image' Field is not an image" ); } break; default: DXErrorGoto ( ERROR_BAD_PARAMETER, "'image' is not an image" ) } } /* * Check to be sure the provided image(s) have the correct deltas * for an image (so that the pixels are written out correctly). */ if (!_dxf_CheckImageDeltas((Object)iargs.image, &transposed)) goto error; if (transposed) DXErrorGoto ( ERROR_INVALID_DATA,"'image' Field has transposed deltas" ); /* * Determine the filename. If the filename parameter is given then * we use it as basename. If it is not specified then we copy "image" * into basename as the default name. */ if ( I_file ) { char *p; if ( !DXExtractString ( I_file, &filename ) || ( filename == NULL ) ) DXErrorGoto2 ( ERROR_MISSING_DATA, "#10200", "'name'" ) p = filename; while (*p && (*p == ' ' || *p == '\t')) p++; exclamation = p; #if !defined(DXD_OS_NON_UNIX) if ( (*p != '!') && strchr ( filename, ':' ) ) #if ( CAN_HAVE_ARRAY_DASD == 1 ) Output_to_ADASD = 1; else Output_to_ADASD = 0; #else DXErrorGoto ( ERROR_NOT_IMPLEMENTED, "cannot support a disk array 'name' on this architecture" ); #endif #endif if (strlen(filename) > MAX_IMAGE_NAMELEN) DXErrorGoto(ERROR_INVALID_DATA, "output file name length too large."); strcpy(basename,filename); } else { filename = NULL; strcpy(basename,"image"); } /* * Assemble filename from input strings: filename and format. */ iargs.gamma = 2.0; if ( I_format ) { if ( !DXExtractString ( I_format, &format ) || ( format == NULL ) ) DXErrorGoto2 ( ERROR_MISSING_DATA, "#10200", "'format'" ) if (!(imginfo = _dxf_ImageInfoFromFormat(format))) DXErrorGoto3 ( ERROR_BAD_PARAMETER, "#10210", format, "the file format" ) iargs.imgtyp = imginfo->type; iargs.gamma = GammaFromFormat(format); if (Output_to_ADASD) { if (!(imginfo->flags & ADASD_OK)) DXErrorGoto2 ( ERROR_NOT_IMPLEMENTED, "format '%s' is not supported on the PVS disk array",format ) } else if (imginfo->flags & ADASD_ONLY) { DXErrorGoto2 ( ERROR_NOT_IMPLEMENTED, "format '%s' is only supported on the PVS disk array",format ) } } else { format = NULL; /* * If the user specified a filename, try and determine the output * image format from the given name. */ if (filename) imginfo = _dxf_ImageInfoFromFileName(filename); else imginfo = NULL; if ( Output_to_ADASD ) { if ( !imginfo ) { /* Can't determine format from args, default to "fb" */ iargs.imgtyp = img_typ_fb; imginfo = _dxf_ImageInfoFromType(img_typ_fb); if ( imginfo == NULL ) DXErrorGoto ( ERROR_INVALID_DATA, "image type lookup failed" ); } else iargs.imgtyp = imginfo->type; if ( (imginfo->flags & ADASD_OK) == 0) DXErrorGoto ( ERROR_NOT_IMPLEMENTED, "The file format indicated in 'name' is not supported on the disk array." ) } else { if ( !imginfo ) { /* Can't determine format from args, default to "rgb" */ iargs.imgtyp = img_typ_rgb; imginfo = _dxf_ImageInfoFromType(img_typ_rgb); if ( imginfo == NULL ) DXErrorGoto ( ERROR_INVALID_DATA, "image type lookup failed" ); } else iargs.imgtyp = imginfo->type; if ( imginfo->flags & ADASD_ONLY) DXErrorGoto ( ERROR_NOT_IMPLEMENTED, "The file format indicated in 'name' is only supported on the PVS disk array." ) } } if ( I_frame ) { if ( !DXExtractInteger ( I_frame, &iargs.startframe ) || (iargs.startframe < 0)) DXErrorGoto2 ( ERROR_INVALID_DATA, "#10030", "'frame'" ) } else iargs.startframe = VALUE_UNSPECIFIED; f = imginfo->write; if (!f) DXErrorGoto ( ERROR_UNEXPECTED, "Image write function not available" ); if (exclamation && *exclamation == '!') { /* Piping output */ #if DXD_POPEN_OK char *p = ++exclamation; if ((imginfo->flags & PIPEABLE_OUTPUT) == 0) { DXErrorGoto( ERROR_BAD_PARAMETER, "Given format does not support the '!' option"); } iargs.pipe = popen(p,"w"); if (!iargs.pipe) { DXSetError( ERROR_BAD_PARAMETER, "Error executing command '%s'",p); goto error; } iargs.basename = NULL; #else DXSetError(ERROR_BAD_PARAMETER, "Cannot support the '!' option on this platform"); goto error; #endif } else { /* Putting output in a file */ /* * DXRemove the extension in basename if it is recognized * and is an acceptable extension for imgtyp. */ _dxf_RemoveImageExtension(basename,iargs.imgtyp); iargs.basename = basename; } iargs.adasd = Output_to_ADASD; iargs.format = format; /* * Handle pipe write errors which can only be caught when we do * a write. We can't do a test write above since we don't know * what/if the ignorable characters are. */ #if DXD_POPEN_OK if (iargs.pipe) { #if HAS_POSIX_SIGNALS # if HANDLE_SIGPIPE action.sa_handler = PipeError; pipe_error_happened = 0; # else action.sa_handler = SIG_IGN; # endif /* HANDLE_SIGPIPE */ sigemptyset(&action.sa_mask); action.sa_flags = 0; sigaction(SIGPIPE, &action, &oaction); #else oaction = signal(SIGPIPE, SIG_IGN); #endif /* HAS_POSIX_SIGNALS */ } #endif /* DXD_POPEN_OK */ r = (*f)(&iargs); #if DXD_POPEN_OK if (iargs.pipe) { #if HAS_POSIX_SIGNALS sigaction,(SIGPIPE, &oaction); #else signal(SIGPIPE, oaction); #endif /* HAS_POSIX_SIGNALS */ #if HANDLE_SIGPIPE if (pipe_error_happened) { pipe_error_happened = 0; goto error; } #endif /* HANDLE_SIGPIPE */ } #endif /* DXD_POPEN_OK */ if (!r) goto error; if ( deleteable ) DXDelete ( (Object) iargs.image ); #if DXD_POPEN_OK if (iargs.pipe) pclose(iargs.pipe); #endif return OK; error: if ( deleteable && iargs.image) DXDelete ( (Object) iargs.image ); #if DXD_POPEN_OK if (iargs.pipe) pclose(iargs.pipe); #endif return ERROR; } static float GammaFromFormat(char *s) { char *p, *q; char buf[200]; int len; p = (char *)strstr(s, "gamma"); if (!p) return 2.0; p = (char *)strstr(p, "="); if (!p) return 2.0; p++; for (q=p; *q && isspace(*q); q++); for (p=q, len=0; *q && !isspace(*q); q++, len++); len++; if (len>=200) return 2.0; strncpy(buf, p, len); buf[len] = '\0'; return (float)atof(buf); }