annotate dynamin/lodepng/decode.d @ 0:aa4efef0f0b1

Initial commit of code.
author Jordan Miner <jminer7@gmail.com>
date Mon, 15 Jun 2009 22:10:48 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
1 // Written in the D programming language
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
2 // www.digitalmars.com/d/
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
3
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
4 /***************************************************************************************************
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
5 License:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
6 Copyright (c) 2005-2007 Lode Vandevenne
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
7 All rights reserved.
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
8
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
9 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
10
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
11 - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.<br>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
12 - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.<br>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
13 - Neither the name of Lode Vandevenne nor the names of his contributors may be used to endorse or promote products derived from this software without specific prior written permission.<br>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
14
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
16
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
17 Authors: Lode Vandevenne (original version in C++), Lutger Blijdestijn (D version) : lutger dot blijdestijn at gmail dot com.
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
18
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
19 About:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
20 The decoder is small but sufficient for most purposes. It is compliant to the png specification and
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
21 has been tested with the png suite. The api is procedural and simple, meant to be easily integrated. It is compatible with the
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
22 Phobos and Tango libraries. For Tango, lodepng expects the zlib binding from phobos in etc.c.zlib.d<br>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
23 This module publicly imports lodepng.Common, where you'll find the data types used by both the encoder
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
24 and decoder, as well as some utility and image format conversion routines.
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
25
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
26 Date: August 7, 2007
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
27
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
28 Features:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
29 The following features are supported by the decoder:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
30 <ul>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
31 <li> conformant decoding of PNGs (all color types, bit depth, interlace mode, CRC checking, etc.)</li>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
32 <li> support for translucent PNG's, including translucent palettes and color key</li>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
33 <li> textual key-value meta-data</li>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
34 <li> the following chunks are interpreted by the decoder
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
35 <ul>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
36 <li>IHDR (image information)</li>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
37 <li>PLTE (color palette)</li>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
38 <li>IDAT (pixel data)</li>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
39 <li>IEND (the final chunk)</li>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
40 <li>tRNS (transparency for palettized images)</li>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
41 <li>bKGD (suggested background color)</li>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
42 <li>tEXt (uncompressed latin-1 key-value strings)</li>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
43 <li>zTXt (compressed latin-1 key-value strings)</li>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
44 <li>iTXt (utf8 key-value strings)</li>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
45 </ul>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
46 </li>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
47 </UL>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
48
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
49 Limitations:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
50 The following features are not supported.
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
51 <ul>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
52 <li> editing a PNG image (unless you use the decoder, then edit it, then use the
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
53 encoder, but ignored chunks will then be gone from the original image)</li>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
54 <li> Streaming / progressive display. All data must be available and is processed in one call.</li>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
55 <li> The following optional chunk types are not interpreted by the decoder
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
56 <ul>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
57 <li>cHRM (device independent color info)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
58 <li>gAMA (device independent color info)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
59 <li>iCCP (device independent color info)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
60 <li>sBIT (original number of significant bits)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
61 <li>sRGB (device independent color info)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
62 <li>pHYs (physical pixel dimensions)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
63 <li>sPLT (suggested reduced palette)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
64 <li>tIME (last image modification time)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
65 </ul>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
66 </li>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
67 </ul>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
68
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
69 Examples:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
70 Here is an example how you could use LodePNG with opengl, see the api documentation for details.
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
71 ---
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
72 uint loadPNG(char[] filename)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
73 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
74 uint textureID;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
75
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
76 glEnable(GL_TEXTURE_2D);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
77 glGenTextures(1, &textureID);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
78 glBindTexture(GL_TEXTURE_2D, textureID);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
79 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
80 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
81
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
82 PngInfo info;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
83 ubyte[] image = decode32(cast(ubyte[])std.file.read(filename), info);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
84
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
85 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, info.image.width, info.image.height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
86 image.ptr);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
87 return textureID;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
88 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
89 ---
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
90
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
91 References:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
92 $(LINK2 http://members.gamedev.net/lode/projects/LodePNG/, Original lodepng) <br>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
93 $(LINK2 http://www.w3.org/TR/PNG/, PNG Specification) <br>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
94 $(LINK2 http://www.libpng.org/pub/png/pngsuite.html, PNG Suite: set of test images) <br>
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
95 $(LINK2 http://optipng.sourceforge.net/, OptiPNG: tool to experimentally optimize png images)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
96 */
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
97
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
98 module dynamin.lodepng.decode;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
99 import dynamin.lodepng.zlib_codec;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
100 import dynamin.lodepng.util;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
101 import std.intrinsic;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
102
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
103 public import dynamin.lodepng.common;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
104
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
105 /***************************************************************************************************
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
106 Parse png image header from memory. The first 33 bytes of the png file need to be available
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
107
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
108 throws: PngException
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
109
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
110 ***************************************************************************************************/
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
111 PngImage readHeader(in ubyte[] source)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
112 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
113 ubyte interlace;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
114 return readHeader(source, interlace);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
115 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
116
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
117 /// ditto
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
118 PngImage readHeader(in ubyte[] source, out ubyte interlace)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
119 in
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
120 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
121 assert(source.length >= HEADER_SIZE, "array is too small to contain png header");
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
122 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
123 body // see spec: http://www.w3.org/TR/PNG/#11IHDR
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
124 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
125 mixin(pngEnforce(`source.length >= HEADER_SIZE`, "png header data is too small"));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
126 mixin(pngEnforce(`source[0..8] == [cast(ubyte)137, 80, 78, 71, 13, 10, 26, 10]`, "invalid png header "));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
127 mixin(pngEnforce((toUint(source[12..16]) == IHDR).stringof, "invalid png header"));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
128 mixin(pngEnforce(`checkCRC(source[29 .. 33], source[12 .. 29])`, "invalid CRC"));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
129
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
130 PngImage result;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
131 ubyte interlaceMethod;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
132
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
133 with (result)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
134 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
135 width = toUint(source[16..20]);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
136 height = toUint(source[20..24]);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
137 bitDepth = source[24];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
138 colorType = cast(ColorType)source[25];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
139 mixin(pngEnforce( `source[26] == 0`, "unsupported compression method in png header" ));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
140 mixin(pngEnforce( `source[27] == 0`, "unsupported filter method in png header" ));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
141 mixin(pngEnforce( `checkColorValidity(colorType, bitDepth)`, "invalid header: wrong color format" ));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
142 interlaceMethod = source[28];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
143 mixin(pngEnforce( `interlaceMethod < 2`, "invalid interlace method in png header" ));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
144 bpp = numChannels(colorType) * bitDepth;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
145 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
146 interlace = interlaceMethod;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
147 return result;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
148 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
149
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
150 /***************************************************************************************************
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
151 Decode source png file
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
152
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
153 If a buffer is provided, it may be used to store the result. See bufferSize for details.
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
154
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
155 Throws: PngException
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
156 Returns: Decoded image pixels. The color format of the resulting image is the
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
157 same as the source image, see lodepng.Common.convert and decode32 if a specific color format
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
158 is desired.
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
159
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
160 ***************************************************************************************************/
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
161 ubyte[] decode(in ubyte[] source, ref PngInfo info, ubyte[] buffer = null)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
162 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
163 info.image = readHeader(source, info.interlace);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
164
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
165 // holds interlaced filtered scanlines
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
166 ubyte[] ilaceBuffer;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
167
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
168 // to allocate memory as needed
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
169 if (info.interlace == 1)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
170 buffer.length = ((info.image.width * info.image.bpp + 7) / 8) * info.image.height + (info.image.height * 2); // guess
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
171 else
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
172 buffer.length = ((info.image.width * info.image.bpp + 7) / 8) * info.image.height + info.image.height;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
173
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
174
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
175 if (info.interlace == 1)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
176 ilaceBuffer.length = buffer.length - info.image.height;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
177
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
178 auto inflator = DecodeStream.create(buffer);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
179
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
180 foreach(chunk; StreamChunkIter(source[HEADER_SIZE - 1 .. $]))
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
181 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
182 switch(chunk.type)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
183 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
184 case IDAT:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
185 inflator(chunk.data);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
186 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
187 case PLTE:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
188 mixin(pngEnforce(`chunk.data.length <= 256 * 3`, "palette size is too large"));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
189 info.palette.length = chunk.data.length / 3;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
190 foreach(index, ref ubyte[4] color; info.palette)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
191 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
192 color[0..3] = chunk.data[index * 3 .. index * 3 + 3];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
193 color[3] = 255;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
194 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
195
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
196 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
197 case tRNS:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
198 if (chunk.data.length == 0)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
199 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
200 info.colorKey = true;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
201 if (info.image.colorType == ColorType.Palette) // index-values
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
202 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
203 mixin(pngEnforce(`chunk.data.length <= info.palette.length`, "palette size is too large"));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
204 foreach(index, alpha; chunk.data)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
205 info.palette[index][3] = alpha;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
206 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
207 else if (info.image.colorType == ColorType.RGB)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
208 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
209 info.keyR = 256U * chunk.data[0] + chunk.data[1];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
210 info.keyG = 256U * chunk.data[2] + chunk.data[3];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
211 info.keyB = 256U * chunk.data[4] + chunk.data[5];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
212 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
213 else if (info.image.colorType == ColorType.Greyscale)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
214 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
215 info.keyR = 256U * chunk.data[0] + chunk.data[1];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
216 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
217 else
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
218 assert(false);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
219 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
220 case bKGD:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
221 if (info.image.colorType == ColorType.Palette || info.image.bitDepth == 16)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
222 info.backgroundColor = chunk.data.dup;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
223 else
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
224 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
225 info.backgroundColor.length = chunk.data.length / 2;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
226 foreach(index, ref value; info.backgroundColor)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
227 value = chunk.data[index * 2];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
228 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
229 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
230 case zTXt:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
231 if (info.parseText)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
232 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
233 if (info.textual is null)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
234 info.textual = new PngText;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
235 auto sep = strFind(cast(char[])chunk.data, 0);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
236 if (sep > 0)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
237 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
238 if (chunk.data[sep + 1] == 0)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
239 info.textual[chunk.data[0..sep]] = chunk.data[sep + 2 .. $];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
240 else
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
241 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
242 ubyte[] value;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
243 auto decoder = DecodeStream.create(value);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
244 decoder(chunk.data[sep + 2 .. $]);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
245 info.textual[chunk.data[0..sep]] = value;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
246 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
247 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
248 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
249 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
250 case tEXt:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
251 if (info.parseText)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
252 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
253 if (info.textual is null)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
254 info.textual = new PngText;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
255 auto sep = strFind(cast(char[])chunk.data, 0);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
256 if (sep > 0)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
257 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
258 info.textual[chunk.data[0..sep]] = chunk.data[sep + 1 .. $];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
259 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
260 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
261 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
262 case iTXt:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
263 if (info.parseText)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
264 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
265 if (info.textual is null)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
266 info.textual = new PngText;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
267 auto sep = strFind(cast(char[])chunk.data, 0);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
268 char[] keyword = cast(char[])chunk.data[0..sep];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
269 bool compressed = chunk.data[sep + 1] == 0 ? false : true;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
270 sep += strFind(cast(char[])chunk.data[sep + 3 .. $], 0) + 3;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
271 sep += strFind(cast(char[])chunk.data[sep + 1 .. $], 0) + 1;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
272 if (!compressed)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
273 info.textual[keyword] = cast(char[])chunk.data[sep + 1..$];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
274 else
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
275 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
276 ubyte[] value;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
277 auto decoder = DecodeStream.create(value);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
278 decoder(chunk.data[sep + 1..$]);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
279 info.textual[keyword] = cast(char[])value;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
280 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
281 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
282 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
283 default:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
284 mixin(pngEnforce(`(bt(&chunk.type, 6) < 0)`, "unrecognized critical chunk"));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
285 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
286 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
287 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
288 assert(inflator.hasEnded);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
289 buffer = inflator();
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
290
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
291 return (info.interlace == 0) ? reconstruct(buffer, info.image)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
292 : deinterlace(buffer, ilaceBuffer, info.image);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
293 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
294
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
295 /***************************************************************************************************
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
296 Decode source png file to RGBA format
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
297
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
298 Throws: PngException
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
299 Returns: decoded image pixels in 32-bit RGBA format
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
300 ***************************************************************************************************/
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
301 ubyte[] decode32(in ubyte[] source, ref PngInfo info, ubyte[] buffer = null)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
302 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
303 buffer = decode(source, info, buffer);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
304 buffer = convert(buffer, info, ColorType.RGBA);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
305 info.image.colorType = ColorType.RGBA;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
306 info.image.bpp = 32;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
307 info.image.bitDepth = 8;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
308 info.palette.length = 0;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
309 return buffer;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
310 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
311
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
312
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
313
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
314
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
315 /***************************************************************************************************
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
316 Predict size of buffer needed for decoding
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
317
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
318 Estimate of the amount of heap memory needed to decode an image. Interlaced images, images
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
319 with a color format of less than 8 bits per pixel and the parsing of certain information
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
320 such as text will allocate more heap memory.
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
321 ***************************************************************************************************/
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
322 uint bufferSize( /+const+/ ref PngImage image)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
323 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
324 return ((image.width * image.bpp + 7) / 8) * image.height + image.height;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
325 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
326
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
327 ////////////////////////////////////////////////////////////////////////////////////////////////////
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
328 // //
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
329 // PRIVATE SECTION //
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
330 // //
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
331 ////////////////////////////////////////////////////////////////////////////////////////////////////
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
332
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
333 private:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
334
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
335 const uint HEADER_SIZE = 34;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
336
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
337 struct StreamChunkIter
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
338 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
339 int opApply(int delegate(ref Chunk chunk) visitor)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
340 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
341 int result = 0;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
342 uint pos = 0;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
343 Chunk chunk;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
344 while(pos + 12 <= stream.length)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
345 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
346 chunk = Chunk.fromStream(stream[pos..$]);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
347 if (chunk.type == IEND)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
348 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
349 result = visitor(chunk);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
350 if (result)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
351 return result;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
352 pos += chunk.length;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
353 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
354 return result;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
355 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
356 ubyte[] stream;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
357 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
358
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
359 //filter a PNG image scanline by scanline. when the pixels are smaller than 1 byte, the filter works
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
360 //byte per byte (bytewidth = 1)precon is the previous filtered scanline, recon the result, scanline
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
361 //the current one
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
362 void unFilterFirstScanline(ubyte[] result, ubyte[] scanline, uint bytewidth, uint filterType)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
363 in
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
364 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
365 assert(filterType >= 0 && filterType <= 4);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
366 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
367 body
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
368 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
369 mixin(pngEnforce(`filterType >= 0 && filterType <= 4`, "wrong filter byte: image corrupt?"));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
370 switch(filterType)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
371 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
372 case 0:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
373 for(uint i = 0; i < scanline.length; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
374 result[i] = scanline[i];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
375 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
376 case 1:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
377 for(uint i = 0; i < bytewidth; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
378 result[i] = scanline[i];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
379 for(uint i = bytewidth; i < scanline.length; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
380 result[i] = scanline[i] + result[i - bytewidth];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
381 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
382 case 2:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
383 for(size_t i = 0; i < scanline.length; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
384 result[i] = scanline[i];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
385 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
386 case 3:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
387 for(size_t i = 0; i < bytewidth; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
388 result[i] = scanline[i];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
389 for(size_t i = bytewidth; i < scanline.length; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
390 result[i] = (scanline[i] + result[i - bytewidth]) / 2;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
391 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
392 case 4:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
393 for(size_t i = 0; i < bytewidth; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
394 result[i] = scanline[i];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
395 for(size_t i = bytewidth; i < scanline.length; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
396 result[i] = cast(ubyte)(scanline[i] + paethPredictor(result[i - bytewidth], 0, 0));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
397 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
398 default:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
399 mixin(pngEnforce("false", "wrong type of filter"));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
400 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
401
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
402 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
403 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
404
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
405 //filter a PNG image scanline by scanline. when the pixels are smaller than 1 byte, the filter works
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
406 //byte per byte (bytewidth = 1) precon is the previous filtered scanline, recon the result,
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
407 //scanline the current one
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
408 void unFilterScanline(ubyte[] result, ubyte[] scanline, ubyte[] previous, uint bytewidth,
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
409 uint filterType)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
410 in
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
411 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
412 assert(filterType >= 0 && filterType <= 4);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
413 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
414 body
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
415 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
416 switch(filterType)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
417 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
418 case 4:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
419 for(size_t i = 0; i < bytewidth; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
420 result[i] = cast(ubyte)(scanline[i] + previous[i] );
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
421 for(size_t i = bytewidth; i < scanline.length; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
422 result[i] = cast(ubyte)(scanline[i] +
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
423 paethPredictor(result[i - bytewidth],
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
424 previous[i],
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
425 previous[i - bytewidth]));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
426 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
427 case 3:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
428 for(size_t i = 0; i < bytewidth; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
429 result[i] = scanline[i] + previous[i] / 2;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
430 for(size_t i = bytewidth; i < scanline.length; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
431 result[i] = scanline[i] + ((result[i - bytewidth] + previous[i]) / 2);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
432 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
433 case 2:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
434 for(size_t i = 0; i < scanline.length; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
435 result[i] = scanline[i] + previous[i];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
436 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
437 case 1:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
438 for(size_t i = 0; i < bytewidth; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
439 result[i] = scanline[i];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
440 for(size_t i = bytewidth; i < scanline.length; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
441 result[i] = scanline[i] + result[i - bytewidth];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
442 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
443 case 0:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
444 for(uint i = 0; i < scanline.length; i++) result[i] = scanline[i];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
445 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
446 default:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
447 mixin(pngEnforce("false", "wrong type of filter"));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
448 break;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
449 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
450 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
451
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
452 ubyte[] deinterlace(in ubyte[] scanlines, ref ubyte[] result, ref PngImage image)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
453 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
454 const x = 0;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
455 const y = 1;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
456 uint bytewidth = (image.bpp + 7) / 8; // bytewidth is used for filtering
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
457 ubyte[] source;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
458 ubyte[] scanlineo = new ubyte[image.width * bytewidth]; //"old" scanline
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
459 ubyte[] scanlinen = new ubyte[image.width * bytewidth]; //"new" scanline
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
460
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
461 uint[7][2] passDim;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
462 passDim[x][0] = (image.width + 7) / 8; passDim[y][0] = (image.height + 7) / 8;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
463 passDim[x][1] = (image.width + 3) / 8; passDim[y][1] = (image.height + 7) / 8;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
464 passDim[x][2] = (image.width + 3) / 4; passDim[y][2] = (image.height + 3) / 8;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
465 passDim[x][3] = (image.width + 1) / 4; passDim[y][3] = (image.height + 3) / 4;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
466 passDim[x][4] = (image.width + 1) / 2; passDim[y][4] = (image.height + 1) / 4;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
467 passDim[x][5] = (image.width + 0) / 2; passDim[y][5] = (image.height + 1) / 2;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
468 passDim[x][6] = (image.width + 0) / 1; passDim[y][6] = (image.height + 0) / 2;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
469
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
470 // locate start in source of each pass, note:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
471 // (HACK) pass can be empty, sets both x and y axis to zero to recognize this in processPass
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
472
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
473 size_t[7] passstart;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
474 passstart[0] = 0;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
475 for(int i = 0; i < 6; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
476 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
477 if (passDim[y][i] * passDim[x][i] == 0)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
478 passDim[y][i] = passDim[x][i] = 0;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
479
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
480 passstart[i + 1] = passstart[i] + (passDim[y][i] * (1 + (passDim[x][i] * image.bpp + 7) / 8));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
481 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
482
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
483 void adam7Pass( size_t passleft, size_t passtop, size_t spacex, size_t spacey,
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
484 size_t passw, size_t passh)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
485 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
486 size_t linelength = 1 + ((image.bpp * passw + 7) / 8);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
487 size_t linestart = 0;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
488 uint filterType = source[0];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
489
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
490 void placePixels(uint s)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
491 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
492 if(image.bpp >= 8)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
493 for(size_t i = 0; i < passw; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
494 for(size_t b = 0; b < bytewidth; b++) //b = current byte of this pixel
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
495 result[bytewidth * image.width * (passtop + spacey * s) + bytewidth *
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
496 (passleft + spacex * i) + b] = scanlinen[bytewidth * i + b];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
497 else
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
498 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
499 for(size_t i = 0; i < passw; i++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
500 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
501 size_t outbitp = image.bpp * image.width * (passtop + spacey * s) +
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
502 image.bpp * (passleft + spacex * i);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
503 for(size_t b = 0; b < image.bpp; b++) //b = current bit of this pixel
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
504 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
505 size_t obp = outbitp + b;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
506 //where bitpos 0 refers to the LSB, bitpot 7 to the MSB of a byte
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
507 size_t obitpos = 7 - (obp & 0x7);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
508 size_t bp = i * image.bpp + b;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
509 //where bitpos 0 refers to the LSB, bitpot 7 to the MSB of a byte
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
510 size_t bitpos = 7 - (bp & 0x7);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
511 uint _bit = (scanlinen[bp / 8] >> bitpos) & 1;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
512 result[obp / 8] = cast(ubyte)((result[obp / 8] & ~(1 << obitpos)) |
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
513 (_bit << obitpos));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
514 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
515 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
516 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
517 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
518
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
519 void swapScanlines()
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
520 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
521 ubyte[] temp = scanlinen;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
522 scanlinen = scanlineo;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
523 scanlineo = temp;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
524 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
525
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
526 unFilterFirstScanline(scanlinen, source[linestart + 1 .. linestart + linelength],
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
527 bytewidth, filterType);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
528 placePixels(0);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
529 swapScanlines();
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
530
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
531 for(uint s = 1; s < passh; s++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
532 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
533 linestart = s * linelength;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
534 filterType = source[linestart];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
535
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
536 unFilterScanline(scanlinen, source[linestart + 1 .. linestart + linelength],
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
537 scanlineo, bytewidth, filterType);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
538 placePixels(s);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
539 swapScanlines();
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
540 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
541 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
542
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
543 void processPass(size_t pass, size_t left, size_t top, size_t sx, size_t sy)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
544 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
545 // check if pass is empty
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
546 if (pass > 0 && (passDim[x][pass] * passDim[y][pass] == 0))
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
547 return;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
548 source = scanlines[passstart[pass]..$];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
549 adam7Pass( left, top, sx, sy, passDim[x][pass], passDim[y][pass]);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
550 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
551
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
552
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
553 processPass(0, 0, 0, 8, 8);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
554 processPass(1, 4, 0, 8, 8);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
555 processPass(2, 0, 4, 4, 8);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
556 processPass(3, 2, 0, 4, 4);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
557 processPass(4, 0, 2, 2, 4);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
558 processPass(5, 1, 0, 2, 2);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
559 processPass(6, 0, 1, 1, 2);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
560
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
561 return result;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
562 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
563
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
564 ubyte[] reconstruct(ref ubyte[] buffer, /+const+/ ref PngImage image)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
565 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
566 //filter and interlace
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
567 uint bytewidth = (image.bpp + 7) / 8; // bytewidth is used for filtering
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
568 uint outlength = image.height * image.width * bytewidth;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
569
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
570
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
571 size_t linestart = 0; //start of current scanline
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
572
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
573 // bits are tightly packed, but scanlines are always padded to 1 byte bounderies:
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
574 uint scanlength = ((image.width * image.bpp) + 7) / 8;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
575
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
576 mixin(pngEnforce( `buffer.length >= (scanlength + 1) * image.height && buffer.length > 0`, "invalid size of source data"));
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
577
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
578 uint filterType = buffer[linestart];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
579
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
580
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
581 if(image.bpp >= 8) //byte per byte
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
582 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
583 filterType = buffer[linestart];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
584 unFilterFirstScanline(buffer, buffer[1..1 + scanlength], bytewidth, filterType);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
585
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
586 //go to start of next scanline
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
587 linestart += 1 + scanlength;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
588
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
589 for(size_t s = 1; s < image.height; ++s)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
590 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
591 filterType = buffer[linestart];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
592 unFilterScanline(buffer[linestart - s..$],
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
593 buffer[linestart + 1 .. linestart + 1 + scanlength],
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
594 buffer[(s - 1) * image.width * bytewidth..$],
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
595 bytewidth, filterType);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
596
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
597
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
598 //go to start of next scanline
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
599 linestart += 1 + scanlength;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
600 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
601 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
602 else //less than 8 bits per pixel, so fill it up bit per bit
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
603 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
604 size_t obp = 0; //out bit pointer
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
605
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
606 ubyte[] templine = new ubyte[scanlength];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
607 filterType = buffer[linestart];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
608 unFilterFirstScanline(templine, buffer[1 .. 1 + scanlength], bytewidth, filterType);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
609
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
610 linestart += 1 + scanlength;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
611
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
612 //bp is here bit pointer in templine
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
613 for(size_t bp = 0; bp < image.width * image.bpp; bp++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
614 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
615 size_t obitpos = 7 - (obp & 0x7);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
616 size_t bitpos = 7 - (bp & 0x7);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
617 uint _bit = (templine[bp / 8] >> bitpos) & 1;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
618 buffer[obp / 8] = cast(ubyte)((buffer[obp / 8] & ~(1 << obitpos)) |
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
619 (_bit << obitpos)); //set current bit
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
620 obp++;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
621 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
622
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
623 for(size_t s = 1; s < image.height; ++s)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
624 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
625 filterType = buffer[linestart];
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
626 unFilterScanline( templine,
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
627 buffer[linestart + 1 .. linestart + 1 + scanlength],
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
628 buffer[(s - 1) * scanlength..$],
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
629 bytewidth,
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
630 filterType);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
631
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
632 //bp is here bit pointer in templine
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
633 for(size_t bp = 0; bp < image.width * image.bpp; bp++)
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
634 {
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
635 size_t obitpos = 7 - (obp & 0x7);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
636 size_t bitpos = 7 - (bp & 0x7);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
637 uint _bit = (templine[bp / 8] >> bitpos) & 1;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
638 buffer[obp / 8] = cast(ubyte)((buffer[obp / 8] & ~(1 << obitpos)) |
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
639 (_bit << obitpos)); //set current bit
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
640 obp++;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
641 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
642
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
643 //go to start of next scanline
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
644 linestart += 1 + ((image.width * image.bpp + 7) / 8);
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
645 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
646 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
647 return buffer;
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
648 }
aa4efef0f0b1 Initial commit of code.
Jordan Miner <jminer7@gmail.com>
parents:
diff changeset
649