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 *******************************************************************************/ 13 module org.eclipse.swt.graphics.PaletteData; 14 15 import java.lang.all; 16 17 18 import org.eclipse.swt.SWT; 19 import org.eclipse.swt.graphics.RGB; 20 21 /** 22 * Instances of this class describe the color data used by an image. 23 * <p> 24 * Depending on the depth of the image, the PaletteData can take one 25 * of two forms, indicated by the isDirect field: 26 * </p> 27 * <dl> 28 * <dt> 29 * <em>isDirect is false</em> 30 * </dt> 31 * <dd> 32 * If isDirect is <code>false</code>, this palette is an indexed 33 * palette which maps pixel values to RGBs. The actual RGB values 34 * may be retrieved by using the getRGBs() method. 35 * </dd> 36 * <dt> 37 * <em>isDirect is true</em> 38 * </dt> 39 * <dd> 40 * If isDirect is <code>true</code>, this palette is a direct color 41 * palette. Instead of containing RGB values, it contains red, 42 * green and blue mask and shift information which indicates how 43 * the color components may be extracted from a given pixel. 44 * This means that the RGB value is actually encoded in the pixel value. 45 * <p> 46 * In this case, the shift data is the number of bits required to shift 47 * the RGB value to the left in order to align the high bit of the 48 * corresponding mask with the high bit of the first byte. This number 49 * may be negative, so care must be taken when shifting. For example, 50 * with a red mask of 0xFF0000, the red shift would be -16. With a red 51 * mask of 0x1F, the red shift would be 3. 52 * </p> 53 * </dd> 54 * </dl> 55 * 56 * @see Image 57 * @see RGB 58 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> 59 */ 60 61 public final class PaletteData { 62 63 /** 64 * true if the receiver is a direct palette, 65 * and false otherwise 66 */ 67 public bool isDirect; 68 69 /** 70 * the RGB values for an indexed palette, where the 71 * indices of the array correspond to pixel values 72 */ 73 public RGB[] colors; 74 75 /** 76 * the red mask for a direct palette 77 */ 78 public int redMask; 79 80 /** 81 * the green mask for a direct palette 82 */ 83 public int greenMask; 84 85 /** 86 * the blue mask for a direct palette 87 */ 88 public int blueMask; 89 90 /** 91 * the red shift for a direct palette 92 */ 93 public int redShift; 94 95 /** 96 * the green shift for a direct palette 97 */ 98 public int greenShift; 99 100 /** 101 * the blue shift for a direct palette 102 */ 103 public int blueShift; 104 105 /** 106 * Constructs a new indexed palette given an array of RGB values. 107 * 108 * @param colors the array of <code>RGB</code>s for the palette 109 * 110 * @exception IllegalArgumentException <ul> 111 * <li>ERROR_NULL_ARGUMENT - if the argument is null</li> 112 * </ul> 113 */ 114 public this(RGB[] colors) { 115 if (colors is null) SWT.error(SWT.ERROR_NULL_ARGUMENT); 116 this.colors = colors; 117 this.isDirect = false; 118 } 119 120 /** 121 * Constructs a new direct palette given the red, green and blue masks. 122 * 123 * @param redMask the red mask 124 * @param greenMask the green mask 125 * @param blueMask the blue mask 126 */ 127 public this(int redMask, int greenMask, int blueMask) { 128 this.redMask = redMask; 129 this.greenMask = greenMask; 130 this.blueMask = blueMask; 131 this.isDirect = true; 132 this.redShift = shiftForMask(redMask); 133 this.greenShift = shiftForMask(greenMask); 134 this.blueShift = shiftForMask(blueMask); 135 } 136 137 /** 138 * Returns the pixel value corresponding to the given <code>RGB</code>. 139 * 140 * @param rgb the RGB to get the pixel value for 141 * @return the pixel value for the given RGB 142 * 143 * @exception IllegalArgumentException <ul> 144 * <li>ERROR_NULL_ARGUMENT - if the argument is null</li> 145 * <li>ERROR_INVALID_ARGUMENT - if the RGB is not found in the palette</li> 146 * </ul> 147 */ 148 public int getPixel(RGB rgb) { 149 if (rgb is null) SWT.error(SWT.ERROR_NULL_ARGUMENT); 150 if (isDirect) { 151 int pixel = 0; 152 pixel |= (redShift < 0 ? rgb.red << -redShift : rgb.red >>> redShift) & redMask; 153 pixel |= (greenShift < 0 ? rgb.green << -greenShift : rgb.green >>> greenShift) & greenMask; 154 pixel |= (blueShift < 0 ? rgb.blue << -blueShift : rgb.blue >>> blueShift) & blueMask; 155 return pixel; 156 } else { 157 for (int i = 0; i < colors.length; i++) { 158 if (colors[i].opEquals(rgb) ) return i; 159 } 160 /* The RGB did not exist in the palette */ 161 SWT.error(SWT.ERROR_INVALID_ARGUMENT); 162 return 0; 163 } 164 } 165 166 /** 167 * Returns an <code>RGB</code> corresponding to the given pixel value. 168 * 169 * @param pixel the pixel to get the RGB value for 170 * @return the RGB value for the given pixel 171 * 172 * @exception IllegalArgumentException <ul> 173 * <li>ERROR_NULL_ARGUMENT - if the argument is null</li> 174 * <li>ERROR_INVALID_ARGUMENT - if the pixel does not exist in the palette</li> 175 * </ul> 176 */ 177 public RGB getRGB(int pixel) { 178 if (isDirect) { 179 int r = pixel & redMask; 180 r = (redShift < 0) ? r >>> -redShift : r << redShift; 181 int g = pixel & greenMask; 182 g = (greenShift < 0) ? g >>> -greenShift : g << greenShift; 183 int b = pixel & blueMask; 184 b = (blueShift < 0) ? b >>> -blueShift : b << blueShift; 185 return new RGB(r, g, b); 186 } else { 187 if (pixel < 0 || pixel >= colors.length) { 188 SWT.error(SWT.ERROR_INVALID_ARGUMENT); 189 } 190 return colors[pixel]; 191 } 192 } 193 194 /** 195 * Returns all the RGB values in the receiver if it is an 196 * indexed palette, or null if it is a direct palette. 197 * 198 * @return the <code>RGB</code>s for the receiver or null 199 */ 200 public RGB[] getRGBs() { 201 return colors; 202 } 203 204 /** 205 * Computes the shift value for a given mask. 206 * 207 * @param mask the mask to compute the shift for 208 * @return the shift amount 209 * 210 * @see PaletteData 211 */ 212 int shiftForMask(int mask) { 213 for (int i = 31; i >= 0; i--) { 214 if (((mask >> i) & 0x1) !is 0) return 7 - i; 215 } 216 return 32; 217 } 218 219 }