1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package wjhk.jupload2.filedata;
23
24 import java.awt.Canvas;
25 import java.awt.Image;
26 import java.awt.image.BufferedImage;
27 import java.io.File;
28 import java.io.FileInputStream;
29 import java.io.FileNotFoundException;
30 import java.io.FileOutputStream;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.util.Iterator;
34
35 import javax.imageio.IIOImage;
36 import javax.imageio.ImageIO;
37 import javax.imageio.ImageReader;
38 import javax.imageio.metadata.IIOMetadata;
39 import javax.imageio.stream.FileImageInputStream;
40 import javax.swing.ImageIcon;
41 import javax.swing.JOptionPane;
42
43 import wjhk.jupload2.exception.JUploadException;
44 import wjhk.jupload2.exception.JUploadIOException;
45 import wjhk.jupload2.filedata.helper.ImageHelper;
46 import wjhk.jupload2.filedata.helper.ImageReaderWriterHelper;
47 import wjhk.jupload2.policies.PictureUploadPolicy;
48 import wjhk.jupload2.policies.UploadPolicy;
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 public class PictureFileData extends DefaultFileData {
67
68
69
70
71 boolean isPicture = false;
72
73
74
75
76
77 Image offscreenImage = null;
78
79
80
81
82
83
84
85
86
87
88
89 int quarterRotation = 0;
90
91
92
93
94
95
96 int originalWidth = -1;
97
98
99
100
101 int originalHeight = -1;
102
103
104
105
106
107 File transformedPictureFile = null;
108
109
110
111
112
113
114
115
116
117 long uploadLength = -1;
118
119
120
121
122
123
124
125 File workingCopyTempFile = null;
126
127
128
129
130 String targetPictureFormat;
131
132
133
134
135
136
137
138
139
140 public PictureFileData(File file, PictureUploadPolicy uploadPolicy) throws JUploadIOException {
141 super(file, uploadPolicy);
142
143 String fileExtension = getFileExtension();
144
145
146 uploadPolicy.displayDebug("Looking for iterator of extension '" + file + "'", 80);
147 this.isPicture = isFileAPicture(file);
148
149
150 uploadPolicy.displayDebug("isPicture=" + this.isPicture + " (" + file.getName() + "), extension="
151 + fileExtension, 50);
152
153
154 if (this.isPicture) {
155 setMimeTypeByExtension(fileExtension);
156 }
157 }
158
159
160
161
162
163
164
165
166 public static void freeMemory(String caller, UploadPolicy uploadPolicy) {
167 Runtime rt = Runtime.getRuntime();
168
169 rt.runFinalization();
170 rt.gc();
171
172 if (uploadPolicy.getDebugLevel() >= 50) {
173 uploadPolicy.displayDebug(
174 "freeMemory (after " + caller + ") : " + rt.freeMemory() + " (maxMemory: " + rt.maxMemory()
175 + ", totalMemory: " + rt.totalMemory() + ")", 50);
176 }
177 }
178
179
180
181
182
183
184
185
186 @Override
187 public void beforeUpload(String uploadFileRoot) throws JUploadException {
188 uploadPolicy.displayDebug(this.hashCode() + "|Entering PictureFileData.beforeUpload()", 95);
189
190 if (!this.preparedForUpload) {
191 if (this.uploadLength < 0) {
192 try {
193
194
195 freeMemory("Picture manabeforeUpload(): before initTransformedPictureFile", uploadPolicy);
196
197
198 initTransformedPictureFile();
199
200
201
202 uploadPolicy.displayDebug(this.getClass().getName()
203 + ".beforeUpload(): after call to initTransformedPictureFile()", 100);
204
205 } catch (OutOfMemoryError e) {
206
207
208
209
210
211
212
213
214
215 uploadPolicy.displayDebug(this.getClass().getName() + ".beforeUpload(): OutOfMemoryError", 30);
216 deleteTransformedPictureFile();
217 deleteWorkingCopyPictureFile();
218
219
220 freeMemory("beforeUpload(): in OutOfMemoryError", uploadPolicy);
221
222 tooBigPicture();
223 }
224
225
226
227
228 synchronized (this) {
229 if (this.transformedPictureFile != null) {
230 this.uploadLength = this.transformedPictureFile.length();
231 setMimeTypeByExtension(this.targetPictureFormat);
232 } else {
233 this.uploadLength = getFile().length();
234 }
235 }
236 }
237 }
238
239
240
241 uploadPolicy.displayDebug(this.getClass().getName() + ".beforeUpload(): before call to super.beforeUpload()",
242 100);
243
244 super.beforeUpload(uploadFileRoot);
245
246
247
248 uploadPolicy.displayDebug(this.getClass().getName() + ".beforeUpload(): after call to super.beforeUpload()",
249 100);
250 }
251
252
253
254
255
256
257
258 @Override
259 public long getUploadLength() {
260
261
262 if (!this.preparedForUpload) {
263 throw new IllegalStateException("The file " + getFileName() + " is not prepared for upload");
264 }
265 return this.uploadLength;
266 }
267
268
269
270
271
272
273
274
275 @Override
276 public synchronized InputStream getInputStream() throws JUploadException {
277 uploadPolicy.displayDebug(this.hashCode() + "|Entering PictureFileData.getInputStream()", 95);
278 if (!this.preparedForUpload) {
279 throw new IllegalStateException("The file " + getFileName() + " is not prepared for upload");
280 }
281
282 if (this.transformedPictureFile != null) {
283 try {
284 return new FileInputStream(this.transformedPictureFile);
285 } catch (FileNotFoundException e) {
286 throw new JUploadIOException(e);
287 }
288 }
289
290 return super.getInputStream();
291 }
292
293
294
295
296
297
298 @Override
299 public void afterUpload() {
300
301 deleteTransformedPictureFile();
302 deleteWorkingCopyPictureFile();
303 this.uploadLength = -1;
304
305 super.afterUpload();
306 }
307
308
309
310
311
312
313
314
315
316
317
318
319
320 public Image getImage(Canvas canvas, boolean shadow) throws JUploadException {
321 Image localImage = null;
322
323
324
325
326
327 if (canvas == null) {
328 throw new JUploadException("canvas null in PictureFileData.getImage");
329 }
330
331 if (shadow && this.offscreenImage != null) {
332 return this.offscreenImage;
333 }
334
335 int canvasWidth = canvas.getWidth();
336 int canvasHeight = canvas.getHeight();
337 if (canvasWidth <= 0 || canvasHeight <= 0) {
338 uploadPolicy.displayDebug("canvas width and/or height null in PictureFileData.getImage()", 1);
339 return null;
340 }
341
342 if (!this.isPicture) {
343 uploadPolicy
344 .displayWarn("canvas width and/or height null in PictureFileData.getImage(). PictureFileData.getImage will return null");
345 return null;
346 }
347
348
349
350
351 try {
352
353 ImageReaderWriterHelper irwh = new ImageReaderWriterHelper((PictureUploadPolicy) uploadPolicy, this);
354 BufferedImage sourceImage = irwh.readImage(0);
355 irwh.dispose();
356 irwh = null;
357 ImageHelper ih = new ImageHelper((PictureUploadPolicy) uploadPolicy, this, canvasWidth, canvasHeight,
358 this.quarterRotation);
359 localImage = ih.getBufferedImage(((PictureUploadPolicy) uploadPolicy).getHighQualityPreview(), sourceImage);
360
361 sourceImage.flush();
362 sourceImage = null;
363 } catch (OutOfMemoryError e) {
364
365 localImage = null;
366 tooBigPicture();
367 }
368
369
370 if (shadow) {
371 this.offscreenImage = localImage;
372 }
373
374 freeMemory("end of " + this.getClass().getName() + ".getImage()", uploadPolicy);
375
376
377 uploadPolicy.getContext().getUploadPanel().getPreparationProgressBar().setValue(0);
378
379 return localImage;
380 }
381
382
383
384
385
386
387
388
389 public void addRotation(int quarter) {
390 this.quarterRotation += quarter;
391
392
393
394
395 deleteWorkingCopyPictureFile();
396 deleteTransformedPictureFile();
397 this.uploadLength = -1;
398
399
400 while (this.quarterRotation < 0) {
401 this.quarterRotation += 4;
402 }
403 while (this.quarterRotation >= 4) {
404 this.quarterRotation -= 4;
405 }
406
407
408 if (this.offscreenImage != null) {
409 this.offscreenImage.flush();
410 this.offscreenImage = null;
411 }
412 }
413
414
415
416
417
418
419 public boolean isPicture() {
420 return this.isPicture;
421 }
422
423
424 @Override
425 public String getMimeType() {
426 return this.mimeType;
427 }
428
429
430
431
432
433
434
435
436
437 public synchronized void deleteTransformedPictureFile() {
438 uploadPolicy.displayDebug(this.hashCode() + "|Entering PictureFileData.deleteTransformedPictureFile()", 95);
439
440 if (null != this.transformedPictureFile && uploadPolicy.getDebugLevel() <= 100) {
441 if (!this.transformedPictureFile.delete()) {
442 uploadPolicy.displayWarn("Unable to delete " + this.transformedPictureFile.getName());
443 }
444 this.transformedPictureFile = null;
445
446 }
447 }
448
449
450
451
452
453
454
455
456
457 void initTransformedPictureFile() throws JUploadException {
458 uploadPolicy.displayDebug(this.hashCode() + "|Entering PictureFileData.initTransformedPictureFile()", 95);
459 int targetMaxWidth;
460 int targetMaxHeight;
461
462
463
464
465
466
467 if (this.quarterRotation == 0) {
468 targetMaxWidth = ((PictureUploadPolicy) uploadPolicy).getMaxWidth();
469 targetMaxHeight = ((PictureUploadPolicy) uploadPolicy).getMaxHeight();
470 } else {
471 targetMaxWidth = ((PictureUploadPolicy) uploadPolicy).getRealMaxWidth();
472 targetMaxHeight = ((PictureUploadPolicy) uploadPolicy).getRealMaxHeight();
473 }
474
475
476
477 ImageHelper imageHelper = new ImageHelper((PictureUploadPolicy) uploadPolicy, this, targetMaxWidth,
478 targetMaxHeight, this.quarterRotation);
479
480
481
482 synchronized (this) {
483 if (imageHelper.hasToTransformPicture() && this.transformedPictureFile == null) {
484
485
486
487
488 try {
489 createTranformedPictureFile(imageHelper);
490 } catch (JUploadException e) {
491
492
493 deleteTransformedPictureFile();
494 throw e;
495 }
496 }
497 }
498 }
499
500
501
502
503
504
505
506
507
508 synchronized void createTranformedPictureFile(ImageHelper imageHelper) throws JUploadException {
509 uploadPolicy.displayDebug(this.hashCode() + "|Entering PictureFileData.createTransformedPictureFile()", 95);
510
511 IIOMetadata metadata = null;
512 IIOImage iioImage = null;
513 BufferedImage originalImage = null;
514 BufferedImage transformedImage = null;
515 ImageReaderWriterHelper imageWriterHelper = new ImageReaderWriterHelper((PictureUploadPolicy) uploadPolicy,
516 this);
517 boolean transmitMetadata = ((PictureUploadPolicy) uploadPolicy).getPictureTransmitMetadata();
518
519
520 createTransformedTempFile();
521 this.targetPictureFormat = imageWriterHelper.getTargetPictureFormat();
522 imageWriterHelper.setOutput(this.transformedPictureFile);
523
524
525
526 int nbPictures = 1;
527
528
529 if (getExtension(getFileName()).equalsIgnoreCase("gif")) {
530 nbPictures = Integer.MAX_VALUE;
531 }
532 uploadPolicy.displayDebug("Reading image with imageWriterHelper.readImage(i)", 50);
533
534
535
536
537
538 try {
539 for (int i = 0; i < nbPictures; i += 1) {
540 originalImage = imageWriterHelper.readImage(i);
541 transformedImage = imageHelper.getBufferedImage(true, originalImage);
542
543
544
545 if (transmitMetadata) {
546 metadata = imageWriterHelper.getImageMetadata(i);
547 }
548
549 iioImage = new IIOImage(transformedImage, null, metadata);
550 imageWriterHelper.write(iioImage);
551
552
553
554
555 if (originalImage != null) {
556 originalImage.flush();
557 originalImage = null;
558 }
559 }
560 } catch (IndexOutOfBoundsException e) {
561
562
563
564 uploadPolicy
565 .displayDebug("IndexOutOfBoundsException catched: end of reading for file " + getFileName(), 10);
566 }
567
568 if (originalImage != null) {
569 originalImage.flush();
570 originalImage = null;
571 }
572
573
574 imageWriterHelper.dispose();
575
576 }
577
578
579
580
581
582
583 void tooBigPicture() {
584 String msg = uploadPolicy.getLocalizedString("tooBigPicture", getFileName());
585 uploadPolicy.displayWarn(msg);
586 JOptionPane.showMessageDialog(null, msg, "Warning", JOptionPane.WARNING_MESSAGE);
587 }
588
589
590
591
592
593 void setMimeTypeByExtension(String fileExtension) {
594 String ext = fileExtension.toLowerCase();
595 if (ext.equals("jpg")) {
596 ext = "jpeg";
597 }
598 this.mimeType = "image/" + ext;
599 }
600
601
602
603
604
605
606
607 synchronized void createTransformedTempFile() throws JUploadIOException {
608 uploadPolicy.displayDebug(this.hashCode() + "|Entering PictureFileData.createTransformedTempFile()", 95);
609
610 if (this.transformedPictureFile == null) {
611 try {
612 this.transformedPictureFile = File.createTempFile("jupload_", ".tmp");
613 } catch (IOException e) {
614 throw new JUploadIOException("PictureFileData.createTransformedTempFile()", e);
615 }
616 uploadPolicy.getContext().registerUnload(this, "deleteTransformedPictureFile");
617 uploadPolicy.displayDebug("Using transformed temp file " + this.transformedPictureFile.getAbsolutePath()
618 + " for " + getFileName(), 30);
619 }
620 }
621
622
623
624
625
626
627
628
629
630 void initWidthAndHeight() throws JUploadIOException {
631
632 if (this.isPicture && (this.originalHeight < 0 || this.originalWidth < 0)) {
633
634
635
636
637 Iterator<ImageReader> iter = ImageIO.getImageReadersByFormatName(getFileExtension().toLowerCase());
638 if (iter.hasNext()) {
639
640
641 try {
642 FileImageInputStream fiis = new FileImageInputStream(getFile());
643 ImageReader ir = iter.next();
644 ir.setInput(fiis);
645 this.originalHeight = ir.getHeight(0);
646 this.originalWidth = ir.getWidth(0);
647 ir.dispose();
648 fiis.close();
649 } catch (IOException e) {
650 throw new JUploadIOException("PictureFileData()", e);
651 }
652 }
653 }
654 }
655
656
657
658
659
660
661
662 synchronized void createWorkingCopyTempFile() throws IOException {
663 uploadPolicy.displayDebug(this.hashCode() + "|Entering PictureFileData.createWorkingCopyTempFile()", 95);
664 if (this.workingCopyTempFile == null) {
665
666
667 this.workingCopyTempFile = File.createTempFile("jupload_",
668 ".tmp." + DefaultFileData.getExtension(getFileName()));
669 uploadPolicy.getContext().registerUnload(this, "deleteWorkingCopyPictureFile");
670 uploadPolicy.displayDebug("Using working copy temp file " + this.workingCopyTempFile.getAbsolutePath()
671 + " for " + getFileName(), 30);
672 }
673 }
674
675
676
677
678
679 public synchronized void deleteWorkingCopyPictureFile() {
680
681
682 if (null != this.workingCopyTempFile && uploadPolicy.getDebugLevel() <= 100) {
683 if (!this.workingCopyTempFile.delete()) {
684 uploadPolicy.displayWarn("Unable to delete " + this.workingCopyTempFile.getName());
685 }
686 this.workingCopyTempFile = null;
687
688 }
689 }
690
691
692
693
694
695
696
697
698
699 public synchronized File getWorkingSourceFile() throws JUploadIOException {
700
701 if (this.workingCopyTempFile == null) {
702 uploadPolicy.displayDebug("[getWorkingSourceFile] Creating a copy of " + getFileName()
703 + " as a source working target.", 30);
704 FileInputStream is = null;
705 FileOutputStream os = null;
706 try {
707 createWorkingCopyTempFile();
708
709 is = new FileInputStream(getFile());
710 os = new FileOutputStream(this.workingCopyTempFile);
711 byte b[] = new byte[1024];
712 int l;
713 while ((l = is.read(b)) > 0) {
714 os.write(b, 0, l);
715 }
716 } catch (IOException e) {
717 throw new JUploadIOException("ImageReaderWriterHelper.getWorkingSourceFile()", e);
718 } finally {
719 if (is != null) {
720 try {
721 is.close();
722 } catch (IOException e) {
723 uploadPolicy
724 .displayWarn(e.getClass().getName()
725 + " while trying to close FileInputStream, in PictureUploadPolicy.copyOriginalToWorkingCopyTempFile.");
726 } finally {
727 is = null;
728 }
729 }
730 if (os != null) {
731 try {
732 os.close();
733 } catch (IOException e) {
734 uploadPolicy
735 .displayWarn(e.getClass().getName()
736 + " while trying to close FileOutputStream, in PictureUploadPolicy.copyOriginalToWorkingCopyTempFile.");
737 } finally {
738 os = null;
739 }
740 }
741 }
742 }
743 return this.workingCopyTempFile;
744 }
745
746
747
748
749
750 public int getOriginalWidth() throws JUploadIOException {
751 initWidthAndHeight();
752 return this.originalWidth;
753 }
754
755
756
757
758
759 public int getOriginalHeight() throws JUploadIOException {
760 initWidthAndHeight();
761 return this.originalHeight;
762 }
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779 public static ImageIcon getImageIcon(File pictureFile, int maxWidth, int maxHeight, UploadPolicy uploadPolicy)
780 throws JUploadException {
781 ImageIcon imageIcon = null;
782
783 if (pictureFile != null) {
784 BufferedImage tmpImage = null;
785 try {
786
787 if (pictureFile.canRead() && pictureFile.isFile()) {
788
789 if (ImageIO.getImageReaders(new FileImageInputStream(pictureFile)).hasNext()) {
790 tmpImage = ImageIO.read(pictureFile);
791 }
792 }
793 } catch (IOException e) {
794 throw new JUploadIOException("An error occured while loading the image for "
795 + pictureFile.getAbsolutePath(), e);
796 }
797 if (tmpImage != null) {
798
799 double scaleWidth = ((double) maxWidth) / tmpImage.getWidth();
800 double scaleHeight = ((double) maxHeight) / tmpImage.getHeight();
801 double scale = Math.min(scaleWidth, scaleHeight);
802
803 if (scale < 1) {
804 int width = (int) (scale * tmpImage.getWidth());
805 int height = (int) (scale * tmpImage.getHeight());
806
807 Image rescaledImage = tmpImage.getScaledInstance(width, height, Image.SCALE_FAST);
808 BufferedImage tempBufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
809 tempBufferedImage.getGraphics().drawImage(rescaledImage, 0, 0, null);
810 imageIcon = new ImageIcon(tempBufferedImage);
811 uploadPolicy.displayDebug("Icon generated (witdh=" + imageIcon.getIconWidth() + ", imageheight="
812 + imageIcon.getIconHeight() + ")", 80);
813 }
814 tmpImage.flush();
815 tmpImage = null;
816
817 freeMemory("PictureFileData.getImageIcon()", uploadPolicy);
818 }
819 }
820 return imageIcon;
821 }
822
823
824
825
826
827
828
829
830
831 public static boolean isFileAPicture(File file) {
832
833
834 Iterator<ImageReader> iter = ImageIO.getImageReadersByFormatName(DefaultFileData.getExtension(file.getName())
835 .toLowerCase());
836 return iter.hasNext();
837 }
838 }