📄 picturefiledata.java
字号:
//
// $Id: PictureFileData.java 287 2007-06-17 09:07:04 +0000 (dim., 17 juin 2007)
// felfert $
//
// jupload - A file upload applet.
// Copyright 2007 The JUpload Team
//
// Created: 2006-05-09
// Creator: etienne_sf
// Last modified: $Date: 2009-02-16 12:25:46 +0100 (lun., 16 févr. 2009) $
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version. This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details. You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation, Inc.,
// 675 Mass Ave, Cambridge, MA 02139, USA.
package wjhk.jupload2.filedata;
import java.awt.Canvas;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.FileImageInputStream;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import wjhk.jupload2.exception.JUploadException;
import wjhk.jupload2.exception.JUploadIOException;
import wjhk.jupload2.filedata.helper.ImageHelper;
import wjhk.jupload2.filedata.helper.ImageReaderWriterHelper;
import wjhk.jupload2.policies.PictureUploadPolicy;
import wjhk.jupload2.policies.UploadPolicy;
/**
* This class contains all data about files to upload as a picture. It adds the
* following elements to the {@link wjhk.jupload2.filedata.FileData} class :<BR>
* <UL>
* <LI>Ability to define a target format (to convert pictures to JPG before
* upload, for instance)
* <LI>Optional definition of a maximal width and/or height.
* <LI>Ability to rotate a picture, with {@link #addRotation(int)}
* <LI>Ability to store a picture into a BufferedImage. This is actualy a bad
* idea within an applet (should run within a java application) : the applet
* runs very quickly out of memory. With pictures from my Canon EOS20D (3,5M), I
* can only display two pictures. The third one generates an out of memory
* error, despite the System.finalize and System.gc I've put everywhere in the
* code!
* </UL>
*
* @author etienne_sf
* @version $Revision: 611 $
*/
public class PictureFileData extends DefaultFileData {
/**
* Indicate whether the data for this fileData has already been intialized.
*/
// private boolean initialized = false;
/**
* Indicates if this file is a picture or not. This is bases on the return
* of ImageIO.getImageReadersByFormatName().
*/
private boolean isPicture = false;
/**
* If set to true, the PictureFileData will keep the BufferedImage in
* memory. That is: it won't load it again from the hard drive, and resize
* and/or rotate it (if necessary) when the user select this picture. When
* picture are big this is nice. <BR>
* <BR>
* <B>Caution:</B> this parameter is currently unused, as the navigator
* applet runs quickly out of memory (after three or four picture for my
* Canon EOS 20D, 8,5 Mega pixels).
*
* @see UploadPolicy
*/
boolean storeBufferedImage = UploadPolicy.DEFAULT_STORE_BUFFERED_IMAGE;
// Will be erased in the constructor.
/*
* bufferedImage contains a preloaded picture. This buffer is used according
* to PictureFileDataPolicy.storeBufferedImage.
*
* @see PictureUploadPolicy#storeBufferedImage
*/
// private BufferedImage bufferedImage = null;
// Currently commented, as it leads to memory leaks.
/**
* This picture is precalculated, and stored to avoid to calculate it each
* time the user select this picture again, or each time the use switch from
* an application to another.
*/
private Image offscreenImage = null;
/**
* quarterRotation contains the current rotation that will be applied to the
* picture. Its value should be one of 0, 1, 2, 3. It is controled by the
* {@link #addRotation(int)} method.
* <UL>
* <LI>0 means no rotation.
* <LI>1 means a rotation of 90� clockwise (word = Ok ??).
* <LI>2 means a rotation of 180�.
* <LI>3 means a rotation of 900 counterclockwise (word = Ok ??).
* </UL>
*/
int quarterRotation = 0;
/**
* Width of the original picture. The width is taken from the first image of
* the file. We expect that all pictures in a file are of the same size (for
* instance, for animated gif). Calculated in the
* {@link #PictureFileData(File, File, PictureUploadPolicy)} constructor.
*/
int originalWidth = -1;
/**
* Same as {@link #originalWidth}, for the height of the first image in the
* picture file.
*/
int originalHeight = -1;
/**
* transformedPictureFile contains the reference to the temporary file that
* stored the transformed picture, during upload. It is created by
* {@link #getInputStream()} and freed by {@link #afterUpload()}.
*/
private File transformedPictureFile = null;
/**
* uploadLength contains the uploadLength, which is : <BR>
* - The size of the original file, if no transformation is needed. <BR>
* - The size of the transformed file, if a transformation were made. <BR>
* <BR>
* It is set to -1 whenever the user ask for a rotation (current only action
* that need to recalculate the picture).
*/
private long uploadLength = -1;
/**
* Contains the reference to a copy of the original picture files.
* Originally created because a SUN bug would prevent picture to be
* correctly resized if the original picture filename contains accents (or
* any non-ASCII characters).
*/
private File workingCopyTempFile = null;
/**
* Standard constructor: needs a PictureFileDataPolicy.
*
* @param file The files which data are to be handled by this instance.
* @param root The root directory, to calculate the relative dir (see
* {@link #getRelativeDir()}.
* @param uploadPolicy The current upload policy
* @throws JUploadIOException Encapsulation of the IOException, if any would
* occurs.
*/
public PictureFileData(File file, File root,
PictureUploadPolicy uploadPolicy) throws JUploadIOException {
super(file, root, uploadPolicy);
// EGR Should be useless
// this.uploadPolicy = (PictureUploadPolicy) super.uploadPolicy;
this.storeBufferedImage = uploadPolicy.hasToStoreBufferedImage();
String fileExtension = getFileExtension();
// Is it a picture?
this.isPicture = isFileAPictrue(file);
// Let's log the test result
uploadPolicy.displayDebug("isPicture=" + this.isPicture + " ("
+ file.getName() + "), extension=" + fileExtension, 50);
// If it's a picture, we override the default mime type:
if (this.isPicture) {
setMimeTypeByExtension(fileExtension);
}
}
/**
* Free any available memory. This method is called very often here, to be
* sure that we don't use too much memory. But we still run out of memory in
* some case.
*
* @param caller Indicate the method or treatment from which this method is
* called.
*/
public void freeMemory(String caller) {
Runtime rt = Runtime.getRuntime();
// rt.runFinalization();
rt.gc();
this.uploadPolicy.displayDebug("freeMemory (after " + caller + ") : "
+ rt.freeMemory(), 50);
}
/**
* If this pictures needs transformation, a temporary file is created. This
* can occurs if the original picture is bigger than the maxWidth or
* maxHeight, of if it has to be rotated. This temporary file contains the
* transformed picture. <BR>
* The call to this method is optional, if the caller calls
* {@link #getUploadLength()}. This method calls beforeUpload() if the
* uploadLength is unknown.
*/
@Override
public void beforeUpload() throws JUploadException {
if (this.uploadLength < 0) {
try {
// Get the transformed picture file, if needed.
initTransformedPictureFile();
} catch (OutOfMemoryError e) {
// Oups ! My EOS 20D has too big pictures to handle more than
// two pictures in a navigator applet !!!!!
// :-(
//
// We don't transform it. We clean the file, if it has been
// created.
deleteTransformedPictureFile();
//
tooBigPicture();
}
// If the transformed picture is correctly created, we'll upload it.
// Else we upload the original file.
if (this.transformedPictureFile != null) {
this.uploadLength = this.transformedPictureFile.length();
} else {
this.uploadLength = getFile().length();
}
}
// Let's check that everything is Ok
super.beforeUpload();
}
/**
* Returns the number of bytes, for this upload. If needed, that is, if
* uploadlength is unknown, {@link #beforeUpload()} is called.
*
* @return The length of upload. In this class, this is ... the size of the
* original file, or the transformed file!
*/
@Override
public long getUploadLength() throws JUploadException {
if (this.uploadLength < 0) {
// Hum, beforeUpload should have been called before. Let's correct
// that.
beforeUpload();
}
return this.uploadLength;
}
/**
* This function create an input stream for this file. The caller is
* responsible for closing this input stream. <BR>
* This function assumes that the {@link #getUploadLength()} method has
* already be called : it is responsible for creating the temporary file (if
* needed). If not called, the original file will be sent.
*
* @return An inputStream
*/
@Override
public InputStream getInputStream() throws JUploadException {
// Do we have to transform the picture ?
if (this.transformedPictureFile != null) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -