1 11 package org.eclipse.swt.internal.image; 12 13 14 import org.eclipse.swt.*; 15 import org.eclipse.swt.graphics.*; 16 17 final class LZWCodec { 18 int bitsPerPixel, blockSize, blockIndex, currentByte, bitsLeft, 19 codeSize, clearCode, endCode, newCodes, topSlot, currentSlot, 20 imageWidth, imageHeight, imageX, imageY, pass, line, codeMask; 21 byte[] block, lineArray; 22 int[] stack, suffix, prefix; 23 LZWNode[] nodeStack; 24 LEDataInputStream inputStream; 25 LEDataOutputStream outputStream; 26 ImageData image; 27 ImageLoader loader; 28 boolean interlaced; 29 static final int[] MASK_TABLE = new int[] { 30 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F, 31 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF 32 }; 33 34 37 void decode() { 38 int code; 39 int oc = 0; 40 int fc = 0; 41 byte[] buf = new byte[imageWidth]; 42 int stackIndex = 0; 43 int bufIndex = 0; 44 int c; 45 while ((c = nextCode()) != endCode) { 46 if (c == clearCode) { 47 codeSize = bitsPerPixel + 1; 48 codeMask = MASK_TABLE[bitsPerPixel]; 49 currentSlot = newCodes; 50 topSlot = 1 << codeSize; 51 while ((c = nextCode()) == clearCode) {} 52 if (c != endCode) { 53 oc = fc = c; 54 buf[bufIndex] = (byte)c; 55 bufIndex++; 56 if (bufIndex == imageWidth) { 57 nextPutPixels(buf); 58 bufIndex = 0; 59 } 60 } 61 } else { 62 code = c; 63 if (code >= currentSlot) { 64 code = oc; 65 stack[stackIndex] = fc; 66 stackIndex++; 67 } 68 while (code >= newCodes) { 69 stack[stackIndex] = suffix[code]; 70 stackIndex++; 71 code = prefix[code]; 72 } 73 stack[stackIndex] = code; 74 stackIndex++; 75 if (currentSlot < topSlot) { 76 fc = code; 77 suffix[currentSlot] = fc; 78 prefix[currentSlot] = oc; 79 currentSlot++; 80 oc = c; 81 } 82 if (currentSlot >= topSlot) { 83 if (codeSize < 12) { 84 codeMask = MASK_TABLE[codeSize]; 85 codeSize++; 86 topSlot = topSlot + topSlot; 87 } 88 } 89 while (stackIndex > 0) { 90 stackIndex--; 91 buf[bufIndex] = (byte)stack[stackIndex]; 92 bufIndex++; 93 if (bufIndex == imageWidth) { 94 nextPutPixels(buf); 95 bufIndex = 0; 96 } 97 } 98 } 99 } 100 if (bufIndex != 0 && line < imageHeight) { 101 nextPutPixels(buf); 102 } 103 } 104 108 public void decode(LEDataInputStream inputStream, ImageLoader loader, ImageData image, boolean interlaced, int depth) { 109 this.inputStream = inputStream; 110 this.loader = loader; 111 this.image = image; 112 this.interlaced = interlaced; 113 this.bitsPerPixel = depth; 114 initializeForDecoding(); 115 decode(); 116 } 117 120 void encode() { 121 nextPutCode(clearCode); 122 int lastPrefix = encodeLoop(); 123 nextPutCode(lastPrefix); 124 nextPutCode(endCode); 125 126 if (bitsLeft == 8) { 128 block[0] = (byte)(blockIndex - 1); } else { 130 block[0] = (byte)(blockIndex); } 132 writeBlock(); 133 134 if (block[0] != 0) { 136 block[0] = 0; 137 writeBlock(); 138 } 139 } 140 144 public void encode(LEDataOutputStream byteStream, ImageData image) { 145 this.outputStream = byteStream; 146 this.image = image; 147 initializeForEncoding(); 148 encode(); 149 } 150 153 int encodeLoop() { 154 int pixel = nextPixel(); 155 boolean found; 156 LZWNode node; 157 while (true) { 158 int currentPrefix = pixel; 159 node = nodeStack[currentPrefix]; 160 found = true; 161 pixel = nextPixel(); 162 if (pixel < 0) 163 return currentPrefix; 164 while (found && (node.children != null)) { 165 node = node.children; 166 while (found && (node.suffix != pixel)) { 167 if (pixel < node.suffix) { 168 if (node.left == null) { 169 node.left = new LZWNode(); 170 found = false; 171 } 172 node = node.left; 173 } else { 174 if (node.right == null) { 175 node.right = new LZWNode(); 176 found = false; 177 } 178 node = node.right; 179 } 180 } 181 if (found) { 182 currentPrefix = node.code; 183 pixel = nextPixel(); 184 if (pixel < 0) 185 return currentPrefix; 186 } 187 } 188 if (found) { 189 node.children = new LZWNode(); 190 node = node.children; 191 } 192 node.children = null; 193 node.left = null; 194 node.right = null; 195 node.code = currentSlot; 196 node.prefix = currentPrefix; 197 node.suffix = pixel; 198 nextPutCode(currentPrefix); 199 currentSlot++; 200 if (currentSlot < 4096) { 202 if (currentSlot > topSlot) { 203 codeSize++; 204 codeMask = MASK_TABLE[codeSize - 1]; 205 topSlot *= 2; 206 } 207 } else { 208 nextPutCode(clearCode); 209 for (int i = 0; i < nodeStack.length; i++) 210 nodeStack[i].children = null; 211 codeSize = bitsPerPixel + 1; 212 codeMask = MASK_TABLE[codeSize - 1]; 213 currentSlot = newCodes; 214 topSlot = 1 << codeSize; 215 } 216 } 217 } 218 222 void initializeForDecoding() { 223 pass = 1; 224 line = 0; 225 codeSize = bitsPerPixel + 1; 226 topSlot = 1 << codeSize; 227 clearCode = 1 << bitsPerPixel; 228 endCode = clearCode + 1; 229 newCodes = currentSlot = endCode + 1; 230 currentByte = -1; 231 blockSize = bitsLeft = 0; 232 blockIndex = 0; 233 codeMask = MASK_TABLE[codeSize - 1]; 234 stack = new int[4096]; 235 suffix = new int[4096]; 236 prefix = new int[4096]; 237 block = new byte[256]; 238 imageWidth = image.width; 239 imageHeight = image.height; 240 } 241 245 void initializeForEncoding() { 246 interlaced = false; 247 bitsPerPixel = image.depth; 248 codeSize = bitsPerPixel + 1; 249 topSlot = 1 << codeSize; 250 clearCode = 1 << bitsPerPixel; 251 endCode = clearCode + 1; 252 newCodes = currentSlot = endCode + 1; 253 bitsLeft = 8; 254 currentByte = 0; 255 blockIndex = 1; 256 blockSize = 255; 257 block = new byte[blockSize]; 258 block[0] = (byte)(blockSize - 1); 259 nodeStack = new LZWNode[1 << bitsPerPixel]; 260 for (int i = 0; i < nodeStack.length; i++) { 261 LZWNode node = new LZWNode(); 262 node.code = i + 1; 263 node.prefix = -1; 264 node.suffix = i + 1; 265 nodeStack[i] = node; 266 } 267 imageWidth = image.width; 268 imageHeight = image.height; 269 imageY = -1; 270 lineArray = new byte[imageWidth]; 271 imageX = imageWidth + 1; } 273 276 int nextCode() { 277 int code; 278 if (bitsLeft == 0) { 279 if (blockIndex >= blockSize) { 280 blockSize = readBlock(); 281 blockIndex = 0; 282 if (blockSize == 0) return endCode; 283 } 284 blockIndex++; 285 currentByte = block[blockIndex] & 0xFF; 286 bitsLeft = 8; 287 code = currentByte; 288 } else { 289 int shift = bitsLeft - 8; 290 if (shift < 0) 291 code = currentByte >> (0 - shift); 292 else 293 code = currentByte << shift; 294 } 295 while (codeSize > bitsLeft) { 296 if (blockIndex >= blockSize) { 297 blockSize = readBlock(); 298 blockIndex = 0; 299 if (blockSize == 0) return endCode; 300 } 301 blockIndex++; 302 currentByte = block[blockIndex] & 0xFF; 303 code += currentByte << bitsLeft; 304 bitsLeft += 8; 305 } 306 bitsLeft -= codeSize; 307 return code & codeMask; 308 } 309 312 int nextPixel() { 313 imageX++; 314 if (imageX > imageWidth) { 315 imageY++; 316 if (imageY >= imageHeight) { 317 return -1; 318 } else { 319 nextPixels(lineArray, imageWidth); 320 } 321 imageX = 1; 322 } 323 return this.lineArray[imageX - 1] & 0xFF; 324 } 325 328 void nextPixels(byte[] buf, int lineWidth) { 329 if (image.depth == 8) { 330 System.arraycopy(image.data, imageY * image.bytesPerLine, buf, 0, lineWidth); 331 } else { 332 image.getPixels(0, imageY, lineWidth, buf, 0); 333 } 334 } 335 338 void nextPutCode(int aCode) { 339 int codeToDo = aCode; 340 int codeBitsToDo = codeSize; 341 int c = codeToDo & MASK_TABLE[bitsLeft - 1]; 344 currentByte = currentByte | (c << (8 - bitsLeft)); 345 block[blockIndex] = (byte)currentByte; 346 codeBitsToDo -= bitsLeft; 347 if (codeBitsToDo < 1) { 348 bitsLeft -= codeSize; 350 if (bitsLeft == 0) { 351 bitsLeft = 8; 354 blockIndex++; 355 if (blockIndex >= blockSize) { 356 writeBlock(); 357 blockIndex = 1; 358 } 359 currentByte = 0; 360 } 361 return; 362 } 363 codeToDo = codeToDo >> bitsLeft; 364 365 blockIndex++; 367 if (blockIndex >= blockSize) { 368 writeBlock(); 369 blockIndex = 1; 370 } 371 while (codeBitsToDo >= 8) { 372 currentByte = codeToDo & 0xFF; 373 block[blockIndex] = (byte)currentByte; 374 codeToDo = codeToDo >> 8; 375 codeBitsToDo -= 8; 376 blockIndex++; 377 if (blockIndex >= blockSize) { 378 writeBlock(); 379 blockIndex = 1; 380 } 381 } 382 bitsLeft = 8 - codeBitsToDo; 384 currentByte = codeToDo; 385 block[blockIndex] = (byte)currentByte; 386 } 387 390 void nextPutPixels(byte[] buf) { 391 if (image.depth == 8) { 392 int start = line * image.bytesPerLine; 394 for (int i = 0; i < imageWidth; i++) 395 image.data[start + i] = buf[i]; 396 } else { 397 image.setPixels(0, line, imageWidth, buf, 0); 398 } 399 if (interlaced) { 400 if (pass == 1) { 401 copyRow(buf, 7); 402 line += 8; 403 } else if (pass == 2) { 404 copyRow(buf, 3); 405 line += 8; 406 } else if (pass == 3) { 407 copyRow(buf, 1); 408 line += 4; 409 } else if (pass == 4) { 410 line += 2; 411 } else if (pass == 5) { 412 line += 0; 413 } 414 if (line >= imageHeight) { 415 pass++; 416 if (pass == 2) line = 4; 417 else if (pass == 3) line = 2; 418 else if (pass == 4) line = 1; 419 else if (pass == 5) line = 0; 420 if (pass < 5) { 421 if (loader.hasListeners()) { 422 ImageData imageCopy = (ImageData) image.clone(); 423 loader.notifyListeners( 424 new ImageLoaderEvent(loader, imageCopy, pass - 2, false)); 425 } 426 } 427 } 428 if (line >= imageHeight) line = 0; 429 } else { 430 line++; 431 } 432 } 433 437 void copyRow(byte[] buf, int copies) { 438 for (int i = 1; i <= copies; i++) { 439 if (line + i < imageHeight) { 440 image.setPixels(0, line + i, imageWidth, buf, 0); 441 } 442 } 443 } 444 449 int readBlock() { 450 int size = -1; 451 try { 452 size = inputStream.read(); 453 if (size == -1) { 454 SWT.error(SWT.ERROR_INVALID_IMAGE); 455 } 456 block[0] = (byte)size; 457 size = inputStream.read(block, 1, size); 458 if (size == -1) { 459 SWT.error(SWT.ERROR_INVALID_IMAGE); 460 } 461 } catch (Exception e) { 462 SWT.error(SWT.ERROR_IO, e); 463 } 464 return size; 465 } 466 470 void writeBlock() { 471 try { 472 outputStream.write(block, 0, (block[0] & 0xFF) + 1); 473 } catch (Exception e) { 474 SWT.error(SWT.ERROR_IO, e); 475 } 476 } 477 } 478 | Popular Tags |