Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: d659a677d8df6b2732ddba98342eda5f48ec27b3 (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
/*******************************************************************************
 * Copyright (c) 2000, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.internal.image;


import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;

public class PngTrnsChunk extends PngChunk {
	static final int TRANSPARENCY_TYPE_PIXEL = 0;
	static final int TRANSPARENCY_TYPE_ALPHAS = 1;
	static final int RGB_DATA_LENGTH = 6;
	
PngTrnsChunk(RGB rgb) {
	super(RGB_DATA_LENGTH);
	setType(TYPE_tRNS);
	setInt16(DATA_OFFSET, rgb.red);
	setInt16(DATA_OFFSET + 2, rgb.green);
	setInt16(DATA_OFFSET + 4, rgb.blue);	
	setCRC(computeCRC());
}

PngTrnsChunk(byte[] reference){
	super(reference);
}

int getChunkType() {
	return CHUNK_tRNS;
}

void validateLength(PngIhdrChunk header, PngPlteChunk paletteChunk) {
	boolean valid;
	switch (header.getColorType()) {
		case PngIhdrChunk.COLOR_TYPE_RGB:
			// Three 2-byte values (RGB)
			valid = getLength() == 6;
			break;
		case PngIhdrChunk.COLOR_TYPE_PALETTE:
			// Three 2-byte values (RGB)
			valid = getLength() <= paletteChunk.getLength();
			break;
		case PngIhdrChunk.COLOR_TYPE_GRAYSCALE:
			// One 2-byte value
			valid = getLength() == 2;
			break;
		// Cannot use both Alpha and tRNS
		case PngIhdrChunk.COLOR_TYPE_RGB_WITH_ALPHA:
		case PngIhdrChunk.COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
		default:
			valid = false;
	}
	if (!valid) {
		SWT.error(SWT.ERROR_INVALID_IMAGE);
	}
}

/**
 * Answer whether the chunk is a valid tRNS chunk.
 */
void validate(PngFileReadState readState, PngIhdrChunk headerChunk, PngPlteChunk paletteChunk) {
	if (!readState.readIHDR
		|| (headerChunk.getMustHavePalette() && !readState.readPLTE)
		|| readState.readIDAT
		|| readState.readIEND) 
	{
		SWT.error(SWT.ERROR_INVALID_IMAGE);
	} else {
		readState.readTRNS = true;
	}
	
	validateLength(headerChunk, paletteChunk);
	
	super.validate(readState, headerChunk);
}


int getTransparencyType(PngIhdrChunk header) {
	if (header.getColorType() == PngIhdrChunk.COLOR_TYPE_PALETTE) {
		return TRANSPARENCY_TYPE_ALPHAS;
	}
	return TRANSPARENCY_TYPE_PIXEL;
}

/**
 * Answer the transparent pixel RGB value.
 * This is not valid for palette color types.
 * This is not valid for alpha color types.
 * This will convert a grayscale value into
 * a palette index.
 * It will compress a 6 byte RGB into a 3 byte
 * RGB.
 */
int getSwtTransparentPixel(PngIhdrChunk header) {
	switch (header.getColorType()) {
		case PngIhdrChunk.COLOR_TYPE_GRAYSCALE:
			int gray = ((reference[DATA_OFFSET] & 0xFF) << 8)
				+ (reference[DATA_OFFSET + 1] & 0xFF);
			if (header.getBitDepth() > 8) {
				return PNGFileFormat.compress16BitDepthTo8BitDepth(gray);
			}
			return gray & 0xFF;
		case PngIhdrChunk.COLOR_TYPE_RGB:
			int red = ((reference[DATA_OFFSET] & 0xFF) << 8)
				| (reference[DATA_OFFSET + 1] & 0xFF);
			int green = ((reference[DATA_OFFSET + 2] & 0xFF) << 8)
				| (reference[DATA_OFFSET + 3] & 0xFF);
			int blue = ((reference[DATA_OFFSET + 4] & 0xFF) << 8)
				| (reference[DATA_OFFSET + 5] & 0xFF);			
			if (header.getBitDepth() > 8) {
				red = PNGFileFormat.compress16BitDepthTo8BitDepth(red);
				green = PNGFileFormat.compress16BitDepthTo8BitDepth(green);
				blue = PNGFileFormat.compress16BitDepthTo8BitDepth(blue);			
			}
			return (red << 16) | (green << 8) | blue;	
		default:
			SWT.error(SWT.ERROR_INVALID_IMAGE);
			return -1;
	}
}

/**
 * Answer an array of Alpha values that correspond to the 
 * colors in the palette.
 * This is only valid for the COLOR_TYPE_PALETTE color type.
 */
byte[] getAlphaValues(PngIhdrChunk header, PngPlteChunk paletteChunk) {
	if (header.getColorType() != PngIhdrChunk.COLOR_TYPE_PALETTE) {
		SWT.error(SWT.ERROR_INVALID_IMAGE);
	}
	byte[] alphas = new byte[paletteChunk.getPaletteSize()];
	int dataLength = getLength();
	int i = 0;
	for (i = 0; i < dataLength; i++) {
		alphas[i] = reference[DATA_OFFSET + i];
	}
	/**
	 * Any palette entries which do not have a corresponding
	 * alpha value in the tRNS chunk are spec'd to have an 
	 * alpha of 255.
	 */
	for (int j = i; j < alphas.length; j++) {
		alphas[j] = (byte) 255;
	}
	return alphas;
}
}

Back to the top