Mark Bakelaar
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.
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.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Now we're talking, I'll give this a spinn and see if I can make any sense of it :)
http://www.nsftools.com/tips/JavaTips.htm#jpgimage