Advertisement
Guest User

im

a guest
Apr 8th, 2016
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.84 KB | None | 0 0
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17.  
  18. /* $Id: ImageManager.java 924666 2010-03-18 08:26:30Z jeremias $ */
  19.  
  20. package org.apache.xmlgraphics.image.loader;
  21.  
  22. import java.io.IOException;
  23. import java.util.Iterator;
  24. import java.util.Map;
  25.  
  26. import javax.xml.transform.Source;
  27.  
  28. import org.apache.xmlgraphics.image.loader.cache.ImageCache;
  29. import org.apache.xmlgraphics.image.loader.pipeline.ImageProviderPipeline;
  30. import org.apache.xmlgraphics.image.loader.pipeline.PipelineFactory;
  31. import org.apache.xmlgraphics.image.loader.spi.ImageImplRegistry;
  32. import org.apache.xmlgraphics.image.loader.spi.ImagePreloader;
  33. import org.apache.xmlgraphics.image.loader.util.ImageUtil;
  34. import org.apache.xmlgraphics.image.loader.util.Penalty;
  35.  
  36. /**
  37. * ImageManager is the central starting point for image access.
  38. */
  39. public class ImageManager {
  40.  
  41. /** logger */
  42. // protected static Log log = LogFactory.getLog(ImageManager.class);
  43.  
  44. /** Holds all registered interface implementations for the image package */
  45. private ImageImplRegistry registry;
  46.  
  47. /** Provides session-independent information */
  48. private ImageContext imageContext;
  49.  
  50. /** The image cache for this instance */
  51. private ImageCache cache = new ImageCache();
  52.  
  53. private PipelineFactory pipelineFactory = new PipelineFactory(this);
  54.  
  55. /**
  56. * Main constructor.
  57. * @param context the session-independent context information
  58. */
  59. public ImageManager(ImageContext context) {
  60. this(ImageImplRegistry.getDefaultInstance(), context);
  61. }
  62.  
  63. /**
  64. * Constructor for testing purposes.
  65. * @param registry the implementation registry with all plug-ins
  66. * @param context the session-independent context information
  67. */
  68. public ImageManager(ImageImplRegistry registry, ImageContext context) {
  69. this.registry = registry;
  70. this.imageContext = context;
  71. }
  72.  
  73. /**
  74. * Returns the ImageImplRegistry in use by the ImageManager.
  75. * @return the ImageImplRegistry
  76. */
  77. public ImageImplRegistry getRegistry() {
  78. return this.registry;
  79. }
  80.  
  81. /**
  82. * Returns the ImageContext in use by the ImageManager.
  83. * @return the ImageContext
  84. */
  85. public ImageContext getImageContext() {
  86. return this.imageContext;
  87. }
  88.  
  89. /**
  90. * Returns the ImageCache in use by the ImageManager.
  91. * @return the ImageCache
  92. */
  93. public ImageCache getCache() {
  94. return this.cache;
  95. }
  96.  
  97. /**
  98. * Returns the PipelineFactory in use by the ImageManager.
  99. * @return the PipelineFactory
  100. */
  101. public PipelineFactory getPipelineFactory() {
  102. return this.pipelineFactory;
  103. }
  104.  
  105. /**
  106. * Returns an ImageInfo object containing its intrinsic size for a given URI. The ImageInfo
  107. * is retrieved from an image cache if it has been requested before.
  108. * @param uri the URI of the image
  109. * @param session the session context through which to resolve the URI if the image is not in
  110. * the cache
  111. * @return the ImageInfo object created from the image
  112. * @throws ImageException If no suitable ImagePreloader can be found to load the image or
  113. * if an error occurred while preloading the image.
  114. * @throws IOException If an I/O error occurs while preloading the image
  115. */
  116. public ImageInfo getImageInfo(String uri, ImageSessionContext session)
  117. throws ImageException, IOException {
  118. if (getCache() != null) {
  119. return getCache().needImageInfo(uri, session, this);
  120. } else {
  121. return preloadImage(uri, session);
  122. }
  123. }
  124.  
  125. /**
  126. * Preloads an image, i.e. the format of the image is identified and some basic information
  127. * (MIME type, intrinsic size and possibly other values) are loaded and returned as an
  128. * ImageInfo object. Note that the image is not fully loaded normally. Only with certain formats
  129. * the image is already fully loaded and references added to the ImageInfo's custom objects
  130. * (see {@link ImageInfo#getOriginalImage()}).
  131. * <p>
  132. * The reason for the preloading: Apache FOP, for example, only needs the image's intrinsic
  133. * size during layout. Only when the document is rendered to the final format does FOP need
  134. * to load the full image. Like this a lot of memory can be saved.
  135. * @param uri the original URI of the image
  136. * @param session the session context through which to resolve the URI
  137. * @return the ImageInfo object created from the image
  138. * @throws ImageException If no suitable ImagePreloader can be found to load the image or
  139. * if an error occurred while preloading the image.
  140. * @throws IOException If an I/O error occurs while preloading the image
  141. */
  142. public ImageInfo preloadImage(String uri, ImageSessionContext session)
  143. throws ImageException, IOException {
  144. Source src = session.needSource(uri);
  145. ImageInfo info = preloadImage(uri, src);
  146. session.returnSource(uri, src);
  147. return info;
  148. }
  149.  
  150. /**
  151. * Preloads an image, i.e. the format of the image is identified and some basic information
  152. * (MIME type, intrinsic size and possibly other values) are loaded and returned as an
  153. * ImageInfo object. Note that the image is not fully loaded normally. Only with certain formats
  154. * the image is already fully loaded and references added to the ImageInfo's custom objects
  155. * (see {@link ImageInfo#getOriginalImage()}).
  156. * <p>
  157. * The reason for the preloading: Apache FOP, for example, only needs the image's intrinsic
  158. * size during layout. Only when the document is rendered to the final format does FOP need
  159. * to load the full image. Like this a lot of memory can be saved.
  160. * @param uri the original URI of the image
  161. * @param src the Source object to load the image from
  162. * @return the ImageInfo object created from the image
  163. * @throws ImageException If no suitable ImagePreloader can be found to load the image or
  164. * if an error occurred while preloading the image.
  165. * @throws IOException If an I/O error occurs while preloading the image
  166. */
  167. public ImageInfo preloadImage(String uri, Source src)
  168. throws ImageException, IOException {
  169. Iterator iter = registry.getPreloaderIterator();
  170.  
  171. while (iter.hasNext()) {
  172. ImagePreloader preloader = (ImagePreloader)iter.next();
  173.  
  174. ImageInfo info = preloader.preloadImage(uri, src, imageContext);
  175. if (info != null) {
  176. return info;
  177. }
  178. }
  179. throw new ImageException("The file format is not supported. No ImagePreloader found for "
  180. + uri);
  181. }
  182.  
  183. private Map prepareHints(Map hints, ImageSessionContext sessionContext) {
  184. Map newHints = new java.util.HashMap();
  185. if (hints != null) {
  186. newHints.putAll(hints); //Copy in case an unmodifiable map is passed in
  187. }
  188. if (!newHints.containsKey(ImageProcessingHints.IMAGE_SESSION_CONTEXT)
  189. && sessionContext != null) {
  190. newHints.put(ImageProcessingHints.IMAGE_SESSION_CONTEXT, sessionContext);
  191.  
  192. }
  193. if (!newHints.containsKey(ImageProcessingHints.IMAGE_MANAGER)) {
  194. newHints.put(ImageProcessingHints.IMAGE_MANAGER, this);
  195. }
  196. return newHints;
  197. }
  198.  
  199. /**
  200. * Loads an image. The caller can indicate what kind of image flavor is requested. When this
  201. * method is called the code looks for a suitable ImageLoader and, if necessary, builds
  202. * a conversion pipeline so it can return the image in exactly the form the caller needs.
  203. * <p>
  204. * Optionally, it is possible to pass in Map of hints. These hints may be used by ImageLoaders
  205. * and ImageConverters to act on the image. See {@link ImageProcessingHints} for common hints
  206. * used by the bundled implementations. You can, of course, define your own hints.
  207. * @param info the ImageInfo instance for the image (obtained by
  208. * {@link #getImageInfo(String, ImageSessionContext)})
  209. * @param flavor the requested image flavor.
  210. * @param hints a Map of hints to any of the background components or null
  211. * @param session the session context
  212. * @return the fully loaded image
  213. * @throws ImageException If no suitable loader/converter combination is available to fulfill
  214. * the request or if an error occurred while loading the image.
  215. * @throws IOException If an I/O error occurs
  216. */
  217. public Image getImage(ImageInfo info, ImageFlavor flavor, Map hints,
  218. ImageSessionContext session)
  219. throws ImageException, IOException {
  220. hints = prepareHints(hints, session);
  221.  
  222. Image img = null;
  223. ImageProviderPipeline pipeline = getPipelineFactory().newImageConverterPipeline(
  224. info, flavor);
  225. if (pipeline != null) {
  226. img = pipeline.execute(info, hints, session);
  227. }
  228. if (img == null) {
  229. throw new ImageException(
  230. "Cannot load image (no suitable loader/converter combination available) for "
  231. + info);
  232. }
  233. ImageUtil.closeQuietly(session.getSource(info.getOriginalURI()));
  234. return img;
  235. }
  236.  
  237. /**
  238. * Loads an image. The caller can indicate what kind of image flavors are requested. When this
  239. * method is called the code looks for a suitable ImageLoader and, if necessary, builds
  240. * a conversion pipeline so it can return the image in exactly the form the caller needs.
  241. * The array of image flavors is ordered, so the first image flavor is given highest priority.
  242. * <p>
  243. * Optionally, it is possible to pass in Map of hints. These hints may be used by ImageLoaders
  244. * and ImageConverters to act on the image. See {@link ImageProcessingHints} for common hints
  245. * used by the bundled implementations. You can, of course, define your own hints.
  246. * @param info the ImageInfo instance for the image (obtained by
  247. * {@link #getImageInfo(String, ImageSessionContext)})
  248. * @param flavors the requested image flavors (in preferred order).
  249. * @param hints a Map of hints to any of the background components or null
  250. * @param session the session context
  251. * @return the fully loaded image
  252. * @throws ImageException If no suitable loader/converter combination is available to fulfill
  253. * the request or if an error occurred while loading the image.
  254. * @throws IOException If an I/O error occurs
  255. */
  256. public Image getImage(ImageInfo info, ImageFlavor[] flavors, Map hints,
  257. ImageSessionContext session)
  258. throws ImageException, IOException {
  259. hints = prepareHints(hints, session);
  260.  
  261. Image img = null;
  262. ImageProviderPipeline[] candidates = getPipelineFactory().determineCandidatePipelines(
  263. info, flavors);
  264. ImageProviderPipeline pipeline = choosePipeline(candidates);
  265.  
  266. if (pipeline != null) {
  267. img = pipeline.execute(info, hints, session);
  268. }
  269. if (img == null) {
  270. throw new ImageException(
  271. "Cannot load image (no suitable loader/converter combination available) for "
  272. + info);
  273. }
  274. ImageUtil.closeQuietly(session.getSource(info.getOriginalURI()));
  275. return img;
  276. }
  277.  
  278. /**
  279. * Loads an image with no hints. See
  280. * {@link #getImage(ImageInfo, ImageFlavor, Map, ImageSessionContext)} for more
  281. * information.
  282. * @param info the ImageInfo instance for the image (obtained by
  283. * {@link #getImageInfo(String, ImageSessionContext)})
  284. * @param flavor the requested image flavor.
  285. * @param session the session context
  286. * @return the fully loaded image
  287. * @throws ImageException If no suitable loader/converter combination is available to fulfill
  288. * the request or if an error occurred while loading the image.
  289. * @throws IOException If an I/O error occurs
  290. */
  291. public Image getImage(ImageInfo info, ImageFlavor flavor, ImageSessionContext session)
  292. throws ImageException, IOException {
  293. return getImage(info, flavor, ImageUtil.getDefaultHints(session), session);
  294. }
  295.  
  296. /**
  297. * Loads an image with no hints. See
  298. * {@link #getImage(ImageInfo, ImageFlavor[], Map, ImageSessionContext)} for more
  299. * information.
  300. * @param info the ImageInfo instance for the image (obtained by
  301. * {@link #getImageInfo(String, ImageSessionContext)})
  302. * @param flavors the requested image flavors (in preferred order).
  303. * @param session the session context
  304. * @return the fully loaded image
  305. * @throws ImageException If no suitable loader/converter combination is available to fulfill
  306. * the request or if an error occurred while loading the image.
  307. * @throws IOException If an I/O error occurs
  308. */
  309. public Image getImage(ImageInfo info, ImageFlavor[] flavors, ImageSessionContext session)
  310. throws ImageException, IOException {
  311. return getImage(info, flavors, ImageUtil.getDefaultHints(session), session);
  312. }
  313.  
  314. /**
  315. * Converts an image. The caller can indicate what kind of image flavors are requested. When
  316. * this method is called the code looks for a suitable combination of ImageConverters so it
  317. * can return the image in exactly the form the caller needs.
  318. * The array of image flavors is ordered, so the first image flavor is given highest priority.
  319. * <p>
  320. * Optionally, it is possible to pass in Map of hints. These hints may be used by
  321. * ImageConverters to act on the image. See {@link ImageProcessingHints} for common hints
  322. * used by the bundled implementations. You can, of course, define your own hints.
  323. * @param image the image to convert
  324. * @param flavors the requested image flavors (in preferred order).
  325. * @param hints a Map of hints to any of the background components or null
  326. * @return the fully loaded image
  327. * @throws ImageException If no suitable loader/converter combination is available to fulfill
  328. * the request or if an error occurred while loading the image.
  329. * @throws IOException If an I/O error occurs
  330. */
  331. public Image convertImage(Image image, ImageFlavor[] flavors, Map hints)
  332. throws ImageException, IOException {
  333. hints = prepareHints(hints, null);
  334. ImageInfo info = image.getInfo();
  335.  
  336. Image img = null;
  337. int count = flavors.length;
  338. for (int i = 0; i < count; i++) {
  339. if (image.getFlavor().equals(flavors[i])) {
  340. //Shortcut (the image is already in one of the requested formats)
  341. return image;
  342. }
  343. }
  344. ImageProviderPipeline[] candidates = getPipelineFactory().determineCandidatePipelines(
  345. image, flavors);
  346. ImageProviderPipeline pipeline = choosePipeline(candidates);
  347.  
  348. if (pipeline != null) {
  349. img = pipeline.execute(info, image, hints, null);
  350. }
  351. if (img == null) {
  352. throw new ImageException(
  353. "Cannot convert image " + image
  354. + " (no suitable converter combination available)");
  355. }
  356. return img;
  357. }
  358.  
  359. /**
  360. * Converts an image with no hints. See
  361. * {@link #convertImage(Image, ImageFlavor[], Map)} for more
  362. * information.
  363. * @param image the image to convert
  364. * @param flavors the requested image flavors (in preferred order).
  365. * @return the fully loaded image
  366. * @throws ImageException If no suitable loader/converter combination is available to fulfill
  367. * the request or if an error occurred while loading the image.
  368. * @throws IOException If an I/O error occurs
  369. */
  370. public Image convertImage(Image image, ImageFlavor[] flavors)
  371. throws ImageException, IOException {
  372. return convertImage(image, flavors, null);
  373. }
  374.  
  375. /**
  376. * Chooses the best {@link ImageProviderPipeline} from a set of candidates.
  377. * @param candidates the candidates
  378. * @return the best pipeline
  379. */
  380. public ImageProviderPipeline choosePipeline(ImageProviderPipeline[] candidates) {
  381. ImageProviderPipeline pipeline = null;
  382. int minPenalty = Integer.MAX_VALUE;
  383. int count = candidates.length;
  384.  
  385.  
  386. for (int i = count - 1; i >= 0; i--) {
  387. if (candidates[i] == null) {
  388. continue;
  389. }
  390. Penalty penalty = candidates[i].getConversionPenalty(getRegistry());
  391. if (penalty.isInfinitePenalty()) {
  392. continue; //Exclude candidate on infinite penalty
  393. }
  394. if (penalty.getValue() <= minPenalty) {
  395. pipeline = candidates[i];
  396. minPenalty = penalty.getValue();
  397. }
  398. }
  399.  
  400.  
  401. return pipeline;
  402. }
  403.  
  404. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement