1 11 package org.eclipse.swt.internal.image; 12 13 14 import org.eclipse.swt.*; 15 import org.eclipse.swt.graphics.*; 16 import java.io.*; 17 18 final class WinICOFileFormat extends FileFormat { 19 20 byte[] bitInvertData(byte[] data, int startIndex, int endIndex) { 21 for (int i = startIndex; i < endIndex; i++) { 23 data[i] = (byte)(255 - data[i - startIndex]); 24 } 25 return data; 26 } 27 28 static final byte[] convertPad(byte[] data, int width, int height, int depth, int pad, int newPad) { 29 if (pad == newPad) return data; 30 int stride = (width * depth + 7) / 8; 31 int bpl = (stride + (pad - 1)) / pad * pad; 32 int newBpl = (stride + (newPad - 1)) / newPad * newPad; 33 byte[] newData = new byte[height * newBpl]; 34 int srcIndex = 0, destIndex = 0; 35 for (int y = 0; y < height; y++) { 36 System.arraycopy(data, srcIndex, newData, destIndex, newBpl); 37 srcIndex += bpl; 38 destIndex += newBpl; 39 } 40 return newData; 41 } 42 46 int iconSize(ImageData i) { 47 int shapeDataStride = (i.width * i.depth + 31) / 32 * 4; 48 int maskDataStride = (i.width + 31) / 32 * 4; 49 int dataSize = (shapeDataStride + maskDataStride) * i.height; 50 int paletteSize = i.palette.colors != null ? i.palette.colors.length * 4 : 0; 51 return WinBMPFileFormat.BMPHeaderFixedSize + paletteSize + dataSize; 52 } 53 boolean isFileFormat(LEDataInputStream stream) { 54 try { 55 byte[] header = new byte[4]; 56 stream.read(header); 57 stream.unread(header); 58 return header[0] == 0 && header[1] == 0 && header[2] == 1 && header[3] == 0; 59 } catch (Exception e) { 60 return false; 61 } 62 } 63 boolean isValidIcon(ImageData i) { 64 switch (i.depth) { 65 case 1: 66 case 4: 67 case 8: 68 if (i.palette.isDirect) return false; 69 int size = i.palette.colors.length; 70 return size == 2 || size == 16 || size == 32 || size == 256; 71 case 24: 72 case 32: 73 return i.palette.isDirect; 74 } 75 return false; 76 } 77 int loadFileHeader(LEDataInputStream byteStream) { 78 int[] fileHeader = new int[3]; 79 try { 80 fileHeader[0] = byteStream.readShort(); 81 fileHeader[1] = byteStream.readShort(); 82 fileHeader[2] = byteStream.readShort(); 83 } catch (IOException e) { 84 SWT.error(SWT.ERROR_IO, e); 85 } 86 if ((fileHeader[0] != 0) || (fileHeader[1] != 1)) 87 SWT.error(SWT.ERROR_INVALID_IMAGE); 88 int numIcons = fileHeader[2]; 89 if (numIcons <= 0) 90 SWT.error(SWT.ERROR_INVALID_IMAGE); 91 return numIcons; 92 } 93 int loadFileHeader(LEDataInputStream byteStream, boolean hasHeader) { 94 int[] fileHeader = new int[3]; 95 try { 96 if (hasHeader) { 97 fileHeader[0] = byteStream.readShort(); 98 fileHeader[1] = byteStream.readShort(); 99 } else { 100 fileHeader[0] = 0; 101 fileHeader[1] = 1; 102 } 103 fileHeader[2] = byteStream.readShort(); 104 } catch (IOException e) { 105 SWT.error(SWT.ERROR_IO, e); 106 } 107 if ((fileHeader[0] != 0) || (fileHeader[1] != 1)) 108 SWT.error(SWT.ERROR_INVALID_IMAGE); 109 int numIcons = fileHeader[2]; 110 if (numIcons <= 0) 111 SWT.error(SWT.ERROR_INVALID_IMAGE); 112 return numIcons; 113 } 114 ImageData[] loadFromByteStream() { 115 int numIcons = loadFileHeader(inputStream); 116 int[][] headers = loadIconHeaders(numIcons); 117 ImageData[] icons = new ImageData[headers.length]; 118 for (int i = 0; i < icons.length; i++) { 119 icons[i] = loadIcon(headers[i]); 120 } 121 return icons; 122 } 123 126 ImageData loadIcon(int[] iconHeader) { 127 byte[] infoHeader = loadInfoHeader(iconHeader); 128 WinBMPFileFormat bmpFormat = new WinBMPFileFormat(); 129 bmpFormat.inputStream = inputStream; 130 PaletteData palette = bmpFormat.loadPalette(infoHeader); 131 byte[] shapeData = bmpFormat.loadData(infoHeader); 132 int width = (infoHeader[4] & 0xFF) | ((infoHeader[5] & 0xFF) << 8) | ((infoHeader[6] & 0xFF) << 16) | ((infoHeader[7] & 0xFF) << 24); 133 int height = (infoHeader[8] & 0xFF) | ((infoHeader[9] & 0xFF) << 8) | ((infoHeader[10] & 0xFF) << 16) | ((infoHeader[11] & 0xFF) << 24); 134 if (height < 0) height = -height; 135 int depth = (infoHeader[14] & 0xFF) | ((infoHeader[15] & 0xFF) << 8); 136 infoHeader[14] = 1; 137 infoHeader[15] = 0; 138 byte[] maskData = bmpFormat.loadData(infoHeader); 139 maskData = convertPad(maskData, width, height, 1, 4, 2); 140 bitInvertData(maskData, 0, maskData.length); 141 return ImageData.internal_new( 142 width, 143 height, 144 depth, 145 palette, 146 4, 147 shapeData, 148 2, 149 maskData, 150 null, 151 -1, 152 -1, 153 SWT.IMAGE_ICO, 154 0, 155 0, 156 0, 157 0); 158 } 159 int[][] loadIconHeaders(int numIcons) { 160 int[][] headers = new int[numIcons][7]; 161 try { 162 for (int i = 0; i < numIcons; i++) { 163 headers[i][0] = inputStream.read(); 164 headers[i][1] = inputStream.read(); 165 headers[i][2] = inputStream.readShort(); 166 headers[i][3] = inputStream.readShort(); 167 headers[i][4] = inputStream.readShort(); 168 headers[i][5] = inputStream.readInt(); 169 headers[i][6] = inputStream.readInt(); 170 } 171 } catch (IOException e) { 172 SWT.error(SWT.ERROR_IO, e); 173 } 174 return headers; 175 } 176 byte[] loadInfoHeader(int[] iconHeader) { 177 int width = iconHeader[0]; 178 int height = iconHeader[1]; 179 int numColors = iconHeader[2]; if (numColors == 0) numColors = 256; if ((numColors != 2) && (numColors != 8) && (numColors != 16) && 182 (numColors != 32) && (numColors != 256)) 183 SWT.error(SWT.ERROR_INVALID_IMAGE); 184 if (inputStream.getPosition() < iconHeader[6]) { 185 try { 187 inputStream.skip(iconHeader[6] - inputStream.getPosition()); 188 } catch (IOException e) { 189 SWT.error(SWT.ERROR_IO, e); 190 return null; 191 } 192 } 193 byte[] infoHeader = new byte[WinBMPFileFormat.BMPHeaderFixedSize]; 194 try { 195 inputStream.read(infoHeader); 196 } catch (IOException e) { 197 SWT.error(SWT.ERROR_IO, e); 198 } 199 if (((infoHeader[12] & 0xFF) | ((infoHeader[13] & 0xFF) << 8)) != 1) 200 SWT.error(SWT.ERROR_INVALID_IMAGE); 201 int infoWidth = (infoHeader[4] & 0xFF) | ((infoHeader[5] & 0xFF) << 8) | ((infoHeader[6] & 0xFF) << 16) | ((infoHeader[7] & 0xFF) << 24); 202 int infoHeight = (infoHeader[8] & 0xFF) | ((infoHeader[9] & 0xFF) << 8) | ((infoHeader[10] & 0xFF) << 16) | ((infoHeader[11] & 0xFF) << 24); 203 int bitCount = (infoHeader[14] & 0xFF) | ((infoHeader[15] & 0xFF) << 8); 204 if (height == infoHeight && bitCount == 1) height /= 2; 205 if (!((width == infoWidth) && (height * 2 == infoHeight) && 206 (bitCount == 1 || bitCount == 4 || bitCount == 8 || bitCount == 24 || bitCount == 32))) 207 SWT.error(SWT.ERROR_INVALID_IMAGE); 208 infoHeader[8] = (byte)(height & 0xFF); 209 infoHeader[9] = (byte)((height >> 8) & 0xFF); 210 infoHeader[10] = (byte)((height >> 16) & 0xFF); 211 infoHeader[11] = (byte)((height >> 24) & 0xFF); 212 return infoHeader; 213 } 214 217 void unloadIcon(ImageData icon) { 218 int sizeImage = (((icon.width * icon.depth + 31) / 32 * 4) + 219 ((icon.width + 31) / 32 * 4)) * icon.height; 220 try { 221 outputStream.writeInt(WinBMPFileFormat.BMPHeaderFixedSize); 222 outputStream.writeInt(icon.width); 223 outputStream.writeInt(icon.height * 2); 224 outputStream.writeShort(1); 225 outputStream.writeShort((short)icon.depth); 226 outputStream.writeInt(0); 227 outputStream.writeInt(sizeImage); 228 outputStream.writeInt(0); 229 outputStream.writeInt(0); 230 outputStream.writeInt(icon.palette.colors != null ? icon.palette.colors.length : 0); 231 outputStream.writeInt(0); 232 } catch (IOException e) { 233 SWT.error(SWT.ERROR_IO, e); 234 } 235 236 byte[] rgbs = WinBMPFileFormat.paletteToBytes(icon.palette); 237 try { 238 outputStream.write(rgbs); 239 } catch (IOException e) { 240 SWT.error(SWT.ERROR_IO, e); 241 } 242 unloadShapeData(icon); 243 unloadMaskData(icon); 244 } 245 248 void unloadIconHeader(ImageData i) { 249 int headerSize = 16; 250 int offset = headerSize + 6; 251 int iconSize = iconSize(i); 252 try { 253 outputStream.write(i.width); 254 outputStream.write(i.height); 255 outputStream.writeShort(i.palette.colors != null ? i.palette.colors.length : 0); 256 outputStream.writeShort(0); 257 outputStream.writeShort(0); 258 outputStream.writeInt(iconSize); 259 outputStream.writeInt(offset); 260 } catch (IOException e) { 261 SWT.error(SWT.ERROR_IO, e); 262 } 263 } 264 void unloadIntoByteStream(ImageLoader loader) { 265 267 ImageData image = loader.data[0]; 268 if (!isValidIcon(image)) 269 SWT.error(SWT.ERROR_INVALID_IMAGE); 270 try { 271 outputStream.writeShort(0); 272 outputStream.writeShort(1); 273 outputStream.writeShort(1); 274 } catch (IOException e) { 275 SWT.error(SWT.ERROR_IO, e); 276 } 277 unloadIconHeader(image); 278 unloadIcon(image); 279 } 280 284 void unloadMaskData(ImageData icon) { 285 ImageData mask = icon.getTransparencyMask(); 286 int bpl = (icon.width + 7) / 8; 287 int pad = mask.scanlinePad; 288 int srcBpl = (bpl + pad - 1) / pad * pad; 289 int destBpl = (bpl + 3) / 4 * 4; 290 byte[] buf = new byte[destBpl]; 291 int offset = (icon.height - 1) * srcBpl; 292 byte[] data = mask.data; 293 try { 294 for (int i = 0; i < icon.height; i++) { 295 System.arraycopy(data, offset, buf, 0, bpl); 296 bitInvertData(buf, 0, bpl); 297 outputStream.write(buf, 0, destBpl); 298 offset -= srcBpl; 299 } 300 } catch (IOException e) { 301 SWT.error(SWT.ERROR_IO, e); 302 } 303 } 304 307 void unloadShapeData(ImageData icon) { 308 int bpl = (icon.width * icon.depth + 7) / 8; 309 int pad = icon.scanlinePad; 310 int srcBpl = (bpl + pad - 1) / pad * pad; 311 int destBpl = (bpl + 3) / 4 * 4; 312 byte[] buf = new byte[destBpl]; 313 int offset = (icon.height - 1) * srcBpl; 314 byte[] data = icon.data; 315 try { 316 for (int i = 0; i < icon.height; i++) { 317 System.arraycopy(data, offset, buf, 0, bpl); 318 outputStream.write(buf, 0, destBpl); 319 offset -= srcBpl; 320 } 321 } catch (IOException e) { 322 SWT.error(SWT.ERROR_IO, e); 323 } 324 } 325 } 326 | Popular Tags |