source: 3thparty/jupload/src/main/java/wjhk/jupload2/filedata/helper/ImageReaderWriterHelper.java @ 3951

Revision 3951, 17.6 KB checked in by alexandrecorreia, 13 years ago (diff)

Ticket #1709 - Adicao de codigo fonte java do componente jupload

Line 
1//
2// $Id$
3//
4// jupload - A file upload applet.
5//
6// Copyright 2008 The JUpload Team
7//
8// Created: 12 feb. 08
9// Creator: etienne_sf
10// Last modified: $Date$
11//
12// This program is free software; you can redistribute it and/or modify
13// it under the terms of the GNU General Public License as published by
14// the Free Software Foundation; either version 2 of the License, or
15// (at your option) any later version.
16//
17// This program is distributed in the hope that it will be useful,
18// but WITHOUT ANY WARRANTY; without even the implied warranty of
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20// GNU General Public License for more details.
21//
22// You should have received a copy of the GNU General Public License
23// along with this program; if not, write to the Free Software
24// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
26package wjhk.jupload2.filedata.helper;
27
28import java.awt.image.BufferedImage;
29import java.io.File;
30import java.io.IOException;
31import java.util.Iterator;
32
33import javax.imageio.IIOImage;
34import javax.imageio.ImageIO;
35import javax.imageio.ImageReader;
36import javax.imageio.ImageWriteParam;
37import javax.imageio.ImageWriter;
38import javax.imageio.metadata.IIOMetadata;
39import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
40import javax.imageio.stream.FileImageInputStream;
41import javax.imageio.stream.FileImageOutputStream;
42
43import wjhk.jupload2.exception.JUploadIOException;
44import wjhk.jupload2.filedata.DefaultFileData;
45import wjhk.jupload2.filedata.PictureFileData;
46import wjhk.jupload2.policies.PictureUploadPolicy;
47
48/**
49 *
50 * This package provides low level methods, for picture management. It is used
51 * by {@link PictureFileData} to simplify its processing.
52 *
53 * @author etienne_sf
54 *
55 */
56public class ImageReaderWriterHelper {
57
58    /**
59     * File input, from which the original picture should be read.
60     */
61    FileImageInputStream fileImageInputStream = null;
62
63    /**
64     * File output stream for the current transformation.
65     */
66    FileImageOutputStream fileImageOutputStream;
67
68    /**
69     * The {@link PictureFileData} that this helper will have to help.
70     */
71    PictureFileData pictureFileData;
72
73    /**
74     * Current ImageReader. Initialized by {@link #initImageReader()}
75     */
76    ImageReader imageReader = null;
77
78    /**
79     * Current ImageWriter. Initialized by {@link #initImageWriter()}
80     */
81    ImageWriter imageWriter = null;
82
83    /**
84     * Current ImageWriter. Initialized by {@link #initImageWriter()}
85     */
86    ImageWriteParam imageWriterParam = null;
87
88    /**
89     * Contains the target picture format (in lowercase): gif, jpg... It is used
90     * to find an ImageWriter, and to define the target filename.
91     */
92    String targetPictureFormat;
93
94    /**
95     * The current upload policy must be a {@link PictureUploadPolicy}
96     */
97    PictureUploadPolicy uploadPolicy;
98
99    // ////////////////////////////////////////////////////////////////////
100    // //////////////////// CONSTRUCTOR
101    // ////////////////////////////////////////////////////////////////////
102
103    /**
104     * Standard constructor.
105     *
106     * @param uploadPolicy The current upload policy.
107     * @param pictureFileData The file data to be 'helped'.
108     */
109    public ImageReaderWriterHelper(PictureUploadPolicy uploadPolicy,
110            PictureFileData pictureFileData) {
111        this.uploadPolicy = uploadPolicy;
112        this.pictureFileData = pictureFileData;
113
114        this.targetPictureFormat = uploadPolicy.getImageFileConversionInfo()
115                .getTargetFormat(pictureFileData.getFileExtension());
116    }
117
118    // ////////////////////////////////////////////////////////////////////
119    // //////////////////// PUBLIC METHODS
120    // ////////////////////////////////////////////////////////////////////
121
122    /**
123     * returns the target picture format (lowercase, may be the same as the file
124     * extension)
125     *
126     * @return the target picture format (lowercase, may be the same as the file
127     *         extension)
128     */
129    public String getTargetPictureFormat() {
130        return this.targetPictureFormat;
131    }
132
133    /**
134     * Creates a FileImageOutputStream, and assign it as the output to the
135     * imageWriter.
136     *
137     * @param file The file where the output stream must write.
138     * @throws JUploadIOException Any error...
139     */
140    public void setOutput(File file) throws JUploadIOException {
141        // We first initialize internal variable.
142        initImageWriter();
143
144        try {
145            this.fileImageOutputStream = new FileImageOutputStream(file);
146        } catch (IOException e) {
147            throw new JUploadIOException("ImageReaderWriterHelper.setOutput()",
148                    e);
149        }
150        this.imageWriter.setOutput(this.fileImageOutputStream);
151    }
152
153    /**
154     * Free all reserved resource by this helper. Includes closing of any input
155     * or output stream.
156     *
157     * @throws JUploadIOException Any IO Exception
158     */
159    public void dispose() throws JUploadIOException {
160        // First: let's free any resource used by ImageWriter.
161        if (this.imageWriter != null) {
162            // An imageWriter was initialized. Let's free it.
163            this.imageWriter.dispose();
164            if (this.fileImageOutputStream != null) {
165                try {
166                    this.fileImageOutputStream.close();
167                } catch (IOException e) {
168                    throw new JUploadIOException(
169                            "ImageReaderWriterHelper.dispose() [fileImageOutputStream]",
170                            e);
171                }
172            }
173            this.imageWriter = null;
174            this.fileImageOutputStream = null;
175        }
176
177        // Then, all about ImageReader
178        if (this.imageReader != null) {
179            // An imageReader was initialized. Let's free it.
180            this.imageReader.dispose();
181            try {
182                this.fileImageInputStream.close();
183            } catch (IOException e) {
184                throw new JUploadIOException(
185                        "ImageReaderWriterHelper.dispose() [fileImageInputStream]",
186                        e);
187            }
188            this.imageReader = null;
189            this.fileImageInputStream = null;
190        }
191    }
192
193    /**
194     * Call to imageReader.getNumImages(boolean). Caution: may be long, for big
195     * files.
196     *
197     * @param allowSearch
198     * @return The number of image into this file.
199     * @throws JUploadIOException
200     */
201    public int getNumImages(boolean allowSearch) throws JUploadIOException {
202        initImageReader();
203        try {
204            return this.imageReader.getNumImages(allowSearch);
205        } catch (IOException e) {
206            throw new JUploadIOException(
207                    "ImageReaderWriterHelper.getNumImages() [fileImageInputStream]",
208                    e);
209        }
210    }
211
212    /**
213     * Call to ImageIO.read(fileImageInputStream).
214     *
215     * @return The BufferedImage read
216     * @throws JUploadIOException
217     *
218    public BufferedImage imageIORead() throws JUploadIOException {
219        try {
220            return ImageIO.read(this.pictureFileData.getWorkingSourceFile());
221        } catch (IOException e) {
222            throw new JUploadIOException(
223                    "ImageReaderWriterHelper.ImageIORead()", e);
224        }
225
226    }
227    */
228
229    /**
230     * Read an image, from the pictureFileData.
231     *
232     * @param imageIndex The index number of the picture, in the file. 0 for the
233     *            first picture (only valid value for picture containing one
234     *            picture)
235     * @return The image corresponding to this index, in the picture file.
236     * @throws JUploadIOException
237     * @throws IndexOutOfBoundsException Occurs when the imageIndex is wrong.
238     */
239    public BufferedImage readImage(int imageIndex) throws JUploadIOException,
240            IndexOutOfBoundsException {
241        initImageReader();
242        try {
243            this.uploadPolicy.displayDebug(
244                    "ImageReaderWriterHelper: reading picture number "
245                            + imageIndex + " of file "
246                            + this.pictureFileData.getFileName(), 30);
247            return this.imageReader.read(imageIndex);
248        } catch (IndexOutOfBoundsException e) {
249            // The IndexOutOfBoundsException is transmitted to the caller. It
250            // indicates that the index is out of bound. It's the good way for
251            // the caller to stop the loop through available pictures.
252            throw e;
253        } catch (IOException e) {
254            throw new JUploadIOException("ImageReaderWriterHelper.readImage("
255                    + imageIndex + ")", e);
256        }
257    }
258
259    /**
260     * Read an image, from the pictureFileData.
261     *
262     * @param imageIndex The index number of the picture, in the file. 0 for the
263     *            first picture (only valid value for picture containing one
264     *            picture)
265     * @return The full image data for this index
266     * @throws JUploadIOException
267     * @throws IndexOutOfBoundsException Occurs when the imageIndex is wrong.
268     */
269    public IIOImage readAll(int imageIndex) throws JUploadIOException,
270            IndexOutOfBoundsException {
271        initImageReader();
272        try {
273            this.uploadPolicy.displayDebug(
274                    "ImageReaderWriterHelper: reading picture number "
275                            + imageIndex + " of file "
276                            + this.pictureFileData.getFileName(), 30);
277            return this.imageReader.readAll(imageIndex, this.imageReader
278                    .getDefaultReadParam());
279        } catch (IndexOutOfBoundsException e) {
280            // The IndexOutOfBoundsException is transmitted to the caller. It
281            // indicates that the index is out of bound. It's the good way for
282            // the caller to stop the loop through available pictures.
283            throw e;
284        } catch (IOException e) {
285            throw new JUploadIOException("ImageReaderWriterHelper.readAll("
286                    + imageIndex + ")", e);
287        }
288    }
289
290    /**
291     * Load the metadata associated with one picture in the picture file.
292     *
293     * @param imageIndex
294     * @return The metadata loaded
295     * @throws JUploadIOException Any IOException is encapsulated in this
296     *             exception
297     */
298    public IIOMetadata getImageMetadata(int imageIndex)
299            throws JUploadIOException {
300        // We must have the reader initialized
301        initImageReader();
302
303        // Ok, let's go
304        try {
305            this.uploadPolicy.displayDebug(
306                    "ImageReaderWriterHelper: reading metadata for picture number "
307                            + imageIndex + " of file "
308                            + this.pictureFileData.getFileName(), 30);
309            return this.imageReader.getImageMetadata(imageIndex);
310        } catch (IOException e) {
311            throw new JUploadIOException(
312                    "ImageReaderWriterHelper.getImageMetadata()", e);
313        }
314    }
315
316    /**
317     * Write a picture in the output picture file. Called just before an upload.
318     *
319     * @param numIndex The index of the image in the transformed picture file.
320     * @param iioImage The image to write.
321     * @param iwp The parameter to use to write this image.
322     * @throws JUploadIOException
323     */
324    public void writeInsert(int numIndex, IIOImage iioImage, ImageWriteParam iwp)
325            throws JUploadIOException {
326        initImageWriter();
327        try {
328            this.imageWriter.writeInsert(numIndex, iioImage, iwp);
329        } catch (IOException e) {
330            throw new JUploadIOException(
331                    "ImageReaderWriterHelper.writeInsert()", e);
332        }
333    }
334
335    /**
336     * Write a picture in the output picture file. Called just before an upload.
337     *
338     * @param iioImage The image to write.
339     * @throws JUploadIOException
340     */
341    public void write(IIOImage iioImage) throws JUploadIOException {
342        initImageWriter();
343        try {
344            this.imageWriter.write(null, iioImage, this.imageWriterParam);
345        } catch (IOException e) {
346            throw new JUploadIOException("ImageReaderWriterHelper.write()", e);
347        }
348    }
349
350    // ////////////////////////////////////////////////////////////////////
351    // //////////////////// PRIVATE METHODS
352    // ////////////////////////////////////////////////////////////////////
353
354    /**
355     * Initialize the ImageWriter and the ImageWriteParam for the current
356     * picture helper.
357     *
358     * @throws JUploadIOException
359     */
360    private void initImageWriter() throws JUploadIOException {
361        if (this.imageWriter == null) {
362            // Get the writer (to choose the compression quality)
363            // In the windows world, file extension may be in uppercase, which
364            // is not compatible with the core Java API.
365            Iterator<ImageWriter> iter = ImageIO
366                    .getImageWritersByFormatName(this.targetPictureFormat);
367            if (!iter.hasNext()) {
368                // Too bad: no writer for the selected picture format
369
370                // A particular case: no gif support in JRE 1.5. A JRE upgrade
371                // must be done.
372                if (this.targetPictureFormat.equals("gif")
373                        && System.getProperty("java.version").startsWith("1.5")) {
374                    throw new JUploadIOException(
375                            "gif pictures are not supported in Java 1.5. Please switch to JRE 1.6.");
376                }
377
378                throw new JUploadIOException("No writer for the '"
379                        + this.targetPictureFormat + "' picture format.");
380            } else {
381                this.imageWriter = iter.next();
382                this.imageWriterParam = this.imageWriter.getDefaultWriteParam();
383
384                // For jpeg pictures, we force the compression level.
385                if (this.targetPictureFormat.equalsIgnoreCase("jpg")
386                        || this.targetPictureFormat.equalsIgnoreCase("jpeg")) {
387                    this.imageWriterParam
388                            .setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
389                    // Let's select a good compromise between picture size
390                    // and quality.
391                    this.imageWriterParam
392                            .setCompressionQuality(this.uploadPolicy
393                                    .getPictureCompressionQuality());
394                    // In some case, we need to force the Huffman tables:
395                    ((JPEGImageWriteParam) this.imageWriterParam)
396                            .setOptimizeHuffmanTables(true);
397                }
398
399                //
400                try {
401                    this.uploadPolicy.displayDebug(
402                            "ImageWriter1 (used), CompressionQuality="
403                                    + this.imageWriterParam
404                                            .getCompressionQuality(), 50);
405                } catch (Exception e2) {
406                    // If we come here, compression is not supported for
407                    // this picture format, or parameters are not explicit
408                    // mode, or ... (etc). May trigger several different
409                    // errors. We just ignore them: this par of code is only
410                    // to write some debug info.
411                    this.uploadPolicy.displayWarn(e2.getClass().getName()
412                            + " in ImageReaderWriterHelper.java");
413                }
414            }
415        }
416    }// initImageWriter
417
418    /**
419     * Initialize the ImageReader for the current helper.
420     *
421     * @throws JUploadIOException
422     */
423    private void initImageReader() throws JUploadIOException {
424        // First: we open a ImageInputStream
425        try {
426            this.fileImageInputStream = new FileImageInputStream(
427                    this.pictureFileData.getWorkingSourceFile());
428        } catch (IOException e) {
429            throw new JUploadIOException(
430                    "ImageReaderWriterHelper.initImageReader()", e);
431        }
432
433        // Then: we create an ImageReader, and assign the ImageInputStream to
434        // it.
435        if (this.imageReader == null) {
436            String ext = DefaultFileData.getExtension(this.pictureFileData
437                    .getFile());
438            Iterator<ImageReader> iterator = ImageIO
439                    .getImageReadersBySuffix(ext);
440            if (iterator.hasNext()) {
441                this.imageReader = iterator.next();
442                this.imageReader.setInput(this.fileImageInputStream);
443                this.uploadPolicy.displayDebug("Foud one reader for " + ext
444                        + " extension", 50);
445            }// while
446
447            // Did we find our reader ?
448            if (this.imageReader == null) {
449                this.uploadPolicy.displayErr("Found no reader for " + ext
450                        + " extension");
451            } else if (this.uploadPolicy.getDebugLevel() >= 50) {
452                // This call may be long, so we do it only if useful.
453                try {
454                    this.uploadPolicy.displayDebug("Nb images in "
455                            + this.pictureFileData.getFileName() + ": "
456                            + this.imageReader.getNumImages(true), 50);
457                } catch (IOException e) {
458                    // We mask the error, was just for debug...
459                }
460            }
461        }
462    }
463}
Note: See TracBrowser for help on using the repository browser.