IIOParam.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. /* IIOParam.java --
  2. Copyright (C) 2004 Free Software Foundation, Inc.
  3. This file is part of GNU Classpath.
  4. GNU Classpath is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. GNU Classpath is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Classpath; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. 02110-1301 USA.
  16. Linking this library statically or dynamically with other modules is
  17. making a combined work based on this library. Thus, the terms and
  18. conditions of the GNU General Public License cover the whole
  19. combination.
  20. As a special exception, the copyright holders of this library give you
  21. permission to link this library with independent modules to produce an
  22. executable, regardless of the license terms of these independent
  23. modules, and to copy and distribute the resulting executable under
  24. terms of your choice, provided that you also meet, for each linked
  25. independent module, the terms and conditions of the license of that
  26. module. An independent module is a module which is not derived from
  27. or based on this library. If you modify this library, you may extend
  28. this exception to your version of the library, but you are not
  29. obligated to do so. If you do not wish to do so, delete this
  30. exception statement from your version. */
  31. package javax.imageio;
  32. import java.awt.Point;
  33. import java.awt.Rectangle;
  34. /**
  35. * An IIOParam stores parameters used when encoding or decoding image
  36. * streams. ImageReadParam and ImageWriteParam extend this abstract
  37. * base class.
  38. *
  39. * IIOParams allow control over how source pixels converted into
  40. * destination pixels. This conversion can take place between a
  41. * stream and in-memory image data, when an image reader is doing the
  42. * conversion, or a writer can be doing the conversion from an
  43. * in-memory source to a stream destination.
  44. *
  45. * An image reader can be restricted to only read from a given region;
  46. * likewise a writer can be restricted to only write output to a given
  47. * region.
  48. *
  49. * For image readers and writers, IIOParam supports image pixelation
  50. * -- where the input image is approximated by the output image using
  51. * larger-sized pixel blocks. For example: FIXME
  52. *
  53. * IIOParams can control how pixels are combined into larger blocks
  54. * using sub-sampling matrices. For example: FIXME
  55. *
  56. * They can also control which source bands are read and written; this
  57. * example reads the RGBA (red, green, blue, transparency) data from a
  58. * PNG image and outputs just the red and transparency bands: FIXME
  59. *
  60. * @author Thomas Fitzsimmons (fitzsim@redhat.com)
  61. * @author Michael Koch (konqueror@gmx.de)
  62. */
  63. public abstract class IIOParam
  64. {
  65. /**
  66. * The controller called by this IIOParam to retrieve parameters.
  67. */
  68. protected IIOParamController controller = null;
  69. /**
  70. * The default controller called by this IIOParam to retrieve
  71. * parameters.
  72. */
  73. protected IIOParamController defaultController = null;
  74. /**
  75. * The offset in the destination where the upper-left
  76. * decoded/encoded pixel should be located.
  77. */
  78. protected Point destinationOffset = new Point(0, 0);
  79. /**
  80. * Sets the output colour type when writing or the destination image
  81. * type when reading.
  82. */
  83. protected ImageTypeSpecifier destinationType = null;
  84. /**
  85. * An array indicating which source bands will be used or null.
  86. */
  87. protected int[] sourceBands = null;
  88. /**
  89. * The source pixel region or null.
  90. */
  91. protected Rectangle sourceRegion = null;
  92. /**
  93. * Sample every sourceXSubsampling'th pixel in the source image when
  94. * pixelating the destination image in the horizontal direction.
  95. */
  96. protected int sourceXSubsampling = 1;
  97. /**
  98. * Sample every sourceYSubsampling'th pixel in the source image when
  99. * pixelating the destination image in the vertical direction.
  100. */
  101. protected int sourceYSubsampling = 1;
  102. /**
  103. * Start sampling at this horizontal offset within the source region
  104. * when pixelating the destination image in the horizontal
  105. * direction.
  106. */
  107. protected int subsamplingXOffset = 0;
  108. /**
  109. * Start sampling at this vertical offset within the source region
  110. * when pixelating the destination image in the vertical direction.
  111. */
  112. protected int subsamplingYOffset = 0;
  113. /**
  114. * Indicates whether or not the controller has been explicitly set
  115. * to null.
  116. */
  117. private boolean no_controller = false;
  118. /**
  119. * Constructs an IIOParam object.
  120. */
  121. protected IIOParam()
  122. {
  123. }
  124. /**
  125. * Activates the parameter controller by calling its activate method
  126. * and passing it this IIOParam. A true return value indicates that
  127. * this IIOParam's values are ready for the next read or write
  128. * operation. A return value of false means that this IIOParam's
  129. * values have not been affected because the controller operations
  130. * were cancelled.
  131. *
  132. * @return true if parameters were successfully set, false if
  133. * parameters were not changed
  134. */
  135. public boolean activateController()
  136. {
  137. if (controller == null)
  138. {
  139. if (defaultController == null || no_controller)
  140. return false;
  141. else
  142. return defaultController.activate (this);
  143. }
  144. else
  145. return controller.activate(this);
  146. }
  147. /**
  148. * Retrieve the currently set controller if one has been set, or the
  149. * default controller, or null if the controller has been explicitly
  150. * set to null.
  151. *
  152. * @return the currently used controller or null
  153. */
  154. public IIOParamController getController()
  155. {
  156. return controller == null ?
  157. (no_controller ? null : defaultController) : controller;
  158. }
  159. /**
  160. * Retrieve the default controller regardless of whether or not a
  161. * non-default controller has been set. The default controller may
  162. * be null.
  163. *
  164. * @return the default controller or null
  165. */
  166. public IIOParamController getDefaultController()
  167. {
  168. return defaultController;
  169. }
  170. /**
  171. * Retrieve the offset in the destination where the upper-left
  172. * decoded/encoded pixel should be located. (0, 0) by default.
  173. *
  174. * @return the destination offset
  175. */
  176. public Point getDestinationOffset()
  177. {
  178. return destinationOffset;
  179. }
  180. /**
  181. * Retrieve the currently set image-type specifier or null if none
  182. * has been set.
  183. *
  184. * @return the current image-type specifier or null
  185. */
  186. public ImageTypeSpecifier getDestinationType()
  187. {
  188. return destinationType;
  189. }
  190. /**
  191. * Retrieve the current source band values or null if source band
  192. * values have not been set.
  193. *
  194. * The returned array is a copy of this IIOParam's source band
  195. * array.
  196. *
  197. * @return the current set of source band values or null
  198. */
  199. public int[] getSourceBands()
  200. {
  201. if (sourceBands == null)
  202. return null;
  203. int[] sourceBandsCopy = new int[sourceBands.length];
  204. System.arraycopy (sourceBands, 0, sourceBandsCopy, 0, sourceBands.length);
  205. return sourceBandsCopy;
  206. }
  207. /**
  208. * Retrieve the source rectangle from which pixels should be read or
  209. * null if no source region has been set.
  210. *
  211. * @return the current source region or null
  212. */
  213. public Rectangle getSourceRegion()
  214. {
  215. return sourceRegion;
  216. }
  217. /**
  218. * Retrieve the number of pixel columns to advance before taking a
  219. * pixel sample.
  220. *
  221. * @return the horizontal sub-sampling interval
  222. */
  223. public int getSourceXSubsampling()
  224. {
  225. return sourceXSubsampling;
  226. }
  227. /**
  228. * Retrieve the number of pixel rows to advance before taking a
  229. * pixel sample.
  230. *
  231. * @return the vertical sub-sampling interval
  232. */
  233. public int getSourceYSubsampling()
  234. {
  235. return sourceYSubsampling;
  236. }
  237. /**
  238. * Retrieve the number of pixel columns to advance before taking any
  239. * pixel samples.
  240. *
  241. * @return the horizontal sub-sampling offset
  242. */
  243. public int getSubsamplingXOffset()
  244. {
  245. return subsamplingXOffset;
  246. }
  247. /**
  248. * Retrieve the number of pixel rows to advance before taking any
  249. * pixel samples.
  250. *
  251. * @return the vertical sub-sampling offset
  252. */
  253. public int getSubsamplingYOffset()
  254. {
  255. return subsamplingYOffset;
  256. }
  257. /**
  258. * Check if a non-null controller is currently available.
  259. *
  260. * @return true if getController returns a non-null value, false if
  261. * getController returns null
  262. */
  263. public boolean hasController()
  264. {
  265. return getController() != null;
  266. }
  267. /**
  268. * Sets the controller for this IIOParam. This is the controller
  269. * that will be activated when activateController is called. The
  270. * argument controller overrides this IIOParam's default controller.
  271. * If the argument is null then no controller will be set, not even
  272. * the default one. To reset the default controller call
  273. * setController(getDefaultController()).
  274. *
  275. * @param controller the controller to set or null
  276. */
  277. public void setController(IIOParamController controller)
  278. {
  279. if (controller == defaultController)
  280. {
  281. this.controller = null;
  282. no_controller = false;
  283. }
  284. else
  285. {
  286. no_controller = (controller == null);
  287. this.controller = controller;
  288. }
  289. }
  290. /**
  291. * Set the destination image type.
  292. *
  293. * If this value is set on an image reader then its read method will
  294. * return a new BufferedImage of the specified destination type. In
  295. * this case any destination image set using setDestination() is
  296. * ignored.
  297. *
  298. * If this is set on an image writer then the destination type
  299. * affects only the colour model of the destination image. The
  300. * destination type's SampleModel is ignored. The destination
  301. * type's ColorModel will override the source image's colour model.
  302. *
  303. * @param destinationType the sample and colour models of the
  304. * destination image
  305. */
  306. public void setDestinationType (ImageTypeSpecifier destinationType)
  307. {
  308. this.destinationType = destinationType;
  309. }
  310. /**
  311. * Specify the destination pixel offset. Image writers are only
  312. * affected by this setting when ImageWriter.replacePixels is called
  313. * in which case the offset is into the region of pixels being
  314. * changed.
  315. *
  316. * @param destinationOffset the offset where pixel writing should
  317. * begin
  318. */
  319. public void setDestinationOffset(Point destinationOffset)
  320. {
  321. if (destinationOffset == null)
  322. throw new IllegalArgumentException("destinationOffset is null");
  323. this.destinationOffset = destinationOffset;
  324. }
  325. /**
  326. * Set the indices of the source bands to be used. Duplicate
  327. * indices are not allowed. A value of null means use all source
  328. * bands. The argument array is copied and stored, so subsequent
  329. * updates to it will not be reflected in this IIOParam.
  330. *
  331. * @param sourceBands the array of source bands to use
  332. */
  333. public void setSourceBands(int[] sourceBands)
  334. {
  335. int[] sourceBandsCopy = new int[sourceBands.length];
  336. System.arraycopy (sourceBands, 0, sourceBandsCopy, 0, sourceBands.length);
  337. this.sourceBands = sourceBandsCopy;
  338. }
  339. /**
  340. * Set the source region from which to read. The number of pixels
  341. * sampled from the source region depends on the source sub-sampling
  342. * settings. If the combination of this sourceRegion and the
  343. * current sub-sampling settings would result in no pixels being
  344. * sampled then an IllegalStateException will be thrown.
  345. *
  346. * The source region is specified in the source image coordinate
  347. * system which has point (0, 0) at the top-left and increases down
  348. * and to the right. The argument source region is clipped to the
  349. * image boundaries at read-time.
  350. *
  351. * A null argument sets the source region to null meaning that the
  352. * whole image should be read.
  353. *
  354. * @param sourceRegion the rectangular source region
  355. *
  356. * @exception IllegalArgumentException if sourceRegion has width or
  357. * height <= 0 or x or y < 0
  358. * @exception IllegalStateException if the given sourceRegion and
  359. * the current sampling settings would produce zero samples
  360. */
  361. public void setSourceRegion(Rectangle sourceRegion)
  362. {
  363. if (sourceRegion != null
  364. && (sourceRegion.x < 0
  365. || sourceRegion.y < 0
  366. || sourceRegion.width <= 0
  367. || sourceRegion.height <= 0))
  368. throw new IllegalArgumentException("illegal source region");
  369. if (sourceRegion != null)
  370. {
  371. int num_rows =
  372. (sourceRegion.height - subsamplingYOffset + sourceYSubsampling - 1)
  373. / sourceYSubsampling;
  374. int num_columns =
  375. (sourceRegion.width - subsamplingXOffset + sourceXSubsampling - 1)
  376. / sourceXSubsampling;
  377. if (num_rows <= 0 || num_columns <= 0)
  378. throw new IllegalStateException("zero pixels in source region");
  379. }
  380. this.sourceRegion = sourceRegion;
  381. }
  382. /**
  383. * Set the source sampling intervals and offsets. Every
  384. * sourceXSubsampling'th pixel horizontally and
  385. * sourceYSubsampling'th pixel vertically will be sampled. Sampling
  386. * will being a the subsamplingXOffset'th column and the
  387. * subsamplingYOffset'th row.
  388. *
  389. * Horizontally, the number of sampled pixels will be:
  390. *
  391. * floor((width - subsamplingXOffset + sourceXSubsampling - 1) / sourceXSubsampling)
  392. *
  393. * Vertically:
  394. *
  395. * floor((height - subsamplingYOffset + sourceYSubsampling - 1) / sourceYSubsampling)
  396. *
  397. * If the current source region setting is such that the given
  398. * sub-sampling arguments would produce zero pixel samples, an
  399. * IllegalStateException is thrown.
  400. *
  401. * The offset parameters can be used to make source regions overlap
  402. * when tiling across an image. This can eliminate seams and
  403. * better-tile images whose width or height is not a multiple of the
  404. * sampling interval.
  405. *
  406. * @param sourceXSubsampling the horizontal sampling interval
  407. * @param sourceYSubsampling the vertical sampling interval
  408. * @param subsamplingXOffset the horizontal offset of the initial
  409. * sample
  410. * @param subsamplingYOffset the vertical offset of the initial
  411. * sample
  412. *
  413. * @exception IllegalArgumentException if either subsamplingXOffset
  414. * or subsamplingYOffset is < 0
  415. * @exception IllegalStateException if the current source region
  416. * combined with the given sub-sampling parameters would produce
  417. * zero pixel samples
  418. */
  419. public void setSourceSubsampling(int sourceXSubsampling, int sourceYSubsampling,
  420. int subsamplingXOffset, int subsamplingYOffset)
  421. {
  422. if (subsamplingXOffset < 0 || subsamplingYOffset < 0)
  423. throw new IllegalArgumentException("subsampling offset < 0");
  424. if (sourceRegion != null)
  425. {
  426. int num_rows =
  427. (sourceRegion.height - subsamplingYOffset + sourceYSubsampling - 1)
  428. / sourceYSubsampling;
  429. int num_columns =
  430. (sourceRegion.width - subsamplingXOffset + sourceXSubsampling - 1)
  431. / sourceXSubsampling;
  432. if (num_rows <= 0 || num_columns <= 0)
  433. throw new IllegalStateException("subsampling parameters would"
  434. + " produce zero pixel samples"
  435. + " in source region");
  436. }
  437. this.sourceXSubsampling = sourceXSubsampling;
  438. this.sourceYSubsampling = sourceYSubsampling;
  439. this.subsamplingXOffset = subsamplingXOffset;
  440. this.subsamplingYOffset = subsamplingYOffset;
  441. }
  442. }