1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.data.cache;
|
---|
3 |
|
---|
4 | import java.awt.image.BufferedImage;
|
---|
5 | import java.io.ByteArrayInputStream;
|
---|
6 | import java.io.IOException;
|
---|
7 |
|
---|
8 | import javax.imageio.ImageIO;
|
---|
9 |
|
---|
10 | /**
|
---|
11 | * Cache Entry that has methods to get the BufferedImage, that will be cached along in memory
|
---|
12 | * but will be not serialized when saved to the disk (to avoid duplication of data)
|
---|
13 | *
|
---|
14 | * @author Wiktor Niesiobędzki
|
---|
15 | */
|
---|
16 | public class BufferedImageCacheEntry extends CacheEntry {
|
---|
17 | private static final long serialVersionUID = 1L; //version
|
---|
18 | // transient to avoid serialization, volatile to avoid synchronization of whole getImage() method
|
---|
19 | private transient volatile BufferedImage img;
|
---|
20 | // we need to have separate control variable, to know, if we already tried to load the image, as img might be null
|
---|
21 | // after we loaded image, as for example, when image file is malformed (eg. HTML file)
|
---|
22 | private transient volatile boolean imageLoaded;
|
---|
23 |
|
---|
24 | /**
|
---|
25 | *
|
---|
26 | * @param content byte array containing image
|
---|
27 | */
|
---|
28 | public BufferedImageCacheEntry(byte[] content) {
|
---|
29 | super(content);
|
---|
30 | }
|
---|
31 |
|
---|
32 | /**
|
---|
33 | * Returns BufferedImage from for the content. Subsequent calls will return the same instance,
|
---|
34 | * to reduce overhead of ImageIO
|
---|
35 | *
|
---|
36 | * @return BufferedImage of cache entry content
|
---|
37 | * @throws IOException if an error occurs during reading.
|
---|
38 | */
|
---|
39 | public BufferedImage getImage() throws IOException {
|
---|
40 | if (imageLoaded)
|
---|
41 | return img;
|
---|
42 | synchronized (this) {
|
---|
43 | if (imageLoaded)
|
---|
44 | return img;
|
---|
45 | byte[] content = getContent();
|
---|
46 | if (content.length > 0) {
|
---|
47 | img = ImageIO.read(new ByteArrayInputStream(content));
|
---|
48 | imageLoaded = true;
|
---|
49 | }
|
---|
50 | }
|
---|
51 | return img;
|
---|
52 | }
|
---|
53 |
|
---|
54 | private void writeObject(java.io.ObjectOutputStream out) throws IOException {
|
---|
55 | /*
|
---|
56 | * This method below will be needed, if Apache Commons JCS (or any other caching system), will update
|
---|
57 | * disk representation of object from memory, once it is put into the cache (for example - at closing the cache)
|
---|
58 | *
|
---|
59 | * For now it is not the case, as we use DiskUsagePattern.UPDATE, which on JCS shutdown doesn't write again memory
|
---|
60 | * contents to file, so the fact, that we've cleared never gets saved to the disk
|
---|
61 | *
|
---|
62 | * This method is commented out, as it will convert all cache entries to PNG files regardless of what was returned.
|
---|
63 | * It might cause recompression/change of format which may result in decreased quality of imagery
|
---|
64 | */
|
---|
65 | /* synchronized (this) {
|
---|
66 | if (content == null && img != null) {
|
---|
67 | ByteArrayOutputStream restoredData = new ByteArrayOutputStream();
|
---|
68 | ImageIO.write(img, "png", restoredData);
|
---|
69 | content = restoredData.toByteArray();
|
---|
70 | }
|
---|
71 | out.writeObject(this);
|
---|
72 | }
|
---|
73 | */
|
---|
74 | synchronized (this) {
|
---|
75 | if (content == null && img != null) {
|
---|
76 | throw new AssertionError("Trying to serialize (save to disk?) an BufferedImageCacheEntry " +
|
---|
77 | "that was converted to BufferedImage and no raw data is present anymore");
|
---|
78 | }
|
---|
79 | out.writeObject(this);
|
---|
80 |
|
---|
81 | if (img != null) {
|
---|
82 | content = null;
|
---|
83 | }
|
---|
84 | }
|
---|
85 | }
|
---|
86 | }
|
---|