Skip to content

Method: dispose()

1: /*
2: * *********************************************************************************************************************
3: *
4: * Mistral: open source imaging engine
5: * http://tidalwave.it/projects/mistral
6: *
7: * Copyright (C) 2003 - 2023 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *********************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
12: * the License. You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
17: * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
18: * specific language governing permissions and limitations under the License.
19: *
20: * *********************************************************************************************************************
21: *
22: * git clone https://bitbucket.org/tidalwave/mistral-src
23: * git clone https://github.com/tidalwave-it/mistral-src
24: *
25: * *********************************************************************************************************************
26: */
27: package it.tidalwave.image;
28:
29: import java.io.Externalizable;
30: import java.io.IOException;
31: import java.io.InputStream;
32: import java.io.ObjectInput;
33: import java.io.ObjectOutput;
34: import java.io.OutputStream;
35: import java.io.Serializable;
36: import javax.imageio.ImageIO;
37: import java.awt.image.ColorModel;
38: import java.awt.image.RenderedImage;
39: import it.tidalwave.image.op.ImplementationFactory;
40:
41: /***********************************************************************************************************************
42: *
43: * @author Fabrizio Giudici
44: *
45: **********************************************************************************************************************/
46: public abstract class ImageModel implements Externalizable
47: {
48: private Serializable id;
49: private String nickName;
50: protected transient Object model;
51:
52: /*******************************************************************************************************************
53: *
54: * Default constructor for serialization. DO NOT CALL.
55: *
56: ******************************************************************************************************************/
57: public ImageModel()
58: {
59: // Just deserialized. There's no model, so it should not go in cache
60: }
61:
62: /*******************************************************************************************************************
63: *
64: *
65: ******************************************************************************************************************/
66: public ImageModel (final Object model)
67: {
68: if (model == null)
69: {
70: throw new IllegalArgumentException("model is null");
71: }
72:
73: id = "" + (System.nanoTime() - 1182021416080087000L); // FIXME: use UUID
74: // System.err.println("CREATED ImageModel " + id);
75: this.model = model;
76: // ImageModelCache.getInstance().add(this);
77: }
78:
79: /*******************************************************************************************************************
80: *
81: *
82: ******************************************************************************************************************/
83: public void dispose()
84: {
85: ImageModelCache.getInstance().remove(id, true);
86: // model = null; FIXME??
87: }
88:
89: /*******************************************************************************************************************
90: *
91: *
92: ******************************************************************************************************************/
93: public final Serializable getId()
94: {
95: return id;
96: }
97:
98: public void setNickName (final String nickName)
99: {
100: this.nickName = nickName;
101: }
102:
103: public String getNickName()
104: {
105: return nickName;
106: }
107:
108: /*******************************************************************************************************************
109: *
110: *
111: ******************************************************************************************************************/
112: @Override
113: public final int hashCode()
114: {
115: return (id != null) ? id.hashCode() : 0;
116: }
117:
118: /*******************************************************************************************************************
119: *
120: *
121: ******************************************************************************************************************/
122: @Override
123: public final boolean equals (final Object object)
124: {
125: if (!(object instanceof ImageModel))
126: {
127: return false;
128: }
129:
130: final var imageModel = (ImageModel)object;
131:
132: if ((id == null) || (imageModel.id == null))
133: {
134: return false;
135: }
136:
137: return id.equals(imageModel.id);
138: }
139:
140: /*******************************************************************************************************************
141: *
142: *
143: ******************************************************************************************************************/
144: public void setImage (final Object image)
145: {
146: ImageModelCache.getInstance().update(this);
147: }
148:
149: /*******************************************************************************************************************
150: *
151: *
152: ******************************************************************************************************************/
153: public final Object getImage()
154: {
155: return model;
156: }
157:
158: /*******************************************************************************************************************
159: *
160: *
161: ******************************************************************************************************************/
162: public abstract int getWidth();
163:
164: /*******************************************************************************************************************
165: *
166: *
167: ******************************************************************************************************************/
168: public abstract int getHeight();
169:
170: /*******************************************************************************************************************
171: *
172: *
173: ******************************************************************************************************************/
174: public abstract EditableImage.DataType getDataType();
175:
176: /*******************************************************************************************************************
177: *
178: *
179: ******************************************************************************************************************/
180: public abstract int getBandCount();
181:
182: /*******************************************************************************************************************
183: *
184: *
185: ******************************************************************************************************************/
186: public abstract ImplementationFactory getFactory();
187:
188: /*******************************************************************************************************************
189: *
190: *
191: ******************************************************************************************************************/
192: public abstract ColorModel getColorModel();
193:
194: /*******************************************************************************************************************
195: *
196: * Creates a similar image, that is a blank image with the same characteristics
197: * of this image (width, height, data type, sample model, color model).
198: *
199: * @return a new, similar image
200: *
201: ******************************************************************************************************************/
202: public abstract EditableImage createCopy (boolean copyContents);
203:
204: /*******************************************************************************************************************
205: *
206: *
207: ******************************************************************************************************************/
208: public abstract <T> T getInnerProperty (Class<T> propertyClass);
209:
210: /*******************************************************************************************************************
211: *
212: * Returns an estimate of the memory allocated by this image. The default
213: * implementation returns the number of pixels multiplied by the number of bands
214: * multiplied the size in bytes of each pixel. Can be overridden for more
215: * accurate implementations.
216: *
217: * @return the memory allocated for this image
218: *
219: ******************************************************************************************************************/
220: public long getMemorySize()
221: {
222: final var dataType = getDataType();
223: return (dataType == null) ? 0 : ((long)dataType.getSize() * getWidth() * getHeight() * getBandCount()) / 8;
224: }
225:
226: /*******************************************************************************************************************
227: *
228: *
229: ******************************************************************************************************************/
230: @Override
231: public final void writeExternal (final ObjectOutput out)
232: throws IOException
233: {
234: out.writeObject(id);
235: out.writeObject((nickName != null) ? nickName : "NULL"); // FIXME: needed? Can writeObject(null)?
236:
237: final var notNull = model != null;
238: out.writeBoolean(notNull);
239:
240: if (notNull)
241: {
242: writeRaster(new OutputStream()
243: {
244: @Override
245: public void write (final byte[] buffer, final int off, final int len)
246: throws IOException
247: {
248: out.write(buffer, off, len);
249: }
250:
251: @Override
252: public void write (final int b)
253: throws IOException
254: {
255: out.write(b);
256: }
257: });
258: }
259: }
260:
261: /*******************************************************************************************************************
262: *
263: *
264: ******************************************************************************************************************/
265: @Override
266: public final void readExternal (final ObjectInput in)
267: throws IOException, ClassNotFoundException
268: {
269: id = (Serializable)in.readObject();
270: nickName = (String)in.readObject();
271:
272: if (nickName.equals("NULL"))
273: {
274: nickName = null;
275: }
276:
277: if (in.readBoolean())
278: {
279: readRaster(new InputStream()
280: {
281: @Override
282: public int read (final byte[] b, final int off, final int len)
283: throws IOException
284: {
285: return in.read(b, off, len);
286: }
287:
288: @Override
289: public int read()
290: throws IOException
291: {
292: return in.read();
293: }
294: });
295: }
296: }
297:
298: /*******************************************************************************************************************
299: *
300: *
301: ******************************************************************************************************************/
302: protected abstract RenderedImage toRenderedImageForSerialization();
303:
304: /*******************************************************************************************************************
305: *
306: *
307: ******************************************************************************************************************/
308: protected abstract Object toObjectForDeserialization (final RenderedImage renderedImage);
309:
310: /*******************************************************************************************************************
311: *
312: * TODO: check performance
313: *
314: ******************************************************************************************************************/
315: protected void writeRaster (final OutputStream out)
316: throws IOException
317: {
318: // System.err.println(CLASS + ".writeExternal() - model: " + model);
319: /* ImageWriter imageWriter = null;
320:
321: for (final Iterator<ImageWriter> i = ImageIO.getImageWritersByFormatName("TIFF"); i.hasNext(); )
322: {
323: final ImageWriter testImageWriter = i.next();
324:
325: if ((testImageWriter != null) && testImageWriter.getClass().getName().equals("com.sun.media
326: .imageioimpl.plugins.tiff.TIFFImageWriter"))
327: {
328: imageWriter = testImageWriter;
329: break;
330: }
331: }
332:
333: if (imageWriter == null)
334: {
335: throw new RuntimeException("No JAI ImageIO ImageWriter for TIFF format! Can't serialize ImageModel");
336: }
337:
338: System.err.println("SERIALIZING WITH " + imageWriter);
339: final ImageOutputStream ios = ImageIO.createImageOutputStream(out);
340: imageWriter.setOutput(ios);
341: imageWriter.write(toRenderedImageForSerialization());
342: imageWriter.dispose();*/
343: ImageIO.write(toRenderedImageForSerialization(), "TIFF", out);
344: }
345:
346: /*******************************************************************************************************************
347: *
348: * TODO: check performance
349: *
350: ******************************************************************************************************************/
351: protected void readRaster (final InputStream in)
352: throws IOException
353: {
354: try
355: {
356: Class.forName("com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriter");
357: }
358: catch (ClassNotFoundException ex)
359: {
360: throw new RuntimeException("Can't deserialize ImageModels since JAI ImageIO is not in the classpath");
361: }
362:
363: model = toObjectForDeserialization(ImageIO.read(in));
364: }
365:
366: /*******************************************************************************************************************
367: *
368: *
369: ******************************************************************************************************************/
370: @Override
371: public final String toString()
372: {
373: return getClass().getName() + "[id: " + getId() +
374: ((nickName != null) ? (", nickName: " + nickName) : "") +
375: //", model: " + model +
376: "]";
377: }
378:
379: /*******************************************************************************************************************
380: *
381: *
382: ******************************************************************************************************************/
383: @Override
384: protected void finalize()
385: {
386: // FIXME: not sure about this - for sure should only remove from the local cache
387: }
388: }