static void attach_exif_entry( ExifEntry *entry, IMAGE *im ) { char name_text[256]; VipsBuf name; char value_text[256]; VipsBuf value; char exif_value[256]; vips_buf_init_static( &name, name_text, 256 ); vips_buf_init_static( &value, value_text, 256 ); vips_buf_appendf( &name, "exif-%s", exif_tag_get_title( entry->tag ) ); vips_buf_appendf( &value, "%s (%s, %d bytes)", exif_entry_get_value( entry, exif_value, 256 ), exif_format_get_name( entry->format ), entry->size ); /* Can't do anything sensible with the error return. */ (void) im_meta_set_string( im, vips_buf_all( &name ), vips_buf_all( &value ) ); }
static int vips_fits_get_header( VipsFits *fits, VipsImage *out ) { int status; int bitpix; int width, height, bands, format, type; int keysexist; int i; status = 0; if( fits_get_img_paramll( fits->fptr, 10, &bitpix, &fits->naxis, fits->naxes, &status ) ) { vips_fits_error( status ); return( -1 ); } #ifdef VIPS_DEBUG VIPS_DEBUG_MSG( "naxis = %d\n", fits->naxis ); for( i = 0; i < fits->naxis; i++ ) VIPS_DEBUG_MSG( "%d) %lld\n", i, fits->naxes[i] ); #endif /*VIPS_DEBUG*/ width = 1; height = 1; bands = 1; switch( fits->naxis ) { /* If you add more dimensions here, adjust data read below. See also * the definition of MAX_DIMENSIONS above. */ case 10: case 9: case 8: case 7: case 6: case 5: case 4: for( i = fits->naxis; i > 3; i-- ) if( fits->naxes[i - 1] != 1 ) { im_error( "fits", "%s", _( "dimensions above 3 " "must be size 1" ) ); return( -1 ); } case 3: bands = fits->naxes[2]; case 2: height = fits->naxes[1]; case 1: width = fits->naxes[0]; break; default: im_error( "fits", _( "bad number of axis %d" ), fits->naxis ); return( -1 ); } /* Are we in one-band mode? */ if( fits->band_select != -1 ) bands = 1; /* Get image format. We want the 'raw' format of the image, our caller * can convert using the meta info if they want. */ for( i = 0; i < VIPS_NUMBER( fits2vips_formats ); i++ ) if( fits2vips_formats[i][0] == bitpix ) break; if( i == VIPS_NUMBER( fits2vips_formats ) ) { im_error( "fits", _( "unsupported bitpix %d\n" ), bitpix ); return( -1 ); } format = fits2vips_formats[i][1]; fits->datatype = fits2vips_formats[i][2]; if( bands == 1 ) { if( format == VIPS_FORMAT_USHORT ) type = VIPS_INTERPRETATION_GREY16; else type = VIPS_INTERPRETATION_B_W; } else if( bands == 3 ) { if( format == VIPS_FORMAT_USHORT ) type = VIPS_INTERPRETATION_RGB16; else type = VIPS_INTERPRETATION_RGB; } else type = VIPS_INTERPRETATION_MULTIBAND; im_initdesc( out, width, height, bands, im_bits_of_fmt( format ), format, VIPS_CODING_NONE, type, 1.0, 1.0, 0, 0 ); /* Read all keys into meta. */ if( fits_get_hdrspace( fits->fptr, &keysexist, NULL, &status ) ) { vips_fits_error( status ); return( -1 ); } for( i = 0; i < keysexist; i++ ) { char record[81]; char vipsname[100]; if( fits_read_record( fits->fptr, i + 1, record, &status ) ) { vips_fits_error( status ); return( -1 ); } VIPS_DEBUG_MSG( "fits2vips: setting meta on vips image:\n" ); VIPS_DEBUG_MSG( " record == \"%s\"\n", record ); /* FITS lets keys repeat. For example, HISTORY appears many * times, each time with a fresh line of history attached. We * have to include the key index in the vips name we assign. */ im_snprintf( vipsname, 100, "fits-%d", i ); if( im_meta_set_string( out, vipsname, record ) ) return( -1 ); } return( 0 ); }
static int parse_header( Read *read ) { IMAGE *im = read->im; Image *image = read->image; Image *p; int i; /* Handy for testimng IM/GM printf( "parse_header: filename = %s\n", read->filename ); printf( "GetImageChannelDepth(DefaultChannels) = %ld\n", GetImageChannelDepth( image, DefaultChannels, &image->exception ) ); printf( "GetImageChannelDepth(AllChannels) = %ld\n", GetImageChannelDepth( image, AllChannels, &image->exception ) ); printf( "GetImageDepth() = %ld\n", GetImageDepth( image, &image->exception ) ); printf( "image->depth = %lu\n", image->depth ); printf( "GetImageQuantumDepth(MagickFalse) = %ld\n", GetImageQuantumDepth( image, MagickFalse ) ); printf( "GetImageType() = %d\n", GetImageType( image, &image->exception ) ); printf( "IsGrayImage() = %d\n", IsGrayImage( image, &image->exception ) ); printf( "IsMonochromeImage() = %d\n", IsMonochromeImage( image, &image->exception ) ); printf( "IsOpaqueImage() = %d\n", IsOpaqueImage( image, &image->exception ) ); */ im->Xsize = image->columns; im->Ysize = image->rows; read->frame_height = image->rows; if( (im->Bands = get_bands( image )) < 0 ) return( -1 ); /* Depth can be 'fractional'. You'd think we should use * GetImageDepth() but that seems unreliable. 16-bit mono DICOM images * are reported as depth 1, for example. */ im->BandFmt = -1; if( image->depth >= 1 && image->depth <= 8 ) im->BandFmt = IM_BANDFMT_UCHAR; if( image->depth >= 9 && image->depth <= 16 ) im->BandFmt = IM_BANDFMT_USHORT; #ifdef UseHDRI if( image->depth == 32 ) im->BandFmt = IM_BANDFMT_FLOAT; if( image->depth == 64 ) im->BandFmt = IM_BANDFMT_DOUBLE; #else /*!UseHDRI*/ if( image->depth == 32 ) im->BandFmt = IM_BANDFMT_UINT; #endif /*UseHDRI*/ if( im->BandFmt == -1 ) { im_error( "im_magick2vips", _( "unsupported bit depth %d" ), (int) image->depth ); return( -1 ); } switch( image->colorspace ) { case GRAYColorspace: if( im->BandFmt == IM_BANDFMT_USHORT ) im->Type = IM_TYPE_GREY16; else im->Type = IM_TYPE_B_W; break; case RGBColorspace: if( im->BandFmt == IM_BANDFMT_USHORT ) im->Type = IM_TYPE_RGB16; else im->Type = IM_TYPE_RGB; break; case sRGBColorspace: if( im->BandFmt == IM_BANDFMT_USHORT ) im->Type = IM_TYPE_RGB16; else im->Type = IM_TYPE_sRGB; break; case CMYKColorspace: im->Type = IM_TYPE_CMYK; break; default: im_error( "im_magick2vips", _( "unsupported colorspace %d" ), (int) image->colorspace ); return( -1 ); } switch( image->units ) { case PixelsPerInchResolution: im->Xres = image->x_resolution / 25.4; im->Yres = image->y_resolution / 25.4; break; case PixelsPerCentimeterResolution: im->Xres = image->x_resolution / 10.0; im->Yres = image->y_resolution / 10.0; break; default: im->Xres = 1.0; im->Yres = 1.0; break; } /* Other fields. */ im->Coding = IM_CODING_NONE; /* Three ways to loop over attributes / properties :-( */ #ifdef HAVE_RESETIMAGEPROPERTYITERATOR { char *key; /* This is the most recent imagemagick API, test for this first. */ ResetImagePropertyIterator( image ); while( (key = GetNextImageProperty( image )) ) { char name_text[256]; VipsBuf name = VIPS_BUF_STATIC( name_text ); vips_buf_appendf( &name, "magick-%s", key ); im_meta_set_string( im, vips_buf_all( &name ), GetImageProperty( image, key ) ); } } #elif defined(HAVE_RESETIMAGEATTRIBUTEITERATOR) { const ImageAttribute *attr; /* magick6.1-ish and later, deprecated in 6.5ish. */ ResetImageAttributeIterator( image ); while( (attr = GetNextImageAttribute( image )) ) { char name_text[256]; VipsBuf name = VIPS_BUF_STATIC( name_text ); vips_buf_appendf( &name, "magick-%s", attr->key ); im_meta_set_string( im, vips_buf_all( &name ), attr->value ); } } #else { const ImageAttribute *attr; /* GraphicsMagick is missing the iterator: we have to loop ourselves. * ->attributes is marked as private in the header, but there's no * getter so we have to access it directly. */ for( attr = image->attributes; attr; attr = attr->next ) { char name_text[256]; VipsBuf name = VIPS_BUF_STATIC( name_text ); vips_buf_appendf( &name, "magick-%s", attr->key ); im_meta_set_string( im, vips_buf_all( &name ), attr->value ); } } #endif /* Do we have a set of equal-sized frames? Append them. FIXME ... there must be an attribute somewhere from dicom read which says this is a volumetric image */ read->n_frames = 0; for( p = image; p; (p = GetNextImageInList( p )) ) { if( p->columns != (unsigned int) im->Xsize || p->rows != (unsigned int) im->Ysize || get_bands( p ) != im->Bands ) break; read->n_frames += 1; } if( p ) /* Nope ... just do the first image in the list. */ read->n_frames = 1; /* Record frame pointers. */ im->Ysize *= read->n_frames; if( !(read->frames = IM_ARRAY( NULL, read->n_frames, Image * )) ) return( -1 ); p = image; for( i = 0; i < read->n_frames; i++ ) { read->frames[i] = p; p = GetNextImageInList( p ); } return( 0 ); }