YUVImage.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. /*
  2. * Copyright (C)2014, 2017 D. R. Commander. All Rights Reserved.
  3. * Copyright (C)2015 Viktor Szathmáry. All Rights Reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * - Redistributions of source code must retain the above copyright notice,
  9. * this list of conditions and the following disclaimer.
  10. * - Redistributions in binary form must reproduce the above copyright notice,
  11. * this list of conditions and the following disclaimer in the documentation
  12. * and/or other materials provided with the distribution.
  13. * - Neither the name of the libjpeg-turbo Project nor the names of its
  14. * contributors may be used to endorse or promote products derived from this
  15. * software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
  18. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  21. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  24. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  25. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  26. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. * POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. package org.libjpegturbo.turbojpeg;
  30. /**
  31. * This class encapsulates a YUV planar image and the metadata
  32. * associated with it. The TurboJPEG API allows both the JPEG compression and
  33. * decompression pipelines to be split into stages: YUV encode, compress from
  34. * YUV, decompress to YUV, and YUV decode. A <code>YUVImage</code> instance
  35. * serves as the destination image for YUV encode and decompress-to-YUV
  36. * operations and as the source image for compress-from-YUV and YUV decode
  37. * operations.
  38. * <p>
  39. * Technically, the JPEG format uses the YCbCr colorspace (which technically is
  40. * not a "colorspace" but rather a "color transform"), but per the convention
  41. * of the digital video community, the TurboJPEG API uses "YUV" to refer to an
  42. * image format consisting of Y, Cb, and Cr image planes.
  43. * <p>
  44. * Each plane is simply a 2D array of bytes, each byte representing the value
  45. * of one of the components (Y, Cb, or Cr) at a particular location in the
  46. * image. The width and height of each plane are determined by the image
  47. * width, height, and level of chrominance subsampling. The luminance plane
  48. * width is the image width padded to the nearest multiple of the horizontal
  49. * subsampling factor (2 in the case of 4:2:0 and 4:2:2, 4 in the case of
  50. * 4:1:1, 1 in the case of 4:4:4 or grayscale.) Similarly, the luminance plane
  51. * height is the image height padded to the nearest multiple of the vertical
  52. * subsampling factor (2 in the case of 4:2:0 or 4:4:0, 1 in the case of 4:4:4
  53. * or grayscale.) The chrominance plane width is equal to the luminance plane
  54. * width divided by the horizontal subsampling factor, and the chrominance
  55. * plane height is equal to the luminance plane height divided by the vertical
  56. * subsampling factor.
  57. * <p>
  58. * For example, if the source image is 35 x 35 pixels and 4:2:2 subsampling is
  59. * used, then the luminance plane would be 36 x 35 bytes, and each of the
  60. * chrominance planes would be 18 x 35 bytes. If you specify a line padding of
  61. * 4 bytes on top of this, then the luminance plane would be 36 x 35 bytes, and
  62. * each of the chrominance planes would be 20 x 35 bytes.
  63. */
  64. public class YUVImage {
  65. private static final String NO_ASSOC_ERROR =
  66. "No image data is associated with this instance";
  67. /**
  68. * Create a new <code>YUVImage</code> instance backed by separate image
  69. * planes, and allocate memory for the image planes.
  70. *
  71. * @param width width (in pixels) of the YUV image
  72. *
  73. * @param strides an array of integers, each specifying the number of bytes
  74. * per line in the corresponding plane of the YUV image. Setting the stride
  75. * for any plane to 0 is the same as setting it to the plane width (see
  76. * {@link YUVImage above}.) If <code>strides</code> is null, then the
  77. * strides for all planes will be set to their respective plane widths. When
  78. * using this constructor, the stride for each plane must be equal to or
  79. * greater than the plane width.
  80. *
  81. * @param height height (in pixels) of the YUV image
  82. *
  83. * @param subsamp the level of chrominance subsampling to be used in the YUV
  84. * image (one of {@link TJ#SAMP_444 TJ.SAMP_*})
  85. */
  86. public YUVImage(int width, int[] strides, int height, int subsamp) {
  87. setBuf(null, null, width, strides, height, subsamp, true);
  88. }
  89. /**
  90. * Create a new <code>YUVImage</code> instance backed by a unified image
  91. * buffer, and allocate memory for the image buffer.
  92. *
  93. * @param width width (in pixels) of the YUV image
  94. *
  95. * @param pad Each line of each plane in the YUV image buffer will be padded
  96. * to this number of bytes (must be a power of 2.)
  97. *
  98. * @param height height (in pixels) of the YUV image
  99. *
  100. * @param subsamp the level of chrominance subsampling to be used in the YUV
  101. * image (one of {@link TJ#SAMP_444 TJ.SAMP_*})
  102. */
  103. public YUVImage(int width, int pad, int height, int subsamp) {
  104. setBuf(new byte[TJ.bufSizeYUV(width, pad, height, subsamp)], width, pad,
  105. height, subsamp);
  106. }
  107. /**
  108. * Create a new <code>YUVImage</code> instance from a set of existing image
  109. * planes.
  110. *
  111. * @param planes an array of buffers representing the Y, U (Cb), and V (Cr)
  112. * image planes (or just the Y plane, if the image is grayscale.) These
  113. * planes can be contiguous or non-contiguous in memory. Plane
  114. * <code>i</code> should be at least <code>offsets[i] +
  115. * {@link TJ#planeSizeYUV TJ.planeSizeYUV}(i, width, strides[i], height, subsamp)</code>
  116. * bytes in size.
  117. *
  118. * @param offsets If this <code>YUVImage</code> instance represents a
  119. * subregion of a larger image, then <code>offsets[i]</code> specifies the
  120. * offset (in bytes) of the subregion within plane <code>i</code> of the
  121. * larger image. Setting this to null is the same as setting the offsets for
  122. * all planes to 0.
  123. *
  124. * @param width width (in pixels) of the new YUV image (or subregion)
  125. *
  126. * @param strides an array of integers, each specifying the number of bytes
  127. * per line in the corresponding plane of the YUV image. Setting the stride
  128. * for any plane to 0 is the same as setting it to the plane width (see
  129. * {@link YUVImage above}.) If <code>strides</code> is null, then the
  130. * strides for all planes will be set to their respective plane widths. You
  131. * can adjust the strides in order to add an arbitrary amount of line padding
  132. * to each plane or to specify that this <code>YUVImage</code> instance is a
  133. * subregion of a larger image (in which case, <code>strides[i]</code> should
  134. * be set to the plane width of plane <code>i</code> in the larger image.)
  135. *
  136. * @param height height (in pixels) of the new YUV image (or subregion)
  137. *
  138. * @param subsamp the level of chrominance subsampling used in the YUV
  139. * image (one of {@link TJ#SAMP_444 TJ.SAMP_*})
  140. */
  141. public YUVImage(byte[][] planes, int[] offsets, int width, int[] strides,
  142. int height, int subsamp) {
  143. setBuf(planes, offsets, width, strides, height, subsamp, false);
  144. }
  145. /**
  146. * Create a new <code>YUVImage</code> instance from an existing unified image
  147. * buffer.
  148. *
  149. * @param yuvImage image buffer that contains or will contain YUV planar
  150. * image data. Use {@link TJ#bufSizeYUV} to determine the minimum size for
  151. * this buffer. The Y, U (Cb), and V (Cr) image planes are stored
  152. * sequentially in the buffer (see {@link YUVImage above} for a description
  153. * of the image format.)
  154. *
  155. * @param width width (in pixels) of the YUV image
  156. *
  157. * @param pad the line padding used in the YUV image buffer. For
  158. * instance, if each line in each plane of the buffer is padded to the
  159. * nearest multiple of 4 bytes, then <code>pad</code> should be set to 4.
  160. *
  161. * @param height height (in pixels) of the YUV image
  162. *
  163. * @param subsamp the level of chrominance subsampling used in the YUV
  164. * image (one of {@link TJ#SAMP_444 TJ.SAMP_*})
  165. */
  166. public YUVImage(byte[] yuvImage, int width, int pad, int height,
  167. int subsamp) {
  168. setBuf(yuvImage, width, pad, height, subsamp);
  169. }
  170. /**
  171. * Assign a set of image planes to this <code>YUVImage</code> instance.
  172. *
  173. * @param planes an array of buffers representing the Y, U (Cb), and V (Cr)
  174. * image planes (or just the Y plane, if the image is grayscale.) These
  175. * planes can be contiguous or non-contiguous in memory. Plane
  176. * <code>i</code> should be at least <code>offsets[i] +
  177. * {@link TJ#planeSizeYUV TJ.planeSizeYUV}(i, width, strides[i], height, subsamp)</code>
  178. * bytes in size.
  179. *
  180. * @param offsets If this <code>YUVImage</code> instance represents a
  181. * subregion of a larger image, then <code>offsets[i]</code> specifies the
  182. * offset (in bytes) of the subregion within plane <code>i</code> of the
  183. * larger image. Setting this to null is the same as setting the offsets for
  184. * all planes to 0.
  185. *
  186. * @param width width (in pixels) of the YUV image (or subregion)
  187. *
  188. * @param strides an array of integers, each specifying the number of bytes
  189. * per line in the corresponding plane of the YUV image. Setting the stride
  190. * for any plane to 0 is the same as setting it to the plane width (see
  191. * {@link YUVImage above}.) If <code>strides</code> is null, then the
  192. * strides for all planes will be set to their respective plane widths. You
  193. * can adjust the strides in order to add an arbitrary amount of line padding
  194. * to each plane or to specify that this <code>YUVImage</code> image is a
  195. * subregion of a larger image (in which case, <code>strides[i]</code> should
  196. * be set to the plane width of plane <code>i</code> in the larger image.)
  197. *
  198. * @param height height (in pixels) of the YUV image (or subregion)
  199. *
  200. * @param subsamp the level of chrominance subsampling used in the YUV
  201. * image (one of {@link TJ#SAMP_444 TJ.SAMP_*})
  202. */
  203. public void setBuf(byte[][] planes, int[] offsets, int width, int[] strides,
  204. int height, int subsamp) {
  205. setBuf(planes, offsets, width, strides, height, subsamp, false);
  206. }
  207. private void setBuf(byte[][] planes, int[] offsets, int width, int[] strides,
  208. int height, int subsamp, boolean alloc) {
  209. if ((planes == null && !alloc) || width < 1 || height < 1 || subsamp < 0 ||
  210. subsamp >= TJ.NUMSAMP)
  211. throw new IllegalArgumentException("Invalid argument in YUVImage::setBuf()");
  212. int nc = (subsamp == TJ.SAMP_GRAY ? 1 : 3);
  213. if ((planes != null && planes.length != nc) ||
  214. (offsets != null && offsets.length != nc) ||
  215. (strides != null && strides.length != nc))
  216. throw new IllegalArgumentException("YUVImage::setBuf(): planes, offsets, or strides array is the wrong size");
  217. if (planes == null)
  218. planes = new byte[nc][];
  219. if (offsets == null)
  220. offsets = new int[nc];
  221. if (strides == null)
  222. strides = new int[nc];
  223. for (int i = 0; i < nc; i++) {
  224. int pw = TJ.planeWidth(i, width, subsamp);
  225. int ph = TJ.planeHeight(i, height, subsamp);
  226. int planeSize = TJ.planeSizeYUV(i, width, strides[i], height, subsamp);
  227. if (strides[i] == 0)
  228. strides[i] = pw;
  229. if (alloc) {
  230. if (strides[i] < pw)
  231. throw new IllegalArgumentException("Stride must be >= plane width when allocating a new YUV image");
  232. planes[i] = new byte[strides[i] * ph];
  233. }
  234. if (planes[i] == null || offsets[i] < 0)
  235. throw new IllegalArgumentException("Invalid argument in YUVImage::setBuf()");
  236. if (strides[i] < 0 && offsets[i] - planeSize + pw < 0)
  237. throw new IllegalArgumentException("Stride for plane " + i +
  238. " would cause memory to be accessed below plane boundary");
  239. if (planes[i].length < offsets[i] + planeSize)
  240. throw new IllegalArgumentException("Image plane " + i +
  241. " is not large enough");
  242. }
  243. yuvPlanes = planes;
  244. yuvOffsets = offsets;
  245. yuvWidth = width;
  246. yuvStrides = strides;
  247. yuvHeight = height;
  248. yuvSubsamp = subsamp;
  249. }
  250. /**
  251. * Assign a unified image buffer to this <code>YUVImage</code> instance.
  252. *
  253. * @param yuvImage image buffer that contains or will contain YUV planar
  254. * image data. Use {@link TJ#bufSizeYUV} to determine the minimum size for
  255. * this buffer. The Y, U (Cb), and V (Cr) image planes are stored
  256. * sequentially in the buffer (see {@link YUVImage above} for a description
  257. * of the image format.)
  258. *
  259. * @param width width (in pixels) of the YUV image
  260. *
  261. * @param pad the line padding used in the YUV image buffer. For
  262. * instance, if each line in each plane of the buffer is padded to the
  263. * nearest multiple of 4 bytes, then <code>pad</code> should be set to 4.
  264. *
  265. * @param height height (in pixels) of the YUV image
  266. *
  267. * @param subsamp the level of chrominance subsampling used in the YUV
  268. * image (one of {@link TJ#SAMP_444 TJ.SAMP_*})
  269. */
  270. public void setBuf(byte[] yuvImage, int width, int pad, int height,
  271. int subsamp) {
  272. if (yuvImage == null || width < 1 || pad < 1 || ((pad & (pad - 1)) != 0) ||
  273. height < 1 || subsamp < 0 || subsamp >= TJ.NUMSAMP)
  274. throw new IllegalArgumentException("Invalid argument in YUVImage::setBuf()");
  275. if (yuvImage.length < TJ.bufSizeYUV(width, pad, height, subsamp))
  276. throw new IllegalArgumentException("YUV image buffer is not large enough");
  277. int nc = (subsamp == TJ.SAMP_GRAY ? 1 : 3);
  278. byte[][] planes = new byte[nc][];
  279. int[] strides = new int[nc];
  280. int[] offsets = new int[nc];
  281. planes[0] = yuvImage;
  282. strides[0] = pad(TJ.planeWidth(0, width, subsamp), pad);
  283. if (subsamp != TJ.SAMP_GRAY) {
  284. strides[1] = strides[2] = pad(TJ.planeWidth(1, width, subsamp), pad);
  285. planes[1] = planes[2] = yuvImage;
  286. offsets[1] = offsets[0] +
  287. strides[0] * TJ.planeHeight(0, height, subsamp);
  288. offsets[2] = offsets[1] +
  289. strides[1] * TJ.planeHeight(1, height, subsamp);
  290. }
  291. yuvPad = pad;
  292. setBuf(planes, offsets, width, strides, height, subsamp);
  293. }
  294. /**
  295. * Returns the width of the YUV image (or subregion.)
  296. *
  297. * @return the width of the YUV image (or subregion)
  298. */
  299. public int getWidth() {
  300. if (yuvWidth < 1)
  301. throw new IllegalStateException(NO_ASSOC_ERROR);
  302. return yuvWidth;
  303. }
  304. /**
  305. * Returns the height of the YUV image (or subregion.)
  306. *
  307. * @return the height of the YUV image (or subregion)
  308. */
  309. public int getHeight() {
  310. if (yuvHeight < 1)
  311. throw new IllegalStateException(NO_ASSOC_ERROR);
  312. return yuvHeight;
  313. }
  314. /**
  315. * Returns the line padding used in the YUV image buffer (if this image is
  316. * stored in a unified buffer rather than separate image planes.)
  317. *
  318. * @return the line padding used in the YUV image buffer
  319. */
  320. public int getPad() {
  321. if (yuvPlanes == null)
  322. throw new IllegalStateException(NO_ASSOC_ERROR);
  323. if (yuvPad < 1 || ((yuvPad & (yuvPad - 1)) != 0))
  324. throw new IllegalStateException("Image is not stored in a unified buffer");
  325. return yuvPad;
  326. }
  327. /**
  328. * Returns the number of bytes per line of each plane in the YUV image.
  329. *
  330. * @return the number of bytes per line of each plane in the YUV image
  331. */
  332. public int[] getStrides() {
  333. if (yuvStrides == null)
  334. throw new IllegalStateException(NO_ASSOC_ERROR);
  335. return yuvStrides;
  336. }
  337. /**
  338. * Returns the offsets (in bytes) of each plane within the planes of a larger
  339. * YUV image.
  340. *
  341. * @return the offsets (in bytes) of each plane within the planes of a larger
  342. * YUV image
  343. */
  344. public int[] getOffsets() {
  345. if (yuvOffsets == null)
  346. throw new IllegalStateException(NO_ASSOC_ERROR);
  347. return yuvOffsets;
  348. }
  349. /**
  350. * Returns the level of chrominance subsampling used in the YUV image. See
  351. * {@link TJ#SAMP_444 TJ.SAMP_*}.
  352. *
  353. * @return the level of chrominance subsampling used in the YUV image
  354. */
  355. public int getSubsamp() {
  356. if (yuvSubsamp < 0 || yuvSubsamp >= TJ.NUMSAMP)
  357. throw new IllegalStateException(NO_ASSOC_ERROR);
  358. return yuvSubsamp;
  359. }
  360. /**
  361. * Returns the YUV image planes. If the image is stored in a unified buffer,
  362. * then all image planes will point to that buffer.
  363. *
  364. * @return the YUV image planes
  365. */
  366. public byte[][] getPlanes() {
  367. if (yuvPlanes == null)
  368. throw new IllegalStateException(NO_ASSOC_ERROR);
  369. return yuvPlanes;
  370. }
  371. /**
  372. * Returns the YUV image buffer (if this image is stored in a unified
  373. * buffer rather than separate image planes.)
  374. *
  375. * @return the YUV image buffer
  376. */
  377. public byte[] getBuf() {
  378. if (yuvPlanes == null || yuvSubsamp < 0 || yuvSubsamp >= TJ.NUMSAMP)
  379. throw new IllegalStateException(NO_ASSOC_ERROR);
  380. int nc = (yuvSubsamp == TJ.SAMP_GRAY ? 1 : 3);
  381. for (int i = 1; i < nc; i++) {
  382. if (yuvPlanes[i] != yuvPlanes[0])
  383. throw new IllegalStateException("Image is not stored in a unified buffer");
  384. }
  385. return yuvPlanes[0];
  386. }
  387. /**
  388. * Returns the size (in bytes) of the YUV image buffer (if this image is
  389. * stored in a unified buffer rather than separate image planes.)
  390. *
  391. * @return the size (in bytes) of the YUV image buffer
  392. */
  393. public int getSize() {
  394. if (yuvPlanes == null || yuvSubsamp < 0 || yuvSubsamp >= TJ.NUMSAMP)
  395. throw new IllegalStateException(NO_ASSOC_ERROR);
  396. int nc = (yuvSubsamp == TJ.SAMP_GRAY ? 1 : 3);
  397. if (yuvPad < 1)
  398. throw new IllegalStateException("Image is not stored in a unified buffer");
  399. for (int i = 1; i < nc; i++) {
  400. if (yuvPlanes[i] != yuvPlanes[0])
  401. throw new IllegalStateException("Image is not stored in a unified buffer");
  402. }
  403. return TJ.bufSizeYUV(yuvWidth, yuvPad, yuvHeight, yuvSubsamp);
  404. }
  405. private static int pad(int v, int p) {
  406. return (v + p - 1) & (~(p - 1));
  407. }
  408. protected long handle = 0;
  409. protected byte[][] yuvPlanes = null;
  410. protected int[] yuvOffsets = null;
  411. protected int[] yuvStrides = null;
  412. protected int yuvPad = 0;
  413. protected int yuvWidth = 0;
  414. protected int yuvHeight = 0;
  415. protected int yuvSubsamp = -1;
  416. }