Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 4037fe85456bead878f98370d81454888fa6f5ee (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.opengl.examples;

import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;

public class ImageDataUtil {
	/**
	 * Alpha mode, values 0 - 255 specify global alpha level
	 */
	static final int
		ALPHA_OPAQUE = 255,           // Fully opaque (ignores any alpha data)
		ALPHA_TRANSPARENT = 0,        // Fully transparent (ignores any alpha data)
		ALPHA_CHANNEL_SEPARATE = -1,  // Use alpha channel from separate alphaData
		ALPHA_CHANNEL_SOURCE = -2,    // Use alpha channel embedded in sourceData
		ALPHA_MASK_UNPACKED = -3,     // Use transparency mask formed by bytes in alphaData (non-zero is opaque)
		ALPHA_MASK_PACKED = -4,       // Use transparency mask formed by packed bits in alphaData
		ALPHA_MASK_INDEX = -5,        // Consider source palette indices transparent if in alphaData array
		ALPHA_MASK_RGB = -6;          // Consider source RGBs transparent if in RGB888 format alphaData array
		
	/**
	 * Data types (internal)
	 */
	private static final int
		// direct / true color formats with arbitrary masks & shifts
		TYPE_GENERIC_8 = 0,
		TYPE_GENERIC_16_MSB = 1,
		TYPE_GENERIC_16_LSB = 2,
		TYPE_GENERIC_24 = 3,
		TYPE_GENERIC_32_MSB = 4,
		TYPE_GENERIC_32_LSB = 5;
		
	/**
	 * Byte and bit order constants.
	 */
	static final int LSB_FIRST = 0;
	static final int MSB_FIRST = 1;
	
	/**
	 * Blit operation bits to be OR'ed together to specify the desired operation.
	 */
	static final int
		BLIT_SRC = 1,     // copy source directly, else applies logic operations
		BLIT_ALPHA = 2,   // enable alpha blending
		BLIT_DITHER = 4;  // enable dithering in low color modes
		
	/**
	 * Arbitrary channel width data to 8-bit conversion table.
	 */
	static final byte[][] ANY_TO_EIGHT = new byte[9][];
	static {
		for (int b = 0; b < 9; ++b) {
			byte[] data = ANY_TO_EIGHT[b] = new byte[1 << b];
			if (b == 0) continue;
			int inc = 0;
			for (int bit = 0x10000; (bit >>= b) != 0;) inc |= bit;
			for (int v = 0, p = 0; v < 0x10000; v+= inc) data[p++] = (byte)(v >> 8);
		}
	}

	/**
	 * Blits a direct palette image into a direct palette image.
	 * <p>
	 * Note: When the source and destination depth, order and masks
	 * are pairwise equal and the blitter operation is BLIT_SRC,
	 * the masks are ignored.  Hence when not changing the image
	 * data format, 0 may be specified for the masks.
	 * </p>
	 * 
	 * @param op the blitter operation: a combination of BLIT_xxx flags
	 *        (see BLIT_xxx constants)
	 * @param srcData the source byte array containing image data
	 * @param srcDepth the source depth: one of 8, 16, 24, 32
	 * @param srcStride the source number of bytes per line
	 * @param srcOrder the source byte ordering: one of MSB_FIRST or LSB_FIRST;
	 *        ignored if srcDepth is not 16 or 32
	 * @param srcX the top-left x-coord of the source blit region
	 * @param srcY the top-left y-coord of the source blit region
	 * @param srcWidth the width of the source blit region
	 * @param srcHeight the height of the source blit region
	 * @param srcRedMask the source red channel mask
	 * @param srcGreenMask the source green channel mask
	 * @param srcBlueMask the source blue channel mask
	 * @param alphaMode the alpha blending or mask mode, may be
	 *        an integer 0-255 for global alpha; ignored if BLIT_ALPHA
	 *        not specified in the blitter operations
	 *        (see ALPHA_MODE_xxx constants)
	 * @param alphaData the alpha blending or mask data, varies depending
	 *        on the value of alphaMode and sometimes ignored
	 * @param alphaStride the alpha data number of bytes per line
	 * @param alphaX the top-left x-coord of the alpha blit region
	 * @param alphaY the top-left y-coord of the alpha blit region
	 * @param destData the destination byte array containing image data
	 * @param destDepth the destination depth: one of 8, 16, 24, 32
	 * @param destStride the destination number of bytes per line
	 * @param destOrder the destination byte ordering: one of MSB_FIRST or LSB_FIRST;
	 *        ignored if destDepth is not 16 or 32
	 * @param destX the top-left x-coord of the destination blit region
	 * @param destY the top-left y-coord of the destination blit region
	 * @param destWidth the width of the destination blit region
	 * @param destHeight the height of the destination blit region
	 * @param destRedMask the destination red channel mask
	 * @param destGreenMask the destination green channel mask
	 * @param destBlueMask the destination blue channel mask
	 * @param flipX if true the resulting image is flipped along the vertical axis
	 * @param flipY if true the resulting image is flipped along the horizontal axis
	 */
	static void blit(int op,
		byte[] srcData, int srcDepth, int srcStride, int srcOrder,
		int srcX, int srcY, int srcWidth, int srcHeight,
		int srcRedMask, int srcGreenMask, int srcBlueMask,
		int alphaMode, byte[] alphaData, int alphaStride, int alphaX, int alphaY,
		byte[] destData, int destDepth, int destStride, int destOrder,
		int destX, int destY, int destWidth, int destHeight,
		int destRedMask, int destGreenMask, int destBlueMask,
		boolean flipX, boolean flipY) {
		if ((destWidth <= 0) || (destHeight <= 0) || (alphaMode == ALPHA_TRANSPARENT)) return;

		// these should be supplied as params later
		final int srcAlphaMask = 0, destAlphaMask = 0;

		/*** Prepare scaling data ***/
		final int dwm1 = destWidth - 1;
		final int sfxi = (dwm1 != 0) ? (int)((((long)srcWidth << 16) - 1) / dwm1) : 0;
		final int dhm1 = destHeight - 1;
		final int sfyi = (dhm1 != 0) ? (int)((((long)srcHeight << 16) - 1) / dhm1) : 0;

		/*** Prepare source-related data ***/
		final int sbpp, stype;
		switch (srcDepth) {
			case 8:
				sbpp = 1;
				stype = TYPE_GENERIC_8;
				break;
			case 16:
				sbpp = 2;
				stype = (srcOrder == MSB_FIRST) ? TYPE_GENERIC_16_MSB : TYPE_GENERIC_16_LSB;
				break;
			case 24:
				sbpp = 3;
				stype = TYPE_GENERIC_24;
				break;
			case 32:
				sbpp = 4;
				stype = (srcOrder == MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB;
				break;
			default:
				//throw new IllegalArgumentException("Invalid source type");
				return;
		}			
		int spr = srcY * srcStride + srcX * sbpp;

		/*** Prepare destination-related data ***/
		final int dbpp, dtype;
		switch (destDepth) {
			case 8:
				dbpp = 1;
				dtype = TYPE_GENERIC_8;
				break;
			case 16:
				dbpp = 2;
				dtype = (destOrder == MSB_FIRST) ? TYPE_GENERIC_16_MSB : TYPE_GENERIC_16_LSB;
				break;
			case 24:
				dbpp = 3;
				dtype = TYPE_GENERIC_24;
				break;
			case 32:
				dbpp = 4;
				dtype = (destOrder == MSB_FIRST) ? TYPE_GENERIC_32_MSB : TYPE_GENERIC_32_LSB;
				break;
			default:
				//throw new IllegalArgumentException("Invalid destination type");
				return;
		}			
		int dpr = ((flipY) ? destY + dhm1 : destY) * destStride + ((flipX) ? destX + dwm1 : destX) * dbpp;
		final int dprxi = (flipX) ? -dbpp : dbpp;
		final int dpryi = (flipY) ? -destStride : destStride;

		/*** Prepare special processing data ***/
		int apr;
		if ((op & BLIT_ALPHA) != 0) {
			switch (alphaMode) {
				case ALPHA_MASK_UNPACKED:
				case ALPHA_CHANNEL_SEPARATE:
					if (alphaData == null) alphaMode = 0x10000;
					apr = alphaY * alphaStride + alphaX;
					break;
				case ALPHA_MASK_PACKED:
					if (alphaData == null) alphaMode = 0x10000;
					alphaStride <<= 3;
					apr = alphaY * alphaStride + alphaX;
					break;
				case ALPHA_MASK_INDEX:
					//throw new IllegalArgumentException("Invalid alpha type");
					return;
				case ALPHA_MASK_RGB:
					if (alphaData == null) alphaMode = 0x10000;
					apr = 0;
					break;
				default:
					alphaMode = (alphaMode << 16) / 255; // prescale
				case ALPHA_CHANNEL_SOURCE:
					apr = 0;
					break;
			}
		} else {
			alphaMode = 0x10000;
			apr = 0;
		}

		/*** Blit ***/
		int dp = dpr;
		int sp = spr;
		if ((alphaMode == 0x10000) && (stype == dtype) &&
			(srcRedMask == destRedMask) && (srcGreenMask == destGreenMask) &&
			(srcBlueMask == destBlueMask) && (srcAlphaMask == destAlphaMask)) {
			/*** Fast blit (straight copy) ***/
			switch (sbpp) {
				case 1:
					for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
						for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
							destData[dp] = srcData[sp];
							sp += (sfx >>> 16);
						}
					}
					break;					
				case 2:
					for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
						for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
							destData[dp] = srcData[sp];
							destData[dp + 1] = srcData[sp + 1];
							sp += (sfx >>> 16) * 2;
						}
					}
					break;
				case 3:
					for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
						for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
							destData[dp] = srcData[sp];
							destData[dp + 1] = srcData[sp + 1];
							destData[dp + 2] = srcData[sp + 2];
							sp += (sfx >>> 16) * 3;
						}
					}
					break;
				case 4:
					for (int dy = destHeight, sfy = sfyi; dy > 0; --dy, sp = spr += (sfy >>> 16) * srcStride, sfy = (sfy & 0xffff) + sfyi, dp = dpr += dpryi) {
						for (int dx = destWidth, sfx = sfxi; dx > 0; --dx, dp += dprxi, sfx = (sfx & 0xffff) + sfxi) {
							destData[dp] = srcData[sp];
							destData[dp + 1] = srcData[sp + 1];
							destData[dp + 2] = srcData[sp + 2];
							destData[dp + 3] = srcData[sp + 3];
							sp += (sfx >>> 16) * 4;
						}
					}
					break;
			}
			return;
		}
		/*** Comprehensive blit (apply transformations) ***/
		final int srcRedShift = getChannelShift(srcRedMask);
		final byte[] srcReds = ANY_TO_EIGHT[getChannelWidth(srcRedMask, srcRedShift)];
		final int srcGreenShift = getChannelShift(srcGreenMask);
		final byte[] srcGreens = ANY_TO_EIGHT[getChannelWidth(srcGreenMask, srcGreenShift)];
		final int srcBlueShift = getChannelShift(srcBlueMask);
		final byte[] srcBlues = ANY_TO_EIGHT[getChannelWidth(srcBlueMask, srcBlueShift)];
		final int srcAlphaShift = getChannelShift(srcAlphaMask);
		final byte[] srcAlphas = ANY_TO_EIGHT[getChannelWidth(srcAlphaMask, srcAlphaShift)];

		final int destRedShift = getChannelShift(destRedMask);
		final int destRedWidth = getChannelWidth(destRedMask, destRedShift);
		final byte[] destReds = ANY_TO_EIGHT[destRedWidth];
		final int destRedPreShift = 8 - destRedWidth;
		final int destGreenShift = getChannelShift(destGreenMask);
		final int destGreenWidth = getChannelWidth(destGreenMask, destGreenShift);
		final byte[] destGreens = ANY_TO_EIGHT[destGreenWidth];
		final int destGreenPreShift = 8 - destGreenWidth;
		final int destBlueShift = getChannelShift(destBlueMask);
		final int destBlueWidth = getChannelWidth(destBlueMask, destBlueShift);
		final byte[] destBlues = ANY_TO_EIGHT[destBlueWidth];
		final int destBluePreShift = 8 - destBlueWidth;
		final int destAlphaShift = getChannelShift(destAlphaMask);
		final int destAlphaWidth = getChannelWidth(destAlphaMask, destAlphaShift);
		final byte[] destAlphas = ANY_TO_EIGHT[destAlphaWidth];
		final int destAlphaPreShift = 8 - destAlphaWidth;

		int ap = apr, alpha = alphaMode;
		int r = 0, g = 0, b = 0, a = 0;
		int rq = 0, gq = 0, bq = 0, aq = 0;
		for (int dy = destHeight, sfy = sfyi; dy > 0; --dy,
				sp = spr += (sfy >>> 16) * srcStride,
				ap = apr += (sfy >>> 16) * alphaStride,
				sfy = (sfy & 0xffff) + sfyi,
				dp = dpr += dpryi) {
			for (int dx = destWidth, sfx = sfxi; dx > 0; --dx,
					dp += dprxi,
					sfx = (sfx & 0xffff) + sfxi) {
				/*** READ NEXT PIXEL ***/
				switch (stype) {
					case TYPE_GENERIC_8: {
						final int data = srcData[sp] & 0xff;
						sp += (sfx >>> 16);
						r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
						g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
						b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
						a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
					} break;
					case TYPE_GENERIC_16_MSB: {
						final int data = ((srcData[sp] & 0xff) << 8) | (srcData[sp + 1] & 0xff);
						sp += (sfx >>> 16) * 2;
						r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
						g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
						b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
						a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
					} break;
					case TYPE_GENERIC_16_LSB: {
						final int data = ((srcData[sp + 1] & 0xff) << 8) | (srcData[sp] & 0xff);
						sp += (sfx >>> 16) * 2;
						r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
						g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
						b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
						a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
					} break;
					case TYPE_GENERIC_24: {
						final int data = (( ((srcData[sp] & 0xff) << 8) |
							(srcData[sp + 1] & 0xff)) << 8) |
							(srcData[sp + 2] & 0xff);
						sp += (sfx >>> 16) * 3;
						r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
						g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
						b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
						a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
					} break;
					case TYPE_GENERIC_32_MSB: {
						final int data = (( (( ((srcData[sp] & 0xff) << 8) |
							(srcData[sp + 1] & 0xff)) << 8) |
							(srcData[sp + 2] & 0xff)) << 8) |
							(srcData[sp + 3] & 0xff);
						sp += (sfx >>> 16) * 4;
						r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
						g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
						b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
						a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
					} break;
					case TYPE_GENERIC_32_LSB: {
						final int data = (( (( ((srcData[sp + 3] & 0xff) << 8) |
							(srcData[sp + 2] & 0xff)) << 8) |
							(srcData[sp + 1] & 0xff)) << 8) |
							(srcData[sp] & 0xff);
						sp += (sfx >>> 16) * 4;
						r = srcReds[(data & srcRedMask) >>> srcRedShift] & 0xff;
						g = srcGreens[(data & srcGreenMask) >>> srcGreenShift] & 0xff;
						b = srcBlues[(data & srcBlueMask) >>> srcBlueShift] & 0xff;
						a = srcAlphas[(data & srcAlphaMask) >>> srcAlphaShift] & 0xff;
					} break;
				}

				/*** DO SPECIAL PROCESSING IF REQUIRED ***/
				switch (alphaMode) {
					case ALPHA_CHANNEL_SEPARATE:
						alpha = ((alphaData[ap] & 0xff) << 16) / 255;
						ap += (sfx >> 16);
						break;
					case ALPHA_CHANNEL_SOURCE:
						alpha = (a << 16) / 255;
						break;
					case ALPHA_MASK_UNPACKED:
						alpha = (alphaData[ap] != 0) ? 0x10000 : 0;
						ap += (sfx >> 16);
						break;						
					case ALPHA_MASK_PACKED:
						alpha = (alphaData[ap >> 3] << ((ap & 7) + 9)) & 0x10000;
						ap += (sfx >> 16);
						break;
					case ALPHA_MASK_RGB:
						alpha = 0x10000;
						for (int i = 0; i < alphaData.length; i += 3) {
							if ((r == alphaData[i]) && (g == alphaData[i + 1]) && (b == alphaData[i + 2])) {
								alpha = 0x0000;
								break;
							}
						}
						break;
				}
				if (alpha != 0x10000) {
					if (alpha == 0x0000) continue;
					switch (dtype) {
						case TYPE_GENERIC_8: {
							final int data = destData[dp] & 0xff;
							rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
							gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
							bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
							aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
						} break;
						case TYPE_GENERIC_16_MSB: {
							final int data = ((destData[dp] & 0xff) << 8) | (destData[dp + 1] & 0xff);
							rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
							gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
							bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
							aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
						} break;
						case TYPE_GENERIC_16_LSB: {
							final int data = ((destData[dp + 1] & 0xff) << 8) | (destData[dp] & 0xff);
							rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
							gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
							bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
							aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
						} break;
						case TYPE_GENERIC_24: {
							final int data = (( ((destData[dp] & 0xff) << 8) |
								(destData[dp + 1] & 0xff)) << 8) |
								(destData[dp + 2] & 0xff);
							rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
							gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
							bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
							aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
						} break;
						case TYPE_GENERIC_32_MSB: {
							final int data = (( (( ((destData[dp] & 0xff) << 8) |
								(destData[dp + 1] & 0xff)) << 8) |
								(destData[dp + 2] & 0xff)) << 8) |
								(destData[dp + 3] & 0xff);
							rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
							gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
							bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
							aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
						} break;
						case TYPE_GENERIC_32_LSB: {
							final int data = (( (( ((destData[dp + 3] & 0xff) << 8) |
								(destData[dp + 2] & 0xff)) << 8) |
								(destData[dp + 1] & 0xff)) << 8) |
								(destData[dp] & 0xff);
							rq = destReds[(data & destRedMask) >>> destRedShift] & 0xff;
							gq = destGreens[(data & destGreenMask) >>> destGreenShift] & 0xff;
							bq = destBlues[(data & destBlueMask) >>> destBlueShift] & 0xff;
							aq = destAlphas[(data & destAlphaMask) >>> destAlphaShift] & 0xff;
						} break;
					}
					// Perform alpha blending
					a = aq + ((a - aq) * alpha >> 16);
					r = rq + ((r - rq) * alpha >> 16);
					g = gq + ((g - gq) * alpha >> 16);
					b = bq + ((b - bq) * alpha >> 16);
				}

				/*** WRITE NEXT PIXEL ***/
				final int data = 
					(r >>> destRedPreShift << destRedShift) |
					(g >>> destGreenPreShift << destGreenShift) |
					(b >>> destBluePreShift << destBlueShift) |
					(a >>> destAlphaPreShift << destAlphaShift);
				switch (dtype) {
					case TYPE_GENERIC_8: {
						destData[dp] = (byte) data;
					} break;
					case TYPE_GENERIC_16_MSB: {
						destData[dp] = (byte) (data >>> 8);
						destData[dp + 1] = (byte) (data & 0xff);
					} break;
					case TYPE_GENERIC_16_LSB: {
						destData[dp] = (byte) (data & 0xff);
						destData[dp + 1] = (byte) (data >>> 8);
					} break;
					case TYPE_GENERIC_24: {
						destData[dp] = (byte) (data >>> 16);
						destData[dp + 1] = (byte) (data >>> 8);
						destData[dp + 2] = (byte) (data & 0xff);
					} break;
					case TYPE_GENERIC_32_MSB: {
						destData[dp] = (byte) (data >>> 24);
						destData[dp + 1] = (byte) (data >>> 16);
						destData[dp + 2] = (byte) (data >>> 8);
						destData[dp + 3] = (byte) (data & 0xff);
					} break;
					case TYPE_GENERIC_32_LSB: {
						destData[dp] = (byte) (data & 0xff);
						destData[dp + 1] = (byte) (data >>> 8);
						destData[dp + 2] = (byte) (data >>> 16);
						destData[dp + 3] = (byte) (data >>> 24);
					} break;
				}
			}
		}			
	}

	/**
	 * Computes the required channel shift from a mask.
	 */
	static int getChannelShift(int mask) {
		if (mask == 0) return 0;
		int i;
		for (i = 0; ((mask & 1) == 0) && (i < 32); ++i) {
			mask >>>= 1;
		}
		return i;
	}
	
	/**
	 * Computes the required channel width (depth) from a mask.
	 */
	static int getChannelWidth(int mask, int shift) {
		if (mask == 0) return 0;
		int i;
		mask >>>= shift;
		for (i = shift; ((mask & 1) != 0) && (i < 32); ++i) {
			mask >>>= 1;
		}
		return i - shift;
	}

	public static ImageData convertImageData (ImageData source) {
		PaletteData palette = new PaletteData (0xff0000, 0xff00, 0xff);
		ImageData newSource = new ImageData (source.width, source.height, 24, palette);

		ImageDataUtil.blit (
			1,
			source.data,
			source.depth,
			source.bytesPerLine,
			(source.depth != 16) ? MSB_FIRST : LSB_FIRST,
			0,
			0,
			source.width,
			source.height,
			source.palette.redMask,
			source.palette.greenMask,
			source.palette.blueMask,
			255,
			null,
			0,
			0,
			0,
			newSource.data,
			newSource.depth,
			newSource.bytesPerLine,
			(newSource.depth != 16) ? MSB_FIRST : LSB_FIRST,
			0,
			0,
			newSource.width,
			newSource.height,
			newSource.palette.redMask,
			newSource.palette.greenMask,
			newSource.palette.blueMask,
			false,
			true);

		return newSource;
	}
}

Back to the top