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