support for reading/writing image resolution (dpi), for PNG and TIFF,
authorCampbell Barton <ideasman42@gmail.com>
Fri, 13 May 2011 14:27:12 +0000 (14:27 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 13 May 2011 14:27:12 +0000 (14:27 +0000)
only RNA access currently 'image.resolution'.

source/blender/imbuf/IMB_imbuf_types.h
source/blender/imbuf/intern/allocimbuf.c
source/blender/imbuf/intern/png.c
source/blender/imbuf/intern/tiff.c
source/blender/makesrna/intern/rna_image.c

index 52afe2ed8546a88a612a03ace85ff8bc64801fc9..5717a92db54f0a8ca8b136a3e1420f43b83567ad 100644 (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;
index efa37aa119661128ffe296a2fe2a69471a7e8a0a..91583f02a4969a2fa66f8e5949d6188393b10a00 100644 (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) {
index 200ff0af9af2af6beb7fa1d1028ee7e253aa135a..6b6dcdb88afd4b729504e5c010270c7a17120b82 100644 (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");
        }
 
index 67d20d564664913921ae5f820eec7571b7bc668b..36130aa0dbfedf95af10fc0dc35a425d7aecfadd 100644 (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,
index 5872542d10a659640c3825afb18687dca364a70d..3db90c2de0e80aee87ff8d139715d4f2ecb41ef3 100644 (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);