root/trunk/lodepng/lodepng/examples/png2bin.d

Revision 256, 6.0 kB (checked in by Lutger, 6 months ago)

bugfixes, added png2bin.d example

Line 
1 module png2bin;
2
3 version(Windows)
4 {
5     pragma(lib, "zlib");
6 }
7
8 import lodepng.Decode,
9        lodepng.Encode;
10
11 import tango.util.Arguments,
12        tango.io.Stdout,
13        tango.io.FilePath,
14        tango.io.FileConduit,
15        tango.io.FileScan,
16        tango.io.Console,
17        tango.util.Convert,
18        tango.text.convert.Layout,
19        tango.text.Unicode;
20
21 int main(char[][] args)
22 {
23     //todo: implent target colortype option
24     auto arguments = new Arguments(args, ["pngfile"],
25         [["R", "r", "recursive"], ["t", "target", "T"], ["h", "H","help"], ["f", "F", "force"]]);
26     arguments.addValidation("r", false, false);
27     arguments.addValidation("t", false, true);
28     arguments.addValidation("h", false, false);
29     arguments.addValidation("f", false, false);
30    
31     //todo: write this helpMessage so it is useful
32     char[] helpMessage = "usage: png2bin file [dstfile] [options]";
33     char[][] messages;
34     try
35     {
36         arguments.validate();
37     }
38     catch (ArgumentException ex)
39     {
40         messages ~= Stdout.layout.convert("{}: {} - {}", ex.name, ex.msg,
41                     ex.reason == ArgumentException.ExceptionReason.INVALID_PARAMETER ?
42                     "invalid parameter" : ex.reason == ArgumentException.ExceptionReason.MISSING_PARAMETER ?
43                     "missing parameter" : "missing argument");
44         Stdout(messages).newline;
45         Stdout(helpMessage).newline;
46         return 0;
47     }
48    
49     char[] pngFileName = arguments["pngfile"].length ? arguments["pngfile"][0] : null;
50    
51     if (!pngFileName)
52     {
53         Stdout("error: missing argument png file").newline;
54         Stdout(helpMessage).newline;
55         return 0;
56     }
57    
58     ubyte[] buffer;
59     ubyte[] pixels;
60    
61     void pngToD(FilePath source, FilePath target, ColorType destCT = ColorType.Any)
62     {
63         auto srcConduit = new FileConduit(source);
64         scope(exit)
65             srcConduit.close();
66         auto dstConduit = new FileConduit(target, FileConduit.WriteCreate);
67         scope(exit)
68             dstConduit.close();
69        
70         buffer.length = srcConduit.length;
71         auto bytesRead = srcConduit.input.read(buffer);
72         assert(bytesRead==buffer.length);
73        
74         PngInfo info;
75        
76         pixels = buffer.decode(info, pixels);
77         if (destCT != ColorType.Any && info.image.colorType != destCT)
78         {
79             pixels = pixels.convert(info, destCT);
80             info.image.colorType = destCT;
81         }
82        
83         char[][] dFileStrings = ["module " ~ target.name ~ ";\n"];
84        
85         dFileStrings.writeDeclarations(pixels, info);
86
87         foreach(str; dFileStrings)
88         {
89             dstConduit.output.write(str);
90             dstConduit.output.write("\n");
91         }
92     }
93    
94     auto src = new FilePath(pngFileName);
95     if (!src.exists)
96     {
97         Stdout.format("error: {} does not exist\n", pngFileName);
98         return 1;
99     }
100    
101     bool force = "f" in arguments;
102    
103     if (src.isFolder)
104     {
105        
106         foreach( source; (new FileScan)(src.toString(), ".png", "r" in arguments).files() )
107         {
108             auto dst = source.dup;
109             dst.suffix = "d";
110             if(!force && dst.exists)
111             {
112                 switch(confirm("file " ~ source.file() ~ " exists, overwrite? "))
113                 {
114                     case Yes: pngToD(source, dst);
115                         break;
116                     case No:
117                         break;
118                     case Quit: return 0;
119                         break;
120                         default:
121                             assert(false);
122                         return 1;
123                 }
124             }
125             else
126             {
127                 pngToD(source, dst);
128             }
129         }
130     }
131     else
132     {
133         auto dst = src.dup();
134         dst.suffix = "d";
135         if(!force && dst.exists)
136         {
137             switch(confirm("file " ~ src.file() ~ " exists, overwrite? "))
138             {
139                 case Yes: pngToD(src, dst);
140                     break;
141                 case No:
142                     break;
143                 case Quit: return 0;
144                     break;
145                     default:
146                         assert(false);
147                     return 1;
148             }
149         }
150         else
151         {
152             pngToD(src, dst);
153         }
154     }
155    
156     return 0;
157 }
158
159 enum : int
160 {
161     Yes,
162     No,
163     Quit
164 }
165
166 int confirm(char[] message)
167 {
168    
169     char[] input;
170     while(true)
171     {
172         Stdout(message ~ " Y(es)/N(o)/Q(uit)").newline;
173         Cin.readln(input);
174         input = input.toLower();
175         if (input == "y")
176             return Yes;
177         else if (input == "n")
178             return No;
179         else if (input == "q")
180             return Quit;
181     }
182     return Quit;
183 }
184
185 void writeDeclarations(ref char[][] strings, ubyte[] pixels, ref PngInfo info)
186 {
187     strings ~= "uint width = "      ~ to!(char[])(info.image.width)~ ";";
188     strings ~= "uint height = "     ~ to!(char[])(info.image.height)~ ";";
189     strings ~= "uint bitDepth = "   ~ to!(char[])(info.image.bitDepth)~ ";";
190
191     char[] ct = colorTypeToString(info.image.colorType);
192     strings ~= "char[" ~ to!(char[])(ct.length) ~ "] colorType = \"" ~ ct ~ "\";";
193    
194     if (!hasAlphaChannel(info.image.colorType) && info.colorKey)
195     {
196         char[] type = (info.image.bitDepth > 8) ? "ushort[3]" : "ubyte[3]";
197
198         strings ~= type ~ " colorkey = ["   ~ to!(char[])(info.keyR) ~ ", "
199                                             ~ to!(char[])(info.keyG) ~ ", "
200                                             ~ to!(char[])(info.keyB) ~ "];";
201     }
202     if (info.backgroundColor.length)
203     {
204       //TODO
205     }
206
207     strings ~=  "ubyte[" ~ to!(char[])(pixels.length) ~ "] pixels = \n" ~
208                     formatArrayToStrings(pixels, (info.image.bitDepth / 8) * info.image.width) ~ ";";
209  }
210
211 char[] formatArrayToStrings(ubyte[] array, size_t width = 0)
212 {
213     //TODO: make type of array generic, error checking (allow 16 bit images)
214     Layout!(char) Layouter = new Layout!(char)();
215    
216     uint hexLength = 4;
217     uint stringLength = array.length * (hexLength + 2) + width;
218     char[] result = new char[stringLength];
219                        
220     if (width == 0)
221         width = array.length;
222
223     result[0..2] = "[ ";
224
225     Layouter.sprint( result[2 .. $], "0x{:x2}", array[0] );
226     size_t pos = hexLength + 2;
227     size_t x = 1;
228    
229     for (size_t y = 0; y < array.length / width; y++)
230     {
231    
232         for (; x < width + (y * width); x++, pos += hexLength + 2)
233         {
234             Layouter.sprint( result[pos .. $], ", 0x{:x2}", array[x] );
235         }
236         result[pos..pos+1] = "\n";
237         pos+=1;
238     }
239     result[pos -1..pos] = "]";
240
241    
242     return result;
243 }
Note: See TracBrowser for help on using the browser.