PageRenderTime 49ms CodeModel.GetById 192ms app.highlight 492ms RepoModel.GetById 31ms app.codeStats 2ms

/src/org/eclipse/swt/graphics/ImageData.d

https://github.com/yurigoro/org.eclipse.swt.win32.win32.x86
D | 3676 lines | 2665 code | 130 blank | 881 comment | 515 complexity | 50a2d38fbb8b0974a49bf6591c84fa78 MD5 | raw file

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

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

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