root/trunk/lodepng/lodepng/ZlibCodec.d

Revision 256, 3.7 kB (checked in by Lutger, 9 months ago)

bugfixes, added png2bin.d example

Line 
1 /// wraps zlib
2 module lodepng.ZlibCodec;
3
4 version(Windows)
5 {
6     pragma(lib, "zlib");
7 }
8
9 version (Tango)
10 {
11     import czlib = tango.io.compress.c.zlib;
12 }
13 else
14 {
15     import czlib = etc.c.zlib;
16 }
17
18 import lodepng.util;
19
20
21 // buffered decompression of zlib streams, avoiding GC provocation where possible
22 struct DecodeStream
23 {
24     // TODO: should be scope class for releasing zlib resources on scope exit
25
26     // constructor: initialize with target, will be resized as needed
27     static DecodeStream create(ref ubyte[] dest)
28     {
29         DecodeStream result;
30         result.dest = dest;
31
32         result.zlibStream.next_out = dest.ptr;
33         result.zlibStream.avail_out = dest.length;
34         result.zlibStream.avail_out = dest.length; //Z_BINARY
35         result.zlibStream.data_type = czlib.Z_BINARY;
36
37         return result;
38     }
39
40     ubyte[] opCall()
41     {
42         return dest;
43     }
44
45     void opCall(in ubyte[] input)
46     {
47         zlibStream.next_in = input.ptr;
48         zlibStream.avail_in = input.length;
49
50         if (!isInit)
51         {
52             isInit = true;
53             msg = czlib.inflateInit(&zlibStream);
54             if (msg)
55             {
56                 czlib.inflateEnd(&zlibStream);
57                 throw new Exception("");// TODO: toString(msg));
58             }
59         }
60
61         while(zlibStream.avail_in)
62         {
63             msg = czlib.inflate(&zlibStream, czlib.Z_NO_FLUSH);
64
65             if (msg == czlib.Z_STREAM_END)
66             {
67                 czlib.inflateEnd(&zlibStream);
68                 hasEnded = true;
69                 dest.length = zlibStream.total_out;
70                 return;
71             }
72             else if (msg != czlib.Z_OK)
73             {
74                 czlib.inflateEnd(&zlibStream);
75                 throw new Exception("");// TODO: toString(zlibStream.msg));
76             }
77             else if(zlibStream.avail_out == 0)
78             {
79                 dest.length = dest.length * 2;
80                 zlibStream.next_out = &dest[dest.length / 2];
81                 zlibStream.avail_out = dest.length / 2;
82             }
83         }
84     }
85
86     bool isInit = false;
87     bool hasEnded = false;
88
89     package
90     {
91         ubyte[] dest;
92         int msg = 0;
93         czlib.z_stream zlibStream;
94     }
95 }
96
97 struct Encoder
98 {
99     static Encoder create(ubyte strategy = czlib.Z_RLE, uint clevel = 9)
100     {
101         Encoder result;
102         result.level = clevel;
103         result.strategy = strategy;
104         return result;
105     }
106     ubyte[] opCall(in ubyte[] source)
107     {
108         ubyte[] result;
109         return this.opCall(source, result);
110
111     }
112     ubyte[] opCall(in ubyte[] source, ref ubyte[] buffer)
113     {
114         if (source.length == 0)
115         {
116             buffer.length = 0;
117             return buffer;
118         }
119
120         buffer.length = source.length / 4;
121         czlib.z_stream stream;
122         stream.next_in = source.ptr;
123         stream.avail_in = source.length;
124         stream.next_out = buffer.ptr;
125         stream.avail_out = buffer.length;
126         stream.data_type = czlib.Z_BINARY;
127
128         czlib.deflateInit2(&stream, 9, czlib.Z_DEFLATED, 15, level, strategy);
129         auto msg = czlib.deflate(&stream, czlib.Z_FINISH);
130         while(msg != czlib.Z_STREAM_END)
131         {
132             buffer.length = buffer.length + buffer.length;
133             stream.next_out = &buffer[buffer.length / 2];
134             stream.avail_out = buffer.length / 2;
135             msg = czlib.deflate(&stream, czlib.Z_FINISH);
136         }
137
138         assert(msg == czlib.Z_STREAM_END);
139         buffer.length = stream.total_out;
140         czlib.deflateEnd(&stream);
141
142         return buffer;
143     }
144
145     private ubyte strategy = czlib.Z_RLE;
146     private ubyte level = 9;
147 }
Note: See TracBrowser for help on using the browser.