PageRenderTime 12ms CodeModel.GetById 4ms app.highlight 146ms RepoModel.GetById 1ms app.codeStats 1ms

/dwt/graphics/ImageData.d

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

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