Skip to main content

Adding a date stamp to your digital pictures

Posted by kirillcool on October 30, 2006 at 10:17 AM PST

You can call me old-fashioned, but i prefer holding a photo album in my hands (the same goes for the books). Sure, it feels bulky and may require more energy spent to page through it, but it just feels right. Especially now with the new baby in town we take quite a lot of pictures and send them to the proud grandparents and other selected family members. How do we do it - copy the pictures to a disk-on-key, drop it at the nearest photoshop and pick up the printed pictures an hour later. The only problem is that neither our camera (one of this Pentax line, not that photoshop can add a timestamp in the bottom-right (or any for that matter) corner of the picture.

This may be fine for now, but when i look through older pictures of me and my family, it's nice to know when the pictures were taken. Of course, i could look for another photoshop, but then i can do it myself. So, without further ado, here is how you can add a date stamp in the bottom-right corner and have it not cut-off when your 4:3 file is printed on a 3:2 paper:

<font color="#ffffff">&nbsp;&nbsp;</font><font color="#7f0055"><b>public&nbsp;static&nbsp;</b></font><font color="#7f0055"><b>void&nbsp;</b></font><font color="#000000">addDate</font><font color="#000000">(</font><font color="#000000">File&nbsp;inputFile</font><font color="#000000">)&nbsp;</font><font color="#7f0055"><b>throws&nbsp;</b></font><font color="#000000">Exception&nbsp;</font><font color="#000000">{</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">String&nbsp;inputFilename&nbsp;=&nbsp;inputFile.getPath</font><font color="#000000">()</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">System.out.println</font><font color="#000000">(</font><font color="#2a00ff">&#34;Starting&nbsp;with&nbsp;'&#34;&nbsp;</font><font color="#000000">+&nbsp;inputFilename&nbsp;+&nbsp;</font><font color="#2a00ff">&#34;'&#34;</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">BufferedImage&nbsp;input&nbsp;=&nbsp;ImageIO.read</font><font color="#000000">(</font><font color="#000000">inputFile</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">Graphics2D&nbsp;graphics&nbsp;=&nbsp;</font><font color="#000000">(</font><font color="#000000">Graphics2D</font><font color="#000000">)&nbsp;</font><font color="#000000">input.createGraphics</font><font color="#000000">()</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">Date&nbsp;lastModified&nbsp;=&nbsp;</font><font color="#7f0055"><b>new&nbsp;</b></font><font color="#000000">Date</font><font color="#000000">(</font><font color="#000000">inputFile.lastModified</font><font color="#000000">())</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">SimpleDateFormat&nbsp;sdf&nbsp;=&nbsp;</font><font color="#7f0055"><b>new&nbsp;</b></font><font color="#000000">SimpleDateFormat</font><font color="#000000">(</font><font color="#2a00ff">&#34;dd/MM/yyyy&#34;</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">String&nbsp;dateStamp&nbsp;=&nbsp;sdf.format</font><font color="#000000">(</font><font color="#000000">lastModified</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#7f0055"><b>int&nbsp;</b></font><font color="#000000">fontSize&nbsp;=&nbsp;</font><font color="#000000">(</font><font color="#7f0055"><b>int</b></font><font color="#000000">)&nbsp;(</font><font color="#990000">0.4&nbsp;</font><font color="#000000">*&nbsp;input.getHeight</font><font color="#000000">()&nbsp;</font><font color="#000000">/&nbsp;</font><font color="#990000">10.0</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">Font&nbsp;font&nbsp;=&nbsp;</font><font color="#7f0055"><b>new&nbsp;</b></font><font color="#000000">Font</font><font color="#000000">(</font><font color="#2a00ff">&#34;Arial&#34;</font><font color="#000000">,&nbsp;Font.BOLD,&nbsp;fontSize</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">graphics.setFont</font><font color="#000000">(</font><font color="#000000">font</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#7f0055"><b>int&nbsp;</b></font><font color="#000000">height&nbsp;=&nbsp;graphics.getFontMetrics</font><font color="#000000">()</font><font color="#000000">.getHeight</font><font color="#000000">()</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#7f0055"><b>int&nbsp;</b></font><font color="#000000">width&nbsp;=&nbsp;graphics.getFontMetrics</font><font color="#000000">()</font><font color="#000000">.stringWidth</font><font color="#000000">(</font><font color="#000000">dateStamp</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff"></font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">BufferedImage&nbsp;dateImage&nbsp;=&nbsp;</font><font color="#7f0055"><b>new&nbsp;</b></font><font color="#000000">BufferedImage</font><font color="#000000">(</font><font color="#990000">2&nbsp;</font><font color="#000000">*&nbsp;fontSize&nbsp;+&nbsp;width,&nbsp;</font><font color="#990000">2</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">*&nbsp;fontSize&nbsp;+&nbsp;height,&nbsp;BufferedImage.TYPE_INT_ARGB</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">Graphics2D&nbsp;dateGraphics&nbsp;=&nbsp;</font><font color="#000000">(</font><font color="#000000">Graphics2D</font><font color="#000000">)&nbsp;</font><font color="#000000">dateImage.getGraphics</font><font color="#000000">()</font><font color="#000000">.create</font><font color="#000000">()</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">dateGraphics.setColor</font><font color="#000000">(</font><font color="#7f0055"><b>new&nbsp;</b></font><font color="#000000">Color</font><font color="#000000">(</font><font color="#990000">0</font><font color="#000000">,&nbsp;</font><font color="#990000">0</font><font color="#000000">,&nbsp;</font><font color="#990000">0</font><font color="#000000">,&nbsp;</font><font color="#990000">0</font><font color="#000000">))</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">dateGraphics.setComposite</font><font color="#000000">(</font><font color="#000000">AlphaComposite.Src</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">dateGraphics.fillRect</font><font color="#000000">(</font><font color="#990000">0</font><font color="#000000">,&nbsp;</font><font color="#990000">0</font><font color="#000000">,&nbsp;width,&nbsp;height</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff"></font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">dateGraphics.setComposite</font><font color="#000000">(</font><font color="#000000">AlphaComposite.SrcOver</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">dateGraphics.setFont</font><font color="#000000">(</font><font color="#000000">font</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">dateGraphics.setColor</font><font color="#000000">(</font><font color="#000000">Color.black</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">dateGraphics.setRenderingHint</font><font color="#000000">(</font><font color="#000000">RenderingHints.KEY_ANTIALIASING,</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">RenderingHints.VALUE_ANTIALIAS_ON</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">GlyphVector&nbsp;gv&nbsp;=&nbsp;font.createGlyphVector</font><font color="#000000">(</font><font color="#000000">dateGraphics</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">.getFontRenderContext</font><font color="#000000">()</font><font color="#000000">,&nbsp;dateStamp</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#3f7f5f">//&nbsp;dateGraphics.drawString(dateStamp,&nbsp;fontSize,&nbsp;fontSize);</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">dateGraphics.translate</font><font color="#000000">(</font><font color="#000000">fontSize,&nbsp;</font><font color="#990000">2&nbsp;</font><font color="#000000">*&nbsp;fontSize</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#7f0055"><b>for&nbsp;</b></font><font color="#000000">(</font><font color="#7f0055"><b>int&nbsp;</b></font><font color="#000000">i&nbsp;=&nbsp;</font><font color="#990000">0</font><font color="#000000">;&nbsp;i&nbsp;&lt;&nbsp;gv.getNumGlyphs</font><font color="#000000">()</font><font color="#000000">;&nbsp;i++</font><font color="#000000">)&nbsp;{</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">Shape&nbsp;glyph&nbsp;=&nbsp;gv.getGlyphOutline</font><font color="#000000">(</font><font color="#000000">i</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">dateGraphics.setStroke</font><font color="#000000">(</font><font color="#7f0055"><b>new&nbsp;</b></font><font color="#000000">BasicStroke</font><font color="#000000">(</font><font color="#000000">fontSize&nbsp;/&nbsp;</font><font color="#990000">10</font><font color="#000000">))</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">dateGraphics.draw</font><font color="#000000">(</font><font color="#000000">glyph</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">}</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#7f0055"><b>float</b></font><font color="#000000">[]&nbsp;</font><font color="#000000">kernel&nbsp;=&nbsp;</font><font color="#7f0055"><b>new&nbsp;</b></font><font color="#7f0055"><b>float</b></font><font color="#000000">[</font><font color="#990000">25</font><font color="#000000">]</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#7f0055"><b>for&nbsp;</b></font><font color="#000000">(</font><font color="#7f0055"><b>int&nbsp;</b></font><font color="#000000">i&nbsp;=&nbsp;</font><font color="#990000">0</font><font color="#000000">;&nbsp;i&nbsp;&lt;&nbsp;kernel.length;&nbsp;i++</font><font color="#000000">)</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">kernel</font><font color="#000000">[</font><font color="#000000">i</font><font color="#000000">]&nbsp;</font><font color="#000000">=&nbsp;</font><font color="#990000">1.0f&nbsp;</font><font color="#000000">/&nbsp;kernel.length;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">ConvolveOp&nbsp;cOp&nbsp;=&nbsp;</font><font color="#7f0055"><b>new&nbsp;</b></font><font color="#000000">ConvolveOp</font><font color="#000000">(</font><font color="#7f0055"><b>new&nbsp;</b></font><font color="#000000">Kernel</font><font color="#000000">(</font><font color="#990000">5</font><font color="#000000">,&nbsp;</font><font color="#990000">5</font><font color="#000000">,&nbsp;kernel</font><font color="#000000">))</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">BufferedImage&nbsp;blurred&nbsp;=&nbsp;cOp.filter</font><font color="#000000">(</font><font color="#000000">dateImage,&nbsp;</font><font color="#7f0055"><b>null</b></font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">dateGraphics.dispose</font><font color="#000000">()</font><font color="#000000">;</font><br />
<font color="#ffffff"></font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#7f0055"><b>int&nbsp;</b></font><font color="#000000">iWidth&nbsp;=&nbsp;input.getWidth</font><font color="#000000">()</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#7f0055"><b>int&nbsp;</b></font><font color="#000000">iHeight&nbsp;=&nbsp;input.getHeight</font><font color="#000000">()</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#7f0055"><b>int&nbsp;</b></font><font color="#000000">cHeight&nbsp;=&nbsp;iWidth&nbsp;*&nbsp;</font><font color="#990000">2&nbsp;</font><font color="#000000">/&nbsp;</font><font color="#990000">3</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#7f0055"><b>int&nbsp;</b></font><font color="#000000">dHeight&nbsp;=&nbsp;</font><font color="#000000">(</font><font color="#000000">iHeight&nbsp;-&nbsp;cHeight</font><font color="#000000">)&nbsp;</font><font color="#000000">/&nbsp;</font><font color="#990000">2</font><font color="#000000">;</font><br />
<font color="#ffffff"></font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#7f0055"><b>int&nbsp;</b></font><font color="#000000">y&nbsp;=&nbsp;</font><font color="#000000">(</font><font color="#000000">iHeight&nbsp;-&nbsp;dHeight</font><font color="#000000">)&nbsp;</font><font color="#000000">-&nbsp;blurred.getHeight</font><font color="#000000">()</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#7f0055"><b>int&nbsp;</b></font><font color="#000000">x&nbsp;=&nbsp;iWidth&nbsp;-&nbsp;blurred.getWidth</font><font color="#000000">()</font><font color="#000000">;</font><br />
<font color="#ffffff"></font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">graphics.drawImage</font><font color="#000000">(</font><font color="#000000">blurred,&nbsp;x&nbsp;-&nbsp;fontSize,&nbsp;y&nbsp;-&nbsp;</font><font color="#990000">2&nbsp;</font><font color="#000000">*&nbsp;fontSize,&nbsp;</font><font color="#7f0055"><b>null</b></font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">graphics.setFont</font><font color="#000000">(</font><font color="#000000">font</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">graphics.setColor</font><font color="#000000">(</font><font color="#000000">Color.white</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">graphics.setRenderingHint</font><font color="#000000">(</font><font color="#000000">RenderingHints.KEY_ANTIALIASING,</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">RenderingHints.VALUE_ANTIALIAS_ON</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">graphics.drawString</font><font color="#000000">(</font><font color="#000000">dateStamp,&nbsp;x,&nbsp;y</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">graphics.dispose</font><font color="#000000">()</font><font color="#000000">;</font><br />
<font color="#ffffff"></font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#7f0055"><b>int&nbsp;</b></font><font color="#000000">lastDotIndex&nbsp;=&nbsp;inputFilename.lastIndexOf</font><font color="#000000">(</font><font color="#990000">'.'</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">String&nbsp;outputFilename&nbsp;=&nbsp;inputFilename.substring</font><font color="#000000">(</font><font color="#990000">0</font><font color="#000000">,&nbsp;lastDotIndex</font><font color="#000000">)</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">+&nbsp;</font><font color="#2a00ff">&#34;.new&#34;&nbsp;</font><font color="#000000">+&nbsp;inputFilename.substring</font><font color="#000000">(</font><font color="#000000">lastDotIndex</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">FileOutputStream&nbsp;out&nbsp;=&nbsp;</font><font color="#7f0055"><b>new&nbsp;</b></font><font color="#000000">FileOutputStream</font><font color="#000000">(</font><font color="#000000">outputFilename</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#3f7f5f">/*&nbsp;encodes&nbsp;image&nbsp;as&nbsp;a&nbsp;JPEG&nbsp;data&nbsp;stream&nbsp;*/</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">JPEGImageEncoder&nbsp;encoder&nbsp;=&nbsp;JPEGCodec.createJPEGEncoder</font><font color="#000000">(</font><font color="#000000">out</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">JPEGEncodeParam&nbsp;param&nbsp;=&nbsp;encoder.getDefaultJPEGEncodeParam</font><font color="#000000">(</font><font color="#000000">input</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">param.setQuality</font><font color="#000000">(</font><font color="#990000">0.9f</font><font color="#000000">,&nbsp;</font><font color="#7f0055"><b>true</b></font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">encoder.setJPEGEncodeParam</font><font color="#000000">(</font><font color="#000000">param</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">encoder.encode</font><font color="#000000">(</font><font color="#000000">input</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;&nbsp;&nbsp;</font><font color="#000000">System.out.println</font><font color="#000000">(</font><font color="#2a00ff">&#34;Ending&nbsp;with&nbsp;'&#34;&nbsp;</font><font color="#000000">+&nbsp;inputFilename&nbsp;+&nbsp;</font><font color="#2a00ff">&#34;'&#34;</font><font color="#000000">)</font><font color="#000000">;</font><br />
<font color="#ffffff">&nbsp;&nbsp;</font><font color="#000000">}</font>

Of course, it's not a pinnacle of Java2D programming, nor was it intended to. Since i don't have any imaging-related java.net project, i'm not intending to polish it to perfection. It even uses classes in the com.sun.image.codec.jpeg package. Hereby it is released to the public domain - feel free to use, reuse and abuse it in any way - but don't come back if your nuclear reactor stops functioning because of this :)

The result is quite OK:

imagedate.png

Related Topics >>