We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProcessing DevelopmentLibraries,  Tool Development › My Arbitrary DPI TIFF saving function :)
Page Index Toggle Pages: 1
My Arbitrary DPI TIFF saving function :) (Read 765 times)
My Arbitrary DPI TIFF saving function :)
Jul 19th, 2006, 11:26pm
 
I wrote a function that saves PImages (or PGraphics2 for offscreen drawing, just change the function header) as a high DPI tiff (any DPI you want in fact). Photoshop and Apple's Preview recognize the DPI, and I'm guessing everything else does to. This function doesn't use any Java image libs (except Processing's PImage as a source).

(btw, Ben if you're reading this, it would be nice if saveFrame could do this... *hint* *hint*, you had mentioned that you would like to do this at some point in the alpha forums. A quick high-dpi workaround for a PGraphics2 extention would be to enable smoothing and have the (third) background buffer larger than front and back buffers and scale it down/copy before you flip the back buffer. The only other thing that would need scaling is the mouse coords).


//PImage can also be PGraphics2 with no other modifications
//n is the (complete) filename
//dpi is dots per unit
//format: unit= 1=none, 2=inches, 3=cm
void writeTiff(PImage i,String n,int dpi,int format)
{
 byte[] b=new byte[256+i.width*i.height*3];
 int o=0;
 b[0]=0x4D;b[1]=0x4D;
 make2byte(42,2,b);//42
 make4byte(20,4,b);  //IFD starts at address 20
 
 make2byte(14,20,b);  //13 IDF entries
 //write the TIFF headers for mac format, 42, offset at b20, 13 IDFs
 writeIDF(b,22, 254,T_LONG,1,0); //newSubfileType
 writeIDF(b,22+12, 256,T_LONG,1,i.width); //imageWidth
 writeIDF(b,22+12*2, 257,T_LONG,1,i.height); //imageHeight
 int[] bps={8,8,8};
 writeIDFE(b,22+12*3, 258,T_SHORT,3,194,bps); //bitsPerSample
 writeIDF(b,22+12*4, 259,T_SHORT,1,1); //Compression, none
 writeIDF(b,22+12*5, 262,T_SHORT,1,2); //PhotometricInterpretation
 writeIDF(b,22+12*6, 273,T_LONG,1,234); //StripOffsets, offset for image data is 20(main header) + 2+156+4 (IDF) +24+8+8 (IDF data)= 234
 writeIDF(b,22+12*7, 277,T_SHORT,1,3); //samples per pixel
 writeIDF(b,22+12*8, 278,T_LONG,1, 2147483647); //rowsPerStrip  2^32/2-1.
 writeIDF(b,22+12*9, 279,T_LONG,1,i.height*i.width*3); //StripByteCounts
 int[] dpia={dpi};
 writeIDFE(b,22+12*10, 282,T_RATIONAL,1,194+24,dpia); //XResolution
 writeIDFE(b,22+12*11, 283,T_RATIONAL,1,194+32,dpia); //YResolution
 writeIDF(b,22+12*12, 284,T_SHORT,1,1); //PlanarConfiguration
 writeIDF(b,22+12*13, 296,T_LONG,1,format); //Resolution Unit
 make4byte(0,22+13*14,b); //no more IDFs
 
 o=234;
 i.loadPixels();
 for(int y=0;y<i.height;y++){
   for(int x=0;x<i.width;x++){
     b[o]=byte(i.pixels[y*i.width+x] >>16 & 0xff);
     b[o+1]=byte(i.pixels[y*i.width+x] >>8 & 0xff);
     b[o+2]=byte(i.pixels[y*i.width+x] >>0 & 0xff);
     o+=3;
   }
 }
 
 saveBytes(n, b);
 if(format<2) println(n+" saved at "+dpi+"px/in");
 if(format==2) println(n+" saved at "+dpi+"px/cm");
}

void writeIDF(byte[] b,int o, int tag, int type, int count, int value)
{
 make2byte(tag,o,b);    //IDF tag
 make2byte(type,o+2,b);  //field type
 make4byte(count,o+4,b); //how many values
 if(type==T_LONG) make4byte(value,o+8,b); //how many values
 if(type==T_SHORT) make2byte(value,o+8,b); //how many values
}

void writeIDFE(byte[] b,int o, int tag, int type, int count, int offset, int[] values)
{
 make2byte(tag,o,b);    //IDF tag
 make2byte(type,o+2,b);  //field type
 make4byte(count,o+4,b); //how many values
 make4byte(offset,o+8,b);
 if(type==T_SHORT){
   for(int i=0;i<count;i++) make2byte(values[i],offset+2*i,b); //output all shorts
 }
 if(type==T_RATIONAL){ make4byte(values[0],offset,b); make4byte(1,offset+4,b);} //how many values
}

String[] tifftypes={"null","BYTE","ASCII","SHORT","LONG","RATIONAL","","",""};
int T_BYTE=1;int T_ASCII=2; int T_SHORT=3; int T_LONG=4; int T_RATIONAL=5;

void make4byte(int d, int o, byte[] b){
 int s1=24;int s2=16;int s3=8;int s4=0;
 b[o]=byte((d-d%(256*256*256))/(256*256*256));
 b[o+1]=byte((d-d%(256*256))/(256*256));
 b[o+2]=byte((d-d%256)/256);
 b[o+3]=byte(d%256);
}

void make2byte(int d, int o, byte[] b){
 int s1=8;int s2=0;
 b[o]=byte((d-d%256)/256);
 b[o+1]=byte(d%256);
}
Page Index Toggle Pages: 1