Upload And Resize On The Fly
Upload And Resize On The Fly
- Subject: Upload And Resize On The Fly
- From: John Gregory <email@hidden>
- Date: Tue, 15 Apr 2003 10:24:10 -0700
I have successfully set up file uploading and dynamic resizing of
images within my WebObjects application using Quicktime for Java. This
seems to be working well, and as a bonus, allows users to upload any
file format which is supported by Quicktime (such as tiff or pdf) and
then the resized images are always jpegs.
It should be noted that Quicktime for Java is broken in Java 1.4.1, so
I have to stick with 1.3.1. Apple has asked developers who need to use
Quicktime in Java 1.4.1 to send an email to mailto:email@hidden to
be counted. Please do that to support the continued development of
Quicktime for Java.
I based my solution on code that I dug up in an old message on the
omnigroup mailing list. I don't really know what I'm doing, so I'd
appreciate any suggestions about how I can make this code better. So,
on with the code...
First: Uploading. In my WOComponent, I set up keys called uploadData
(NSData), uploadFilename (String) and uploadMimetype (String) and bound
them to the appropriate bindings of a WOFileUpload. You must enclose
the WOFileUpload component within a form that has its "enctype" binding
set to "multipart/form-data" . There have been some bugs in WebObjects
and Safari that caused problems, but the latest versions (5.2.1 and
v73) seem to have everything working OK. The submit button is bound to
the following action:
public Main saveChanges()
{
Main nextPage = (Main)pageWithName("Main");
if ( uploadData != null && uploadData.length()>0) {
Session session = (Session) session();
Photo newPhoto = new Photo();
newPhoto.setOrigData(uploadData);
newPhoto.setFilename(uploadFilename);
newPhoto.setOrigMimeType(uploadMimetype);
session.defaultEditingContext().insertObject(newPhoto);
}
session().defaultEditingContext().saveChanges();
return nextPage;
}
Now, here's the code for my Photo class, which stores all the data in
the database (for better or worse). I'm nervous about the performance
of using Quicktime to constantly resize the images on-the-fly, so I've
set it up so that it resizes the images to two preset sizes in the
setOrigData method that stores the photo. The makePhotoSized method
could also be used on the fly, but it seems to me that could make a lot
of work for the server. The way that I've done it, all of the resizing
happens when the photo is uploaded, not later when it's displayed.
When using the images later, the WOImage data binding should be set to
origData, smallData or thumbData. However, when using the origData,
bind the mimetype to origMimeType but for the smallData or thumbData
bind the mimetype to a constant "image/jpeg" since the makePhotoSized
method is set to create jpegs.
To use Quicktime, I added the quicktime imports shown below, and added
a file called "QTJava.zip" to the frameworks of my project. I found
that file in /System/Library/Java/Extensions.
// Photo.java
// Created on Mon Mar 10 17:23:42 US/Pacific 2003 by Apple EOModeler
Version 5.2
import com.webobjects.foundation.*;
import com.webobjects.eocontrol.*;
import java.math.BigDecimal;
import java.util.*;
// QT imports needed to scale photos
import quicktime.*;
import quicktime.qd.*;
import quicktime.util.*;
import quicktime.std.StdQTConstants;
import quicktime.std.movies.media.DataRef;
import quicktime.std.image.*;
public class Photo extends EOGenericRecord {
public Photo() {
super();
}
public String filename() {
return (String)storedValueForKey("filename");
}
public void setFilename(String value) {
takeStoredValueForKey(value, "filename");
}
public String origMimeType() {
return (String)storedValueForKey("origMimeType");
}
public void setOrigMimeType(String value) {
takeStoredValueForKey(value, "origMimeType");
}
public NSData origData() {
return (NSData)storedValueForKey("origData");
}
public void setOrigData(NSData value) { // when the uploaded photo
is stored, create two smaller sizes.
takeStoredValueForKey(value, "origData");
setSmallData(makePhotoSized( 125, 125 ));
setThumbData(makePhotoSized( 50,50 ));
}
public NSData smallData() {
return (NSData)storedValueForKey("smallData");
}
public void setSmallData(NSData value) {
takeStoredValueForKey(value, "smallData");
}
public NSData thumbData() {
return (NSData)storedValueForKey("thumbData");
}
public void setThumbData(NSData value) {
takeStoredValueForKey(value, "thumbData");
}
public NSData makePhotoSized( int maxWidth, int maxHeight ) {
NSData scaledPhoto = null;
if ( origData() != null) {
byte[] bytes = origData().bytes();
try
{
QTSession.open ();
QTHandle qtHandle = new QTHandle(bytes);
DataRef dataRef = new DataRef(qtHandle);
GraphicsImporter graphicsImporter = new
GraphicsImporter(dataRef);
QDRect bounds = graphicsImporter.getNaturalBounds();
double widthFactor = (double) maxWidth /
bounds.getWidth();
double heightFactor = (double) maxHeight /
bounds.getHeight();
double minFactor;
if (widthFactor < heightFactor) { // use widthFactor
minFactor = widthFactor;
} else { // use heightFactor
minFactor = heightFactor;
}
QDRect scaledBounds = new
QDRect((int)(bounds.getWidth() * minFactor), (int)(bounds.getHeight() *
minFactor));
graphicsImporter.setBoundsRect(scaledBounds);
GraphicsExporter graphicsExporter = new
GraphicsExporter(StdQTConstants.kQTFileTypeJPEG);
graphicsExporter.setInputGraphicsImporter(graphicsImporter);
QTHandle outHandle = new QTHandle();
graphicsExporter.setOutputHandle(outHandle);
graphicsExporter.doExport();
scaledPhoto = new NSData(outHandle.getBytes());
}
catch (Exception e)
{
System.out.println("QT stuff caught " + e );
}
}
return scaledPhoto;
}
}
_______________________________________________
webobjects-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/webobjects-dev
Do not post admin requests to the list. They will be ignored.