001    package org.hd.d.pg2k.svrCore.MIME;
002    
003    import java.awt.image.BufferedImage;
004    import java.io.IOException;
005    import java.io.InputStream;
006    
007    import org.hd.d.pg2k.svrCore.AllExhibitProperties;
008    import org.hd.d.pg2k.svrCore.ExhibitStaticAttr;
009    import org.hd.d.pg2k.svrCore.ExhibitThumbnails;
010    import org.hd.d.pg2k.svrCore.Name.ExhibitFull;
011    import org.w3c.dom.Node;
012    
013    /**
014     * Created by IntelliJ IDEA.
015     * User: Damon
016     * Date: 06-Apr-2006
017     * Time: 21:48:23
018     */
019    
020    /**Base class implementing Handler with nearly all methods returning default values.
021     * This makes implementation of a new concrete handler as easy as possible.
022     * <p>
023     * The concrete implementation must provide getExhibitType().
024     */
025    public abstract class AbstractHandler implements Handler
026        {
027        /**Efficiently get X,Y pixel dimensions of an image exhibit, else null if dimensions cannot be computed.
028         * This will always return null for items which do not have a fixed
029         * X,Y size in pixels such as for AU sound files for example.
030         * <p>
031         * For something like a movie in a fixed frame this may be able to
032         * return its dimensions, eg to embed in a page.
033         * <p>
034         * This <strong>does not close its input stream</strong> when done.
035         * <p>
036         * This should work efficiently, by directly reading (opening) bytes
037         * of the exhibit passed as an input stream.
038         * <p>
039         * This will only work correctly if the exhibit is of the correct type,
040         * eg its magic number must already have been tested.
041         *
042         * @param is  the exhibit as a binary data stream
043         *
044         * @throws java.io.IOException  in case of problems with corrupt data
045         *     (or a broken exhibit)
046         */
047        public java.awt.Dimension get2DImageDimensions(final InputStream is)
048            throws IOException
049            { return(null); }
050    
051        /**Returns true if handler can make thumbnails for this type.
052         * makeThumbnails() has to be able to succeed for some real exhibits of
053         * this type,
054         * producing thumbnails/samples of the same MIME type
055         * (though possibly at much-reduced fidelity),
056         * but makeThumbnails() need not succeed for all exhibits of this type.
057         * <p>
058         * By default, returns false, ie thumbnails cannot be made.
059         */
060        public boolean canMakeThumbnails()
061            { return(false); }
062    
063        /**Get ThumbnailParameters for a particular handler.
064         * A handler that does not build thumbnails
065         * (ie canMakeThumbnails() returns false)
066         * may return null for this, which is the default,
067         * but otherwise this should return non-null.
068         * <p>
069         * This is assumed to be fast, ie to return a fixed static instance
070         * for each handler.
071         * <p>
072         * This is protected, since only the support routines in this base
073         * class need access this data.
074         */
075        public ThumbnailParams getThumbnailParams()
076            { return(null); } // Default is not to have any.
077    
078        /**Make a byte[]-encoded image of this type constained above and below by size; null if not possible.
079         * This uses a binary-chop algorithm to attempt to quickly
080         * find the optimal "quality" to make the image at,
081         * lower quality values asking the encoder to discard more information,
082         * eg by doing colour reduction or other quantisation.
083         * <p/>
084         * This is not possible for all exhibit types.
085         *
086         * @param upperQualityBound  maximum value of quality to use; non-negative
087         * @param lowerQualityBound  minimum value of quality to use; non-negative
088         *                           and no greater than upperQualityBound
089         * @param initialQualityHint initial suggested quality hint; non-negative,
090         *                           no greater than upperQualityBound, no less than lowerQualityBound
091         * @param scaledImage        the input image to encode
092         * @param targetMin          target lower bound, should be higher than absMinSize
093         * @param targetMax          target upper bound, should be lower than absMaxSize
094         * @param absMinSize         absolute minimum number of bytes
095         * @param absMaxSize         absolute maximum number of bytes
096         * @param targetBytes        target number of bytes
097         * @return encoded image, or null if the image cannot be generated
098         *         with given constraints
099         * @throws java.io.IOException      in case of difficulty generating the image
100         * @throws IllegalArgumentException if the arguments are invalid
101         */
102        public byte[] makeSizeConstrainedEncodedImage(final int lowerQualityBound, final int initialQualityHint, final int upperQualityBound, final BufferedImage scaledImage, final int targetMin, final int targetMax, final int absMinSize, final int absMaxSize, final int targetBytes) throws IOException, IllegalArgumentException
103            { return(null); }
104    
105        /**Make thumbnails/samples for the specified exhibit; null if not possible.
106         * This may fail with an IOException or return null
107         * to indicate that it is currently unable to create
108         * thumbnails/samples (though this condition may be temporary).
109         * <p/>
110         * If this wishes to indicate that it cannot ever make one or more
111         * thumbnails/samples for a given exhibit then this should return a
112         * ExhibitThumbnails object with one or both thumbnails set to null.
113         * <p/>
114         * (If canMakeThumbnails() returns false, this should return null.)
115         * <p/>
116         * This <strong>does not close its input stream</strong> when done.
117         * <p/>
118         * This will only work correctly if the exhibit is of the correct type,
119         * eg its magic number must already have been tested.
120         * <p/>
121         * This assumes enough memory and other resource is available.
122         *
123         * @param is             the whole raw image positioned at its start
124         * @param originalLength is the length of the encoded original in bytes;
125         *                       always positive and must reflect the stream input
126         *                       and will be constrained to Integer.MAX_VALUE if larger
127         * @return thumbnails, else null if not possible now;
128         *         ExhibitThumbnails.NO_THUMBNAILS may be returned if it looks
129         *         like it never be possible/sensible to make thumbnails for
130         *         this exhibit
131         */
132        public ExhibitThumbnails makeThumbnails(final InputStream is, final long originalLength) throws IOException
133            { return(null); }
134    
135        /**Make thumbnails/samples for the specified exhibit; null or ExhibitThumbnails.NO_THUMBNAILS if not possible.
136         * A data source for the exhibit must be supplied,
137         * along with all available properties of that exhibit.
138         * <p/>
139         * This may fail with an IOException or return null
140         * to indicate that it is currently unable to create
141         * thumbnails/samples (though this condition may be temporary).
142         * <p/>
143         * If this wishes to indicate that it cannot make one or more
144         * thumbnails/samples for a given exhibit then this should return a
145         * ExhibitThumbnails object with one or both thumbnails set to null.
146         * <p/>
147         * (If canMakeThumbnails() returns false, this should return null.)
148         * <p/>
149         * By default, returns null, ie thumbnails cannot be made.
150         * <p/>
151         * This routine regulates memory use, rejecting the attempt
152         * to make the thumbnails if it cannot find/reserve sufficient memory
153         * using MemoryTools.runMemoryIntensiveOperation().
154         * <p/>
155         * Calls the InputStream version of makeThumbnails().
156         *
157         * @param unlimitedResources if true, the generation routine is allowed
158         *                           to try to use unlimited resources (especially memory)
159         * @return thumbnails, else null if not possible now;
160         *         ExhibitThumbnails.NO_THUMBNAILS may be returned if it looks
161         *         like it never be possible/sensible to make thumbnails for
162         *         this exhibit
163         */
164        public ExhibitThumbnails makeThumbnails(final ExhibitStaticAttr esa, final AllExhibitProperties.ExhibitDataSource eds, final AllExhibitProperties aep, final boolean unlimitedResources) throws IOException
165            { return(null); }
166    
167        /**Return image as file-format byte array; null if not possible.
168         * This should only be used for making an image that is compatable
169         * with the output format, eg trying to build a GIF from a true-colour
170         * image is unlikely to work.
171         * <p>
172         * This is used for still images and possible animations
173         * or movies where the bounding rectangle and the contained data
174         * is scaled to the given bounds.
175         * <p>
176         * The output image will, if possible, use the same colour scheme
177         * and other characteristics as the input, though some optional
178         * features that usually consume extra space, such as interlacing,
179         * may be disabled.
180         * <p>
181         * If no output can be generated then this returns null,
182         * which is the default behaviour.
183         * <p>
184         * This should adjust the image "quality" with the detail
185         * value (adjusted within the bounds supplied by the handler class)
186         * to try to tune the output size.  For a lossy encoding format
187         * such as JPEG this may be the "quality" factor or compression.
188         * For a lossless format the may have to be the number of
189         * bits-per-pixel that a colour map is reduced to, for example.
190         * <em>If at all possible, no value of the quality parameter
191         * should cause null to be returned if there is any value
192         * that can generate a valud image,
193         * and output size should not decrease at any point as the
194         * value of the quality parameter increases,
195         * else some routines such as thumbnail generation will not work well.</em>
196         * <p>
197         * The quality parameter usage is format- and implementation-
198         * dependent, but 0 will generally be the lowest-quality rendering
199         * available and 100 will be the highest, with values in between
200         * monotonically increasing, though that does not mean that there
201         * will be any distinguishable different in the output with
202         * any pair of adjacent (or indeed any) quality values.
203         *
204         * @param imageIn  source image; must not be null and must be suitable
205         *     for the target format
206         * @param quality  hint as to how good to make the target image
207         *     in norminal range [0-100];
208         *     anything above 100 (eg Integer.MAX_VALUE) indicates maximum quality
209         */
210        public byte[] makeImageBinary(final BufferedImage imageIn, final int quality)
211            throws IOException
212            { return(null); } // Can't make an image by default.
213    
214        /**Decode image as BufferedImage, or null if not possible.
215         * This <strong>does not close its input stream</strong> when done.
216         * <p>
217         * By default, returns null.
218         */
219        public BufferedImage decodeImage(final InputStream is)
220            throws IOException
221            { return(null); }
222    
223    
224    //    /**Empty String array: immutable default result of getEmbeddedText(). */
225    //    private static final String[] NO_TEXT = new String[0];
226    //
227    //    /**Get any embedded text, eg comments, in the exhibit.
228    //     * This is to extract comments, creator details, etc,
229    //     * rather than to read the text by OCR, ie this is
230    //     * quick and unambiguous.
231    //     * <p>
232    //     * This should avoid reading the entire image into memory
233    //     * or any other CPU- or memory- intensive operation
234    //     * if at all possible.
235    //     * <p>
236    //     * This <strong>does not close its input stream</strong> when done.
237    //     * <p>
238    //     * The file must be of the correct exhibit type or behaviour
239    //     * is undefined.
240    //     * <p>
241    //     * The default is to return an empty array, ie as if no such
242    //     * embedded text is available.
243    //     *
244    //     * @return an array of non-null embedded text strings within
245    //     *     the exhibit such as copyright notices and comments; never null
246    //     */
247    //    public String[] getEmbeddedText(final InputStream is)
248    //        throws IOException
249    //        { return(NO_TEXT); }
250    
251        /**Gets all available exhibit metadata as a single XML DOM tree; null if none.
252         * We do not (yet) have a schema for this and may never do so,
253         * since its structure and content will depend on various external sources
254         * and parts of (for example) the ImageIO and JAI subsystems.
255         *
256         * @param is input stream; never null
257         * @return top-level node "metadata" with captured metadata beneath, else null
258         */
259        public Node getMetadata(final InputStream is, final ExhibitFull exhibitName)
260            { return(null); }
261        }