/***********************************************************************/ /* 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/_rgb_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 #if ( CAN_HAVE_ARRAY_DASD == 1 ) #include #include #endif #ifdef DXD_WIN #include #endif /* should be in libsvs*/ static Field OutputR_G_B ( Field image, int fh[3] ); static Field OutputADASD ( Field image, int frame, char* fname ); static Error write_rgb_or_fb(RWImageArgs *iargs); /* * DXWrite out the given image in "fb" format. */ Error _dxf_write_fb(RWImageArgs *iargs) { if (iargs->imgtyp != img_typ_fb) DXErrorGoto(ERROR_INTERNAL, "_dxf_write_fb: mismatched image types"); return write_rgb_or_fb(iargs); error: return ERROR; } /* * DXWrite out the given image in "r+g+b" format. */ Error _dxf_write_r_g_b (RWImageArgs *iargs) { if (iargs->imgtyp != img_typ_r_g_b) DXErrorGoto(ERROR_INTERNAL, "_dxf_write_r_g_b: mismatched image types"); return write_rgb_or_fb(iargs); error: return ERROR; } /* * DXWrite out the given image in "rgb" format. */ Error _dxf_write_rgb (RWImageArgs *iargs) { if (iargs->imgtyp != img_typ_rgb) DXErrorGoto(ERROR_INTERNAL, "_dxf_write_rgb: mismatched image types"); return write_rgb_or_fb(iargs); error: return ERROR; } /* * DXWrite out the given image in "yuv" format. */ Error _dxf_write_yuv (RWImageArgs *iargs) { if (iargs->imgtyp != img_typ_yuv) DXErrorGoto(ERROR_INTERNAL, "_dxf_write_yuv: mismatched image types"); return write_rgb_or_fb(iargs); error: return ERROR; } /* * DXWrite out an "rgb", "r+g+b" or "fb" formatted image file from the * specified field. The input field should not be composite, but may * be series. * By the time we get called, it has been asserted that we can write * the image to the device, be it ADASD or otherwise. */ Field DXOutputRGBSeparate(Field, int *); static Error write_rgb_or_fb(RWImageArgs *iargs) { char imagefilename[MAX_IMAGE_NAMELEN]; char sizefilename[MAX_IMAGE_NAMELEN]; int i, fh[3], series, deleteable = 0; int frame, num_files, frame_size_bytes; SizeData filed_sizes; /* Values from, to the size file */ SizeData image_sizes; /* Values as found in the image object itself */ Field img; fh[0] = fh[1] = fh[2] = -1; if ( !_dxf_GetImageAttributes ( (Object)iargs->image, &image_sizes ) ) goto error; if ( iargs->adasd ) { /* Note that the sizefilename = imagefilename here */ if ( !_dxf_BuildImageFileName(sizefilename, MAX_IMAGE_NAMELEN, iargs->basename, iargs->imgtyp, iargs->startframe,0)) goto error; if ( !_dxf_ReadImageSizesADASD ( sizefilename, &filed_sizes ) ) goto error; } else { /* * Assemble size-file-name from input string filename and "size" * Open and read-in or default backwards. */ if (strlen(iargs->basename) > MAX_IMAGE_NAMELEN - 5) DXErrorGoto ( ERROR_INVALID_DATA, "image file name too long" ); strcpy(sizefilename,iargs->basename); strcat(sizefilename,".size"); if ( !_dxf_ReadSizeFile ( sizefilename, &filed_sizes ) ) goto error; } /* * Validate size-file inputs against those of the command line. */ if ( ( filed_sizes.height != VALUE_UNSPECIFIED ) && ( ( filed_sizes.height != image_sizes.height ) || ( filed_sizes.width != image_sizes.width ) ) ) { DXSetError ( ERROR_BAD_PARAMETER, "Image size (%dx%d) must match size file ('%s' is %dx%d).", image_sizes.height, image_sizes.width, sizefilename, filed_sizes.height, filed_sizes.width ); goto error; } filed_sizes.height = image_sizes.height; filed_sizes.width = image_sizes.width; if ( iargs->startframe != VALUE_UNSPECIFIED ) { image_sizes.startframe += iargs->startframe; image_sizes.endframe += iargs->startframe; } else if ( filed_sizes.endframe != VALUE_UNSPECIFIED ) { image_sizes.startframe += ( filed_sizes.endframe + 1 ); image_sizes.endframe += ( filed_sizes.endframe + 1 ); } if ( filed_sizes.endframe == VALUE_UNSPECIFIED ) { if ( image_sizes.startframe > 0 ) DXWarning ( "Initial write of frames (%d..%d) (>0).", image_sizes.startframe, image_sizes.endframe ); } else if ( image_sizes.startframe > ( filed_sizes.endframe + 1 ) ) DXWarning ( /* TCAT can't handle broken strings. (E.G. "A" "B" implies "AB") */ "already ('%s') have stored frames (%d..%d). Adding frames (%d..%d)", sizefilename, filed_sizes.startframe, filed_sizes.endframe, image_sizes.startframe, image_sizes.endframe ); filed_sizes.startframe = 0; if ( image_sizes.endframe > filed_sizes.endframe ) filed_sizes.endframe = image_sizes.endframe; /* * Attempt to open image file and position to start of frame(s). */ frame_size_bytes = image_sizes.width * image_sizes.height; switch ( iargs->imgtyp ) { case img_typ_rgb: frame_size_bytes *= 3; break; case img_typ_r_g_b: frame_size_bytes *= 1; break; case img_typ_fb: frame_size_bytes *= 4; break; case img_typ_yuv: frame_size_bytes *= 2; break; default: DXErrorGoto ( ERROR_ASSERTION, "imgtyp" ); } if (iargs->imgtyp == img_typ_r_g_b) num_files = 3; else num_files = 1; for ( i=0; ibasename, iargs->imgtyp, iargs->startframe,i)) goto error; if ( iargs->adasd ) { DXASSERTGOTO ( num_files == 1 ); } else { #if !defined(os2) && !defined(DXD_WIN) if ( ( fh[i] = open ( imagefilename, (O_CREAT|O_WRONLY), 0666 ) ) < 0 ) #else /* os2 has a 2 parameter #define for open() _open(). This is the only file * where 3 parameters are required. */ if ( ( fh[i] = _open ( imagefilename, (O_CREAT | O_RDWR | O_BINARY), (_S_IWRITE | _S_IREAD)) ) < 0 ) #endif ErrorGotoPlus1 ( ERROR_INVALID_DATA, "Can't open image file (%s)", imagefilename ); if ( lseek ( fh[i], (image_sizes.startframe*frame_size_bytes), 0 ) != ( image_sizes.startframe * frame_size_bytes ) ) ErrorGotoPlus2 ( ERROR_UNEXPECTED, "Cannot position to frame (%d) in file (%s)", image_sizes.startframe, imagefilename ); } } /* * DXWrite out frame, or frames, if there is a series group imput. */ series = iargs->imgclass == CLASS_SERIES; img = iargs->image; for ( i=0, frame=image_sizes.startframe; frame <= image_sizes.endframe; i++, frame++ ) { if (series) { if (deleteable) DXDelete((Object)img); img = _dxf_GetFlatSeriesImage((Series)iargs->image,i, image_sizes.width,image_sizes.height,&deleteable); if (!img) goto error; } switch ( iargs->imgtyp ) { case img_typ_rgb: if ( !DXOutputRGB ( img, fh[0] ) ) goto error; break; case img_typ_r_g_b: if ( !DXOutputRGBSeparate ( img, fh ) ) goto error; break; case img_typ_fb: if ( !OutputADASD ( img, frame, imagefilename ) ) goto error; break; case img_typ_yuv: if ( !DXOutputYUV ( img, fh[0] ) ) goto error; break; default: DXErrorGoto ( ERROR_ASSERTION, "image type" ); } } if ( !iargs->adasd ) if ( !_dxf_WriteSizeFile ( sizefilename, filed_sizes ) ) goto error; if ( fh[0] >= 0 ) close ( fh[0] ); if ( fh[1] >= 0 ) close ( fh[1] ); if ( fh[2] >= 0 ) close ( fh[2] ); if (deleteable && img) DXDelete((Object)img); return OK; error: if ( fh[0] >= 0 ) close ( fh[0] ); if ( fh[1] >= 0 ) close ( fh[1] ); if ( fh[2] >= 0 ) close ( fh[2] ); if (deleteable && img) DXDelete((Object)img); return ERROR; } /* everything below this line should be in libsvs somewhere */ SizeData * _dxf_ReadImageSizesADASD ( char *name, SizeData *sd ) { #if ( CAN_HAVE_ARRAY_DASD == 0 ) DXErrorReturn ( ERROR_ASSERTION, "_dxf_ReadImageSizesADASD() call on illegal architecture" ); #else int mov_errcode; /* 'mov_errno' is a global */ mov_stat_t ms; DXASSERT ( name ); DXASSERT ( sd ); if ( ( mov_errcode = mov_stat ( name, &ms ) ) < 0 ) { /* error if not 'file does not exist' */ if ( ( mov_errcode != MOV_ERROR_PFS ) || ( mov_pfserrno != PFS_ERROR_NOENT ) ) ErrorGotoPlus1 ( ERROR_INTERNAL, "ADASD error: %s (mov_stat)", mov_errmsg ( mov_errcode ) ) /* * A nonexistant file is considered logically equivalent * to one containing all unspecified values */ sd->height = VALUE_UNSPECIFIED; sd->width = VALUE_UNSPECIFIED; sd->startframe = VALUE_UNSPECIFIED; sd->endframe = VALUE_UNSPECIFIED; } else { sd->height = ms.height; sd->width = ms.width; sd->startframe = 0; sd->endframe = ms.frames - 1; } return sd; error: if ( DXGetError() == ERROR_NONE ) DXSetError ( ERROR_INTERNAL, "_dxf_ReadImageSizesADASD()" ); return ERROR; #endif } /* Output an image to the Array-Direct-Access-Storage-Device */ static Field OutputADASD ( Field image, int frame, char* fname ) { #if ( CAN_HAVE_ARRAY_DASD == 0 ) DXErrorReturn ( ERROR_ASSERTION, "OutputADASD() call on illegal architecture" ); #else typedef struct { unsigned char b, g, r, a } BGRA; char *buffer = NULL; int mov_errcode; /* 'mov_errno' is a global */ u_int *buffer_aligned; mov_id mid = 0; RGBColor *ipixels; RGBColor *ip; BGRA *opixels; BGRA *op; int width; int height; int i, j; int P; if ( !DXGetImageSize ( image, &width, &height ) || !( ipixels = DXGetPixels ( image ) ) || !( buffer = (char *)DXAllocate ( ( width * height * sizeof ( BGRA ) ) + 1023 ) ) ) goto error; buffer_aligned = ( (int)buffer % 1024 ) ? (u_int *)( (int)buffer + 1024 - ( (int)buffer % 1024 ) ) : (u_int *)buffer; if ( ( mov_errcode = mov_create ( fname, MOV_FORMAT_ARGB, 0, (u_int)width, (u_int)height, 1 ) ) < 0 ) /* * This is the check for error not 'file exists'. */ if ( ( mov_errcode != MOV_ERROR_PFS ) || ( mov_pfserrno != PFS_ERROR_EXIST ) ) ErrorGotoPlus1 ( ERROR_INTERNAL, "ADASD error: %s, (mov_create)", mov_errmsg ( mov_errcode)) /* File now exists */ if ( !( mid = mov_open ( fname ) ) ) ErrorGotoPlus1 ( ERROR_INTERNAL, "ADASD error: %s, (mov_open)", mov_errmsg ( mov_errno ) ) #define CLAMP1(p) ( ( (P=(p)) < 0 ) ? 0 : (P<=255) ? P : 255 ) opixels = (BGRA *) buffer_aligned; for ( i=0; ia = (unsigned char) 0xff; /* XXX ? must be -1 for the hardware card */ op->r = (unsigned char) CLAMP1 ( 255.0 * ip->r ); op->g = (unsigned char) CLAMP1 ( 255.0 * ip->g ); op->b = (unsigned char) CLAMP1 ( 255.0 * ip->b ); } } if ( ( mov_errcode = mov_put ( mid, ( frame + 1 ), ( frame + 1 ), (u_int *)buffer_aligned ) ) < 0 ) ErrorGotoPlus1 ( ERROR_INTERNAL, "ADASD error: %s, (mov_put)", mov_errmsg ( mov_errcode ) ) if ( ( mov_errcode = mov_close ( mid ) ) < 0 ) ErrorGotoPlus1 ( ERROR_INTERNAL, "ADASD error: %s, (mov_close)", mov_errmsg ( mov_errcode ) ) mid = 0; DXFree ( (Pointer) buffer ); return image; error: if ( DXGetError() == ERROR_NONE ) DXSetError ( ERROR_INTERNAL, "OutputADASD()" ); DXFree ( (Pointer) buffer ); return ERROR; #endif } SizeData * _dxf_ReadSizeFile ( char *name, SizeData *sd ) { char record[128]; int rl; int fh = -1; DXASSERT ( sd ); if ( ( fh = open ( name, O_RDONLY ) ) < 0 ) { /* * A nonexistant size file is considered logically equivalent * to one containing all unspecified values */ sd->height = VALUE_UNSPECIFIED; sd->width = VALUE_UNSPECIFIED; sd->startframe = VALUE_UNSPECIFIED; sd->endframe = VALUE_UNSPECIFIED; } else { if ( ( rl = read ( fh, record, sizeof ( record ) ) ) <= 0 ) { DXSetError ( ERROR_INVALID_DATA, "Can't read from size file (%s).", name ); goto error; } else if ( rl >= sizeof ( record ) ) /* == is more a worry than > */ { DXSetError ( ERROR_INVALID_DATA, "Unexpectedly long size file (%s).", name ); goto error; } record [ rl ] = '\0'; if ( sscanf ( record, "%dx%dx%d", &sd->width, &sd->height, &sd->endframe ) == 3 ) { sd->startframe = 0; sd->endframe = sd->endframe - 1; } else if ( sscanf ( record, "%dx%d", &sd->width, &sd->height ) == 2 ) { sd->startframe = 0; sd->endframe = 0; } else { DXSetError ( ERROR_INVALID_DATA, "Bad format in size file (%s)", name ); goto error; } } if ( fh >= 0 ) close ( fh ); return sd; error: if ( fh >= 0 ) close ( fh ); return ERROR; } /*-------------------*/ Error _dxf_WriteSizeFile ( char *name, SizeData sd ) { char record[128]; int fh = -1; /* * Insist on a frame count specification. */ DXASSERTGOTO ( sd.startframe != VALUE_UNSPECIFIED ); DXASSERTGOTO ( sd.endframe != VALUE_UNSPECIFIED ); #if !defined(os2) && !defined(DXD_WIN) if ( ( fh = open ( name, ( O_CREAT | O_RDWR ), 0666 ) ) < 0 ) #else /* os2 has a 2 parameter #define for open() _open(). This is the only file * where 3 parameters are required. */ if ( ( fh = _open ( name, ( O_CREAT | O_RDWR | O_BINARY), (_S_IREAD | _S_IWRITE) ) ) < 0 ) #endif { DXSetError ( ERROR_INVALID_DATA, "can't open file %s", name ); goto error; } if ( sprintf ( record, "%dx%dx%d\n", sd.width, sd.height, ( sd.endframe + 1 ) ) <= 0 ) DXErrorGoto ( ERROR_INTERNAL, "sprintf()" ); if ( strlen ( record ) != write ( fh, (char*)record, strlen ( record ) ) ) { DXSetError ( ERROR_UNEXPECTED, "can't write to size file %s", name ); goto error; } if ( fh >= 0 ) close ( fh ); return OK; error: if ( fh >= 0 ) close ( fh ); return ERROR; }