PageRenderTime 69ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/Eclipse SWT/common/org/eclipse/swt/graphics/ImageData.java

https://github.com/skovatch/org.eclipse.swt
Java | 3673 lines | 2670 code | 121 blank | 882 comment | 785 complexity | b656a716b49b1fd3c15da18f8f757e1a MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*******************************************************************************
  2. * Copyright (c) 2000, 2009 IBM Corporation and others.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors:
  9. * IBM Corporation - initial API and implementation
  10. *******************************************************************************/
  11. package org.eclipse.swt.graphics;
  12. import java.io.*;
  13. import org.eclipse.swt.*;
  14. import org.eclipse.swt.internal.CloneableCompatibility;
  15. /**
  16. * Instances of this class are device-independent descriptions
  17. * of images. They are typically used as an intermediate format
  18. * between loading from or writing to streams and creating an
  19. * <code>Image</code>.
  20. * <p>
  21. * Note that the public fields <code>x</code>, <code>y</code>,
  22. * <code>disposalMethod</code> and <code>delayTime</code> are
  23. * typically only used when the image is in a set of images used
  24. * for animation.
  25. * </p>
  26. *
  27. * @see Image
  28. * @see ImageLoader
  29. * @see <a href="http://www.eclipse.org/swt/snippets/#image">ImageData snippets</a>
  30. * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ImageAnalyzer</a>
  31. * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
  32. */
  33. public final class ImageData implements CloneableCompatibility {
  34. /**
  35. * The width of the image, in pixels.
  36. */
  37. public int width;
  38. /**
  39. * The height of the image, in pixels.
  40. */
  41. public int height;
  42. /**
  43. * The color depth of the image, in bits per pixel.
  44. * <p>
  45. * Note that a depth of 8 or less does not necessarily
  46. * mean that the image is palette indexed, or
  47. * conversely that a depth greater than 8 means that
  48. * the image is direct color. Check the associated
  49. * PaletteData's isDirect field for such determinations.
  50. */
  51. public int depth;
  52. /**
  53. * The scanline padding.
  54. * <p>
  55. * If one scanline of the image is not a multiple of
  56. * this number, it will be padded with zeros until it is.
  57. * </p>
  58. */
  59. public int scanlinePad;
  60. /**
  61. * The number of bytes per scanline.
  62. * <p>
  63. * This is a multiple of the scanline padding.
  64. * </p>
  65. */
  66. public int bytesPerLine;
  67. /**
  68. * The pixel data of the image.
  69. * <p>
  70. * Note that for 16 bit depth images the pixel data is stored
  71. * in least significant byte order; however, for 24bit and
  72. * 32bit depth images the pixel data is stored in most
  73. * significant byte order.
  74. * </p>
  75. */
  76. public byte[] data;
  77. /**
  78. * The color table for the image.
  79. */
  80. public PaletteData palette;
  81. /**
  82. * The transparent pixel.
  83. * <p>
  84. * Pixels with this value are transparent.
  85. * </p><p>
  86. * The default is -1 which means 'no transparent pixel'.
  87. * </p>
  88. */
  89. public int transparentPixel;
  90. /**
  91. * An icon-specific field containing the data from the icon mask.
  92. * <p>
  93. * This is a 1 bit bitmap stored with the most significant
  94. * bit first. The number of bytes per scanline is
  95. * '((width + 7) / 8 + (maskPad - 1)) / maskPad * maskPad'.
  96. * </p><p>
  97. * The default is null which means 'no transparency mask'.
  98. * </p>
  99. */
  100. public byte[] maskData;
  101. /**
  102. * An icon-specific field containing the scanline pad of the mask.
  103. * <p>
  104. * If one scanline of the transparency mask is not a
  105. * multiple of this number, it will be padded with zeros until
  106. * it is.
  107. * </p>
  108. */
  109. public int maskPad;
  110. /**
  111. * The alpha data of the image.
  112. * <p>
  113. * Every pixel can have an <em>alpha blending</em> value that
  114. * varies from 0, meaning fully transparent, to 255 meaning
  115. * fully opaque. The number of bytes per scanline is
  116. * 'width'.
  117. * </p>
  118. */
  119. public byte[] alphaData;
  120. /**
  121. * The global alpha value to be used for every pixel.
  122. * <p>
  123. * If this value is set, the <code>alphaData</code> field
  124. * is ignored and when the image is rendered each pixel
  125. * will be blended with the background an amount
  126. * proportional to this value.
  127. * </p><p>
  128. * The default is -1 which means 'no global alpha value'
  129. * </p>
  130. */
  131. public int alpha;
  132. /**
  133. * The type of file from which the image was read.
  134. *
  135. * It is expressed as one of the following values:
  136. * <dl>
  137. * <dt><code>IMAGE_BMP</code></dt>
  138. * <dd>Windows BMP file format, no compression</dd>
  139. * <dt><code>IMAGE_BMP_RLE</code></dt>
  140. * <dd>Windows BMP file format, RLE compression if appropriate</dd>
  141. * <dt><code>IMAGE_GIF</code></dt>
  142. * <dd>GIF file format</dd>
  143. * <dt><code>IMAGE_ICO</code></dt>
  144. * <dd>Windows ICO file format</dd>
  145. * <dt><code>IMAGE_JPEG</code></dt>
  146. * <dd>JPEG file format</dd>
  147. * <dt><code>IMAGE_PNG</code></dt>
  148. * <dd>PNG file format</dd>
  149. * </dl>
  150. */
  151. public int type;
  152. /**
  153. * The x coordinate of the top left corner of the image
  154. * within the logical screen (this field corresponds to
  155. * the GIF89a Image Left Position value).
  156. */
  157. public int x;
  158. /**
  159. * The y coordinate of the top left corner of the image
  160. * within the logical screen (this field corresponds to
  161. * the GIF89a Image Top Position value).
  162. */
  163. public int y;
  164. /**
  165. * A description of how to dispose of the current image
  166. * before displaying the next.
  167. *
  168. * It is expressed as one of the following values:
  169. * <dl>
  170. * <dt><code>DM_UNSPECIFIED</code></dt>
  171. * <dd>disposal method not specified</dd>
  172. * <dt><code>DM_FILL_NONE</code></dt>
  173. * <dd>do nothing - leave the image in place</dd>
  174. * <dt><code>DM_FILL_BACKGROUND</code></dt>
  175. * <dd>fill with the background color</dd>
  176. * <dt><code>DM_FILL_PREVIOUS</code></dt>
  177. * <dd>restore the previous picture</dd>
  178. * </dl>
  179. * (this field corresponds to the GIF89a Disposal Method value)
  180. */
  181. public int disposalMethod;
  182. /**
  183. * The time to delay before displaying the next image
  184. * in an animation (this field corresponds to the GIF89a
  185. * Delay Time value).
  186. */
  187. public int delayTime;
  188. /**
  189. * Arbitrary channel width data to 8-bit conversion table.
  190. */
  191. static final byte[][] ANY_TO_EIGHT = new byte[9][];
  192. static {
  193. for (int b = 0; b < 9; ++b) {
  194. byte[] data = ANY_TO_EIGHT[b] = new byte[1 << b];
  195. if (b == 0) continue;
  196. int inc = 0;
  197. for (int bit = 0x10000; (bit >>= b) != 0;) inc |= bit;
  198. for (int v = 0, p = 0; v < 0x10000; v+= inc) data[p++] = (byte)(v >> 8);
  199. }
  200. }
  201. static final byte[] ONE_TO_ONE_MAPPING = ANY_TO_EIGHT[8];
  202. /**
  203. * Scaled 8x8 Bayer dither matrix.
  204. */
  205. static final int[][] DITHER_MATRIX = {
  206. { 0xfc0000, 0x7c0000, 0xdc0000, 0x5c0000, 0xf40000, 0x740000, 0xd40000, 0x540000 },
  207. { 0x3c0000, 0xbc0000, 0x1c0000, 0x9c0000, 0x340000, 0xb40000, 0x140000, 0x940000 },
  208. { 0xcc0000, 0x4c0000, 0xec0000, 0x6c0000, 0xc40000, 0x440000, 0xe40000, 0x640000 },
  209. { 0x0c0000, 0x8c0000, 0x2c0000, 0xac0000, 0x040000, 0x840000, 0x240000, 0xa40000 },
  210. { 0xf00000, 0x700000, 0xd00000, 0x500000, 0xf80000, 0x780000, 0xd80000, 0x580000 },
  211. { 0x300000, 0xb00000, 0x100000, 0x900000, 0x380000, 0xb80000, 0x180000, 0x980000 },
  212. { 0xc00000, 0x400000, 0xe00000, 0x600000, 0xc80000, 0x480000, 0xe80000, 0x680000 },
  213. { 0x000000, 0x800000, 0x200000, 0xa00000, 0x080000, 0x880000, 0x280000, 0xa80000 }
  214. };
  215. /**
  216. * Constructs a new, empty ImageData with the given width, height,
  217. * depth and palette. The data will be initialized to an (all zero)
  218. * array of the appropriate size.
  219. *
  220. * @param width the width of the image
  221. * @param height the height of the image
  222. * @param depth the depth of the image
  223. * @param palette the palette of the image (must not be null)
  224. *
  225. * @exception IllegalArgumentException <ul>
  226. * <li>ERROR_INVALID_ARGUMENT - if the width or height is zero or negative, or if the depth is not
  227. * one of 1, 2, 4, 8, 16, 24 or 32</li>
  228. * <li>ERROR_NULL_ARGUMENT - if the palette is null</li>
  229. * </ul>
  230. */
  231. public ImageData(int width, int height, int depth, PaletteData palette) {
  232. this(width, height, depth, palette,
  233. 4, null, 0, null,
  234. null, -1, -1, SWT.IMAGE_UNDEFINED,
  235. 0, 0, 0, 0);
  236. }
  237. /**
  238. * Constructs a new, empty ImageData with the given width, height,
  239. * depth, palette, scanlinePad and data.
  240. *
  241. * @param width the width of the image
  242. * @param height the height of the image
  243. * @param depth the depth of the image
  244. * @param palette the palette of the image
  245. * @param scanlinePad the padding of each line, in bytes
  246. * @param data the data of the image
  247. *
  248. * @exception IllegalArgumentException <ul>
  249. * <li>ERROR_INVALID_ARGUMENT - if the width or height is zero or negative, or if the depth is not
  250. * one of 1, 2, 4, 8, 16, 24 or 32, or the data array is too small to contain the image data</li>
  251. * <li>ERROR_NULL_ARGUMENT - if the palette or data is null</li>
  252. * <li>ERROR_CANNOT_BE_ZERO - if the scanlinePad is zero</li>
  253. * </ul>
  254. */
  255. public ImageData(int width, int height, int depth, PaletteData palette, int scanlinePad, byte[] data) {
  256. this(width, height, depth, palette,
  257. scanlinePad, checkData(data), 0, null,
  258. null, -1, -1, SWT.IMAGE_UNDEFINED,
  259. 0, 0, 0, 0);
  260. }
  261. /**
  262. * Constructs an <code>ImageData</code> loaded from the specified
  263. * input stream. Throws an error if an error occurs while loading
  264. * the image, or if the image has an unsupported type. Application
  265. * code is still responsible for closing the input stream.
  266. * <p>
  267. * This constructor is provided for convenience when loading a single
  268. * image only. If the stream contains multiple images, only the first
  269. * one will be loaded. To load multiple images, use
  270. * <code>ImageLoader.load()</code>.
  271. * </p><p>
  272. * This constructor may be used to load a resource as follows:
  273. * </p>
  274. * <pre>
  275. * static ImageData loadImageData (Class clazz, String string) {
  276. * InputStream stream = clazz.getResourceAsStream (string);
  277. * if (stream == null) return null;
  278. * ImageData imageData = null;
  279. * try {
  280. * imageData = new ImageData (stream);
  281. * } catch (SWTException ex) {
  282. * } finally {
  283. * try {
  284. * stream.close ();
  285. * } catch (IOException ex) {}
  286. * }
  287. * return imageData;
  288. * }
  289. * </pre>
  290. *
  291. * @param stream the input stream to load the image from (must not be null)
  292. *
  293. * @exception IllegalArgumentException <ul>
  294. * <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
  295. * </ul>
  296. * @exception SWTException <ul>
  297. * <li>ERROR_IO - if an IO error occurs while reading from the stream</li>
  298. * <li>ERROR_INVALID_IMAGE - if the image stream contains invalid data</li>
  299. * <li>ERROR_UNSUPPORTED_FORMAT - if the image stream contains an unrecognized format</li>
  300. * </ul>
  301. *
  302. * @see ImageLoader#load(InputStream)
  303. */
  304. public ImageData(InputStream stream) {
  305. ImageData[] data = ImageDataLoader.load(stream);
  306. if (data.length < 1) SWT.error(SWT.ERROR_INVALID_IMAGE);
  307. ImageData i = data[0];
  308. setAllFields(
  309. i.width,
  310. i.height,
  311. i.depth,
  312. i.scanlinePad,
  313. i.bytesPerLine,
  314. i.data,
  315. i.palette,
  316. i.transparentPixel,
  317. i.maskData,
  318. i.maskPad,
  319. i.alphaData,
  320. i.alpha,
  321. i.type,
  322. i.x,
  323. i.y,
  324. i.disposalMethod,
  325. i.delayTime);
  326. }
  327. /**
  328. * Constructs an <code>ImageData</code> loaded from a file with the
  329. * specified name. Throws an error if an error occurs loading the
  330. * image, or if the image has an unsupported type.
  331. * <p>
  332. * This constructor is provided for convenience when loading a single
  333. * image only. If the file contains multiple images, only the first
  334. * one will be loaded. To load multiple images, use
  335. * <code>ImageLoader.load()</code>.
  336. * </p>
  337. *
  338. * @param filename the name of the file to load the image from (must not be null)
  339. *
  340. * @exception IllegalArgumentException <ul>
  341. * <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
  342. * </ul>
  343. * @exception SWTException <ul>
  344. * <li>ERROR_IO - if an IO error occurs while reading from the file</li>
  345. * <li>ERROR_INVALID_IMAGE - if the image file contains invalid data</li>
  346. * <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
  347. * </ul>
  348. */
  349. public ImageData(String filename) {
  350. ImageData[] data = ImageDataLoader.load(filename);
  351. if (data.length < 1) SWT.error(SWT.ERROR_INVALID_IMAGE);
  352. ImageData i = data[0];
  353. setAllFields(
  354. i.width,
  355. i.height,
  356. i.depth,
  357. i.scanlinePad,
  358. i.bytesPerLine,
  359. i.data,
  360. i.palette,
  361. i.transparentPixel,
  362. i.maskData,
  363. i.maskPad,
  364. i.alphaData,
  365. i.alpha,
  366. i.type,
  367. i.x,
  368. i.y,
  369. i.disposalMethod,
  370. i.delayTime);
  371. }
  372. /**
  373. * Prevents uninitialized instances from being created outside the package.
  374. */
  375. ImageData() {
  376. }
  377. /**
  378. * Constructs an image data by giving values for all non-computable fields.
  379. * <p>
  380. * This method is for internal use, and is not described further.
  381. * </p>
  382. */
  383. ImageData(
  384. int width, int height, int depth, PaletteData palette,
  385. int scanlinePad, byte[] data, int maskPad, byte[] maskData,
  386. byte[] alphaData, int alpha, int transparentPixel, int type,
  387. int x, int y, int disposalMethod, int delayTime)
  388. {
  389. if (palette == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
  390. if (!(depth == 1 || depth == 2 || depth == 4 || depth == 8
  391. || depth == 16 || depth == 24 || depth == 32)) {
  392. SWT.error(SWT.ERROR_INVALID_ARGUMENT);
  393. }
  394. if (width <= 0 || height <= 0) {
  395. SWT.error(SWT.ERROR_INVALID_ARGUMENT);
  396. }
  397. if (scanlinePad == 0) SWT.error (SWT.ERROR_CANNOT_BE_ZERO);
  398. int bytesPerLine = (((width * depth + 7) / 8) + (scanlinePad - 1))
  399. / scanlinePad * scanlinePad;
  400. /*
  401. * When the image is being loaded from a PNG, we need to use the theoretical minimum
  402. * number of bytes per line to check whether there is enough data, because the actual
  403. * number of bytes per line is calculated based on the given depth, which may be larger
  404. * than the actual depth of the PNG.
  405. */
  406. int minBytesPerLine = type == SWT.IMAGE_PNG ? ((((width + 7) / 8) + 3) / 4) * 4 : bytesPerLine;
  407. if (data != null && data.length < minBytesPerLine * height) {
  408. SWT.error(SWT.ERROR_INVALID_ARGUMENT);
  409. }
  410. setAllFields(
  411. width,
  412. height,
  413. depth,
  414. scanlinePad,
  415. bytesPerLine,
  416. data != null ? data : new byte[bytesPerLine * height],
  417. palette,
  418. transparentPixel,
  419. maskData,
  420. maskPad,
  421. alphaData,
  422. alpha,
  423. type,
  424. x,
  425. y,
  426. disposalMethod,
  427. delayTime);
  428. }
  429. /**
  430. * Initializes all fields in the receiver. This method must be called
  431. * by all public constructors to ensure that all fields are initialized
  432. * for a new ImageData object. If a new field is added to the class,
  433. * then it must be added to this method.
  434. * <p>
  435. * This method is for internal use, and is not described further.
  436. * </p>
  437. */
  438. void setAllFields(int width, int height, int depth, int scanlinePad,
  439. int bytesPerLine, byte[] data, PaletteData palette, int transparentPixel,
  440. byte[] maskData, int maskPad, byte[] alphaData, int alpha,
  441. int type, int x, int y, int disposalMethod, int delayTime) {
  442. this.width = width;
  443. this.height = height;
  444. this.depth = depth;
  445. this.scanlinePad = scanlinePad;
  446. this.bytesPerLine = bytesPerLine;
  447. this.data = data;
  448. this.palette = palette;
  449. this.transparentPixel = transparentPixel;
  450. this.maskData = maskData;
  451. this.maskPad = maskPad;
  452. this.alphaData = alphaData;
  453. this.alpha = alpha;
  454. this.type = type;
  455. this.x = x;
  456. this.y = y;
  457. this.disposalMethod = disposalMethod;
  458. this.delayTime = delayTime;
  459. }
  460. /**
  461. * Invokes internal SWT functionality to create a new instance of
  462. * this class.
  463. * <p>
  464. * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
  465. * API for <code>ImageData</code>. It is marked public only so that it
  466. * can be shared within the packages provided by SWT. It is subject
  467. * to change without notice, and should never be called from
  468. * application code.
  469. * </p>
  470. * <p>
  471. * This method is for internal use, and is not described further.
  472. * </p>
  473. */
  474. public static ImageData internal_new(
  475. int width, int height, int depth, PaletteData palette,
  476. int scanlinePad, byte[] data, int maskPad, byte[] maskData,
  477. byte[] alphaData, int alpha, int transparentPixel, int type,
  478. int x, int y, int disposalMethod, int delayTime)
  479. {
  480. return new ImageData(
  481. width, height, depth, palette, scanlinePad, data, maskPad, maskData,
  482. alphaData, alpha, transparentPixel, type, x, y, disposalMethod, delayTime);
  483. }
  484. ImageData colorMaskImage(int pixel) {
  485. ImageData mask = new ImageData(width, height, 1, bwPalette(),
  486. 2, null, 0, null, null, -1, -1, SWT.IMAGE_UNDEFINED,
  487. 0, 0, 0, 0);
  488. int[] row = new int[width];
  489. for (int y = 0; y < height; y++) {
  490. getPixels(0, y, width, row, 0);
  491. for (int i = 0; i < width; i++) {
  492. if (pixel != -1 && row[i] == pixel) {
  493. row[i] = 0;
  494. } else {
  495. row[i] = 1;
  496. }
  497. }
  498. mask.setPixels(0, y, width, row, 0);
  499. }
  500. return mask;
  501. }
  502. static byte[] checkData(byte [] data) {
  503. if (data == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
  504. return data;
  505. }
  506. /**
  507. * Returns a new instance of the same class as the receiver,
  508. * whose slots have been filled in with <em>copies</em> of
  509. * the values in the slots of the receiver. That is, the
  510. * returned object is a <em>deep copy</em> of the receiver.
  511. *
  512. * @return a copy of the receiver.
  513. */
  514. public Object clone() {
  515. byte[] cloneData = new byte[data.length];
  516. System.arraycopy(data, 0, cloneData, 0, data.length);
  517. byte[] cloneMaskData = null;
  518. if (maskData != null) {
  519. cloneMaskData = new byte[maskData.length];
  520. System.arraycopy(maskData, 0, cloneMaskData, 0, maskData.length);
  521. }
  522. byte[] cloneAlphaData = null;
  523. if (alphaData != null) {
  524. cloneAlphaData = new byte[alphaData.length];
  525. System.arraycopy(alphaData, 0, cloneAlphaData, 0, alphaData.length);
  526. }
  527. return new ImageData(
  528. width,
  529. height,
  530. depth,
  531. palette,
  532. scanlinePad,
  533. cloneData,
  534. maskPad,
  535. cloneMaskData,
  536. cloneAlphaData,
  537. alpha,
  538. transparentPixel,
  539. type,
  540. x,
  541. y,
  542. disposalMethod,
  543. delayTime);
  544. }
  545. /**
  546. * Returns the alpha value at offset <code>x</code> in
  547. * scanline <code>y</code> in the receiver's alpha data.
  548. * The alpha value is between 0 (transparent) and
  549. * 255 (opaque).
  550. *
  551. * @param x the x coordinate of the pixel to get the alpha value of
  552. * @param y the y coordinate of the pixel to get the alpha value of
  553. * @return the alpha value at the given coordinates
  554. *
  555. * @exception IllegalArgumentException <ul>
  556. * <li>ERROR_INVALID_ARGUMENT - if either argument is out of range</li>
  557. * </ul>
  558. */
  559. public int getAlpha(int x, int y) {
  560. if (x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
  561. if (alphaData == null) return 255;
  562. return alphaData[y * width + x] & 0xFF;
  563. }
  564. /**
  565. * Returns <code>getWidth</code> alpha values starting at offset
  566. * <code>x</code> in scanline <code>y</code> in the receiver's alpha
  567. * data starting at <code>startIndex</code>. The alpha values
  568. * are unsigned, between <code>(byte)0</code> (transparent) and
  569. * <code>(byte)255</code> (opaque).
  570. *
  571. * @param x the x position of the pixel to begin getting alpha values
  572. * @param y the y position of the pixel to begin getting alpha values
  573. * @param getWidth the width of the data to get
  574. * @param alphas the buffer in which to put the alpha values
  575. * @param startIndex the offset into the image to begin getting alpha values
  576. *
  577. * @exception IndexOutOfBoundsException if getWidth is too large
  578. * @exception IllegalArgumentException <ul>
  579. * <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
  580. * <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
  581. * <li>ERROR_INVALID_ARGUMENT - if getWidth is negative</li>
  582. * </ul>
  583. */
  584. public void getAlphas(int x, int y, int getWidth, byte[] alphas, int startIndex) {
  585. if (alphas == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
  586. if (getWidth < 0 || x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
  587. if (getWidth == 0) return;
  588. if (alphaData == null) {
  589. int endIndex = startIndex + getWidth;
  590. for (int i = startIndex; i < endIndex; i++) {
  591. alphas[i] = (byte)255;
  592. }
  593. return;
  594. }
  595. // may throw an IndexOutOfBoundsException
  596. System.arraycopy(alphaData, y * width + x, alphas, startIndex, getWidth);
  597. }
  598. /**
  599. * Returns the pixel value at offset <code>x</code> in
  600. * scanline <code>y</code> in the receiver's data.
  601. *
  602. * @param x the x position of the pixel to get
  603. * @param y the y position of the pixel to get
  604. * @return the pixel at the given coordinates
  605. *
  606. * @exception IllegalArgumentException <ul>
  607. * <li>ERROR_INVALID_ARGUMENT - if either argument is out of bounds</li>
  608. * </ul>
  609. * @exception SWTException <ul>
  610. * <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
  611. * </ul>
  612. */
  613. public int getPixel(int x, int y) {
  614. if (x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
  615. int index;
  616. int theByte;
  617. int mask;
  618. switch (depth) {
  619. case 32:
  620. index = (y * bytesPerLine) + (x * 4);
  621. return ((data[index] & 0xFF) << 24) + ((data[index+1] & 0xFF) << 16) +
  622. ((data[index+2] & 0xFF) << 8) + (data[index+3] & 0xFF);
  623. case 24:
  624. index = (y * bytesPerLine) + (x * 3);
  625. return ((data[index] & 0xFF) << 16) + ((data[index+1] & 0xFF) << 8) +
  626. (data[index+2] & 0xFF);
  627. case 16:
  628. index = (y * bytesPerLine) + (x * 2);
  629. return ((data[index+1] & 0xFF) << 8) + (data[index] & 0xFF);
  630. case 8:
  631. index = (y * bytesPerLine) + x ;
  632. return data[index] & 0xFF;
  633. case 4:
  634. index = (y * bytesPerLine) + (x >> 1);
  635. theByte = data[index] & 0xFF;
  636. if ((x & 0x1) == 0) {
  637. return theByte >> 4;
  638. } else {
  639. return theByte & 0x0F;
  640. }
  641. case 2:
  642. index = (y * bytesPerLine) + (x >> 2);
  643. theByte = data[index] & 0xFF;
  644. int offset = 3 - (x % 4);
  645. mask = 3 << (offset * 2);
  646. return (theByte & mask) >> (offset * 2);
  647. case 1:
  648. index = (y * bytesPerLine) + (x >> 3);
  649. theByte = data[index] & 0xFF;
  650. mask = 1 << (7 - (x & 0x7));
  651. if ((theByte & mask) == 0) {
  652. return 0;
  653. } else {
  654. return 1;
  655. }
  656. }
  657. SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
  658. return 0;
  659. }
  660. /**
  661. * Returns <code>getWidth</code> pixel values starting at offset
  662. * <code>x</code> in scanline <code>y</code> in the receiver's
  663. * data starting at <code>startIndex</code>.
  664. *
  665. * @param x the x position of the first pixel to get
  666. * @param y the y position of the first pixel to get
  667. * @param getWidth the width of the data to get
  668. * @param pixels the buffer in which to put the pixels
  669. * @param startIndex the offset into the byte array to begin storing pixels
  670. *
  671. * @exception IndexOutOfBoundsException if getWidth is too large
  672. * @exception IllegalArgumentException <ul>
  673. * <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
  674. * <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
  675. * <li>ERROR_INVALID_ARGUMENT - if getWidth is negative</li>
  676. * </ul>
  677. * @exception SWTException <ul>
  678. * <li>ERROR_UNSUPPORTED_DEPTH - if the depth is not one of 1, 2, 4 or 8
  679. * (For higher depths, use the int[] version of this method.)</li>
  680. * </ul>
  681. */
  682. public void getPixels(int x, int y, int getWidth, byte[] pixels, int startIndex) {
  683. if (pixels == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
  684. if (getWidth < 0 || x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
  685. if (getWidth == 0) return;
  686. int index;
  687. int theByte;
  688. int mask = 0;
  689. int n = getWidth;
  690. int i = startIndex;
  691. int srcX = x, srcY = y;
  692. switch (depth) {
  693. case 8:
  694. index = (y * bytesPerLine) + x;
  695. for (int j = 0; j < getWidth; j++) {
  696. pixels[i] = data[index];
  697. i++;
  698. srcX++;
  699. if (srcX >= width) {
  700. srcY++;
  701. index = srcY * bytesPerLine;
  702. srcX = 0;
  703. } else {
  704. index++;
  705. }
  706. }
  707. return;
  708. case 4:
  709. index = (y * bytesPerLine) + (x >> 1);
  710. if ((x & 0x1) == 1) {
  711. theByte = data[index] & 0xFF;
  712. pixels[i] = (byte)(theByte & 0x0F);
  713. i++;
  714. n--;
  715. srcX++;
  716. if (srcX >= width) {
  717. srcY++;
  718. index = srcY * bytesPerLine;
  719. srcX = 0;
  720. } else {
  721. index++;
  722. }
  723. }
  724. while (n > 1) {
  725. theByte = data[index] & 0xFF;
  726. pixels[i] = (byte)(theByte >> 4);
  727. i++;
  728. n--;
  729. srcX++;
  730. if (srcX >= width) {
  731. srcY++;
  732. index = srcY * bytesPerLine;
  733. srcX = 0;
  734. } else {
  735. pixels[i] = (byte)(theByte & 0x0F);
  736. i++;
  737. n--;
  738. srcX++;
  739. if (srcX >= width) {
  740. srcY++;
  741. index = srcY * bytesPerLine;
  742. srcX = 0;
  743. } else {
  744. index++;
  745. }
  746. }
  747. }
  748. if (n > 0) {
  749. theByte = data[index] & 0xFF;
  750. pixels[i] = (byte)(theByte >> 4);
  751. }
  752. return;
  753. case 2:
  754. index = (y * bytesPerLine) + (x >> 2);
  755. theByte = data[index] & 0xFF;
  756. int offset;
  757. while (n > 0) {
  758. offset = 3 - (srcX % 4);
  759. mask = 3 << (offset * 2);
  760. pixels[i] = (byte)((theByte & mask) >> (offset * 2));
  761. i++;
  762. n--;
  763. srcX++;
  764. if (srcX >= width) {
  765. srcY++;
  766. index = srcY * bytesPerLine;
  767. if (n > 0) theByte = data[index] & 0xFF;
  768. srcX = 0;
  769. } else {
  770. if (offset == 0) {
  771. index++;
  772. theByte = data[index] & 0xFF;
  773. }
  774. }
  775. }
  776. return;
  777. case 1:
  778. index = (y * bytesPerLine) + (x >> 3);
  779. theByte = data[index] & 0xFF;
  780. while (n > 0) {
  781. mask = 1 << (7 - (srcX & 0x7));
  782. if ((theByte & mask) == 0) {
  783. pixels[i] = 0;
  784. } else {
  785. pixels[i] = 1;
  786. }
  787. i++;
  788. n--;
  789. srcX++;
  790. if (srcX >= width) {
  791. srcY++;
  792. index = srcY * bytesPerLine;
  793. if (n > 0) theByte = data[index] & 0xFF;
  794. srcX = 0;
  795. } else {
  796. if (mask == 1) {
  797. index++;
  798. if (n > 0) theByte = data[index] & 0xFF;
  799. }
  800. }
  801. }
  802. return;
  803. }
  804. SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
  805. }
  806. /**
  807. * Returns <code>getWidth</code> pixel values starting at offset
  808. * <code>x</code> in scanline <code>y</code> in the receiver's
  809. * data starting at <code>startIndex</code>.
  810. *
  811. * @param x the x position of the first pixel to get
  812. * @param y the y position of the first pixel to get
  813. * @param getWidth the width of the data to get
  814. * @param pixels the buffer in which to put the pixels
  815. * @param startIndex the offset into the buffer to begin storing pixels
  816. *
  817. * @exception IndexOutOfBoundsException if getWidth is too large
  818. * @exception IllegalArgumentException <ul>
  819. * <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
  820. * <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
  821. * <li>ERROR_INVALID_ARGUMENT - if getWidth is negative</li>
  822. * </ul>
  823. * @exception SWTException <ul>
  824. * <li>ERROR_UNSUPPORTED_DEPTH - if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
  825. * </ul>
  826. */
  827. public void getPixels(int x, int y, int getWidth, int[] pixels, int startIndex) {
  828. if (pixels == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
  829. if (getWidth < 0 || x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
  830. if (getWidth == 0) return;
  831. int index;
  832. int theByte;
  833. int mask;
  834. int n = getWidth;
  835. int i = startIndex;
  836. int srcX = x, srcY = y;
  837. switch (depth) {
  838. case 32:
  839. index = (y * bytesPerLine) + (x * 4);
  840. i = startIndex;
  841. for (int j = 0; j < getWidth; j++) {
  842. pixels[i] = ((data[index] & 0xFF) << 24) | ((data[index+1] & 0xFF) << 16)
  843. | ((data[index+2] & 0xFF) << 8) | (data[index+3] & 0xFF);
  844. i++;
  845. srcX++;
  846. if (srcX >= width) {
  847. srcY++;
  848. index = srcY * bytesPerLine;
  849. srcX = 0;
  850. } else {
  851. index += 4;
  852. }
  853. }
  854. return;
  855. case 24:
  856. index = (y * bytesPerLine) + (x * 3);
  857. for (int j = 0; j < getWidth; j++) {
  858. pixels[i] = ((data[index] & 0xFF) << 16) | ((data[index+1] & 0xFF) << 8)
  859. | (data[index+2] & 0xFF);
  860. i++;
  861. srcX++;
  862. if (srcX >= width) {
  863. srcY++;
  864. index = srcY * bytesPerLine;
  865. srcX = 0;
  866. } else {
  867. index += 3;
  868. }
  869. }
  870. return;
  871. case 16:
  872. index = (y * bytesPerLine) + (x * 2);
  873. for (int j = 0; j < getWidth; j++) {
  874. pixels[i] = ((data[index+1] & 0xFF) << 8) + (data[index] & 0xFF);
  875. i++;
  876. srcX++;
  877. if (srcX >= width) {
  878. srcY++;
  879. index = srcY * bytesPerLine;
  880. srcX = 0;
  881. } else {
  882. index += 2;
  883. }
  884. }
  885. return;
  886. case 8:
  887. index = (y * bytesPerLine) + x;
  888. for (int j = 0; j < getWidth; j++) {
  889. pixels[i] = data[index] & 0xFF;
  890. i++;
  891. srcX++;
  892. if (srcX >= width) {
  893. srcY++;
  894. index = srcY * bytesPerLine;
  895. srcX = 0;
  896. } else {
  897. index++;
  898. }
  899. }
  900. return;
  901. case 4:
  902. index = (y * bytesPerLine) + (x >> 1);
  903. if ((x & 0x1) == 1) {
  904. theByte = data[index] & 0xFF;
  905. pixels[i] = theByte & 0x0F;
  906. i++;
  907. n--;
  908. srcX++;
  909. if (srcX >= width) {
  910. srcY++;
  911. index = srcY * bytesPerLine;
  912. srcX = 0;
  913. } else {
  914. index++;
  915. }
  916. }
  917. while (n > 1) {
  918. theByte = data[index] & 0xFF;
  919. pixels[i] = theByte >> 4;
  920. i++;
  921. n--;
  922. srcX++;
  923. if (srcX >= width) {
  924. srcY++;
  925. index = srcY * bytesPerLine;
  926. srcX = 0;
  927. } else {
  928. pixels[i] = theByte & 0x0F;
  929. i++;
  930. n--;
  931. srcX++;
  932. if (srcX >= width) {
  933. srcY++;
  934. index = srcY * bytesPerLine;
  935. srcX = 0;
  936. } else {
  937. index++;
  938. }
  939. }
  940. }
  941. if (n > 0) {
  942. theByte = data[index] & 0xFF;
  943. pixels[i] = theByte >> 4;
  944. }
  945. return;
  946. case 2:
  947. index = (y * bytesPerLine) + (x >> 2);
  948. theByte = data[index] & 0xFF;
  949. int offset;
  950. while (n > 0) {
  951. offset = 3 - (srcX % 4);
  952. mask = 3 << (offset * 2);
  953. pixels[i] = (byte)((theByte & mask) >> (offset * 2));
  954. i++;
  955. n--;
  956. srcX++;
  957. if (srcX >= width) {
  958. srcY++;
  959. index = srcY * bytesPerLine;
  960. if (n > 0) theByte = data[index] & 0xFF;
  961. srcX = 0;
  962. } else {
  963. if (offset == 0) {
  964. index++;
  965. theByte = data[index] & 0xFF;
  966. }
  967. }
  968. }
  969. return;
  970. case 1:
  971. index = (y * bytesPerLine) + (x >> 3);
  972. theByte = data[index] & 0xFF;
  973. while (n > 0) {
  974. mask = 1 << (7 - (srcX & 0x7));
  975. if ((theByte & mask) == 0) {
  976. pixels[i] = 0;
  977. } else {
  978. pixels[i] = 1;
  979. }
  980. i++;
  981. n--;
  982. srcX++;
  983. if (srcX >= width) {
  984. srcY++;
  985. index = srcY * bytesPerLine;
  986. if (n > 0) theByte = data[index] & 0xFF;
  987. srcX = 0;
  988. } else {
  989. if (mask == 1) {
  990. index++;
  991. if (n > 0) theByte = data[index] & 0xFF;
  992. }
  993. }
  994. }
  995. return;
  996. }
  997. SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
  998. }
  999. /**
  1000. * Returns an array of <code>RGB</code>s which comprise the
  1001. * indexed color table of the receiver, or null if the receiver
  1002. * has a direct color model.
  1003. *
  1004. * @return the RGB values for the image or null if direct color
  1005. *
  1006. * @see PaletteData#getRGBs()
  1007. */
  1008. public RGB[] getRGBs() {
  1009. return palette.getRGBs();
  1010. }
  1011. /**
  1012. * Returns an <code>ImageData</code> which specifies the
  1013. * transparency mask information for the receiver. If the
  1014. * receiver has no transparency or is not an icon, returns
  1015. * an opaque mask.
  1016. *
  1017. * @return the transparency mask
  1018. */
  1019. public ImageData getTransparencyMask() {
  1020. if (getTransparencyType() == SWT.TRANSPARENCY_MASK) {
  1021. return new ImageData(width, height, 1, bwPalette(), maskPad, maskData);
  1022. } else {
  1023. return colorMaskImage(transparentPixel);
  1024. }
  1025. }
  1026. /**
  1027. * Returns the image transparency type, which will be one of
  1028. * <code>SWT.TRANSPARENCY_NONE</code>, <code>SWT.TRANSPARENCY_MASK</code>,
  1029. * <code>SWT.TRANSPARENCY_PIXEL</code> or <code>SWT.TRANSPARENCY_ALPHA</code>.
  1030. *
  1031. * @return the receiver's transparency type
  1032. */
  1033. public int getTransparencyType() {
  1034. if (maskData != null) return SWT.TRANSPARENCY_MASK;
  1035. if (transparentPixel != -1) return SWT.TRANSPARENCY_PIXEL;
  1036. if (alphaData != null) return SWT.TRANSPARENCY_ALPHA;
  1037. return SWT.TRANSPARENCY_NONE;
  1038. }
  1039. /**
  1040. * Returns the byte order of the receiver.
  1041. *
  1042. * @return MSB_FIRST or LSB_FIRST
  1043. */
  1044. int getByteOrder() {
  1045. return depth != 16 ? MSB_FIRST : LSB_FIRST;
  1046. }
  1047. /**
  1048. * Returns a copy of the receiver which has been stretched or
  1049. * shrunk to the specified size. If either the width or height
  1050. * is negative, the resulting image will be inverted in the
  1051. * associated axis.
  1052. *
  1053. * @param width the width of the new ImageData
  1054. * @param height the height of the new ImageData
  1055. * @return a scaled copy of the image
  1056. */
  1057. public ImageData scaledTo(int width, int height) {
  1058. /* Create a destination image with no data */
  1059. final boolean flipX = (width < 0);
  1060. if (flipX) width = - width;
  1061. final boolean flipY = (height < 0);
  1062. if (flipY) height = - height;
  1063. ImageData dest = new ImageData(
  1064. width, height, depth, palette,
  1065. scanlinePad, null, 0, null,
  1066. null, -1, transparentPixel, type,
  1067. x, y, disposalMethod, delayTime);
  1068. /* Scale the image contents */
  1069. if (palette.isDirect) blit(BLIT_SRC,
  1070. this.data, this.depth, this.bytesPerLine, this.getByteOrder(), 0, 0, this.width, this.height, 0, 0, 0,
  1071. ALPHA_OPAQUE, null, 0, 0, 0,
  1072. dest.data, dest.depth, dest.bytesPerLine, dest.getByteOrder(), 0, 0, dest.width, dest.height, 0, 0, 0,
  1073. flipX, flipY);
  1074. else blit(BLIT_SRC,
  1075. this.data, this.depth, this.bytesPerLine, this.getByteOrder(), 0, 0, this.width, this.height, null, null, null,
  1076. ALPHA_OPAQUE, null, 0, 0, 0,
  1077. dest.data, dest.depth, dest.bytesPerLine, dest.getByteOrder(), 0, 0, dest.width, dest.height, null, null, null,
  1078. flipX, flipY);
  1079. /* Scale the image mask or alpha */
  1080. if (maskData != null) {
  1081. dest.maskPad = this.maskPad;
  1082. int destBpl = (dest.width + 7) / 8;
  1083. destBpl = (destBpl + (dest.maskPad - 1)) / dest.maskPad * dest.maskPad;
  1084. dest.maskData = new byte[destBpl * dest.height];
  1085. int srcBpl = (this.width + 7) / 8;
  1086. srcBpl = (srcBpl + (this.maskPad - 1)) / this.maskPad * this.maskPad;
  1087. blit(BLIT_SRC,
  1088. this.maskData, 1, srcBpl, MSB_FIRST, 0, 0, this.width, this.height, null, null, null,
  1089. ALPHA_OPAQUE, null, 0, 0, 0,
  1090. dest.maskData, 1, destBpl, MSB_FIRST, 0, 0, dest.width, dest.height, null, null, null,
  1091. flipX, flipY);
  1092. } else if (alpha != -1) {
  1093. dest.alpha = this.alpha;
  1094. } else if (alphaData != null) {
  1095. dest.alphaData = new byte[dest.width * dest.height];
  1096. blit(BLIT_SRC,
  1097. this.alphaData, 8, this.width, MSB_FIRST, 0, 0, this.width, this.height, null, null, null,
  1098. ALPHA_OPAQUE, null, 0, 0, 0,
  1099. dest.alphaData, 8, dest.width, MSB_FIRST, 0, 0, dest.width, dest.height, null, null, null,
  1100. flipX, flipY);
  1101. }
  1102. return dest;
  1103. }
  1104. /**
  1105. * Sets the alpha value at offset <code>x</code> in
  1106. * scanline <code>y</code> in the receiver's alpha data.
  1107. * The alpha value must be between 0 (transparent)
  1108. * and 255 (opaque).
  1109. *
  1110. * @param x the x coordinate of the alpha value to set
  1111. * @param y the y coordinate of the alpha value to set
  1112. * @param alpha the value to set the alpha to
  1113. *
  1114. * @exception IllegalArgumentException <ul>
  1115. * <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
  1116. * </ul>
  1117. */
  1118. public void setAlpha(int x, int y, int alpha) {
  1119. if (x >= width || y >= height || x < 0 || y < 0 || alpha < 0 || alpha > 255)
  1120. SWT.error(SWT.ERROR_INVALID_ARGUMENT);
  1121. if (alphaData == null) alphaData = new byte[width * height];
  1122. alphaData[y * width + x] = (byte)alpha;
  1123. }
  1124. /**
  1125. * Sets the alpha values starting at offset <code>x</code> in
  1126. * scanline <code>y</code> in the receiver's alpha data to the
  1127. * values from the array <code>alphas</code> starting at
  1128. * <code>startIndex</code>. The alpha values must be between
  1129. * <code>(byte)0</code> (transparent) and <code>(byte)255</code> (opaque)
  1130. *
  1131. * @param x the x coordinate of the pixel to being setting the alpha values
  1132. * @param y the y coordinate of the pixel to being setting the alpha values
  1133. * @param putWidth the width of the alpha values to set
  1134. * @param alphas the alpha values to set
  1135. * @param startIndex the index at which to begin setting
  1136. *
  1137. * @exception IndexOutOfBoundsException if putWidth is too large
  1138. * @exception IllegalArgumentException <ul>
  1139. * <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
  1140. * <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
  1141. * <li>ERROR_INVALID_ARGUMENT - if putWidth is negative</li>
  1142. * </ul>
  1143. */
  1144. public void setAlphas(int x, int y, int putWidth, byte[] alphas, int startIndex) {
  1145. if (alphas == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
  1146. if (putWidth < 0 || x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
  1147. if (putWidth == 0) return;
  1148. if (alphaData == null) alphaData = new byte[width * height];
  1149. // may throw an IndexOutOfBoundsException
  1150. System.arraycopy(alphas, startIndex, alphaData, y * width + x, putWidth);
  1151. }
  1152. /**
  1153. * Sets the pixel value at offset <code>x</code> in
  1154. * scanline <code>y</code> in the receiver's data.
  1155. *
  1156. * @param x the x coordinate of the pixel to set
  1157. * @param y the y coordinate of the pixel to set
  1158. * @param pixelValue the value to set the pixel to
  1159. *
  1160. * @exception IllegalArgumentException <ul>
  1161. * <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
  1162. * </ul>
  1163. * @exception SWTException <ul>
  1164. * <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
  1165. * </ul>
  1166. */
  1167. public void setPixel(int x, int y, int pixelValue) {
  1168. if (x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
  1169. int index;
  1170. byte theByte;
  1171. int mask;
  1172. switch (depth) {
  1173. case 32:
  1174. index = (y * bytesPerLine) + (x * 4);
  1175. data[index] = (byte)((pixelValue >> 24) & 0xFF);
  1176. data[index + 1] = (byte)((pixelValue >> 16) & 0xFF);
  1177. data[index + 2] = (byte)((pixelValue >> 8) & 0xFF);
  1178. data[index + 3] = (byte)(pixelValue & 0xFF);
  1179. return;
  1180. case 24:
  1181. index = (y * bytesPerLine) + (x * 3);
  1182. data[index] = (byte)((pixelValue >> 16) & 0xFF);
  1183. data[index + 1] = (byte)((pixelValue >> 8) & 0xFF);
  1184. data[index + 2] = (byte)(pixelValue & 0xFF);
  1185. return;
  1186. case 16:
  1187. index = (y * bytesPerLine) + (x * 2);
  1188. data[index + 1] = (byte)((pixelValue >> 8) & 0xFF);
  1189. data[index] = (byte)(pixelValue & 0xFF);
  1190. return;
  1191. case 8:
  1192. index = (y * bytesPerLine) + x ;
  1193. data[index] = (byte)(pixelValue & 0xFF);
  1194. return;
  1195. case 4:
  1196. index = (y * bytesPerLine) + (x >> 1);
  1197. if ((x & 0x1) == 0) {
  1198. data[index] = (byte)((data[index] & 0x0F) | ((pixelValue & 0x0F) << 4));
  1199. } else {
  1200. data[index] = (byte)((data[index] & 0xF0) | (pixelValue & 0x0F));
  1201. }
  1202. return;
  1203. case 2:
  1204. index = (y * bytesPerLine) + (x >> 2);
  1205. theByte = data[index];
  1206. int offset = 3 - (x % 4);
  1207. mask = 0xFF ^ (3 << (offset * 2));
  1208. data[index] = (byte)((data[index] & mask) | (pixelValue << (offset * 2)));
  1209. return;
  1210. case 1:
  1211. index = (y * bytesPerLine) + (x >> 3);
  1212. theByte = data[index];
  1213. mask = 1 << (7 - (x & 0x7));
  1214. if ((pixelValue & 0x1) == 1) {
  1215. data[index] = (byte)(theByte | mask);
  1216. } else {
  1217. data[index] = (byte)(theByte & (mask ^ -1));
  1218. }
  1219. return;
  1220. }
  1221. SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
  1222. }
  1223. /**
  1224. * Sets the pixel values starting at offset <code>x</code> in
  1225. * scanline <code>y</code> in the receiver's data to the
  1226. * values from the array <code>pixels</code> starting at
  1227. * <code>startIndex</code>.
  1228. *
  1229. * @param x the x position of the pixel to set
  1230. * @param y the y position of the pixel to set
  1231. * @param putWidth the width of the pixels to set
  1232. * @param pixels the pixels to set
  1233. * @param startIndex the index at which to begin setting
  1234. *
  1235. * @exception IndexOutOfBoundsException if putWidth is too large
  1236. * @exception IllegalArgumentException <ul>
  1237. * <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
  1238. * <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
  1239. * <li>ERROR_INVALID_ARGUMENT - if putWidth is negative</li>
  1240. * </ul>
  1241. * @exception SWTException <ul>
  1242. * <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8
  1243. * (For higher depths, use the int[] version of this method.)</li>
  1244. * </ul>
  1245. */
  1246. public void setPixels(int x, int y, int putWidth, byte[] pixels, int startIndex) {
  1247. if (pixels == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
  1248. if (putWidth < 0 || x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
  1249. if (putWidth == 0) return;
  1250. int index;
  1251. int theByte;
  1252. int mask;
  1253. int n = putWidth;
  1254. int i = startIndex;
  1255. int srcX = x, srcY = y;
  1256. switch (depth) {
  1257. case 8:
  1258. index = (y * bytesPerLine) + x;
  1259. for (int j = 0; j < putWidth; j++) {
  1260. data[index] = (byte)(pixels[i] & 0xFF);
  1261. i++;
  1262. srcX++;
  1263. if (srcX >= width) {
  1264. srcY++;
  1265. index = srcY * bytesPerLine;
  1266. srcX = 0;
  1267. } else {
  1268. index++;
  1269. }
  1270. }
  1271. return;
  1272. case 4:
  1273. index = (y * bytesPerLine) + (x >> 1);
  1274. boolean high = (x & 0x1) == 0;
  1275. while (n > 0) {
  1276. theByte = pixels[i] & 0x0F;
  1277. if (high) {
  1278. data[index] = (byte)((data[index] & 0x0F) | (theByte << 4));
  1279. } else {
  1280. data[index] = (byte)((data[index] & 0xF0) | theByte);
  1281. }
  1282. i++;
  1283. n--;
  1284. srcX++;
  1285. if (srcX >= width) {
  1286. srcY++;
  1287. index = srcY * bytesPerLine;
  1288. high = true;
  1289. srcX = 0;
  1290. } else {
  1291. if (!high) index++;
  1292. high = !high;
  1293. }
  1294. }
  1295. return;
  1296. case 2:
  1297. byte [] masks = { (byte)0xFC, (byte)0xF3, (byte)0xCF, (byte)0x3F };
  1298. index = (y * bytesPerLine) + (x >> 2);
  1299. int offset = 3 - (x % 4);
  1300. while (n > 0) {
  1301. theByte = pixels[i] & 0x3;
  1302. data[index] = (byte)((data[index] & masks[offset]) | (theByte << (offset * 2)));
  1303. i++;
  1304. n--;
  1305. srcX++;
  1306. if (srcX >= width) {
  1307. srcY++;
  1308. index = srcY * bytesPerLine;
  1309. offset = 0;
  1310. srcX = 0;
  1311. } else {
  1312. if (offset == 0) {
  1313. index++;
  1314. offset = 3;
  1315. } else {
  1316. offset--;
  1317. }
  1318. }
  1319. }
  1320. return;
  1321. case 1:
  1322. index = (y * bytesPerLine) + (x >> 3);
  1323. while (n > 0) {
  1324. mask = 1 << (7 - (srcX & 0x7));
  1325. if ((pixels[i] & 0x1) == 1) {
  1326. data[index] = (byte)((data[index] & 0xFF) | mask);
  1327. } else {
  1328. data[index] = (byte)((data[index] & 0xFF) & (mask ^ -1));
  1329. }
  1330. i++;
  1331. n--;
  1332. srcX++;
  1333. if (srcX >= width) {
  1334. srcY++;
  1335. index = srcY * bytesPerLine;
  1336. srcX = 0;
  1337. } else {
  1338. if (mask == 1) {
  1339. index++;
  1340. }
  1341. }
  1342. }
  1343. return;
  1344. }
  1345. SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
  1346. }
  1347. /**
  1348. * Sets the pixel values starting at offset <code>x</code> in
  1349. * scanline <code>y</code> in the receiver's data to the
  1350. * values from the array <code>pixels</code> starting at
  1351. * <code>startIndex</code>.
  1352. *
  1353. * @param x the x position of the pixel to set
  1354. * @param y the y position of the pixel to set
  1355. * @param putWidth the width of the pixels to set
  1356. * @param pixels the pixels to set
  1357. * @param startIndex the index at which to begin setting
  1358. *
  1359. * @exception IndexOutOfBoundsException if putWidth is too large
  1360. * @exception IllegalArgumentException <ul>
  1361. * <li>ERROR_NULL_ARGUMENT - if pixels is null</li>
  1362. * <li>ERROR_INVALID_ARGUMENT - if x or y is out of bounds</li>
  1363. * <li>ERROR_INVALID_ARGUMENT - if putWidth is negative</li>
  1364. * </ul>
  1365. * @exception SWTException <ul>
  1366. * <li>ERROR_UNSUPPORTED_DEPTH if the depth is not one of 1, 2, 4, 8, 16, 24 or 32</li>
  1367. * </ul>
  1368. */
  1369. public void setPixels(int x, int y, int putWidth, int[] pixels, int startIndex) {
  1370. if (pixels == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
  1371. if (putWidth < 0 || x >= width || y >= height || x < 0 || y < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
  1372. if (putWidth == 0) return;
  1373. int index;
  1374. int theByte;
  1375. int mask;
  1376. int n = putWidth;
  1377. int i = startIndex;
  1378. int pixel;
  1379. int srcX = x, srcY = y;
  1380. switch (depth) {
  1381. case 32:
  1382. index = (y * bytesPerLine) + (x * 4);
  1383. for (int j = 0; j < putWidth; j++) {
  1384. pixel = pixels[i];
  1385. data[index] = (byte)((pixel >> 24) & 0xFF);
  1386. data[index + 1] = (byte)((pixel >> 16) & 0xFF);
  1387. data[index + 2] = (byte)((pixel >> 8) & 0xFF);
  1388. data[index + 3] = (byte)(pixel & 0xFF);
  1389. i++;
  1390. srcX++;
  1391. if (srcX >= width) {
  1392. srcY++;
  1393. index = srcY * bytesPerLine;
  1394. srcX = 0;
  1395. } else {
  1396. index += 4;
  1397. }
  1398. }
  1399. return;
  1400. case 24:
  1401. index = (y * bytesPerLine) + (x * 3);
  1402. for (int j = 0; j < putWidth; j++) {
  1403. pixel = pixels[i];
  1404. data[index] = (byte)((pixel >> 16) & 0xFF);
  1405. data[index + 1] = (byte)((pixel >> 8) & 0xFF);
  1406. data[index + 2] = (byte)(pixel & 0xFF);
  1407. i++;
  1408. srcX++;
  1409. if (srcX >= width) {
  1410. srcY++;
  1411. index = srcY * bytesPerLine;
  1412. srcX = 0;
  1413. } else {
  1414. index += 3;
  1415. }
  1416. }
  1417. return;
  1418. case 16:
  1419. index = (y * bytesPerLine) + (x * 2);
  1420. for (int j = 0; j < putWidth; j++) {
  1421. pixel = pixels[i];
  1422. data[index] = (byte)(pixel & 0xFF);
  1423. data[index + 1] = (byte)((pixel >> 8) & 0xFF);
  1424. i++;
  1425. srcX++;
  1426. if (srcX >= width) {
  1427. srcY++;
  1428. index = srcY * bytesPerLine;
  1429. srcX = 0;
  1430. } else {
  1431. index += 2;
  1432. }
  1433. }
  1434. return;
  1435. case 8:
  1436. index = (y * bytesPerLine) + x;
  1437. for (int j = 0; j < putWidth; j++) {
  1438. data[index] = (byte)(pixels[i] & 0xFF);
  1439. i++;
  1440. srcX++;
  1441. if (srcX >= width) {
  1442. srcY++;
  1443. index = srcY * bytesPerLine;
  1444. srcX = 0;
  1445. } else {
  1446. index++;
  1447. }
  1448. }
  1449. return;
  1450. case 4:
  1451. index = (y * bytesPerLine) + (x >> 1);
  1452. boolean high = (x & 0x1) == 0;
  1453. while (n > 0) {
  1454. theByte = pixels[i] & 0x0F;
  1455. if (high) {
  1456. data[index] = (byte)((data[index] & 0x0F) | (theByte << 4));
  1457. } else {
  1458. data[index] = (byte)((data[index] & 0xF0) | theByte);
  1459. }
  1460. i++;
  1461. n--;
  1462. srcX++;
  1463. if (srcX >= width) {
  1464. srcY++;
  1465. index = srcY * bytesPerLine;
  1466. high = true;
  1467. srcX = 0;
  1468. } else {
  1469. if (!high) index++;
  1470. high = !high;
  1471. }
  1472. }
  1473. return;
  1474. case 2:
  1475. byte [] masks = { (byte)0xFC, (byte)0xF3, (byte)0xCF, (byte)0x3F };
  1476. index = (y * bytesPerLine) + (x >> 2);
  1477. int offset = 3 - (x % 4);
  1478. while (n > 0) {
  1479. theByte = pixels[i] & 0x3;
  1480. data[index] = (byte)((data[index] & masks[offset]) | (theByte << (offset * 2)));
  1481. i++;
  1482. n--;
  1483. srcX++;
  1484. if (srcX >= width) {
  1485. srcY++;
  1486. index = srcY * bytesPerLine;
  1487. offset = 3;
  1488. srcX = 0;
  1489. } else {
  1490. if (offset == 0) {
  1491. index++;
  1492. offset = 3;
  1493. } else {
  1494. offset--;
  1495. }
  1496. }
  1497. }
  1498. return;
  1499. case 1:
  1500. index = (y * bytesPerLine) + (x >> 3);
  1501. while (n > 0) {
  1502. mask = 1 << (7 - (srcX & 0x7));
  1503. if ((pixels[i] & 0x1) == 1) {
  1504. data[index] = (byte)((data[index] & 0xFF) | mask);
  1505. } else {
  1506. data[index] = (byte)((data[index] & 0xFF) & (mask ^ -1));
  1507. }
  1508. i++;
  1509. n--;
  1510. srcX++;
  1511. if (srcX >= width) {
  1512. srcY++;
  1513. index = srcY * bytesPerLine;
  1514. srcX = 0;
  1515. } else {
  1516. if (mask == 1) {
  1517. index++;
  1518. }
  1519. }
  1520. }
  1521. return;
  1522. }
  1523. SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
  1524. }
  1525. /**
  1526. * Returns a palette with 2 colors: black & white.
  1527. */
  1528. static PaletteData bwPalette() {
  1529. return new PaletteData(new RGB[] {new RGB(0, 0, 0), new RGB(255, 255, 255)});
  1530. }
  1531. /**
  1532. * Gets the offset of the most significant bit for
  1533. * the given mask.
  1534. */
  1535. static int getMSBOffset(int mask) {
  1536. for (int i = 31; i >= 0; i--) {
  1537. if (((mask >> i) & 0x1) != 0) return i + 1;
  1538. }
  1539. return 0;
  1540. }
  1541. /**
  1542. * Finds the closest match.
  1543. */
  1544. static int closestMatch(int depth, byte red, byte green, byte blue, int redMask, int greenMask, int blueMask, byte[] reds, byte[] greens, byte[] blues) {
  1545. if (depth > 8) {
  1546. int rshift = 32 - getMSBOffset(redMask);
  1547. int gshift = 32 - getMSBOffset(greenMask);
  1548. int bshift = 32 - getMSBOffset(blueMask);
  1549. return (((red << 24) >>> rshift) & redMask) |
  1550. (((green << 24) >>> gshift) & greenMask) |
  1551. (((blue << 24) >>> bshift) & blueMask);
  1552. }
  1553. int r, g, b;
  1554. int minDistance = 0x7fffffff;
  1555. int nearestPixel = 0;
  1556. int n = reds.length;
  1557. for (int j = 0; j < n; j++) {
  1558. r = (reds[j] & 0xFF) - (red & 0xFF);
  1559. g = (greens[j] & 0xFF) - (green & 0xFF);
  1560. b = (blues[j] & 0xFF) - (blue & 0xFF);
  1561. int distance = r*r + g*g + b*b;
  1562. if (distance < minDistance) {
  1563. nearestPixel = j;
  1564. if (distance == 0) break;
  1565. minDistance = distance;
  1566. }
  1567. }
  1568. return nearestPixel;
  1569. }
  1570. static final ImageData convertMask(ImageData mask) {
  1571. if (mask.depth == 1) return mask;
  1572. PaletteData palette = new PaletteData(new RGB[] {new RGB(0, 0, 0), new RGB(255,255,255)});
  1573. ImageData newMask = new ImageData(mask.width, mask.height, 1, palette);
  1574. /* Find index of black in mask palette */
  1575. int blackIndex = 0;
  1576. RGB[] rgbs = mask.getRGBs();
  1577. if (rgbs != null) {
  1578. while (blackIndex < rgbs.length) {
  1579. if (rgbs[blackIndex].equals(palette.colors[0])) break;
  1580. blackIndex++;
  1581. }
  1582. }
  1583. int[] pixels = new int[mask.width];
  1584. for (int y = 0; y < mask.height; y++) {
  1585. mask.getPixels(0, y, mask.width, pixels, 0);
  1586. for (int i = 0; i < pixels.length; i++) {
  1587. if (pixels[i] == blackIndex) {
  1588. pixels[i] = 0;
  1589. } else {
  1590. pixels[i] = 1;
  1591. }
  1592. }
  1593. newMask.setPixels(0, y, mask.width, pixels, 0);
  1594. }
  1595. return newMask;
  1596. }
  1597. static final byte[] convertPad(byte[] data, int width, int height, int depth, int pad, int newPad) {
  1598. if (pad == newPad) return data;
  1599. int stride = (width * depth + 7) / 8;
  1600. int bpl = (stride + (pad - 1)) / pad * pad;
  1601. int newBpl = (stride + (newPad - 1)) / newPad * newPad;
  1602. byte[] newData = new byte[height * newBpl];
  1603. int srcIndex = 0, destIndex = 0;
  1604. for (int y = 0; y < height; y++) {
  1605. System.arraycopy(data, srcIndex, newData, destIndex, stride);
  1606. srcIndex += bpl;
  1607. destIndex += newBpl;
  1608. }
  1609. return newData;
  1610. }
  1611. /**
  1612. * Blit operation bits to be OR'ed together to specify the desired operation.
  1613. */
  1614. static final int
  1615. BLIT_SRC = 1, // copy source directly, else applies logic operations
  1616. BLIT_ALPHA = 2, // enable alpha blending
  1617. BLIT_DITHER = 4; // enable dithering in low color modes
  1618. /**
  1619. * Alpha mode, values 0 - 255 specify global alpha level
  1620. */
  1621. static final int
  1622. ALPHA_OPAQUE = 255, // Fully opaque (ignores any alpha data)
  1623. ALPHA_TRANSPARENT = 0, // Fully transparent (ignores any alpha data)
  1624. ALPHA_CHANNEL_SEPARATE = -1, // Use alpha channel from separate alphaData
  1625. ALPHA_CHANNEL_SOURCE = -2, // Use alpha channel embedded in sourceData
  1626. ALPHA_MASK_UNPACKED = -3, // Use transparency mask formed by bytes in alphaData (non-zero is opaque)
  1627. ALPHA_MASK_PACKED = -4, // Use transparency mask formed by packed bits in alphaData
  1628. ALPHA_MASK_INDEX = -5, // Consider source palette indices transparent if in alphaData array
  1629. ALPHA_MASK_RGB = -6; // Consider source RGBs transparent if in RGB888 format alphaData array
  1630. /**
  1631. * Byte and bit order constants.
  1632. */
  1633. static final int LSB_FIRST = 0;
  1634. static final int MSB_FIRST = 1;
  1635. /**
  1636. * Data types (internal)
  1637. */
  1638. private static final int
  1639. // direct / true color formats with arbitrary masks & shifts
  1640. TYPE_GENERIC_8 = 0,
  1641. TYPE_GENERIC_16_MSB = 1,
  1642. TYPE_GENERIC_16_LSB = 2,
  1643. TYPE_GENERIC_24 = 3,
  1644. TYPE_GENERIC_32_MSB = 4,
  1645. TYPE_GENERIC_32_LSB = 5,
  1646. // palette indexed color formats
  1647. TYPE_INDEX_8 = 6,
  1648. TYPE_INDEX_4 = 7,
  1649. TYPE_INDEX_2 = 8,
  1650. TYPE_INDEX_1_MSB = 9,
  1651. TYPE_INDEX_1_LSB = 10;
  1652. /**
  1653. * Blits a direct palette image into a direct palette image.
  1654. * <p>
  1655. * Note: When the sour…

Large files files are truncated, but you can click here to view the full file