1 /*******************************************************************************
2 * Copyright (c) 2000, 2015 IBM Corporation and others.
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
9 * SPDX-License-Identifier: EPL-2.0
12 * IBM Corporation - initial API and implementation
13 * Lars Vogel <Lars.Vogel@vogella.com> - Bug 483460
14 *******************************************************************************/
15 package org.eclipse.swt.graphics;
18 import org.eclipse.swt.*;
21 * Instances of this class describe the color data used by an image.
23 * Depending on the depth of the image, the PaletteData can take one
24 * of two forms, indicated by the isDirect field:
28 * <em>isDirect is false</em>
31 * If isDirect is <code>false</code>, this palette is an indexed
32 * palette which maps pixel values to RGBs. The actual RGB values
33 * may be retrieved by using the getRGBs() method.
36 * <em>isDirect is true</em>
39 * If isDirect is <code>true</code>, this palette is a direct color
40 * palette. Instead of containing RGB values, it contains red,
41 * green and blue mask and shift information which indicates how
42 * the color components may be extracted from a given pixel.
43 * This means that the RGB value is actually encoded in the pixel value.
45 * In this case, the shift data is the number of bits required to shift
46 * the RGB value to the left in order to align the high bit of the
47 * corresponding mask with the high bit of the first byte. This number
48 * may be negative, so care must be taken when shifting. For example,
49 * with a red mask of 0xFF0000, the red shift would be -16. With a red
50 * mask of 0x1F, the red shift would be 3.
57 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
60 public final class PaletteData {
63 * true if the receiver is a direct palette,
66 public boolean isDirect;
69 * the RGB values for an indexed palette, where the
70 * indices of the array correspond to pixel values
75 * the red mask for a direct palette
80 * the green mask for a direct palette
85 * the blue mask for a direct palette
90 * the red shift for a direct palette
95 * the green shift for a direct palette
97 public int greenShift;
100 * the blue shift for a direct palette
102 public int blueShift;
105 * Constructs a new indexed palette given an array of RGB values.
107 * @param colors the array of <code>RGB</code>s for the palette
109 * @exception IllegalArgumentException <ul>
110 * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
113 public PaletteData(RGB... colors) {
114 if (colors == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
115 this.colors = colors;
116 this.isDirect = false;
120 * Constructs a new direct palette given the red, green and blue masks.
122 * @param redMask the red mask
123 * @param greenMask the green mask
124 * @param blueMask the blue mask
126 public PaletteData(int redMask, int greenMask, int blueMask) {
127 this.redMask = redMask;
128 this.greenMask = greenMask;
129 this.blueMask = blueMask;
130 this.isDirect = true;
131 this.redShift = shiftForMask(redMask);
132 this.greenShift = shiftForMask(greenMask);
133 this.blueShift = shiftForMask(blueMask);
137 * Returns the pixel value corresponding to the given <code>RGB</code>.
139 * @param rgb the RGB to get the pixel value for
140 * @return the pixel value for the given RGB
142 * @exception IllegalArgumentException <ul>
143 * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
144 * <li>ERROR_INVALID_ARGUMENT - if the RGB is not found in the palette</li>
147 public int getPixel(RGB rgb) {
148 if (rgb == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
151 pixel |= (redShift < 0 ? rgb.red << -redShift : rgb.red >>> redShift) & redMask;
152 pixel |= (greenShift < 0 ? rgb.green << -greenShift : rgb.green >>> greenShift) & greenMask;
153 pixel |= (blueShift < 0 ? rgb.blue << -blueShift : rgb.blue >>> blueShift) & blueMask;
156 for (int i = 0; i < colors.length; i++) {
157 if (colors[i].equals(rgb)) return i;
159 /* The RGB did not exist in the palette */
160 SWT.error(SWT.ERROR_INVALID_ARGUMENT);
166 * Returns an <code>RGB</code> corresponding to the given pixel value.
168 * @param pixel the pixel to get the RGB value for
169 * @return the RGB value for the given pixel
171 * @exception IllegalArgumentException <ul>
172 * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
173 * <li>ERROR_INVALID_ARGUMENT - if the pixel does not exist in the palette</li>
176 public RGB getRGB(int pixel) {
178 int r = pixel & redMask;
179 r = (redShift < 0) ? r >>> -redShift : r << redShift;
180 int g = pixel & greenMask;
181 g = (greenShift < 0) ? g >>> -greenShift : g << greenShift;
182 int b = pixel & blueMask;
183 b = (blueShift < 0) ? b >>> -blueShift : b << blueShift;
184 return new RGB(r, g, b);
186 if (pixel < 0 || pixel >= colors.length) {
187 SWT.error(SWT.ERROR_INVALID_ARGUMENT);
189 return colors[pixel];
194 * Returns all the RGB values in the receiver if it is an
195 * indexed palette, or null if it is a direct palette.
197 * @return the <code>RGB</code>s for the receiver or null
199 public RGB[] getRGBs() {
204 * Computes the shift value for a given mask.
206 * @param mask the mask to compute the shift for
207 * @return the shift amount
211 int shiftForMask(int mask) {
212 for (int i = 31; i >= 0; i--) {
213 if (((mask >> i) & 0x1) != 0) return 7 - i;