/***********************************************************************/ /* 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/readimage.c,v 1.3 1999/05/10 15:45:29 gda Exp $ */ #include /*** MODULE: ReadImage INPUTS: name; string; image.rgb; file name format; string; data dependent; format of file start; integer; first frame; starting movie frame end; integer; last frame; ending movie frame delta; integer; 1; delta of images to read width; integer; data dependent; width of image height; Integer; data dependent; height of image delayed; integer; env. dep; use delayed if present in image file colortype; string; env. dep; "float" or "byte" ***/ #include #include #include #include <_helper_jea.h> #include <_rw_image.h> #include #ifdef DXD_WIN /* ajay */ #include #endif #if DXD_HAS_LIBIOP #include #include #endif #define COLORS_PIXEL 3 #define SPECIFIED(a) ((a) != VALUE_UNSPECIFIED) #define CONCAT_PATHS(a, b, c) \ if (strlen(b)+strlen(c) MAX_IMAGE_NAMELEN) { DXSetError( ERROR_INVALID_DATA, "#12210", "name"); goto error; } strcpy(originalname,filename); } else strcpy(originalname,"image"); strcpy(basename,originalname); envstr_DXDATA = (char *)getenv("DXDATA"); *user_path = '\0'; if ( I_format ) { if ( !DXExtractString ( I_format, &format ) || ( format == NULL ) ) DXErrorGoto2 ( ERROR_MISSING_DATA, "#10200", "format" ) else if (!(imginfo = _dxf_ImageInfoFromFormat(format)) ) DXErrorGoto3 ( ERROR_BAD_PARAMETER, "#10210", format, "the file format" ) imgflags = imginfo->flags; imgtyp = imginfo->type; if (Input_from_ADASD) { if (!(imgflags & ADASD_OK)) DXErrorGoto2 ( ERROR_NOT_IMPLEMENTED, "#12215",format); } else if (imgflags & ADASD_ONLY) { DXErrorGoto2 ( ERROR_NOT_IMPLEMENTED, "#12220",format); } } else { format = NULL; imginfo = _dxf_ImageInfoFromFileName ( basename ); if (imginfo) imgtyp = imginfo->type; if ( Input_from_ADASD ) { if (!imginfo) { imgtyp = img_typ_fb; imginfo = _dxf_ImageInfoFromType(imgtyp); if ( imginfo == NULL ) DXErrorGoto ( ERROR_INVALID_DATA, "image type lookup failed" ); } if ((imginfo->flags & ADASD_OK) == 0) { DXSetError ( ERROR_NOT_IMPLEMENTED, "#12225", "format"); goto error; } } else { if (!imginfo) { imgtyp = img_typ_rgb; imginfo = _dxf_ImageInfoFromType(imgtyp); if ( imginfo == NULL ) DXErrorGoto ( ERROR_INVALID_DATA, "image type lookup failed" ); } if ( imginfo->flags & ADASD_ONLY ) { DXSetError ( ERROR_NOT_IMPLEMENTED, "#12230", "name"); goto error; } } } if ( ( imginfo->read == NULL ) && ( imginfo->type != img_typ_tiff && imginfo->type != img_typ_gif) && imginfo->type != img_typ_miff ) DXErrorGoto ( ERROR_NOT_IMPLEMENTED, "#12235"); /* * Remove the extension in basename if it is recognized * and is an acceptable extension for imgtyp. */ _dxf_RemoveImageExtension(basename,imgtyp); if ( I_start ) { if ( !DXExtractInteger ( I_start, ¶m_sizes.startframe ) || ( param_sizes.startframe < 0 ) ) DXErrorGoto2 ( ERROR_INVALID_DATA, "#10030", "start" ) } else param_sizes.startframe = VALUE_UNSPECIFIED; if ( I_end ) { if ( !DXExtractInteger ( I_end, ¶m_sizes.endframe ) || ( param_sizes.endframe < 0 ) ) DXErrorGoto2 ( ERROR_INVALID_DATA, "#10030", "end" ) } else param_sizes.endframe = VALUE_UNSPECIFIED; if ( I_delta ) { if ( !DXExtractInteger ( I_delta, &delta ) || ( delta < 1 ) ) DXErrorGoto2 ( ERROR_INVALID_DATA, "#10020", "delta" ) } else delta = 1; if ( I_width ) { if ( !DXExtractInteger ( I_width, ¶m_sizes.width ) || ( param_sizes.width <= 0 ) ) DXErrorGoto2 ( ERROR_INVALID_DATA, "#10020", "width" ) } else param_sizes.width = VALUE_UNSPECIFIED; if ( I_height ) { if ( !DXExtractInteger ( I_height, ¶m_sizes.height ) || ( param_sizes.height <= 0 ) ) DXErrorGoto2 ( ERROR_INVALID_DATA, "#10020", "height" ) } else param_sizes.height = VALUE_UNSPECIFIED; /* * Assemble filename from input strings: filename and format. */ if ( Input_from_ADASD ) { DXASSERT ( imgtyp == img_typ_fb ); /* Note that the sizefilename = imagefilename here. * Also, we can pass VALUE_UNSPECIFIED as the 'frame number' to * _dxf_BuildImageFileName, since the fb format has APPENDABLE_FILES and * thus the frame number is ignored. */ try_count = 0; do { CONCAT_PATHS(user_basename, user_path, basename); if (!_dxf_BuildImageFileName(sizefilename, MAX_IMAGE_NAMELEN, user_basename, imgtyp, VALUE_UNSPECIFIED,0)) goto error; if (!_dxf_ReadImageSizesADASD(sizefilename, &filed_sizes)) goto error; } while ( !(got_file = (SPECIFIED(filed_sizes.width) && SPECIFIED(filed_sizes.height))) && (get_subpath(envstr_DXDATA, try_count++, user_path, sizeof(user_path))) ); found_subpath = *user_path != '\0'; /* * Check to see that the file exists (i.e. height/width were found). * If not, then try and open the file without the extension. */ if (!got_file) { int same_name; if (!_dxf_BuildImageFileName(sizefilename, MAX_IMAGE_NAMELEN, basename, imgtyp, VALUE_UNSPECIFIED,0)) goto error; same_name = strcmp(sizefilename,filename) == 0; try_count = 0; if (!same_name) do { CONCAT_PATHS(user_basename, user_path, filename); if (!_dxf_ReadImageSizesADASD(user_basename, &filed_sizes)) goto error; } while ( !(got_file = (SPECIFIED(filed_sizes.width) && SPECIFIED(filed_sizes.height))) && !found_subpath && (get_subpath(envstr_DXDATA, try_count++, user_path, sizeof(user_path))) ); found_subpath = *user_path != '\0'; if (!got_file) { if (same_name) { DXErrorGoto2(ERROR_BAD_PARAMETER, "#12240",sizefilename); } else { DXErrorGoto3(ERROR_BAD_PARAMETER, "#12245",sizefilename,filename); } } } } else { /* * Assemble size-file-name from input string filename and "size" * Open and read-in or default backwards. */ switch ( imgtyp /* imginfo->type */ ) { case img_typ_rgb: case img_typ_r_g_b: case img_typ_fb: default: strcpy(sizefilename,basename); strcat(sizefilename,".size"); try_count=0; do { CONCAT_PATHS(user_basename, user_path, sizefilename); if (!_dxf_ReadSizeFile(user_basename, &filed_sizes)) goto error; } while ( !(got_file = (SPECIFIED(filed_sizes.width)) && (SPECIFIED(filed_sizes.height))) && !found_subpath && get_subpath(envstr_DXDATA, try_count++, user_path, sizeof(user_path)) ); found_subpath = *user_path != '\0'; break; case img_typ_gif: try_count=0; do { CONCAT_PATHS(user_basename, user_path, basename); if ( !_dxf_BuildGIFReadFileName ( gifopts.name, MAX_IMAGE_NAMELEN, user_basename, originalname, (param_sizes.startframe==VALUE_UNSPECIFIED)? 0 : param_sizes.startframe, &gifopts.use_numerics, &gifopts.ext_sel ) ) goto error; got_file = ((fd = open(gifopts.name, O_RDONLY)) != -1); if (got_file) close(fd); } while ( !got_file && !found_subpath && get_subpath(envstr_DXDATA, try_count++, user_path, sizeof(user_path)) ); if (!got_file) DXErrorGoto2 (ERROR_BAD_PARAMETER, "Could not open file %s, nor any other GIF name variation" " in current path or DXDATA", filename); if (!_dxf_ReadImageSizesGIF (gifopts.name, param_sizes.startframe, &filed_sizes, &gifopts.use_numerics, gifopts.ext_sel, &gifopts.multiples)) goto error; found_subpath = *user_path != '\0'; break; case img_typ_tiff: try_count=0; do { CONCAT_PATHS(user_basename, user_path, basename); if ( !_dxf_BuildTIFFReadFileName ( tiffopts.name, MAX_IMAGE_NAMELEN, user_basename, originalname, (param_sizes.startframe==VALUE_UNSPECIFIED)? 0 : param_sizes.startframe, &tiffopts.use_numerics, &tiffopts.ext_sel ) ) goto error; got_file = ((fd = open(tiffopts.name, O_RDONLY)) != -1); if (got_file) close(fd); } while ( !got_file && !found_subpath && get_subpath(envstr_DXDATA, try_count++, user_path, sizeof(user_path)) ); if (!got_file) DXErrorGoto2 (ERROR_BAD_PARAMETER, "Could not open file %s, nor any other TIFF name variation" " in current path or DXDATA", filename); if (!_dxf_ReadImageSizesTIFF (tiffopts.name, param_sizes.startframe, &filed_sizes, &tiffopts.use_numerics, tiffopts.ext_sel, &tiffopts.multiples)) goto error; found_subpath = *user_path != '\0'; break; case img_typ_miff: try_count=0; do { CONCAT_PATHS(user_basename, user_path, basename); if (!_dxf_BuildImageFileName(miffopts.name, MAX_IMAGE_NAMELEN, user_basename, imgtyp, 0, 0)) goto error; miffopts.ext_sel = 0; got_file = ((fd = open(miffopts.name, O_RDONLY)) != -1); if (got_file) close(fd); } while ( !got_file && !found_subpath && get_subpath(envstr_DXDATA, try_count++, user_path, sizeof(user_path)) ); if (!got_file) DXErrorGoto2 (ERROR_BAD_PARAMETER, "Could not open file %s, nor any other MIFF name variation" " in current path or DXDATA", filename); if (!_dxf_ReadImageSizesMIFF (miffopts.name, param_sizes.startframe, &filed_sizes, &miffopts.use_numerics, miffopts.ext_sel, &miffopts.multiples)) goto error; found_subpath = *user_path != '\0'; break; } } /* * Determine size-file inputs from size file and those of the command line. */ /* Size file has precedence */ image_sizes.width = (SPECIFIED(filed_sizes.width) ? filed_sizes.width : param_sizes.width); /* Size file has precedence */ image_sizes.height = (SPECIFIED(filed_sizes.height) ? filed_sizes.height : param_sizes.height); /* User parameter has precedence, with a default of 0 */ image_sizes.startframe = (SPECIFIED(param_sizes.startframe) ? param_sizes.startframe : (SPECIFIED(filed_sizes.startframe) ? filed_sizes.startframe : 0)); /* User parameter has precedence, with a default of 0 */ image_sizes.endframe = (SPECIFIED(param_sizes.endframe) ? param_sizes.endframe : (SPECIFIED(filed_sizes.endframe) ? filed_sizes.endframe : 0)); /* * Warn if the user supplied 'width' and 'height' parameters don't * match those found in the size file (if present). */ if ( SPECIFIED(param_sizes.width) && SPECIFIED(filed_sizes.width) && ( param_sizes.width != filed_sizes.width ) ) { DXSetError(ERROR_BAD_PARAMETER, "#12250", "width"); goto error; } if ( SPECIFIED(param_sizes.height) && SPECIFIED(filed_sizes.height) && ( param_sizes.height != filed_sizes.height ) ) { DXSetError(ERROR_BAD_PARAMETER, "#12250", "height"); goto error; } /* * Verify the user supplied 'start' and 'end' parameters. */ if (SPECIFIED(param_sizes.startframe) && SPECIFIED(filed_sizes.endframe) && ( param_sizes.startframe > filed_sizes.endframe) ) { DXSetError(ERROR_BAD_PARAMETER, "#12255", "start", filed_sizes.startframe, filed_sizes.endframe); return ERROR; } if (SPECIFIED(param_sizes.endframe) && SPECIFIED(filed_sizes.endframe) && ( param_sizes.endframe > filed_sizes.endframe ) ) { DXSetError(ERROR_BAD_PARAMETER, "#12255", "end", filed_sizes.startframe, filed_sizes.endframe); return ERROR; } if ( image_sizes.startframe > image_sizes.endframe ) { DXSetError ( ERROR_INVALID_DATA, "#12260", image_sizes.startframe, image_sizes.endframe ); return ERROR; } if ( #if DXD_HAS_LIBIOP /* The sizes are inside the fb file, so it is always ok for the * height and width to not be specified. */ (imgtyp != img_typ_fb) && #endif (!SPECIFIED(image_sizes.width) || !SPECIFIED(image_sizes.height))) { /* * ARG!!! Because we allow for the .size file to be optional and * we haven't opened the pixel file yet, we need to try and open the * pixel file in order to give the correct error message (i.e. it * could be that 1) the user gave a bad file name or 2) there is no * .size file and one of width and height was not specified). */ /* XXX - tiff name considerations */ try_count=0; do { CONCAT_PATHS(user_basename, user_path, basename); if (!_dxf_BuildImageFileName(imagefilename, MAX_IMAGE_NAMELEN, user_basename, imgtyp, image_sizes.startframe,0)) return ERROR; } while ( ((i = open(imagefilename, O_RDONLY)) <0) && !found_subpath && get_subpath(envstr_DXDATA, try_count++, user_path, sizeof(user_path)) ); found_subpath = *user_path != '\0'; if (i<0) { if (!_dxf_BuildImageFileName(imagefilename, MAX_IMAGE_NAMELEN, basename, imgtyp, image_sizes.startframe,0)) return ERROR; DXSetError( ERROR_INVALID_DATA, "#12240", imagefilename); /* cannot open fname */ } else { close(i); DXSetError ( ERROR_INVALID_DATA, "#12265"); /* size file is missing */ } return ERROR; } /* * Attempt to open image file and position to start of frame(s). */ frame_size_bytes = image_sizes.width * image_sizes.height; switch ( 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_tiff: break; case img_typ_gif: break; case img_typ_miff: break; default: DXErrorGoto ( ERROR_ASSERTION, "imgtyp" ); } num_files = (imgtyp==img_typ_r_g_b)? 3 : 1; for ( i=0; i= 0 ) close ( fh[0] ); if ( fh[1] >= 0 ) close ( fh[1] ); if ( fh[2] >= 0 ) close ( fh[2] ); if (fh_miff != 0) fclose(fh_miff); O_image = ( ( series ) ? (Object)series : (Object) image ); return OK; error: /* Clean up. */ if ( fh[0] >= 0 ) close ( fh[0] ); if ( fh[1] >= 0 ) close ( fh[1] ); if ( fh[2] >= 0 ) close ( fh[2] ); if (fh_miff != 0) fclose(fh_miff); if ( series ) DXDelete ( (Object) series ); if ( !series && image ) DXDelete ( (Object) image ); return ERROR; } #define BYTES_FLOAT 4 /* * Algorithmic considerations: * Since the pixel content of an unread image is undefined, * and is to be completely overwritten after this call; * We therefore use the 'top fourth' of this area for * our read buffer. * Another useful item is that both the On-disk and in * memory formats store in the order (Red-Green-Blue). */ static Field InputRGB (int width, int height, int fh, char *colortype) { int oneline; int oneframe; unsigned char *anchor; float *fptr; unsigned char *cptr0; unsigned char *cptr1; int i, y, x; Array colorsArray; Type type; int expandToFloat; Field image = NULL; int rank, shape[32]; if ((width * height) == 0) { DXSetError ( ERROR_BAD_PARAMETER, "#12275",0); return ERROR; } image = DXMakeImageFormat(width, height, colortype); if (! image) goto error; colorsArray = (Array)DXGetComponentValue(image, "colors"); if (! colorsArray) goto error; DXGetArrayInfo(colorsArray, NULL, &type, NULL, &rank, shape); if (type == TYPE_FLOAT) { expandToFloat = 1; } else { if (rank != 1 || shape[0] != 3) { DXSetError(ERROR_INTERNAL, "readimage from .rgb files requires 3-vector colors"); goto error; } expandToFloat = 0; } anchor = (unsigned char *)DXGetArrayData(colorsArray); oneline = width * COLORS_PIXEL; oneframe = oneline * height; /* Read complete image directly into memory in native disk format. * * Byte format scanlines in image memory after read-in: * +--------------------------------------+ * | empty | * +--------------------------------------+ * | " | * +--------------------------------------+ * | " | * +---------+----------------------------+ * | y0 | " | * +---------+---------+---------+--------+ * | ymax-1 | ymax-2 | ... | y1 | * +---------+---------+---------+--------+ *(origin) */ /* * Note that the above figure is appropriate if the output * image type is float. If its byte, the result is simply: * * +--------------------------------------+ * | y0 | * +--------------------------------------+ * | y1 | * +--------------------------------------+ * | ... | * +--------------------------------------+ * | ymax-2 | * +--------------------------------------+ * | ymax-1 | * +--------------------------------------+ */ if (read(fh, anchor, oneframe) != oneframe) { DXSetError ( ERROR_BAD_PARAMETER, "#12280", height, width ); return ERROR; } /* * Invert ordering of scan-lines */ cptr0 = anchor; cptr1 = anchor + (height-1)*oneline; for (y = 0; y < (height>>1); y++, cptr0 += oneline, cptr1 -= oneline) { unsigned char *c0 = (char *)cptr0; unsigned char *c1 = (char *)cptr1; for (x = 0; x < oneline; x++, c0++, c1++) { unsigned char tmp = *c1; *c1 = *c0; *c0 = tmp; } } if (expandToFloat) { float *dstY = ((float *)anchor) + (height-1)*oneline; unsigned char *srcY = ((unsigned char *)anchor) + (height-1)*oneline; float denom = 1.0 / 255.0; for (y = (height-1); y >= 0; y--, dstY -= oneline, srcY -= oneline) { float *dstX = dstY + (oneline-1); unsigned char *srcX = srcY + (oneline-1); for (x = 0; x < oneline; x++, dstX--, srcX--) *dstX = *srcX * denom; } } return image; error: if (DXGetError() == ERROR_NONE) DXSetError(ERROR_INTERNAL, ""); DXDelete((Object)image); return ERROR; } static Field InputR_G_B (int width, int height, int fh[3], char *colortype) { int oneframe; Pointer *pixels; ubyte *buffer = NULL; ubyte *c_ptr; int c; int i, j; Field image = NULL; Array colorsArray = NULL; Type type; int rank, shape[32]; if ((width * height) == 0) DXErrorReturn(ERROR_BAD_PARAMETER, "Attempt to read 0 sized image"); image = DXMakeImageFormat(width, height, colortype); if (! image) goto error; colorsArray = (Array)DXGetComponentValue(image, "colors"); if (! colorsArray) goto error; pixels = DXGetArrayData(colorsArray); oneframe = width * height; if (!( buffer = DXAllocateLocal(oneframe))) goto error; DXGetArrayInfo(colorsArray, NULL, &type, NULL, &rank, shape); if (type == TYPE_UBYTE) { ubyte *p_ptr; if (rank != 1 || shape[0] != 3) { DXSetError(ERROR_INTERNAL, "readimage from r+g+b files requires 3-vector colors"); goto error; } for (c=0; c<3; c++) { if ( read ( fh[c], buffer, oneframe ) != oneframe ) { DXSetError ( ERROR_BAD_PARAMETER, "#12290", height, width, (c==0)?'r' : (c==1)?'g' : 'b' ); return ERROR; } for ( i=0; i ms.frames) DXErrorGoto2 ( ERROR_INVALID_DATA, "#12300", frame); bufsize = ms.frame_blocks * MOV_BLK_SIZE + 1023; ibuffer = (char *)DXAllocate(bufsize); if (! ibuffer) goto error; buffer_aligned = ( (int)ibuffer % 1024 ) ? (u_int *)( (int)ibuffer + 1024 - ( (int)ibuffer % 1024)) : (u_int *)ibuffer; if ((mid = mov_open(fname)) == 0) DXErrorGoto2 ( ERROR_INTERNAL, "%s, (mov_open)", mov_errmsg ( mov_errno ) ); if ( ( mov_errcode = mov_get ( mid, ( frame + 1 ), ( frame + 1 ), (u_int *)buffer_aligned ) ) < 0 ) DXErrorGoto2 ( ERROR_INTERNAL, "%s, (mov_get)", mov_errmsg ( mov_errcode )); if ( ( mov_errcode = mov_close ( mid ) ) < 0 ) DXErrorGoto2 ( ERROR_INTERNAL, "%s, (mov_close)", mov_errmsg ( mov_errcode )); mid = 0; ipixels = (BGRA *) buffer_aligned; if (type == TYPE_FLOAT) { /* * Pre-Calculate the divisions, so they aren't recalculated on a * per-pixel basis. */ if ( !lut_loaded ) { for (i=0; i<256; i++) lut [i] = ((float)i / 255.0); lut_loaded = 1; } for ( i=0; ir = lut[ip->r]; op->g = lut[ip->g]; op->b = lut[ip->b]; } } } else if (type == TYPE_UBYTE) { for ( i=0; i