diff dwt/internal/image/PngDeflater.d @ 34:5123b17c98ef

Ported dwt.events.*, dwt.graphics.GC, Region, dwt.internal.image.*
author Jacob Carlborg <doob@me.com> <jacob.carlborg@gmail.com>
date Sun, 14 Sep 2008 01:45:57 +0200
parents e831403a80a9
children
line wrap: on
line diff
--- a/dwt/internal/image/PngDeflater.d	Fri Sep 12 13:53:21 2008 +0200
+++ b/dwt/internal/image/PngDeflater.d	Sun Sep 14 01:45:57 2008 +0200
@@ -1,5 +1,5 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2006 IBM Corporation and others.
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 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
@@ -7,44 +7,50 @@
  *
  * Contributors:
  *     IBM Corporation - initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
  *******************************************************************************/
-module dwt.internal.image;
+module dwt.internal.image.PngDeflater;
 
-import java.io.ByteArrayOutputStream;
+import dwt.dwthelper.ByteArrayOutputStream;
 
 public class PngDeflater {
 
-    static final int BASE = 65521;
-    static final int WINDOW = 32768;
-    static final int MIN_LENGTH = 3;
-    static final int MAX_MATCHES = 32;
-    static final int HASH = 8209;
-    
-    byte[] in;
+    static const int BASE = 65521;
+    static const int WINDOW = 32768;
+    static const int MIN_LENGTH = 3;
+    static const int MAX_MATCHES = 32;
+    static const int HASH = 8209;
+
+    byte[] istr;
     int inLength;
-    
-    ByteArrayOutputStream bytes = new ByteArrayOutputStream(1024);
-    
+
+    ByteArrayOutputStream bytes;
+
     int adler32 = 1;
-    
+
     int buffer, bitCount;
-    
-    Link[] hashtable = new Link[HASH];
-    Link[] window = new Link[WINDOW];
+
+    Link[HASH] hashtable;// = new Link[HASH];
+    Link[WINDOW] window;// = new Link[WINDOW];
     int nextWindow;
 
-static class Link {
+public this(){
+    bytes = new ByteArrayOutputStream(1024);
+}
+
+class Link {
 
     int hash, value;
     Link previous, next;
-    
+
     this() {
-    
+
         this.hash = 0;
         this.value = 0;
         this.previous = null;
         this.next = null;
-    
+
     }
 
 }
@@ -52,17 +58,17 @@
 static class Match {
 
     int length, distance;
-    
+
     this(int length, int distance) {
-    
+
         this.length = length;
         this.distance = distance;
-    
+
     }
 
 }
 
-static final short mirrorBytes[] = {
+static const short mirrorBytes[] = [ cast(short)
 
     0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
     0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
@@ -97,97 +103,96 @@
     0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
     0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
 
-};
+];
 
 static class Code {
 
     int code, extraBits, min, max;
-    
+
     this(int code, int extraBits, int min, int max) {
-    
+
         this.code = code;
         this.extraBits = extraBits;
         this.min = min;
         this.max = max;
-    
+
     }
 
 }
 
-static final Code lengthCodes[] = {
-
-    new Code(257, 0, 3, 3),
-    new Code(258, 0, 4, 4),
-    new Code(259, 0, 5, 5),
-    new Code(260, 0, 6, 6),
-    new Code(261, 0, 7, 7),
-    new Code(262, 0, 8, 8),
-    new Code(263, 0, 9, 9),
-    new Code(264, 0, 10, 10),
-    new Code(265, 1, 11, 12),
-    new Code(266, 1, 13, 14),
-    new Code(267, 1, 15, 16),
-    new Code(268, 1, 17, 18),
-    new Code(269, 2, 19, 22),
-    new Code(270, 2, 23, 26),
-    new Code(271, 2, 27, 30),
-    new Code(272, 2, 31, 34),
-    new Code(273, 3, 35, 42),
-    new Code(274, 3, 43, 50),
-    new Code(275, 3, 51, 58),
-    new Code(276, 3, 59, 66),
-    new Code(277, 4, 67, 82),
-    new Code(278, 4, 83, 98),
-    new Code(279, 4, 99, 114),
-    new Code(280, 4, 115, 130),
-    new Code(281, 5, 131, 162),
-    new Code(282, 5, 163, 194),
-    new Code(283, 5, 195, 226),
-    new Code(284, 5, 227, 257),
-    new Code(285, 0, 258, 258)
-
-};
+static const Code lengthCodes[];
+static const Code distanceCodes[];
 
-static final Code distanceCodes[] = {
+static this() {
+    lengthCodes = [
+        new Code(257, 0, 3, 3),
+        new Code(258, 0, 4, 4),
+        new Code(259, 0, 5, 5),
+        new Code(260, 0, 6, 6),
+        new Code(261, 0, 7, 7),
+        new Code(262, 0, 8, 8),
+        new Code(263, 0, 9, 9),
+        new Code(264, 0, 10, 10),
+        new Code(265, 1, 11, 12),
+        new Code(266, 1, 13, 14),
+        new Code(267, 1, 15, 16),
+        new Code(268, 1, 17, 18),
+        new Code(269, 2, 19, 22),
+        new Code(270, 2, 23, 26),
+        new Code(271, 2, 27, 30),
+        new Code(272, 2, 31, 34),
+        new Code(273, 3, 35, 42),
+        new Code(274, 3, 43, 50),
+        new Code(275, 3, 51, 58),
+        new Code(276, 3, 59, 66),
+        new Code(277, 4, 67, 82),
+        new Code(278, 4, 83, 98),
+        new Code(279, 4, 99, 114),
+        new Code(280, 4, 115, 130),
+        new Code(281, 5, 131, 162),
+        new Code(282, 5, 163, 194),
+        new Code(283, 5, 195, 226),
+        new Code(284, 5, 227, 257),
+        new Code(285, 0, 258, 258)];
 
-    new Code(0, 0, 1, 1),
-    new Code(1, 0, 2, 2),
-    new Code(2, 0, 3, 3),
-    new Code(3, 0, 4, 4),
-    new Code(4, 1, 5, 6),
-    new Code(5, 1, 7, 8),
-    new Code(6, 2, 9, 12),
-    new Code(7, 2, 13, 16),
-    new Code(8, 3, 17, 24),
-    new Code(9, 3, 25, 32),
-    new Code(10, 4, 33, 48),
-    new Code(11, 4, 49, 64),
-    new Code(12, 5, 65, 96),
-    new Code(13, 5, 97, 128),
-    new Code(14, 6, 129, 192),
-    new Code(15, 6, 193, 256),
-    new Code(16, 7, 257, 384),
-    new Code(17, 7, 385, 512),
-    new Code(18, 8, 513, 768),
-    new Code(19, 8, 769, 1024),
-    new Code(20, 9, 1025, 1536),
-    new Code(21, 9, 1537, 2048),
-    new Code(22, 10, 2049, 3072),
-    new Code(23, 10, 3073, 4096),
-    new Code(24, 11, 4097, 6144),
-    new Code(25, 11, 6145, 8192),
-    new Code(26, 12, 8193, 12288),
-    new Code(27, 12, 12289, 16384),
-    new Code(28, 13, 16385, 24576),
-    new Code(29, 13, 24577, 32768)
-
-};
+    distanceCodes = [
+        new Code(0, 0, 1, 1),
+        new Code(1, 0, 2, 2),
+        new Code(2, 0, 3, 3),
+        new Code(3, 0, 4, 4),
+        new Code(4, 1, 5, 6),
+        new Code(5, 1, 7, 8),
+        new Code(6, 2, 9, 12),
+        new Code(7, 2, 13, 16),
+        new Code(8, 3, 17, 24),
+        new Code(9, 3, 25, 32),
+        new Code(10, 4, 33, 48),
+        new Code(11, 4, 49, 64),
+        new Code(12, 5, 65, 96),
+        new Code(13, 5, 97, 128),
+        new Code(14, 6, 129, 192),
+        new Code(15, 6, 193, 256),
+        new Code(16, 7, 257, 384),
+        new Code(17, 7, 385, 512),
+        new Code(18, 8, 513, 768),
+        new Code(19, 8, 769, 1024),
+        new Code(20, 9, 1025, 1536),
+        new Code(21, 9, 1537, 2048),
+        new Code(22, 10, 2049, 3072),
+        new Code(23, 10, 3073, 4096),
+        new Code(24, 11, 4097, 6144),
+        new Code(25, 11, 6145, 8192),
+        new Code(26, 12, 8193, 12288),
+        new Code(27, 12, 12289, 16384),
+        new Code(28, 13, 16385, 24576),
+        new Code(29, 13, 24577, 32768)];
+}
 
 void writeShortLSB(ByteArrayOutputStream baos, int theShort) {
 
     byte byte1 = cast(byte) (theShort & 0xff);
     byte byte2 = cast(byte) ((theShort >> 8) & 0xff);
-    byte[] temp = {byte1, byte2};
+    byte[] temp = [byte1, byte2];
     baos.write(temp, 0, 2);
 
 }
@@ -198,7 +203,7 @@
     byte byte2 = cast(byte) ((theInt >> 16) & 0xff);
     byte byte3 = cast(byte) ((theInt >> 8) & 0xff);
     byte byte4 = cast(byte) (theInt & 0xff);
-    byte[] temp = {byte1, byte2, byte3, byte4};
+    byte[] temp = [byte1, byte2, byte3, byte4];
     baos.write(temp, 0, 4);
 
 }
@@ -251,7 +256,7 @@
 void outputLiteral(byte literal) {
 
     int i = literal & 0xff;
-    
+
     if (i <= 143) {
         // 0 through 143 are 8 bits long starting at 00110000
         writeBits(mirrorBytes[0x30 + i], 8);
@@ -266,7 +271,7 @@
 Code findCode(int value, Code[] codes) {
 
     int i, j, k;
-    
+
     i = -1;
     j = codes.length;
     while (true) {
@@ -288,13 +293,13 @@
 
     Code d, l;
     int thisLength;
-    
+
     while (length > 0) {
 
         // we can transmit matches of lengths 3 through 258 inclusive
         // so if length exceeds 258, we must transmit in several steps,
         // with 258 or less in each step
-        
+
         if (length > 260) {
             thisLength = 258;
         }
@@ -304,12 +309,12 @@
         else {
             thisLength = length - 3;
         }
-        
+
         length = length - thisLength;
-                
+
         // find length code
         l = findCode(thisLength, lengthCodes);
-        
+
         // transmit the length code
         // 256 through 279 are 7 bits long starting at 0000000
         // 280 through 287 are 8 bits long starting at 11000000
@@ -319,24 +324,24 @@
         else {
             writeBits(mirrorBytes[0xc0 - 280 + l.code], 8);
         }
-        
+
         // transmit the extra bits
         if (l.extraBits !is 0) {
             writeBits(thisLength - l.min, l.extraBits);
         }
-        
+
         // find distance code
         d = findCode(distance, distanceCodes);
-        
+
         // transmit the distance code
         // 5 bits long starting at 00000
         writeBits(mirrorBytes[d.code * 8], 5);
-        
+
         // transmit the extra bits
         if (d.extraBits !is 0) {
             writeBits(distance - d.min, d.extraBits);
         }
-    
+
     }
 
 }
@@ -346,92 +351,92 @@
     Link link = firstPosition;
     int numberOfMatches = 0;
     Match bestMatch = new Match(-1, -1);
-    
+
     while (true) {
-    
+
         int matchPosition = link.value;
-        
+
         if (position - matchPosition < WINDOW && matchPosition !is 0) {
 
             int i;
-            
+
             for (i = 1; position + i < inLength; i++) {
-                if (in[position + i] !is in[matchPosition + i]) {
+                if (istr[position + i] !is istr[matchPosition + i]) {
                     break;
                 }
             }
-            
+
             if (i >= MIN_LENGTH) {
-            
+
                 if (i > bestMatch.length) {
                     bestMatch.length = i;
                     bestMatch.distance = position - matchPosition;
                 }
-                
+
                 numberOfMatches = numberOfMatches + 1;
-                
+
                 if (numberOfMatches is MAX_MATCHES) {
                     break;
                 }
-            
+
             }
-                        
+
         }
-        
+
         link = link.next;
         if (link is null) {
             break;
         }
-    
+
     }
-    
+
     if (bestMatch.length < MIN_LENGTH || bestMatch.distance < 1 || bestMatch.distance > WINDOW) {
         return null;
     }
-    
-    return bestMatch;   
+
+    return bestMatch;
 
 }
 
 void updateHashtable(int to, int from) {
 
     byte[] data = new byte[3];
-    int hash;
+    int hashval;
     Link temp;
-    
+
     for (int i = to; i < from; i++) {
-        
+
         if (i + MIN_LENGTH > inLength) {
             break;
         }
-        
-        data[0] = in[i];
-        data[1] = in[i + 1];
-        data[2] = in[i + 2];
-        
-        hash = hash(data);
-        
+
+        data[0] = istr[i];
+        data[1] = istr[i + 1];
+        data[2] = istr[i + 2];
+
+        hashval = hash(data);
+
         if (window[nextWindow].previous !is null) {
             window[nextWindow].previous.next = null;
         }
         else if (window[nextWindow].hash !is 0) {
             hashtable[window[nextWindow].hash].next = null;
         }
-        
-        window[nextWindow].hash = hash;
+
+        window[nextWindow].hash = hashval;
         window[nextWindow].value = i;
         window[nextWindow].previous = null;
-        temp = window[nextWindow].next = hashtable[hash].next;
-        hashtable[hash].next = window[nextWindow];
+        temp = window[nextWindow].next = hashtable[hashval].next;
+        hashtable[hashval].next = window[nextWindow];
         if (temp !is null) {
             temp.previous = window[nextWindow];
         }
-        
+
         nextWindow = nextWindow + 1;
         if (nextWindow is WINDOW) {
             nextWindow = 0;
         }
-            
+
     }
 
 }
@@ -440,7 +445,7 @@
 
     int position, newPosition;
     byte[] data = new byte[3];
-    int hash;
+    int hashval;
     for (int i = 0; i < HASH; i++) {
         hashtable[i] = new Link();
     }
@@ -452,39 +457,39 @@
     Match match;
     int deferredPosition = -1;
     Match deferredMatch = null;
-    
+
     writeBits(0x01, 1); // BFINAL = 0x01 (final block)
     writeBits(0x01, 2); // BTYPE = 0x01 (compression with fixed Huffman codes)
-    
+
     // just output first byte so we never match at zero
-    outputLiteral(in[0]);
+    outputLiteral(istr[0]);
     position = 1;
-    
+
     while (position < inLength) {
-    
+
         if (inLength - position < MIN_LENGTH) {
-            outputLiteral(in[position]);
+            outputLiteral(istr[position]);
             position = position + 1;
             continue;
         }
-        
-        data[0] = in[position];
-        data[1] = in[position + 1];
-        data[2] = in[position + 2];
-        
-        hash = hash(data);
-        firstPosition = hashtable[hash];
-        
+
+        data[0] = istr[position];
+        data[1] = istr[position + 1];
+        data[2] = istr[position + 2];
+
+        hashval = hash(data);
+        firstPosition = hashtable[hashval];
+
         match = findLongestMatch(position, firstPosition);
-        
+
         updateHashtable(position, position + 1);
-        
+
         if (match !is null) {
-        
+
             if (deferredMatch !is null) {
                 if (match.length > deferredMatch.length + 1) {
                     // output literal at deferredPosition
-                    outputLiteral(in[deferredPosition]);
+                    outputLiteral(istr[deferredPosition]);
                     // defer this match
                     deferredPosition = position;
                     deferredMatch = match;
@@ -506,11 +511,11 @@
                 deferredMatch = match;
                 position = position + 1;
             }
-        
+
         }
-        
+
         else {
-        
+
             // no match found
             if (deferredMatch !is null) {
                 outputMatch(deferredMatch.length, deferredMatch.distance);
@@ -521,14 +526,14 @@
                 position = newPosition;
             }
             else {
-                outputLiteral(in[position]);
+                outputLiteral(istr[position]);
                 position = position + 1;
             }
-        
+
         }
-    
+
     }
-    
+
     writeBits(0, 7); // end of block code
     alignToByte();
 
@@ -537,17 +542,17 @@
 void compressHuffmanOnly() {
 
     int position;
-    
+
     writeBits(0x01, 1); // BFINAL = 0x01 (final block)
     writeBits(0x01, 2); // BTYPE = 0x01 (compression with fixed Huffman codes)
-    
+
     for (position = 0; position < inLength;) {
-    
-        outputLiteral(in[position]);
+
+        outputLiteral(istr[position]);
         position = position + 1;
-    
+
     }
-    
+
     writeBits(0, 7); // end of block code
     alignToByte();
 
@@ -556,14 +561,14 @@
 void store() {
 
     // stored blocks are limited to 0xffff bytes
-    
+
     int start = 0;
     int length = inLength;
     int blockLength;
     int BFINAL = 0x00; // BFINAL = 0x00 or 0x01 (if final block), BTYPE = 0x00 (no compression)
-    
+
     while (length > 0) {
-    
+
         if (length < 65535) {
             blockLength = length;
             BFINAL = 0x01;
@@ -572,45 +577,45 @@
             blockLength = 65535;
             BFINAL = 0x00;
         }
-        
+
         // write data header
         bytes.write(cast(byte) BFINAL);
         writeShortLSB(bytes, blockLength); // LEN
         writeShortLSB(bytes, blockLength ^ 0xffff); // NLEN (one's complement of LEN)
-    
+
         // write actual data
-        bytes.write(in, start, blockLength);
-        
+        bytes.write(istr, start, blockLength);
+
         length = length - blockLength;
         start = start + blockLength;
-    
+
     }
 
 }
 
 public byte[] deflate(byte[] input) {
 
-    in = input;
+    istr = input;
     inLength = input.length;
-    
+
     // write zlib header
     bytes.write(cast(byte) 0x78); // window size = 0x70 (32768), compression method = 0x08
     bytes.write(cast(byte) 0x9C); // compression level = 0x80 (default), check bits = 0x1C
-    
+
     // compute checksum
     for (int i = 0; i < inLength; i++) {
-        updateAdler(in[i]);
+        updateAdler(istr[i]);
     }
-    
+
     //store();
-    
+
     //compressHuffmanOnly();
-    
+
     compress();
-    
+
     // write checksum
     writeInt(bytes, adler32);
-    
+
     return bytes.toByteArray();
 
 }