support for reading/writing image resolution (dpi), for PNG and TIFF,

only RNA access currently 'image.resolution'.
This commit is contained in:
Campbell Barton
2011-05-13 14:27:12 +00:00
parent 6786f92fe5
commit 05d004fd14
5 changed files with 93 additions and 4 deletions

View File

@@ -93,6 +93,9 @@ typedef struct ImBuf {
char profile_filename[256]; /* to be implemented properly, specific filename for custom profiles */
#endif
/* resolution - pixels per meter */
double ppm[2];
/* tiled pixel storage */
int tilex, tiley;
int xtiles, ytiles;

View File

@@ -348,6 +348,7 @@ ImBuf *IMB_allocImBuf(unsigned int x, unsigned int y, uchar d, unsigned int flag
ibuf->depth= d;
ibuf->ftype= TGA;
ibuf->channels= 4; /* float option, is set to other values when buffers get assigned */
ibuf->ppm[0]= ibuf->ppm[1]= 150.0 / 0.0254; /* 150dpi -> pixels-per-meter */
if(flags & IB_rect) {
if(imb_addrectImBuf(ibuf)==FALSE) {

View File

@@ -257,6 +257,10 @@ int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
}
if(ibuf->ppm[0] > 0.0 && ibuf->ppm[1] > 0.0) {
png_set_pHYs(png_ptr, info_ptr, (unsigned int)(ibuf->ppm[0] + 0.5), (unsigned int)(ibuf->ppm[1] + 0.5), PNG_RESOLUTION_METER);
}
// write the file header information
png_write_info(png_ptr, info_ptr);
@@ -384,7 +388,19 @@ struct ImBuf *imb_loadpng(unsigned char *mem, size_t size, int flags)
if (ibuf) {
ibuf->ftype = PNG;
ibuf->profile = IB_PROFILE_SRGB;
} else {
if (png_get_valid (png_ptr, info_ptr, PNG_INFO_pHYs)) {
int unit_type;
unsigned int xres, yres;
if(png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type))
if(unit_type == PNG_RESOLUTION_METER) {
ibuf->ppm[0]= xres;
ibuf->ppm[1]= yres;
}
}
}
else {
printf("Couldn't allocate memory for PNG image\n");
}

View File

@@ -354,6 +354,25 @@ static void scanline_separate_32bit(float *rectf, float *fbuf, int scanline_w, i
rectf[i*4 + chan] = fbuf[i];
}
static void imb_read_tiff_resolution(ImBuf *ibuf, TIFF *image)
{
uint16 unit;
float xres;
float yres;
TIFFGetFieldDefaulted(image, TIFFTAG_RESOLUTIONUNIT, &unit);
TIFFGetFieldDefaulted(image, TIFFTAG_XRESOLUTION, &xres);
TIFFGetFieldDefaulted(image, TIFFTAG_YRESOLUTION, &yres);
if(unit == RESUNIT_CENTIMETER) {
ibuf->ppm[0]= (double)xres * 100.0;
ibuf->ppm[1]= (double)yres * 100.0;
}
else {
ibuf->ppm[0]= (double)xres / 0.0254;
ibuf->ppm[1]= (double)yres / 0.0254;
}
}
/*
* Use the libTIFF scanline API to read a TIFF image.
@@ -369,10 +388,13 @@ static int imb_read_tiff_pixels(ImBuf *ibuf, TIFF *image, int premul)
int ib_flag=0, row, chan;
float *fbuf=NULL;
unsigned short *sbuf=NULL;
TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &bitspersample);
TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &spp); /* number of 'channels' */
TIFFGetField(image, TIFFTAG_PLANARCONFIG, &config);
imb_read_tiff_resolution(ibuf, image);
scanline = TIFFScanlineSize(image);
if (bitspersample == 32) {
@@ -658,6 +680,7 @@ int imb_savetiff(ImBuf *ibuf, const char *name, int flags)
unsigned char *from = NULL, *to = NULL;
unsigned short *pixels16 = NULL, *to16 = NULL;
float *fromf = NULL;
float xres, yres;
int x, y, from_i, to_i, i;
int extraSampleTypes[1] = { EXTRASAMPLE_ASSOCALPHA };
@@ -783,8 +806,18 @@ int imb_savetiff(ImBuf *ibuf, const char *name, int flags)
TIFFSetField(image, TIFFTAG_COMPRESSION, COMPRESSION_DEFLATE);
TIFFSetField(image, TIFFTAG_FILLORDER, FILLORDER_MSB2LSB);
TIFFSetField(image, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(image, TIFFTAG_XRESOLUTION, 150.0);
TIFFSetField(image, TIFFTAG_YRESOLUTION, 150.0);
if(ibuf->ppm[0] > 0.0 && ibuf->ppm[1] > 0.0) {
xres= (float)(ibuf->ppm[0] * 0.0254);
yres= (float)(ibuf->ppm[1] * 0.0254);
}
else {
xres= yres= 150.0f;
}
TIFFSetField(image, TIFFTAG_XRESOLUTION, xres);
TIFFSetField(image, TIFFTAG_YRESOLUTION, yres);
TIFFSetField(image, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
if(TIFFWriteEncodedStrip(image, 0,
(bitspersample == 16)? (unsigned char*)pixels16: pixels,

View File

@@ -221,6 +221,39 @@ static void rna_Image_size_get(PointerRNA *ptr,int *values)
BKE_image_release_ibuf(im, lock);
}
static void rna_Image_resolution_get(PointerRNA *ptr, float *values)
{
Image *im= (Image*)ptr->data;
ImBuf *ibuf;
void *lock;
ibuf = BKE_image_acquire_ibuf(im, NULL , &lock);
if (ibuf) {
values[0]= ibuf->ppm[0];
values[1]= ibuf->ppm[1];
}
else {
values[0]= 0;
values[1]= 0;
}
BKE_image_release_ibuf(im, lock);
}
static void rna_Image_resolution_set(PointerRNA *ptr, const float *values)
{
Image *im= (Image*)ptr->data;
ImBuf *ibuf;
void *lock;
ibuf = BKE_image_acquire_ibuf(im, NULL , &lock);
if (ibuf) {
ibuf->ppm[0]= values[0];
ibuf->ppm[1]= values[1];
}
BKE_image_release_ibuf(im, lock);
}
static int rna_Image_depth_get(PointerRNA *ptr)
{
@@ -557,6 +590,9 @@ static void rna_def_image(BlenderRNA *brna)
RNA_def_property_int_funcs(prop, "rna_Image_size_get" , NULL, NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop= RNA_def_float_vector(srna, "resolution" , 2 , NULL , 0, 0, "Resolution" , "X/Y pixels per meter" , 0 , 0);
RNA_def_property_float_funcs(prop, "rna_Image_resolution_get" , "rna_Image_resolution_set", NULL);
prop= RNA_def_property(srna, "pixels", PROP_FLOAT, PROP_NONE);
RNA_def_property_flag(prop, PROP_DYNAMIC);
RNA_def_property_multi_array(prop, 1, NULL);