Dynamicaly change image size in a Lotus Notes document

I'm in the process of making some HowTo documents in Lotus Notes.

I have several screenshots to show procedures.

They are added to the document as [inline image]

The thing I would like to do is: Set the scaling to 30% and then when you mouse over or click it will show the image in 100% size.

The files can be made avaliable on a readable filesystem, but i would prefere if they could stay in the lotus notes databese either as:

1. the same picture only not scaled
2. a diffrent import of the same image
3. some other way i havent thought of.

But it has to pretty easy to do this for quite a lot of images.
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Here's the Java code that provides resizing:
This database (as mentioned in previous link) contains LS2J example of using the Java code (from the first post) from LotusScript:

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

I remembered one more thing, a while ago Snapps published (under GNU GPL) "BP303 The Great Code Giveaway - On-Line Photo Album" database, which contains the Java code listed bellow, that re-sizes images to create thumbnails:
*	Agent:			CreateThumbnail
*	Author:			Stragic Net Applications, Inc. 913-381-1465
*	Creation Date:		3/18/2005
* 	Purpose:		This Java program is intended to run as a Lotus Team Workplace PlaceBot. This bot is
*					is called by the photo form. Only one attachment per document should be created.
*					The bot detaches the uploaded image to a temporary directory created by the 
*					application. Then the detached image is loaded and resized. The thumbmail.jpg is 
*					created in the temp directory and attached to the document. The times are adjusted
*					in the h_AttachmentTimes TW system field that tracks the attachment dates.
*	Caveats:		Only one image per page is expected (excluding the thumbnail). If multiple images are
*					attached to the document only the first image receives a thumbnail image. If a second image
*					is attached after the document is created, the dates will not be associated with the correct 
*					image. It is best if the thumbnail image is not placed as the first image in the list.
*					The attachment images relies on a secondary agent to clean up temporary files. If these
*					files are not cleaned up, the disk may run out of space. The administrator should check the
*					amount of disk space on the server regularly. The files remain open until either the bot runs
*					again or the server is rebooted.
*	Notes:			The bot is dependent on the custom field c_AttachmentNames that contains the values in the
*					attachment control. This value is populated by client side javascript on the HTML form.
*					This agent requires Java 1.3.x and above packages. (Domino 6.5+) (e.g. com.sun.image.codec);
import lotus.domino.*;
import com.sun.image.codec.jpeg.*;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.net.*;
import java.util.*;
import java.text.DecimalFormat;

public class CreateThumbnail extends AgentBase {
	private Document c_thisdoc;
	private Database db;
	//log class commented out unless needed for debugging.
	private Log log; 			
	private String sUserDir;
	private String sWorkPath;
	private String sSourceGraphic = "";
	private String sTargetThumbnail = "";

	public void NotesMain() {

		try {
			Session session = getSession();
			AgentContext agentContext = session.getAgentContext();
			db = agentContext.getCurrentDatabase();
			log = session.createLog("Log");
			c_thisdoc = agentContext.getDocumentContext();

			sUserDir = System.getProperty("user.dir");				//Get the server program directory
			log.logAction("sUserDir=" + sUserDir);
			sWorkPath = "images/" + tempDirName();					//Create a unique directory tmp_mmddhhmmssMsMsMsMs
			log.logAction("sWorkPath=" + sWorkPath);
			if (new File(sWorkPath).mkdirs()) { 					//Create the working directory
				log.logAction("directory " + sWorkPath + " created." );										
				sSourceGraphic = detachPhoto(c_thisdoc);				//call method to detach photo
				if (!sSourceGraphic.equals("")) {					//method returns the photo in temp directory if successful
					sTargetThumbnail = sWorkPath + "/" + "thumbnail.jpg";
					log.logAction("Thumbnail path is " + sTargetThumbnail );
					makeThumbnail(sSourceGraphic, sTargetThumbnail);
					attachThumbnail( c_thisdoc, sUserDir + "/" + sTargetThumbnail);
					c_thisdoc.save(true, true);
					deleteDir(new File(sWorkPath));				//an attempt is made to clean up temp files
				} // if graphic not null end
				log.logAction ("Unable to create directory " + sWorkPath );
			} // if directory created end
		} catch (Exception e) {

*		Purpose: 	Method to generate a temporary directory based on the current date & time
*					Returns String of the new directory name					

	public static String tempDirName() {
		Calendar cal;
		int iMonth = 0;
		int iDay = 0;
		int iHour = 0;
		int iMin = 0;
		int iSec = 0;
		int iMs = 0;
		String sReturnVal = "";
		DecimalFormat twoDigits = new DecimalFormat("00");

		cal = new GregorianCalendar();
		iMonth = cal.get(Calendar.MONTH) + 1;
		iDay = cal.get(Calendar.DAY_OF_MONTH);
		iHour = cal.get(Calendar.HOUR_OF_DAY);
		iMin = cal.get(Calendar.MINUTE);
		iSec = cal.get(Calendar.SECOND);
		iMs = cal.get(Calendar.MILLISECOND);

		sReturnVal =
				+ twoDigits.format(iMonth)
				+ twoDigits.format(iDay)
				+ twoDigits.format(iHour)
				+ iSec
				+ iMs;
		return sReturnVal;
	} //tempDirName() method end

*		Purpose: 	Detaches the photo in a document. The method checks to make sure it does not have the
*					thumbnail.jpg image to detach.
*					The parameter for the method is the document that contains the attachment.
*					A string value of the file name is returned by the method.
*		Dependency: method getFirstAttachmetnName(String)
	public String detachPhoto(Document doc) {

		String sAttachmentPath = "";
		String sFileName = "";
		EmbeddedObject embObj = null;
		try {

			Vector vItems = doc.getItemValue("c_AttachmentNames");
			sFileName = getFirstAttachmentName((String) vItems.elementAt(0));

			if (sFileName.length() > 1) {
				sAttachmentPath = sWorkPath + "/" + sFileName;
				embObj = doc.getAttachment(sFileName);
				if (!(embObj == null)) {

				//remove thubmnail before creating a new one
				embObj = doc.getAttachment("thumbnail.jpg");

				if (embObj != null) {
		} catch (NotesException e) {
		return sAttachmentPath;
	} //method detachPhoto end

*		Purpose: 		Method to find the first attachment that is not thumbnail.jpg and ends with the
*						extension .jpg or .jpeg. The assumption here is that the file extention name is
*						correctly named for the file type.
*		Arguments:	A text list of the file names as stored in the custom field c_AttachmentNames.			
*		Notes:			The files uploaded by the upload control in the format of {"file1.jpg,"";"file2.jpg",""}
						This value is stored in the custom field c_AttachmentNames.
	public static String getFirstAttachmentName(String sSource) {
		String sFileName = "";

		StringTokenizer st = new StringTokenizer(sSource, ";");
		while (st.hasMoreTokens()) {
			sFileName = st.nextToken().toLowerCase();

			if ((!sFileName.equalsIgnoreCase("thumbnail.jpg"))
				&& (sFileName.endsWith(".jpg") || sFileName.endsWith(".jpeg"))) {
			} else {
				sFileName = "";
			} //if end
		} //wihle end

		return sFileName;
	} //method end

*		Purpose: 		Creates a thumbnail image based on a larger jpg image.
*						This method only support jpeg images. The default image size is 50 x 38 pixels.
*						Based on the most common aspect ratio of digital cameras of 1 1/3.
*						The method adjustImageSize() will calculate the thumbnail dimensions based on
*						the aspect ration of the image, if it does not have a standard ratio of 1.333...
*						The maximum thumbnail size is 50 pixels the height or widht may vary dependent on 
*						the largest dimension of the graphic. This maximum value is hard coded in the method 
*						and so is the image resolution which is set at 75.
*		Note:			The large the source image the grainer the thumb nail will be rendered. Smaller images will
*						produce better thumbnails.
*		Arguments:	String sSourceFile, the name of the source file to create a thumbnail from.					
*						String sTargetFile, the name of the thumnail image (thumbnail.jpg)
*		Dependency: 	adjustImageSize(...);
	public void makeThumbnail(String sSourceFile, String sTargetFile) {
		int iTnWidth = 50; //DEFAULT VALUE
		int iTnHeight = 38; //DEFAULT VALUE OF 50X38 (MOST CAMERAS)
		int iImgWidth = 0;
		int iImgHeight = 0;
		int iMaxImgSize=100;
		float fRes = (float) .75;

		try {
			log.logAction("Begin of makeThumbnail Try. sSourceFile=" + sSourceFile);
			log.logAction("Attempting to Executed: Toolkit.getDefaultToolkit().getImage(" + sSourceFile + ");");
			//get image from file system and load into image object
			Image image = Toolkit.getDefaultToolkit().getImage(sSourceFile);
			log.logAction("Executed: Toolkit.getDefaultToolkit().getImage(sSourceFile);");
			MediaTracker mt = new MediaTracker(new Frame());
			log.logAction("Executed: new MediaTracker(new Frame()); ");
			mt.addImage(image, 0);
			log.logAction("Executed: mt.addImage(image, 0);");
			log.logAction("Executed: mt.waitForID(0);");

			log.logAction("Completed loading image from the file system.");

			//get the height and width of the loaded image
			iImgWidth = image.getWidth(null);
			iImgHeight = image.getHeight(null);

			//Calculate the height and widht of the thumbnail
			iTnWidth = adjustImageSize(iImgWidth, iImgHeight,  iMaxImgSize, 'W');
			iTnHeight = adjustImageSize(iImgWidth, iImgHeight,  iMaxImgSize, 'H');

			log.logAction("iTnWidth=" + iTnWidth + " and " + " iTnHeight=" + iTnHeight);

			//Create the BufferImage object using the dimensions calculated by ajustImageSize() method
			BufferedImage thumbImage =
				new BufferedImage(
			//Create the graphic and resize 		
			Graphics2D graphics2D = thumbImage.createGraphics();

			graphics2D.drawImage(image, 0, 0, iTnWidth, iTnHeight, null);

			//write new image to disk
			BufferedOutputStream out =
				new BufferedOutputStream(new FileOutputStream(sTargetFile));
			JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
			JPEGEncodeParam param =
			param.setQuality(fRes, false);


		} catch (Exception e) {
*		Purpose: 		Attaches the newly created thumbnail to the document. Since the form by default does not
*						have a rich text control (PageBody) a rich text field is not created. Here one is created
*						via back-end process so the thumbnail can be attached. The field is called c_AttachmentBody
*						and the field does not exist on the photo form.

	public void attachThumbnail(Document doc, String sSource) {
		RichTextItem rti = null;
		try {
			rti = (RichTextItem) doc.getFirstItem("c_AttachmentBody");
			if (rti == null) {
				//not there so create the item
				rti = doc.createRichTextItem("c_AttachmentBody");
				EmbeddedObject.EMBED_ATTACHMENT, null, sSource, null);
		} catch (NotesException e) {
				"**** PlaceBot CreateThumbnail:"
					+ sSource
					+ " - "
					+ e.text
					+ " ****");

*		Purpose: 		To calculate the correct image aspect ratio for the thumbnail
*		Arguments:	adjustImageSize(
*							int iWidth,			Width of the original image
*							int iHeight,			Height of the original image
*							int iMaxSize,		Maximum number of pixels for any side of the image
*							char cRetType		Set return type 'W' for width otherwise height is returned
	public static int adjustImageSize(
		int iWidth,
		int iHeight,
		int iMaxSize,
		char cRetType) {
		//iWidth specifies the image's width in pixels.
		//iHeight specifises the original image's height in pixels.
		//iMaxSize specifies the maximum size of the thumbnail
		//iScaleToWidth, return value, the new width of the thumbnail graphic
		//iScaleToWidth, return value, the new height of the thumbnail graphic
		float fHigh = 0;
		float fLow = 0;
		int iMinSize = 0;
		int iReturnVal = 0;

		fHigh = Math.max(iWidth, iHeight);
		fLow = Math.min(iWidth, iHeight);

		if (fHigh > 0 && fLow > 0) {
			iMinSize = Math.round(iMaxSize * (fLow / fHigh));
			if (iWidth > iHeight) {
				iWidth = iMaxSize;
				iHeight = iMinSize;
			} else {
				iHeight = iMaxSize;
				iWidth = iMinSize;
		} else {
			iWidth = iMaxSize;
			iHeight = iMaxSize;

		} //if fHigh/fLow end
		if (cRetType == 'W') {
			iReturnVal = iWidth;
		} else {
			iReturnVal = iHeight;
		return iReturnVal;
	} //method end
*		Purpose: 	To remove any files and subdirectories if possible. Since the thumbnail file is locked
*					the directory will not be removed. This is to attempt to remove the original image if 
*					possible. Sometimes this image is locked as well and cannot be removed.
*					A scheduled agent should be run to remove these temporary files.
	public static boolean deleteDir(File dir) {
		if (dir.isDirectory()) {
			String[] children = dir.list();
			for (int i = 0; i < children.length; i++) {
				boolean success = deleteDir(new File(dir, children[i]));
				if (!success) {
					return false;
		return dir.delete();

} //Class end

Open in new window

But how you can get those inline images?
Using DXL exporter to serialize the whole document and then extract image part from the XML and decode it into actual image file.

Here's the main part of the code (base64 encoder):

And here's an example of how to use it (and how to extract image data from DXL):
mark_norgeAuthor Commented:
Now we're talking, I'll give this a spinn and see if I can make any sense of it :)
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Lotus IBM

From novice to tech pro — start learning today.