Link to home
Start Free TrialLog in
Avatar of Mark Bakelaar
Mark BakelaarFlag for Norway

asked on

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.
Avatar of mbonaci
mbonaci
Flag of Croatia image

Here's the Java code that provides resizing:
http://www.nsftools.com/tips/JavaTips.htm#jpgimage
ASKER CERTIFIED SOLUTION
Avatar of mbonaci
mbonaci
Flag of Croatia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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");
			log.openAgentLog();
			log.setLogActions(true);		
			
			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
		
			 log.close();
			c_thisdoc.recycle();
			db.recycle();
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println(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 =
			"tmp_"
				+ 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)) {
					embObj.extractFile(sAttachmentPath);
				}

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

				if (embObj != null) {
					embObj.remove();
				}
			}
			
		} catch (NotesException e) {
			System.exit(0);
			System.out.println(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"))) {
				break;
			} 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);");
			mt.waitForID(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(
					iTnWidth,
					iTnHeight,
					BufferedImage.TYPE_INT_RGB);
					
			//Create the graphic and resize 		
			Graphics2D graphics2D = thumbImage.createGraphics();
			graphics2D.setRenderingHint(
				RenderingHints.KEY_INTERPOLATION,
				RenderingHints.VALUE_INTERPOLATION_BILINEAR);

			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 =
				encoder.getDefaultJPEGEncodeParam(thumbImage);
			param.setQuality(fRes, false);

			encoder.setJPEGEncodeParam(param);
			encoder.encode(thumbImage);
			image.flush();
			out.flush();

		} catch (Exception e) {
			System.exit(0);
			System.out.println(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");
			}
			rti.embedObject(
				EmbeddedObject.EMBED_ATTACHMENT, null, sSource, null);
			rti.recycle();
		} catch (NotesException e) {
			System.out.println(
				"**** 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

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Mark Bakelaar

ASKER

Now we're talking, I'll give this a spinn and see if I can make any sense of it :)