diff --git a/3rdparty/dimage/array.d b/3rdparty/dimage/array.d deleted file mode 100644 index 712a66d7..00000000 --- a/3rdparty/dimage/array.d +++ /dev/null @@ -1,243 +0,0 @@ -/* -Copyright (c) 2015 Timur Gafarov - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - -// dimage is actually stripped out part of dlib - just to support reading PNG and JPEG -module dimage.array; //dlib.container.array - -import dimage.memory; - -/* - * GC-free dynamic array implementation. - * Very efficient for small-sized arrays. - */ - -struct DynamicArray(T, size_t chunkSize = 32) -{ - T[chunkSize] staticStorage; - T[] dynamicStorage; - uint numChunks = 0; - uint pos = 0; - - T* storage() - { - if (numChunks == 0) - return staticStorage.ptr; - else - return dynamicStorage.ptr; - } - - void addChunk() - { - if (numChunks == 0) - { - dynamicStorage = New!(T[])(chunkSize); - } - else - { - reallocateArray( - dynamicStorage, - dynamicStorage.length + chunkSize); - } - numChunks++; - } - - void shiftRight() - { - append(T.init); - - for(uint i = pos-1; i > 0; i--) - { - storage[i] = storage[i-1]; - } - } - - void shiftLeft(uint n) - { - for(uint i = 0; i < pos; i++) - { - if (n + i < pos) - storage[i] = storage[n + i]; - else - storage[i] = T.init; - } - } - - void append(T c) - { - if (numChunks == 0) - { - staticStorage[pos] = c; - pos++; - if (pos == chunkSize) - { - addChunk(); - foreach(i, ref v; dynamicStorage) - v = staticStorage[i]; - } - } - else - { - if (pos == dynamicStorage.length) - addChunk(); - - dynamicStorage[pos] = c; - pos++; - } - } - - void appendLeft(T c) - { - shiftRight(); - storage[0] = c; - } - - void append(const(T)[] s) - { - foreach(c; s) - append(cast(T)c); - } - - void appendLeft(const(T)[] s) - { - foreach(c; s) - appendLeft(cast(T)c); - } - - auto opCatAssign(T c) - { - append(c); - return this; - } - - auto opCatAssign(const(T)[] s) - { - append(s); - return this; - } - - uint remove(uint n) - { - if (pos == n) - { - pos = 0; - return n; - } - else if (pos >= n) - { - pos -= n; - return n; - } - else - { - n = pos; - pos = 0; - return n; - } - } - - uint removeLeft(uint n) - { - if (pos == n) - { - pos = 0; - return n; - } - else if (pos > n) - { - shiftLeft(n); - pos -= n; - return n; - } - else - { - n = pos; - pos = 0; - return n; - } - } - - size_t length() - { - return pos; - } - - T[] data() - { - return storage[0..pos]; - } - - T opIndex(size_t index) - { - return data[index]; - } - - T opIndexAssign(T t, size_t index) - { - data[index] = t; - return t; - } - - int opApply(int delegate(size_t i, ref T) dg) - { - foreach(i, ref v; data) - { - dg(i, v); - } - - return 0; - } - - int opApply(int delegate(ref T) dg) - { - foreach(i, ref v; data) - { - dg(v); - } - - return 0; - } - - void free() - { - if (dynamicStorage.length) - Delete(dynamicStorage); - numChunks = 0; - pos = 0; - } -} - -void reallocateArray(T)(ref T[] buffer, size_t len) -{ - T[] buffer2 = New!(T[])(len); - for(uint i = 0; i < buffer2.length; i++) - if (i < buffer.length) - buffer2[i] = buffer[i]; - Delete(buffer); - buffer = buffer2; -} - diff --git a/3rdparty/dimage/bitio.d b/3rdparty/dimage/bitio.d deleted file mode 100644 index 1c3f1f04..00000000 --- a/3rdparty/dimage/bitio.d +++ /dev/null @@ -1,70 +0,0 @@ -/* -Copyright (c) 2015 Timur Gafarov - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - -// dimage is actually stripped out part of dlib - just to support reading PNG and JPEG -module dimage.bitio; //dlib.core.bitio - -/* - * Bit-level manipulations - */ - -enum Endian -{ - Little, - Big -} - -T hiNibble(T)(T b) -{ - return ((b >> 4) & 0x0F); -} - -T loNibble(T)(T b) -{ - return (b & 0x0F); -} - -T swapEndian16(T)(T n) -{ - return cast(T)((n >> 8) | (n << 8)); -} - -T setBit(T)(T b, uint pos, bool state) -{ - if (state) - return cast(T)(b | (1 << pos)); - else - return cast(T)(b & ~(1 << pos)); -} - -bool getBit(T)(T b, uint pos) -{ - return ((b & (1 << pos)) != 0); -} - - diff --git a/3rdparty/dimage/compound.d b/3rdparty/dimage/compound.d deleted file mode 100644 index 51d851fd..00000000 --- a/3rdparty/dimage/compound.d +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright (c) 2011-2013 Timur Gafarov - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - -// dimage is actually stripped out part of dlib - just to support reading PNG and JPEG -//dlib.core.compound -module dimage.compound; - -struct Compound(T...) -{ - T tuple; - alias tuple this; -} - -Compound!(T) compound(T...)(T args) -{ - return Compound!(T)(args); -} - diff --git a/3rdparty/dimage/huffman.d b/3rdparty/dimage/huffman.d deleted file mode 100644 index f623954b..00000000 --- a/3rdparty/dimage/huffman.d +++ /dev/null @@ -1,309 +0,0 @@ -/* -Copyright (c) 2015 Timur Gafarov - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - -// dimage is actually stripped out part of dlib - just to support reading PNG and JPEG -module dimage.huffman; - -import dimage.memory; -import dimage.bitio; - -//import dlib.core.memory; -//import dlib.core.bitio; - -struct HuffmanTreeNode -{ - HuffmanTreeNode* parent; - HuffmanTreeNode* left; - HuffmanTreeNode* right; - ubyte ch; - uint freq; - bool blank = true; - - this( - HuffmanTreeNode* leftNode, - HuffmanTreeNode* rightNode, - ubyte symbol, - uint frequency, - bool isBlank) - { - parent = null; - left = leftNode; - right = rightNode; - - if (left !is null) - left.parent = &this; - if (right !is null) - right.parent = &this; - - ch = symbol; - freq = frequency; - blank = isBlank; - } - - bool isLeaf() - { - return (left is null && right is null); - } - - void free() - { - if (left !is null) - { - left.free(); - Delete(left); - } - - if (right !is null) - { - right.free(); - Delete(right); - } - } - -/* - // TODO: implement this without GC - - void getCodes(ref string[ubyte] table, string code = "") - { - if (isLeaf()) - { - table[ch] = code; - } - else - { - if (left !is null) - left.getCodes(table, code ~ '0'); - if (right !is null) - right.getCodes(table, code ~ '1'); - } - } - - void print(string indent = "") - { - writefln("%s<%s>%x", indent, freq, ch); - indent ~= " "; - if (left !is null) - left.print(indent); - if (right !is null) - right.print(indent); - } -*/ -} - -/* -// TODO: implement this without GC - -HuffmanTreeNode* buildHuffmanTree(ubyte[] data) -{ - // Count frequencies - uint[ubyte] freqs; - foreach(s; data) - { - if (s in freqs) - freqs[s] += 1; - else - freqs[s] = 1; - } - - // Sort in descending order - ubyte[] symbols = freqs.keys; - sort!((a, b) => freqs[a] > freqs[b])(symbols); - - // Create node list - auto nodeList = new HuffmanTreeNode*[symbols.length]; - foreach(i, s; symbols) - nodeList[i] = new HuffmanTreeNode(null, null, s, freqs[s], false); - - // Build tree - while (nodeList.length > 1) - { - // Pop two nodes with minimal frequencies - auto n1 = nodeList[$-1]; - auto n2 = nodeList[$-2]; - nodeList.popBack; - nodeList.popBack; - - // Insert a new parent node - uint fsum = n1.freq + n2.freq; - auto parent = new HuffmanTreeNode(n1, n2, 0, fsum, false); - nodeList ~= parent; - sort!((a, b) => a.freq > b.freq)(nodeList); - } - - auto root = nodeList[0]; - - return root; -} - -void packHuffmanTree(HuffmanTreeNode* node, BitWriter* bw) -{ - if (node.isLeaf) - { - bw.writeBit(true); - bw.writeByte(node.ch); - } - else - { - bw.writeBit(false); - packHuffmanTree(node.left, bw); - packHuffmanTree(node.right, bw); - } -} - -HuffmanTreeNode* unpackHuffmanTree(BitReader* br) -{ - if (!br.end) - { - bool bit = br.readBit(); - if (bit) - { - byte ch = br.readByte(); - return new HuffmanTreeNode(null, null, ch, 0, false); - } - else - { - HuffmanTreeNode* left = unpackHuffmanTree(br); - HuffmanTreeNode* right = unpackHuffmanTree(br); - return new HuffmanTreeNode(left, right, 0, 0, false); - } - } - else return null; -} - -ubyte[] encodeHuffman(ubyte[] data, out HuffmanTreeNode* tree) -{ - // Build Huffman tree - tree = buildHuffmanTree(data); - - // Generate binary codes - string[ubyte] huffTable; - tree.getCodes(huffTable); - - // Encode data - string bitStr; - foreach(s; data) - bitStr ~= huffTable[s]; - - // Pack bits to byte array - uint octetsLen = 0; - ubyte lastBits = 0; - if (bitStr.length == 8) - { - octetsLen = 1; - } - else if (bitStr.length > 8) - { - octetsLen = cast(uint)bitStr.length / 8; - lastBits = cast(ubyte)(bitStr.length % 8); - if (lastBits != 0) - octetsLen++; - } - else - { - octetsLen = 1; - lastBits = cast(ubyte)(bitStr.length); - } - - octetsLen++; - auto octets = new ubyte[octetsLen]; - octets[0] = lastBits; - - uint bitPos = 0; - uint bytePos = 1; - - foreach(bit; bitStr) - { - bool state; - if (bit == '0') - state = false; - else - state = true; - - octets[bytePos] = setBit(octets[bytePos], bitPos, state); - bitPos++; - - if (bitPos == 8) - { - bitPos = 0; - bytePos++; - } - } - - return octets; -} - -ubyte[] decodeHuffman(ubyte[] data, HuffmanTreeNode* tree) -{ - // Generate binary codes - string[ubyte] huffTable; - tree.getCodes(huffTable); - - //Unpack bits from array - ubyte[] result; - bool appendNext = true; - string code = ""; - ubyte lastBits = data[0]; - foreach(i, b; data[1..$]) - { - uint len; - if ((lastBits != 0) && (i == data.length-1)) - len = lastBits; - else - len = 8; - - foreach(bp; 0..len) - { - char bitChr = getBit(b, bp)? '1':'0'; - if (appendNext) - { - code ~= bitChr; - foreach(key, val; huffTable) - { - if (code == val) - { - result ~= key; - appendNext = false; - break; - } - } - } - else - { - code = ""; - code ~= bitChr; - appendNext = true; - } - } - } - - return result; -} - -*/ - - diff --git a/3rdparty/dimage/idct.d b/3rdparty/dimage/idct.d deleted file mode 100644 index 927f6df7..00000000 --- a/3rdparty/dimage/idct.d +++ /dev/null @@ -1,217 +0,0 @@ -/* -Copyright (c) 2014 Timur Gafarov - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - -// dimage is actually stripped out part of dlib - just to support reading PNG and JPEG -module dimage.idct; //dlib.image.io.idct - -import std.math; - -/* - * Inverse discrete cosine transform (DCT) for 64x64 blocks - */ - -enum blockSize = 64; // A DCT block is 8x8. - -enum w1 = 2841; // 2048*sqrt(2)*cos(1*pi/16) -enum w2 = 2676; // 2048*sqrt(2)*cos(2*pi/16) -enum w3 = 2408; // 2048*sqrt(2)*cos(3*pi/16) -enum w5 = 1609; // 2048*sqrt(2)*cos(5*pi/16) -enum w6 = 1108; // 2048*sqrt(2)*cos(6*pi/16) -enum w7 = 565; // 2048*sqrt(2)*cos(7*pi/16) - -enum w1pw7 = w1 + w7; -enum w1mw7 = w1 - w7; -enum w2pw6 = w2 + w6; -enum w2mw6 = w2 - w6; -enum w3pw5 = w3 + w5; -enum w3mw5 = w3 - w5; - -enum r2 = 181; // 256/sqrt(2) - -// idct performs a 2-D Inverse Discrete Cosine Transformation. -// -// The input coefficients should already have been multiplied by the -// appropriate quantization table. We use fixed-point computation, with the -// number of bits for the fractional component varying over the intermediate -// stages. -// -// For more on the actual algorithm, see Z. Wang, "Fast algorithms for the -// discrete W transform and for the discrete Fourier transform", IEEE Trans. on -// ASSP, Vol. ASSP- 32, pp. 803-816, Aug. 1984. -void idct64(int* src) -{ - // Horizontal 1-D IDCT. - for (uint y = 0; y < 8; y++) - { - int y8 = y * 8; - // If all the AC components are zero, then the IDCT is trivial. - if (src[y8+1] == 0 && src[y8+2] == 0 && src[y8+3] == 0 && - src[y8+4] == 0 && src[y8+5] == 0 && src[y8+6] == 0 && src[y8+7] == 0) - { - int dc = src[y8+0] << 3; - src[y8+0] = dc; - src[y8+1] = dc; - src[y8+2] = dc; - src[y8+3] = dc; - src[y8+4] = dc; - src[y8+5] = dc; - src[y8+6] = dc; - src[y8+7] = dc; - continue; - } - - // Prescale. - int x0 = (src[y8+0] << 11) + 128; - int x1 = src[y8+4] << 11; - int x2 = src[y8+6]; - int x3 = src[y8+2]; - int x4 = src[y8+1]; - int x5 = src[y8+7]; - int x6 = src[y8+5]; - int x7 = src[y8+3]; - - // Stage 1. - int x8 = w7 * (x4 + x5); - x4 = x8 + w1mw7*x4; - x5 = x8 - w1pw7*x5; - x8 = w3 * (x6 + x7); - x6 = x8 - w3mw5*x6; - x7 = x8 - w3pw5*x7; - - // Stage 2. - x8 = x0 + x1; - x0 -= x1; - x1 = w6 * (x3 + x2); - x2 = x1 - w2pw6*x2; - x3 = x1 + w2mw6*x3; - x1 = x4 + x6; - x4 -= x6; - x6 = x5 + x7; - x5 -= x7; - - // Stage 3. - x7 = x8 + x3; - x8 -= x3; - x3 = x0 + x2; - x0 -= x2; - x2 = (r2*(x4+x5) + 128) >> 8; - x4 = (r2*(x4-x5) + 128) >> 8; - - // Stage 4. - src[y8+0] = (x7 + x1) >> 8; - src[y8+1] = (x3 + x2) >> 8; - src[y8+2] = (x0 + x4) >> 8; - src[y8+3] = (x8 + x6) >> 8; - src[y8+4] = (x8 - x6) >> 8; - src[y8+5] = (x0 - x4) >> 8; - src[y8+6] = (x3 - x2) >> 8; - src[y8+7] = (x7 - x1) >> 8; - } - - // Vertical 1-D IDCT. - for (uint x = 0; x < 8; x++) - { - // Similar to the horizontal 1-D IDCT case, if all the AC components are zero, then the IDCT is trivial. - // However, after performing the horizontal 1-D IDCT, there are typically non-zero AC components, so - // we do not bother to check for the all-zero case. - - // Prescale. - int y0 = (src[8*0+x] << 8) + 8192; - int y1 = src[8*4+x] << 8; - int y2 = src[8*6+x]; - int y3 = src[8*2+x]; - int y4 = src[8*1+x]; - int y5 = src[8*7+x]; - int y6 = src[8*5+x]; - int y7 = src[8*3+x]; - - // Stage 1. - int y8 = w7*(y4+y5) + 4; - y4 = (y8 + w1mw7*y4) >> 3; - y5 = (y8 - w1pw7*y5) >> 3; - y8 = w3*(y6+y7) + 4; - y6 = (y8 - w3mw5*y6) >> 3; - y7 = (y8 - w3pw5*y7) >> 3; - - // Stage 2. - y8 = y0 + y1; - y0 -= y1; - y1 = w6*(y3+y2) + 4; - y2 = (y1 - w2pw6*y2) >> 3; - y3 = (y1 + w2mw6*y3) >> 3; - y1 = y4 + y6; - y4 -= y6; - y6 = y5 + y7; - y5 -= y7; - - // Stage 3. - y7 = y8 + y3; - y8 -= y3; - y3 = y0 + y2; - y0 -= y2; - y2 = (r2*(y4+y5) + 128) >> 8; - y4 = (r2*(y4-y5) + 128) >> 8; - - // Stage 4. - src[8*0+x] = (y7 + y1) >> 14; - src[8*1+x] = (y3 + y2) >> 14; - src[8*2+x] = (y0 + y4) >> 14; - src[8*3+x] = (y8 + y6) >> 14; - src[8*4+x] = (y8 - y6) >> 14; - src[8*5+x] = (y0 - y4) >> 14; - src[8*6+x] = (y3 - y2) >> 14; - src[8*7+x] = (y7 - y1) >> 14; - } -} - -/* -void idct(float* inMat, float* outMat) -{ - uint i, j, u, v; - float s; - - for (i = 0; i < 8; i++) - for (j = 0; j < 8; j++) - { - s = 0; - - for (u = 0; u < 8; u++) - for (v = 0; v < 8; v++) - { - s += inMat[u * 8 + v] - * cos((2 * i + 1) * u * PI / 16.0f) - * cos((2 * j + 1) * v * PI / 16.0f) - * ((u == 0) ? 1 / sqrt(2.0f) : 1.0f) - * ((v == 0) ? 1 / sqrt(2.0f) : 1.0f); - } - - outMat[i * 8 + j] = s / 4.0f; - } -} -*/ - diff --git a/3rdparty/dimage/image.d b/3rdparty/dimage/image.d deleted file mode 100644 index 3ece3422..00000000 --- a/3rdparty/dimage/image.d +++ /dev/null @@ -1,83 +0,0 @@ -// dimage is actually stripped out part of dlib - just to support reading PNG and JPEG -module dimage.image; - -//import dimage.color; - -class ImageLoadException : Exception -{ - this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null) - { - super(msg, file, line, next); - } -} - - -class SuperImageFactory { - SuperImage createImage(int width, int height, int components, int bitsPerComponent) { - return new SuperImage(width, height, components, bitsPerComponent); - } -} - -class SuperImage { - immutable int width; - immutable int height; - uint[] data; - immutable int channels; - immutable int bitDepth; - immutable int length; - - void opIndexAssign(uint color, int x, int y) { - data[x + y * width] = color; - } - - uint opIndex(int x, int y) { - return data[x + y * width]; - } - - this(int w, int h, int chan, int depth) { - width = w; - height = h; - channels = chan; - bitDepth = depth; - length = width * height; - data.length = width * height; - } - void free() { - data = null; - } -} - -__gshared SuperImageFactory defaultImageFactory = new SuperImageFactory(); - - -/* - * Byte operations - */ -version (BigEndian) -{ - uint bigEndian(uint value) nothrow - { - return value; - } - - uint networkByteOrder(uint value) nothrow - { - return value; - } -} - -version (LittleEndian) -{ - uint bigEndian(uint value) nothrow - { - return value << 24 - | (value & 0x0000FF00) << 8 - | (value & 0x00FF0000) >> 8 - | value >> 24; - } - - uint networkByteOrder(uint value) nothrow - { - return bigEndian(value); - } -} diff --git a/3rdparty/dimage/jpeg.d b/3rdparty/dimage/jpeg.d deleted file mode 100644 index b07c0bda..00000000 --- a/3rdparty/dimage/jpeg.d +++ /dev/null @@ -1,1306 +0,0 @@ -/* -Copyright (c) 2015 Timur Gafarov - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - -// dimage is actually stripped out part of dlib - just to support reading PNG and JPEG -module dimage.jpeg; - -version = USE_DIMAGE; -version(USE_DIMAGE): - - -import std.stdio; -import std.algorithm; -import std.string; -import std.traits; - -import dimage.huffman; -import dimage.stream; -import dimage.compound; -import dimage.array; -//import dimage.color; -import dimage.image; -import dimage.bitio; -import dimage.memory; -import dimage.idct; -//import dlib.core.memory; -//import dlib.core.stream; -//import dlib.core.compound; -//import dlib.container.array; -//import dlib.filesystem.local; -//import dlib.image.color; -//import dlib.image.image; -//import dlib.image.io.idct; - -//import dlib.core.bitio; -//import dlib.coding.huffman; - -/* - * Simple JPEG decoder - * - * Limitations: - * - Doesn't support progressive JPEG - * - Doesn't perform chroma interpolation - * - Doesn't read EXIF metadata - */ - -// Uncomment this to see debug messages -//version = JPEGDebug; - -T readNumeric(T) (InputStream istrm, Endian endian = Endian.Little) -if (is(T == ubyte)) -{ - ubyte b; - istrm.readBytes(&b, 1); - return b; -} - -T readNumeric(T) (InputStream istrm, Endian endian = Endian.Little) -if (is(T == ushort)) -{ - union U16 - { - ubyte[2] asBytes; - ushort asUshort; - } - U16 u16; - istrm.readBytes(u16.asBytes.ptr, 2); - version(LittleEndian) - { - if (endian == Endian.Big) - return u16.asUshort.swapEndian16; - else - return u16.asUshort; - } - else - { - if (endian == Endian.Little) - return u16.asUshort.swapEndian16; - else - return u16.asUshort; - } -} - -char[size] readChars(size_t size) (InputStream istrm) -{ - char[size] chars; - istrm.readBytes(chars.ptr, size); - return chars; -} - -/* - * JPEG-related Huffman coding - */ - -struct HuffmanCode -{ - ushort bits; - ushort length; - - auto bitString() - { - return .bitString(bits, length); - } -} - -struct HuffmanTableEntry -{ - HuffmanCode code; - ubyte value; -} - -DynamicArray!char bitString(T)(T n, uint len = 1) if (isIntegral!T) -{ - DynamicArray!char arr; - - const int size = T.sizeof * 8; - - bool s = 0; - for (int a = 0; a < size; a++) - { - bool bit = n >> (size - 1); - if (bit) - s = 1; - if (s) - { - arr.append(bit + '0'); - } - n <<= 1; - } - - while (arr.length < len) - arr.appendLeft('0'); - - return arr; -} - -HuffmanTreeNode* emptyNode() -{ - return New!HuffmanTreeNode(null, null, cast(ubyte)0, 0, false); -} - -HuffmanTreeNode* treeFromTable(DynamicArray!(HuffmanTableEntry) table) -{ - HuffmanTreeNode* root = emptyNode(); - - foreach(i, v; table.data) - treeAddCode(root, v.code, v.value); - - return root; -} - -void treeAddCode(HuffmanTreeNode* root, HuffmanCode code, ubyte value) -{ - HuffmanTreeNode* node = root; - auto bs = code.bitString; - foreach(bit; bs.data) - { - if (bit == '0') - { - if (node.left is null) - { - node.left = emptyNode(); - node.left.parent = node; - } - - node = node.left; - } - else if (bit == '1') - { - if (node.right is null) - { - node.right = emptyNode(); - node.right.parent = node; - } - - node = node.right; - } - } - assert (node !is null); - node.ch = value; - bs.free(); -} - -/* - * JPEG-related data types - */ - -enum JPEGMarkerType -{ - Unknown, - SOI, - SOF0, - SOF1, - SOF2, - DHT, - DQT, - DRI, - SOS, - RSTn, - APP0, - APPn, - COM, - EOI -} - -struct JPEGImage -{ - struct JFIF - { - ubyte versionMajor; - ubyte versionMinor; - ubyte units; - ushort xDensity; - ushort yDensity; - ubyte thumbnailWidth; - ubyte thumbnailHeight; - ubyte[] thumbnail; - - void free() - { - if (thumbnail.length) - Delete(thumbnail); - } - } - - struct DQT - { - ubyte precision; - ubyte tableId; - ubyte[] table; - - void free() - { - if (table.length) - Delete(table); - } - } - - struct SOF0Component - { - ubyte hSubsampling; - ubyte vSubsampling; - ubyte dqtTableId; - } - - struct SOF0 - { - ubyte precision; - ushort height; - ushort width; - ubyte componentsNum; - SOF0Component[] components; - - void free() - { - if (components.length) - Delete(components); - } - } - - struct DHT - { - ubyte clas; - ubyte tableId; - DynamicArray!HuffmanTableEntry huffmanTable; - HuffmanTreeNode* huffmanTree; - - void free() - { - huffmanTree.free(); - Delete(huffmanTree); - huffmanTable.free(); - } - } - - struct SOSComponent - { - ubyte tableIdDC; - ubyte tableIdAC; - } - - struct SOS - { - ubyte componentsNum; - SOSComponent[] components; - ubyte spectralSelectionStart; - ubyte spectralSelectionEnd; - ubyte successiveApproximationBitHigh; - ubyte successiveApproximationBitLow; - - void free() - { - if (components.length) - Delete(components); - } - } - - JFIF jfif; - DQT[] dqt; - SOF0 sof0; - DHT[] dht; - SOS sos; - - DQT* addDQT() - { - if (dqt.length > 0) - reallocateArray(dqt, dqt.length+1); - else - dqt = New!(DQT[])(1); - return &dqt[$-1]; - } - - DHT* addDHT() - { - if (dht.length > 0) - reallocateArray(dht, dht.length+1); - else - dht = New!(DHT[])(1); - return &dht[$-1]; - } - - void free() - { - jfif.free(); - foreach(ref t; dqt) t.free(); - Delete(dqt); - sof0.free(); - foreach(ref t; dht) t.free(); - Delete(dht); - sos.free(); - } - - DQT* getQuantizationTable(ubyte id) - { - foreach(ref t; dqt) - if (t.tableId == id) - return &t; - return null; - } - - DHT* getHuffmanTable(ubyte clas, ubyte id) - { - foreach(ref t; dht) - if (t.clas == clas && - t.tableId == id) - return &t; - return null; - } -} - -/* - * Load JPEG from file using local FileSystem. - * Causes GC allocation - */ -//SuperImage loadJPEG(string filename) -//{ -// InputStream input = openForInput(filename); -// auto img = loadJPEG(input); -// input.close(); -// return img; -//} - -/* - * Load JPEG from stream using default image factory. - * Causes GC allocation - */ -SuperImage loadJPEG(InputStream istrm) -{ - Compound!(SuperImage, string) res = - loadJPEG(istrm, defaultImageFactory); - if (res[0] is null) - throw new Exception(res[1]); - else - return res[0]; -} - -/* - * Load JPEG from stream using specified image factory. - * GC-free - */ -Compound!(SuperImage, string) loadJPEG( - InputStream istrm, - SuperImageFactory imgFac) -{ - JPEGImage jpg; - SuperImage img = null; - - while (istrm.readable) - { - JPEGMarkerType mt; - auto res = readMarker(&jpg, istrm, &mt); - if (res[0]) - { - // TODO: add progressive JPEG support - if (mt == JPEGMarkerType.SOF2) - { - jpg.free(); - return compound(img, "loadJPEG error: progressive JPEG is not supported"); - } - else if (mt == JPEGMarkerType.SOS) - break; - } - else - { - jpg.free(); - return compound(img, res[1]); - } - } - auto res = decodeScanData(&jpg, istrm, imgFac); - jpg.free(); - return res; -} - -/* - * Decode marker from JPEG stream - */ -Compound!(bool, string) readMarker( - JPEGImage* jpg, - InputStream istrm, - JPEGMarkerType* mt) -{ - ushort magic = istrm.readNumeric!ushort(Endian.Big); - - switch (magic) - { - case 0xFFD8: - *mt = JPEGMarkerType.SOI; - version(JPEGDebug) writeln("SOI"); - break; - - case 0xFFE0: - *mt = JPEGMarkerType.APP0; - return readJFIF(jpg, istrm); - - case 0xFFE1: - *mt = JPEGMarkerType.APPn; - return readAPPn(jpg, istrm, 1); - - case 0xFFE2: - *mt = JPEGMarkerType.APPn; - return readAPPn(jpg, istrm, 2); - - case 0xFFE3: - *mt = JPEGMarkerType.APPn; - return readAPPn(jpg, istrm, 3); - - case 0xFFE4: - *mt = JPEGMarkerType.APPn; - return readAPPn(jpg, istrm, 4); - - case 0xFFE5: - *mt = JPEGMarkerType.APPn; - return readAPPn(jpg, istrm, 5); - - case 0xFFE6: - *mt = JPEGMarkerType.APPn; - return readAPPn(jpg, istrm, 6); - - case 0xFFE7: - *mt = JPEGMarkerType.APPn; - return readAPPn(jpg, istrm, 7); - - case 0xFFE8: - *mt = JPEGMarkerType.APPn; - return readAPPn(jpg, istrm, 8); - - case 0xFFE9: - *mt = JPEGMarkerType.APPn; - return readAPPn(jpg, istrm, 9); - - case 0xFFEA: - *mt = JPEGMarkerType.APPn; - return readAPPn(jpg, istrm, 10); - - case 0xFFEB: - *mt = JPEGMarkerType.APPn; - return readAPPn(jpg, istrm, 11); - - case 0xFFEC: - *mt = JPEGMarkerType.APPn; - return readAPPn(jpg, istrm, 12); - - case 0xFFED: - *mt = JPEGMarkerType.APPn; - return readAPPn(jpg, istrm, 13); - - case 0xFFEE: - *mt = JPEGMarkerType.APPn; - return readAPPn(jpg, istrm, 14); - - case 0xFFEF: - *mt = JPEGMarkerType.APPn; - return readAPPn(jpg, istrm, 15); - - case 0xFFDB: - *mt = JPEGMarkerType.DQT; - return readDQT(jpg, istrm); - - case 0xFFC0: - *mt = JPEGMarkerType.SOF0; - return readSOF0(jpg, istrm); - - case 0xFFC2: - *mt = JPEGMarkerType.SOF2; - break; - - case 0xFFC4: - *mt = JPEGMarkerType.DHT; - return readDHT(jpg, istrm); - - case 0xFFDA: - *mt = JPEGMarkerType.SOS; - return readSOS(jpg, istrm); - - case 0xFFFE: - *mt = JPEGMarkerType.COM; - return readCOM(jpg, istrm); - - default: - *mt = JPEGMarkerType.Unknown; - break; - } - - return compound(true, ""); -} - -Compound!(bool, string) readJFIF(JPEGImage* jpg, InputStream istrm) -{ - ushort jfif_length = istrm.readNumeric!ushort(Endian.Big); - - char[5] jfif_id = istrm.readChars!5; - if (jfif_id != "JFIF\0") - return compound(false, "loadJPEG error: illegal JFIF header"); - - jpg.jfif.versionMajor = istrm.readNumeric!ubyte; - jpg.jfif.versionMinor = istrm.readNumeric!ubyte; - jpg.jfif.units = istrm.readNumeric!ubyte; - jpg.jfif.xDensity = istrm.readNumeric!ushort(Endian.Big); - jpg.jfif.yDensity = istrm.readNumeric!ushort(Endian.Big); - jpg.jfif.thumbnailWidth = istrm.readNumeric!ubyte; - jpg.jfif.thumbnailHeight = istrm.readNumeric!ubyte; - - uint jfif_thumb_length = jpg.jfif.thumbnailWidth * jpg.jfif.thumbnailHeight * 3; - if (jfif_thumb_length > 0) - { - jpg.jfif.thumbnail = New!(ubyte[])(jfif_thumb_length); - istrm.readBytes(jpg.jfif.thumbnail.ptr, jfif_thumb_length); - } - - version(JPEGDebug) - { - writefln("APP0/JFIF length: %s", jfif_length); - writefln("APP0/JFIF identifier: %s", jfif_id); - writefln("APP0/JFIF version major: %s", jpg.jfif.versionMajor); - writefln("APP0/JFIF version minor: %s", jpg.jfif.versionMinor); - writefln("APP0/JFIF units: %s", jpg.jfif.units); - writefln("APP0/JFIF xdensity: %s", jpg.jfif.xDensity); - writefln("APP0/JFIF ydensity: %s", jpg.jfif.yDensity); - writefln("APP0/JFIF xthumbnail: %s", jpg.jfif.thumbnailWidth); - writefln("APP0/JFIF ythumbnail: %s", jpg.jfif.thumbnailHeight); - } - - return compound(true, ""); -} - -/* - * APP1 - EXIF, XMP, ExtendedXMP, QVCI, FLIR - * APP2 - ICC, FPXR, MPF, PreviewImage - * APP3 - Kodak Meta, Stim, PreviewImage - * APP4 - Scalado, FPXR, PreviewImage - * APP5 - RMETA, PreviewImage - * APP6 - EPPIM, NITF, HP TDHD - * APP7 - Pentax, Qualcomm - * APP8 - SPIFF - * APP9 - MediaJukebox - * APP10 - PhotoStudio comment - * APP11 - JPEG-HDR - * APP12 - PictureInfo, Ducky - * APP13 - Photoshop, Adobe CM - * APP14 - Adobe - * APP15 - GraphicConverter - */ -Compound!(bool, string) readAPPn(JPEGImage* jpg, InputStream istrm, uint n) -{ - ushort app_length = istrm.readNumeric!ushort(Endian.Big); - ubyte[] app = New!(ubyte[])(app_length-2); - istrm.readBytes(app.ptr, app_length-2); - - // TODO: interpret APP data (EXIF etc.) and save it somewhere. - // Maybe add a generic ImageInfo object for this? - Delete(app); - - version(JPEGDebug) - { - writefln("APP%s length: %s", n, app_length); - } - - return compound(true, ""); -} - -Compound!(bool, string) readCOM(JPEGImage* jpg, InputStream istrm) -{ - ushort com_length = istrm.readNumeric!ushort(Endian.Big); - ubyte[] com = New!(ubyte[])(com_length-2); - istrm.readBytes(com.ptr, com_length-2); - - version(JPEGDebug) - { - writefln("COM string: \"%s\"", cast(string)com); - writefln("COM length: %s", com_length); - } - - // TODO: save COM data somewhere. - // Maybe add a generic ImageInfo object for this? - Delete(com); - - return compound(true, ""); -} - -Compound!(bool, string) readDQT(JPEGImage* jpg, InputStream istrm) -{ - ushort dqt_length = istrm.readNumeric!ushort(Endian.Big); - version(JPEGDebug) - { - writefln("DQT length: %s", dqt_length); - } - - dqt_length -= 2; - - while(dqt_length) - { - JPEGImage.DQT* dqt = jpg.addDQT(); - - ubyte bite = istrm.readNumeric!ubyte; - dqt.precision = bite.hiNibble; - dqt.tableId = bite.loNibble; - - dqt_length--; - - if (dqt.precision == 0) - { - dqt.table = New!(ubyte[])(64); - dqt_length -= 64; - } - else if (dqt.precision == 1) - { - dqt.table = New!(ubyte[])(128); - dqt_length -= 128; - } - - istrm.readBytes(dqt.table.ptr, dqt.table.length); - - version(JPEGDebug) - { - writefln("DQT precision: %s", dqt.precision); - writefln("DQT table id: %s", dqt.tableId); - writefln("DQT table: %s", dqt.table); - } - } - - return compound(true, ""); -} - -Compound!(bool, string) readSOF0(JPEGImage* jpg, InputStream istrm) -{ - ushort sof0_length = istrm.readNumeric!ushort(Endian.Big); - jpg.sof0.precision = istrm.readNumeric!ubyte; - jpg.sof0.height = istrm.readNumeric!ushort(Endian.Big); - jpg.sof0.width = istrm.readNumeric!ushort(Endian.Big); - jpg.sof0.componentsNum = istrm.readNumeric!ubyte; - - version(JPEGDebug) - { - writefln("SOF0 length: %s", sof0_length); - writefln("SOF0 precision: %s", jpg.sof0.precision); - writefln("SOF0 height: %s", jpg.sof0.height); - writefln("SOF0 width: %s", jpg.sof0.width); - writefln("SOF0 components: %s", jpg.sof0.componentsNum); - } - - jpg.sof0.components = New!(JPEGImage.SOF0Component[])(jpg.sof0.componentsNum); - - foreach(ref c; jpg.sof0.components) - { - ubyte c_id = istrm.readNumeric!ubyte; - ubyte bite = istrm.readNumeric!ubyte; - c.hSubsampling = bite.hiNibble; - c.vSubsampling = bite.loNibble; - c.dqtTableId = istrm.readNumeric!ubyte; - version(JPEGDebug) - { - writefln("SOF0 component id: %s", c_id); - writefln("SOF0 component %s hsubsampling: %s", c_id, c.hSubsampling); - writefln("SOF0 component %s vsubsampling: %s", c_id, c.vSubsampling); - writefln("SOF0 component %s table id: %s", c_id, c.dqtTableId); - } - } - - return compound(true, ""); -} - -Compound!(bool, string) readDHT(JPEGImage* jpg, InputStream istrm) -{ - ushort dht_length = istrm.readNumeric!ushort(Endian.Big); - version(JPEGDebug) - { - writefln("DHT length: %s", dht_length); - } - - dht_length -= 2; - - while(dht_length > 0) - { - JPEGImage.DHT* dht = jpg.addDHT(); - - ubyte bite = istrm.readNumeric!ubyte; - dht_length--; - dht.clas = bite.hiNibble; - dht.tableId = bite.loNibble; - - ubyte[16] dht_code_lengths; - istrm.readBytes(dht_code_lengths.ptr, 16); - dht_length -= 16; - - version(JPEGDebug) - { - writefln("DHT class: %s (%s)", - dht.clas, - dht.clas? "AC":"DC"); - writefln("DHT tableId: %s", dht.tableId); - writefln("DHT Huffman code lengths: %s", dht_code_lengths); - } - - // Read Huffman table - int totalCodes = reduce!("a + b")(0, dht_code_lengths); - int storedCodes = 0; - ubyte treeLevel = 0; - ushort bits = 0; - - while (storedCodes != totalCodes) - { - while (treeLevel < 15 && - dht_code_lengths[treeLevel] == 0) - { - treeLevel++; - bits *= 2; - } - - if (treeLevel < 16) - { - uint bitsNum = treeLevel + 1; - HuffmanCode code = HuffmanCode(bits, cast(ushort)bitsNum); - - auto entry = HuffmanTableEntry(code, istrm.readNumeric!ubyte); - dht.huffmanTable.append(entry); - - dht_length--; - - storedCodes++; - bits++; - dht_code_lengths[treeLevel]--; - } - } - - dht.huffmanTree = treeFromTable(dht.huffmanTable); - } - - return compound(true, ""); -} - -Compound!(bool, string) readSOS(JPEGImage* jpg, InputStream istrm) -{ - ushort sos_length = istrm.readNumeric!ushort(Endian.Big); - jpg.sos.componentsNum = istrm.readNumeric!ubyte; - - version(JPEGDebug) - { - writefln("SOS length: %s", sos_length); - writefln("SOS components: %s", jpg.sos.componentsNum); - } - - jpg.sos.components = New!(JPEGImage.SOSComponent[])(jpg.sos.componentsNum); - - foreach(ref c; jpg.sos.components) - { - ubyte c_id = istrm.readNumeric!ubyte; - ubyte bite = istrm.readNumeric!ubyte; - c.tableIdDC = bite.hiNibble; - c.tableIdAC = bite.loNibble; - version(JPEGDebug) - { - writefln("SOS component id: %s", c_id); - writefln("SOS component %s DC table id: %s", c_id, c.tableIdDC); - writefln("SOS component %s AC table id: %s", c_id, c.tableIdAC); - } - } - - jpg.sos.spectralSelectionStart = istrm.readNumeric!ubyte; - jpg.sos.spectralSelectionEnd = istrm.readNumeric!ubyte; - ubyte bite = istrm.readNumeric!ubyte; - jpg.sos.successiveApproximationBitHigh = bite.hiNibble; - jpg.sos.successiveApproximationBitLow = bite.loNibble; - - version(JPEGDebug) - { - writefln("SOS spectral selection start: %s", jpg.sos.spectralSelectionStart); - writefln("SOS spectral selection end: %s", jpg.sos.spectralSelectionEnd); - writefln("SOS successive approximation bit: %s", jpg.sos.successiveApproximationBitHigh); - writefln("SOS successive approximation bit low: %s", jpg.sos.successiveApproximationBitLow); - } - - return compound(true, ""); -} - -struct ScanBitStream -{ - InputStream istrm; - - bool endMarkerFound = false; - uint bytesRead = 0; - ubyte prevByte = 0x00; - ubyte curByte = 0x00; - - ubyte readNextByte() - { - ubyte b = istrm.readNumeric!ubyte; - bytesRead++; - endMarkerFound = (prevByte == 0xFF && b == 0xD9); - assert(!endMarkerFound); - if (!endMarkerFound) - { - prevByte = b; - curByte = b; - return b; - } - else - { - curByte = 0; - } - return curByte; - } - - bool readable() - { - return !istrm.readable || endMarkerFound; - } - - uint bitPos = 0; - - // Huffman decode a byte - Compound!(bool, string) decodeByte(HuffmanTreeNode* node, ubyte* result) - { - while(!node.isLeaf) - { - ubyte b = curByte; - - bool bit = getBit(b, 7-bitPos); - bitPos++; - if (bitPos == 8) - { - bitPos = 0; - readNextByte(); - - if (b == 0xFF) - { - b = curByte; - if (b == 0x00) - { - readNextByte(); - } - } - } - - if (bit) - node = node.right; - else - node = node.left; - - if (node is null) - return compound(false, "loadJPEG error: no Huffman code found"); - } - - *result = node.ch; - return compound(true, ""); - } - - // Read len bits from stream to buffer - uint readBits(ubyte len) - { - uint buffer = 0; - uint i = 0; - uint by = 0; - uint bi = 0; - - while (i < len) - { - ubyte b = curByte; - - bool bit = getBit(b, 7-bitPos); - buffer = setBit(buffer, (by * 8 + bi), bit); - - bi++; - if (bi == 8) - { - bi = 0; - by++; - } - - i++; - - bitPos++; - if (bitPos == 8) - { - bitPos = 0; - readNextByte(); - - if (b == 0xFF) - { - b = curByte; - if (b == 0x00) - readNextByte(); - } - } - } - - return buffer; - } -} - -/* - * Decodes compressed data and creates RGB image from it - */ -Compound!(SuperImage, string) decodeScanData( - JPEGImage* jpg, - InputStream istrm, - SuperImageFactory imgFac) -{ - SuperImage img = imgFac.createImage(jpg.sof0.width, jpg.sof0.height, 3, 8); - - MCU mcu; - foreach(ci, ref c; jpg.sof0.components) - { - if (ci == 0) - mcu.createYBlocks(c.hSubsampling, c.vSubsampling); - else if (ci == 1) - mcu.createCbBlocks(c.hSubsampling, c.vSubsampling); - else if (ci == 2) - mcu.createCrBlocks(c.hSubsampling, c.vSubsampling); - } - - Compound!(SuperImage, string) error(string errorMsg) - { - mcu.free(); - if (img) - { - img.free(); - img = null; - } - return compound(img, errorMsg); - } - - // Decode DCT coefficient from bit buffer - int decodeCoef(uint buffer, ubyte numBits) - { - bool positive = getBit(buffer, 0); - - int value = 0; - foreach(j; 0..numBits) - { - bool bit = getBit(buffer, numBits-1-j); - value = setBit(value, j, bit); - } - - if (positive) - return value; - else - return value - 2^^numBits + 1; - } - - static const ubyte[64] dezigzag = - [ - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, - 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, - 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, - 53, 60, 61, 54, 47, 55, 62, 63 - ]; - - if (jpg.sos.componentsNum != 3) - { - return error(format( - "loadJPEG error: unsupported number of components: %s", - jpg.sos.componentsNum)); - } - - // Store previous DC coefficients - int[3] dcCoefPrev; - - if (jpg.dqt.length == 0) - return error("loadJPEG error: no DQTs found"); - - ScanBitStream sbs; - sbs.endMarkerFound = false; - sbs.bytesRead = 0; - sbs.prevByte = 0x00; - sbs.curByte = 0x00; - sbs.istrm = istrm; - sbs.readNextByte(); - - uint numMCUsH = jpg.sof0.width / mcu.width + ((jpg.sof0.width % mcu.width) > 0); - uint numMCUsV = jpg.sof0.height / mcu.height + ((jpg.sof0.height % mcu.height) > 0); - - // Read MCUs - foreach(mcuY; 0..numMCUsV) - foreach(mcuX; 0..numMCUsH) - { - // Read MCU for each channel - foreach(ci, ref c; jpg.sos.components) - { - auto tableDC = jpg.getHuffmanTable(0, c.tableIdDC); - auto tableAC = jpg.getHuffmanTable(1, c.tableIdAC); - - if (tableDC is null) - return error("loadJPEG error: illegal DC table index in MCU component"); - if (tableAC is null) - return error("loadJPEG error: illegal AC table index in MCU component"); - - auto component = jpg.sof0.components[ci]; - auto hblocks = component.hSubsampling; - auto vblocks = component.vSubsampling; - auto dqtTableId = component.dqtTableId; - if (dqtTableId >= jpg.dqt.length) - return error("loadJPEG error: illegal DQT table index in MCU component"); - - // Read 8x8 blocks - foreach(by; 0..vblocks) - foreach(bx; 0..hblocks) - { - int[8*8] block; - - // Read DC coefficient - ubyte dcDiffLen; - auto res = sbs.decodeByte(tableDC.huffmanTree, &dcDiffLen); - if (!res[0]) return error(res[1]); - - if (dcDiffLen > 0) - { - uint dcBuffer = sbs.readBits(dcDiffLen); - dcCoefPrev[ci] += decodeCoef(dcBuffer, dcDiffLen); - } - - block[0] = dcCoefPrev[ci]; - - // Read AC coefficients - { - uint i = 1; - bool eob = false; - while (!eob && i < 64) - { - ubyte code; - res = sbs.decodeByte(tableAC.huffmanTree, &code); - if (!res[0]) return error(res[1]); - - if (code == 0x00) // EOB, all next values are zero - eob = true; - else if (code == 0xF0) // ZRL, next 16 values are zero - { - foreach(j; 0..16) - if (i < 64) - { - block[i] = 0; - i++; - } - } - else - { - ubyte hi = hiNibble(code); - ubyte lo = loNibble(code); - - uint zeroes = hi; - foreach(j; 0..zeroes) - if (i < 64) - { - block[i] = 0; - i++; - } - - int acCoef = 0; - if (lo > 0) - { - uint acBuffer = sbs.readBits(lo); - acCoef = decodeCoef(acBuffer, lo); - } - - if (i < 64) - block[i] = acCoef; - - i++; - } - } - } - - // Multiply block by quantization matrix - foreach(i, ref v; block) - v *= jpg.dqt[dqtTableId].table[i]; - - // Convert matrix from zig-zag order to normal order - int[8*8] dctMatrix; - - foreach(i, v; block) - dctMatrix[dezigzag[i]] = v; - - idct64(dctMatrix.ptr); - - // Copy the matrix into corresponding channel - int* outMatrixPtr; - if (ci == 0) - outMatrixPtr = mcu.yBlocks[by * hblocks + bx].ptr; - else if (ci == 1) - outMatrixPtr = mcu.cbBlocks[by * hblocks + bx].ptr; - else if (ci == 2) - outMatrixPtr = mcu.crBlocks[by * hblocks + bx].ptr; - else - return error("loadJPEG error: illegal component index"); - - for(uint i = 0; i < 64; i++) - outMatrixPtr[i] = dctMatrix[i]; - } - } - - // Convert MCU from YCbCr to RGB - foreach(y; 0..mcu.height) // Pixel coordinates in MCU - foreach(x; 0..mcu.width) - { - //Color4f col = mcu.getPixel(x, y); - uint col = mcu.getPixel(x, y); - - // Pixel coordinates in image - uint ix = mcuX * mcu.width + x; - uint iy = mcuY * mcu.height + y; - - if (ix < img.width && iy < img.height) - img[ix, iy] = col; - } - } - - version(JPEGDebug) - { - writefln("Bytes read: %s", sbs.bytesRead); - } - - mcu.free(); - - return compound(img, ""); -} - -/* - * MCU struct keeps a storage for one Minimal Code Unit - * and provides a generalized interface for decoding - * images with different subsampling modes. - * Decoder should read 8x8 blocks one by one for each channel - * and fill corresponding arrays in MCU. - */ -struct MCU -{ - uint width; - uint height; - - alias int[8*8] Block; - Block[] yBlocks; - Block[] cbBlocks; - Block[] crBlocks; - - uint ySamplesH, ySamplesV; - uint cbSamplesH, cbSamplesV; - uint crSamplesH, crSamplesV; - - uint yWidth, yHeight; - uint cbWidth, cbHeight; - uint crWidth, crHeight; - - void createYBlocks(uint hsubsampling, uint vsubsampling) - { - yBlocks = New!(Block[])(hsubsampling * vsubsampling); - - width = hsubsampling * 8; - height = vsubsampling * 8; - - ySamplesH = hsubsampling; - ySamplesV = vsubsampling; - - yWidth = width / ySamplesH; - yHeight = height / ySamplesV; - } - - void createCbBlocks(uint hsubsampling, uint vsubsampling) - { - cbBlocks = New!(Block[])(hsubsampling * vsubsampling); - - cbSamplesH = hsubsampling; - cbSamplesV = vsubsampling; - - cbWidth = width / cbSamplesH; - cbHeight = height / cbSamplesV; - } - - void createCrBlocks(uint hsubsampling, uint vsubsampling) - { - crBlocks = New!(Block[])(hsubsampling * vsubsampling); - - crSamplesH = hsubsampling; - crSamplesV = vsubsampling; - - crWidth = width / crSamplesH; - crHeight = height / crSamplesV; - } - - void free() - { - if (yBlocks.length) Delete(yBlocks); - if (cbBlocks.length) Delete(cbBlocks); - if (crBlocks.length) Delete(crBlocks); - } - - uint getPixel(uint x, uint y) // coordinates relative to upper-left MCU corner - { - // Y block coordinates - uint ybx = x / yWidth; - uint yby = y / yHeight; - uint ybi = yby * ySamplesH + ybx; - - // Pixel coordinates in Y block - uint ybpx = x - ybx * yWidth; - uint ybpy = y - yby * yHeight; - - // Cb block coordinates - uint cbx = x / cbWidth; - uint cby = y / cbHeight; - uint cbi = cby * cbSamplesH + cbx; - - // Pixel coordinates in Cb block - uint cbpx = (x - cbx * cbWidth) / ySamplesH; - uint cbpy = (y - cby * cbHeight) / ySamplesV; - - // Cr block coordinates - uint crx = x / crWidth; - uint cry = y / crHeight; - uint cri = cry * crSamplesH + crx; - - // Pixel coordinates in Cr block - uint crpx = (x - crx * crWidth) / ySamplesH; - uint crpy = (y - cry * crHeight) / ySamplesV; - - // Get color components - float Y = cast(float)yBlocks [ybi][ybpy * 8 + ybpx] + 128.0f; - float Cb = cast(float)cbBlocks[cbi][cbpy * 8 + cbpx]; - float Cr = cast(float)crBlocks[cri][crpy * 8 + crpx]; - - // Convert from YCbCr to RGB - //Color4f col; - uint col_r = clamp(Y + 1.402f * Cr); - uint col_g = clamp(Y - 0.34414f * Cb - 0.71414f * Cr); - uint col_b = clamp(Y + 1.772f * Cb); - //col = col / 255.0f; - //col.a = 1.0f; - - return 0xFF000000 | (col_r << 16) | (col_g << 8) | (col_b) ; - } -} - -uint clamp(float v) { - import std.conv; - if (v < 0) - return 0; - uint res = to!uint(v); - if (v > 255) - return 255; - return res; -} diff --git a/3rdparty/dimage/memory.d b/3rdparty/dimage/memory.d deleted file mode 100644 index 334b6131..00000000 --- a/3rdparty/dimage/memory.d +++ /dev/null @@ -1,208 +0,0 @@ -/* -Copyright (c) 2015 Timur Gafarov - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - -// dimage is actually stripped out part of dlib - just to support reading PNG and JPEG -module dimage.memory;//dlib.core.memory - -import std.stdio; -import std.conv; -import std.traits; -import core.stdc.stdlib; -import core.exception: onOutOfMemoryError; - -/* - * Tools for manual memory management - */ - -//version = MemoryDebug; - -private static size_t _allocatedMemory = 0; - -version(MemoryDebug) -{ - import std.datetime; - import std.algorithm; - - struct AllocationRecord - { - string type; - size_t size; - ulong id; - bool deleted; - } - - AllocationRecord[ulong] records; - ulong counter = 0; - - void addRecord(void* p, string type, size_t size) - { - records[cast(ulong)p] = AllocationRecord(type, size, counter, false); - counter++; - //writefln("Allocated %s (%s bytes)", type, size); - } - - void markDeleted(void* p) - { - ulong k = cast(ulong)p - psize; - //string type = records[k].type; - //size_t size = records[k].size; - records[k].deleted = true; - //writefln("Dellocated %s (%s bytes)", type, size); - } - - void printMemoryLog() - { - writeln("----------------------------------------------------"); - writeln(" Memory allocation log "); - writeln("----------------------------------------------------"); - auto keys = records.keys; - sort!((a, b) => records[a].id < records[b].id)(keys); - foreach(k; keys) - { - AllocationRecord r = records[k]; - if (r.deleted) - writefln(" %s - %s byte(s) at %X", r.type, r.size, k); - else - writefln("REMAINS: %s - %s byte(s) at %X", r.type, r.size, k); - } - writeln("----------------------------------------------------"); - writefln("Total amount of allocated memory: %s", _allocatedMemory); - writeln("----------------------------------------------------"); - } -} -else -{ - void printMemoryLog() {} -} - -size_t allocatedMemory() -{ - return _allocatedMemory; -} - -interface Freeable -{ - void free(); -} - -enum psize = 8; - -T allocate(T, A...) (A args) if (is(T == class)) -{ - enum size = __traits(classInstanceSize, T); - void* p = malloc(size+psize); - if (!p) - onOutOfMemoryError(); - auto memory = p[psize..psize+size]; - *cast(size_t*)p = size; - _allocatedMemory += size; - version(MemoryDebug) - { - addRecord(p, T.stringof, size); - } - auto res = emplace!(T, A)(memory, args); - return res; -} - -T* allocate(T, A...) (A args) if (is(T == struct)) -{ - enum size = T.sizeof; - void* p = malloc(size+psize); - if (!p) - onOutOfMemoryError(); - auto memory = p[psize..psize+size]; - *cast(size_t*)p = size; - _allocatedMemory += size; - version(MemoryDebug) - { - addRecord(p, T.stringof, size); - } - return emplace!(T, A)(memory, args); -} - -T allocate(T) (size_t length) if (isArray!T) -{ - alias AT = ForeachType!T; - size_t size = length * AT.sizeof; - auto mem = malloc(size+psize); - if (!mem) - onOutOfMemoryError(); - T arr = cast(T)mem[psize..psize+size]; - foreach(ref v; arr) - v = v.init; - *cast(size_t*)mem = size; - _allocatedMemory += size; - version(MemoryDebug) - { - addRecord(mem, T.stringof, size); - } - return arr; -} - -void deallocate(T)(ref T obj) if (isArray!T) -{ - void* p = cast(void*)obj.ptr; - size_t size = *cast(size_t*)(p - psize); - free(p - psize); - _allocatedMemory -= size; - version(MemoryDebug) - { - markDeleted(p); - } - obj.length = 0; -} - -void deallocate(T)(T obj) if (is(T == class) || is(T == interface)) -{ - Object o = cast(Object)obj; - void* p = cast(void*)o; - size_t size = *cast(size_t*)(p - psize); - destroy(obj); - free(p - psize); - _allocatedMemory -= size; - version(MemoryDebug) - { - markDeleted(p); - } -} - -void deallocate(T)(T* obj) -{ - void* p = cast(void*)obj; - size_t size = *cast(size_t*)(p - psize); - destroy(obj); - free(p - psize); - _allocatedMemory -= size; - version(MemoryDebug) - { - markDeleted(p); - } -} - -alias allocate New; -alias deallocate Delete; diff --git a/3rdparty/dimage/png.d b/3rdparty/dimage/png.d deleted file mode 100644 index c383257a..00000000 --- a/3rdparty/dimage/png.d +++ /dev/null @@ -1,851 +0,0 @@ -/* -Copyright (c) 2011-2015 Timur Gafarov, Martin Cejp - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - -// dimage is actually stripped out part of dlib - just to support reading PNG and JPEG -module dimage.png; //dlib.image.io.png - -private -{ - import std.stdio; - import std.math; - import std.string; - import std.range; - - import dimage.memory; - import dimage.stream; - import dimage.compound; - //import dlib.filesystem.local; - //import dlib.math.utils; - import dimage.zlib; - import dimage.image; - //import dlib.image.io.io; - - //import dlib.core.memory; - //import dlib.core.stream; - //import dlib.core.compound; - //import dlib.filesystem.local; - //import dlib.math.utils; - //import dlib.coding.zlib; - //import dlib.image.image; - //import dlib.image.io.io; -} - -// uncomment this to see debug messages: -//version = PNGDebug; - -static const ubyte[8] PNGSignature = [137, 80, 78, 71, 13, 10, 26, 10]; -static const ubyte[4] IHDR = ['I', 'H', 'D', 'R']; -static const ubyte[4] IEND = ['I', 'E', 'N', 'D']; -static const ubyte[4] IDAT = ['I', 'D', 'A', 'T']; -static const ubyte[4] PLTE = ['P', 'L', 'T', 'E']; -static const ubyte[4] tRNS = ['t', 'R', 'N', 'S']; -static const ubyte[4] bKGD = ['b', 'K', 'G', 'D']; -static const ubyte[4] tEXt = ['t', 'E', 'X', 't']; -static const ubyte[4] iTXt = ['i', 'T', 'X', 't']; -static const ubyte[4] zTXt = ['z', 'T', 'X', 't']; - -enum ColorType: ubyte -{ - Greyscale = 0, // allowed bit depths: 1, 2, 4, 8 and 16 - RGB = 2, // allowed bit depths: 8 and 16 - Palette = 3, // allowed bit depths: 1, 2, 4 and 8 - GreyscaleAlpha = 4, // allowed bit depths: 8 and 16 - RGBA = 6, // allowed bit depths: 8 and 16 - Any = 7 // one of the above -} - -enum FilterMethod: ubyte -{ - None = 0, - Sub = 1, - Up = 2, - Average = 3, - Paeth = 4 -} - -struct PNGChunk -{ - uint length; - ubyte[4] type; - ubyte[] data; - uint crc; - - void free() - { - if (data.ptr) - Delete(data); - } -} - -struct PNGHeader -{ - union - { - struct - { - uint width; - uint height; - ubyte bitDepth; - ubyte colorType; - ubyte compressionMethod; - ubyte filterMethod; - ubyte interlaceMethod; - }; - ubyte[13] bytes; - } -} -class PNGLoadException: ImageLoadException -{ - this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null) - { - super(msg, file, line, next); - } -} - -/* - * Load PNG from file using local FileSystem. - * Causes GC allocation - */ -//SuperImage loadPNG(string filename) -//{ -// InputStream input = openForInput(filename); -// auto img = loadPNG(input); -// input.close(); -// return img; -//} - -/* - * Save PNG to file using local FileSystem. - * Causes GC allocation - */ -//void savePNG(SuperImage img, string filename) -//{ -// OutputStream output = openForOutput(filename); -// Compound!(bool, string) res = -// savePNG(img, output); -// output.close(); -// -// if (!res[0]) -// throw new PNGLoadException(res[1]); -//} - -/* - * Load PNG from stream using default image factory. - * Causes GC allocation - */ -SuperImage loadPNG(InputStream istrm) -{ - Compound!(SuperImage, string) res = - loadPNG(istrm, defaultImageFactory); - if (res[0] is null) - throw new PNGLoadException(res[1]); - else - return res[0]; -} - -/* - * Load PNG from stream using specified image factory. - * GC-free - */ -Compound!(SuperImage, string) loadPNG( - InputStream istrm, - SuperImageFactory imgFac) -{ - SuperImage img = null; - - Compound!(SuperImage, string) error(string errorMsg) - { - if (img) - { - img.free(); - img = null; - } - return compound(img, errorMsg); - } - - bool readChunk(PNGChunk* chunk) - { - if (!istrm.readBE!uint(&chunk.length) - || !istrm.fillArray(chunk.type)) - { - return false; - } - - version(PNGDebug) writefln("Chunk length = %s", chunk.length); - version(PNGDebug) writefln("Chunk type = %s", cast(char[])chunk.type); - - if (chunk.length > 0) - { - chunk.data = New!(ubyte[])(chunk.length); - - if (!istrm.fillArray(chunk.data)) - { - return false; - } - } - - version(PNGDebug) writefln("Chunk data.length = %s", chunk.data.length); - - if (!istrm.readBE!uint(&chunk.crc)) - { - return false; - } - - // TODO: reimplement CRC check with ranges instead of concatenation - uint calculatedCRC = crc32(chain(chunk.type[0..$], chunk.data)); - - version(PNGDebug) - { - writefln("Chunk CRC = %X", chunk.crc); - writefln("Calculated CRC = %X", calculatedCRC); - writeln("-------------------"); - } - - if (chunk.crc != calculatedCRC) - { - return false; - } - - return true; - } - - bool readHeader(PNGHeader* hdr, PNGChunk* chunk) - { - hdr.bytes[] = chunk.data[]; - hdr.width = bigEndian(hdr.width); - hdr.height = bigEndian(hdr.height); - - version(PNGDebug) - { - writefln("width = %s", hdr.width); - writefln("height = %s", hdr.height); - writefln("bitDepth = %s", hdr.bitDepth); - writefln("colorType = %s", hdr.colorType); - writefln("compressionMethod = %s", hdr.compressionMethod); - writefln("filterMethod = %s", hdr.filterMethod); - writefln("interlaceMethod = %s", hdr.interlaceMethod); - writeln("----------------"); - } - - return true; - } - - ubyte[8] signatureBuffer; - - if (!istrm.fillArray(signatureBuffer)) - { - return error("loadPNG error: signature check failed"); - } - - version(PNGDebug) - { - writeln("----------------"); - writeln("PNG Signature: ", signatureBuffer); - writeln("----------------"); - } - - PNGHeader hdr; - - ZlibDecoder zlibDecoder; - - ubyte[] palette; - ubyte[] transparency; - uint paletteSize = 0; - - bool endChunk = false; - while (!endChunk && istrm.readable) - { - PNGChunk chunk; - bool res = readChunk(&chunk); - if (!res) - { - chunk.free(); - return error("loadPNG error: failed to read chunk"); - } - else - { - if (chunk.type == IEND) - { - endChunk = true; - chunk.free(); - } - else if (chunk.type == IHDR) - { - if (chunk.data.length < hdr.bytes.length) - return error("loadPNG error: illegal header chunk"); - - readHeader(&hdr, &chunk); - chunk.free(); - - bool supportedIndexed = - (hdr.colorType == ColorType.Palette) && - (hdr.bitDepth == 1 || - hdr.bitDepth == 2 || - hdr.bitDepth == 4 || - hdr.bitDepth == 8); - - if (hdr.bitDepth != 8 && hdr.bitDepth != 16 && !supportedIndexed) - return error("loadPNG error: unsupported bit depth"); - - if (hdr.compressionMethod != 0) - return error("loadPNG error: unsupported compression method"); - - if (hdr.filterMethod != 0) - return error("loadPNG error: unsupported filter method"); - - if (hdr.interlaceMethod != 0) - return error("loadPNG error: interlacing is not supported"); - - uint bufferLength = ((hdr.width * hdr.bitDepth + 7) / 8) * hdr.height + hdr.height; - ubyte[] buffer = New!(ubyte[])(bufferLength); - - zlibDecoder = ZlibDecoder(buffer); - - version(PNGDebug) - { - writefln("buffer.length = %s", bufferLength); - writeln("----------------"); - } - } - else if (chunk.type == IDAT) - { - zlibDecoder.decode(chunk.data); - chunk.free(); - } - else if (chunk.type == PLTE) - { - palette = chunk.data; - } - else if (chunk.type == tRNS) - { - transparency = chunk.data; - version(PNGDebug) - { - writeln("----------------"); - writefln("transparency.length = %s", transparency.length); - writeln("----------------"); - } - } - else - { - chunk.free(); - } - } - } - - // finalize decoder - version(PNGDebug) writefln("zlibDecoder.hasEnded = %s", zlibDecoder.hasEnded); - if (!zlibDecoder.hasEnded) - return error("loadPNG error: unexpected end of zlib stream"); - - ubyte[] buffer = zlibDecoder.buffer; - version(PNGDebug) writefln("buffer.length = %s", buffer.length); - - bool transparencyPalette; - - // create image - if (hdr.colorType == ColorType.Greyscale) - { - if (hdr.bitDepth == 8) - img = imgFac.createImage(hdr.width, hdr.height, 1, 8); - else if (hdr.bitDepth == 16) - img = imgFac.createImage(hdr.width, hdr.height, 1, 16); - } - else if (hdr.colorType == ColorType.GreyscaleAlpha) - { - if (hdr.bitDepth == 8) - img = imgFac.createImage(hdr.width, hdr.height, 2, 8); - else if (hdr.bitDepth == 16) - img = imgFac.createImage(hdr.width, hdr.height, 2, 16); - } - else if (hdr.colorType == ColorType.RGB) - { - if (hdr.bitDepth == 8) - img = imgFac.createImage(hdr.width, hdr.height, 3, 8); - else if (hdr.bitDepth == 16) - img = imgFac.createImage(hdr.width, hdr.height, 3, 16); - } - else if (hdr.colorType == ColorType.RGBA) - { - if (hdr.bitDepth == 8) - img = imgFac.createImage(hdr.width, hdr.height, 4, 8); - else if (hdr.bitDepth == 16) - img = imgFac.createImage(hdr.width, hdr.height, 4, 16); - } - else if (hdr.colorType == ColorType.Palette) - { - if (transparency.length > 0) { - img = imgFac.createImage(hdr.width, hdr.height, 4, 8); - transparencyPalette = true; - } else - img = imgFac.createImage(hdr.width, hdr.height, 3, 8); - } - else - return error("loadPNG error: unsupported color type"); - - version(PNGDebug) - { - writefln("img.width = %s", img.width); - writefln("img.height = %s", img.height); - writefln("img.bitDepth = %s", img.bitDepth); - writefln("img.channels = %s", img.channels); - writeln("----------------"); - } - - bool indexed = (hdr.colorType == ColorType.Palette); - - // don't close the stream, just release our reference - istrm = null; - - // apply filtering to the image data - ubyte[] buffer2; - string errorMsg; - if (!filter(&hdr, img.channels, indexed, buffer, buffer2, errorMsg)) - { - return error(errorMsg); - } - Delete(buffer); - buffer = buffer2; - - // if a palette is used, substitute target colors - if (indexed) - { - if (palette.length == 0) - return error("loadPNG error: palette chunk not found"); - - ubyte[] pdata = New!(ubyte[])(img.width * img.height * img.channels); - if (hdr.bitDepth == 8) - { - for (int i = 0; i < buffer.length; ++i) - { - ubyte b = buffer[i]; - pdata[i * img.channels + 0] = palette[b * 3 + 0]; - pdata[i * img.channels + 1] = palette[b * 3 + 1]; - pdata[i * img.channels + 2] = palette[b * 3 + 2]; - if (transparency.length > 0) - pdata[i * img.channels + 3] = - b < transparency.length ? transparency[b] : 0; - } - } - else // bit depths 1, 2, 4 - { - int srcindex = 0; - int srcshift = 8 - hdr.bitDepth; - ubyte mask = cast(ubyte)((1 << hdr.bitDepth) - 1); - int sz = img.width * img.height; - for (int dstindex = 0; dstindex < sz; dstindex++) - { - auto b = ((buffer[srcindex] >> srcshift) & mask); - //assert(b * 3 + 2 < palette.length); - pdata[dstindex * img.channels + 0] = palette[b * 3 + 0]; - pdata[dstindex * img.channels + 1] = palette[b * 3 + 1]; - pdata[dstindex * img.channels + 2] = palette[b * 3 + 2]; - - if (transparency.length > 0) - pdata[dstindex * img.channels + 3] = - b < transparency.length ? transparency[b] : 0; - - if (srcshift <= 0) - { - srcshift = 8 - hdr.bitDepth; - srcindex++; - } - else - { - srcshift -= hdr.bitDepth; - } - } - } - - Delete(buffer); - buffer = pdata; - - Delete(palette); - - if (transparency.length > 0) - Delete(transparency); - } - - //if (img.data.length != buffer.length) - // return error("loadPNG error: uncompressed data length mismatch"); - // - //foreach(i, v; buffer) - // img.data[i] = v; - - int bufindex = 0; - if (hdr.colorType == ColorType.Greyscale) - { - if (hdr.bitDepth == 8) { - //img = imgFac.createImage(hdr.width, hdr.height, 1, 8); - for (int i = 0; i < img.length; i++) { - img.data[i] = ((cast(uint)buffer[bufindex])<<16) | ((cast(uint)buffer[bufindex])<<8) | ((cast(uint)buffer[bufindex])<<0) | 0xFF000000; - bufindex += 1; - } - } else if (hdr.bitDepth == 16) { - //img = imgFac.createImage(hdr.width, hdr.height, 1, 16); - assert(false); - } - } - else if (hdr.colorType == ColorType.GreyscaleAlpha) - { - if (hdr.bitDepth == 8) { - //img = imgFac.createImage(hdr.width, hdr.height, 2, 8); - for (int i = 0; i < img.length; i++) { - img.data[i] = ((cast(uint)buffer[bufindex])<<16) | ((cast(uint)buffer[bufindex])<<8) | ((cast(uint)buffer[bufindex])<<0) | ((cast(uint)buffer[bufindex + 1])<<24); - bufindex += 2; - } - } else if (hdr.bitDepth == 16) { - //img = imgFac.createImage(hdr.width, hdr.height, 2, 16); - assert(false); - } - } - else if (hdr.colorType == ColorType.RGB) - { - if (hdr.bitDepth == 8) { - //img = imgFac.createImage(hdr.width, hdr.height, 3, 8); - for (int i = 0; i < img.length; i++) { - img.data[i] = ((cast(uint)buffer[bufindex])<<16) | ((cast(uint)buffer[bufindex + 1])<<8) | ((cast(uint)buffer[bufindex + 2])<<0) | 0xFF000000; - bufindex += 3; - } - } else if (hdr.bitDepth == 16) { - //img = imgFac.createImage(hdr.width, hdr.height, 3, 16); - assert(false); - } - } - else if (hdr.colorType == ColorType.RGBA) - { - if (hdr.bitDepth == 8) { - //img = imgFac.createImage(hdr.width, hdr.height, 4, 8); - for (int i = 0; i < img.length; i++) { - img.data[i] = ((cast(uint)buffer[bufindex])<<16) | ((cast(uint)buffer[bufindex + 1])<<8) | ((cast(uint)buffer[bufindex + 2])<<0) | ((cast(uint)buffer[bufindex + 3])<<24); - bufindex += 4; - } - } else if (hdr.bitDepth == 16) { - //img = imgFac.createImage(hdr.width, hdr.height, 4, 16); - assert(false); - } - } - else if (hdr.colorType == ColorType.Palette) - { - if (transparencyPalette) { - for (int i = 0; i < img.length; i++) { - img.data[i] = ((cast(uint)buffer[bufindex])<<16) | ((cast(uint)buffer[bufindex + 1])<<8) | ((cast(uint)buffer[bufindex + 2])<<0) | ((cast(uint)buffer[bufindex + 3])<<24); - bufindex += 4; - } - //img = imgFac.createImage(hdr.width, hdr.height, 4, 8); - } else { - //img = imgFac.createImage(hdr.width, hdr.height, 3, 8); - for (int i = 0; i < img.length; i++) { - img.data[i] = ((cast(uint)buffer[bufindex])<<16) | ((cast(uint)buffer[bufindex + 1])<<8) | ((cast(uint)buffer[bufindex + 2])<<0) | 0xFF000000; - bufindex += 3; - } - } - } - - Delete(buffer); - - return compound(img, ""); -} - -version (ENABLE_SAVE_PNG) { -/* - * Save PNG to stream. - * GC-free - */ -Compound!(bool, string) savePNG(SuperImage img, OutputStream output) -in -{ - assert (img.data.length); -} -do -{ - Compound!(bool, string) error(string errorMsg) - { - return compound(false, errorMsg); - } - - if (img.bitDepth != 8) - return error("savePNG error: only 8-bit images are supported by encoder"); - - bool writeChunk(ubyte[4] chunkType, ubyte[] chunkData) - { - PNGChunk hdrChunk; - hdrChunk.length = cast(uint)chunkData.length; - hdrChunk.type = chunkType; - hdrChunk.data = chunkData; - hdrChunk.crc = crc32(chain(chunkType[0..$], hdrChunk.data)); - - if (!output.writeBE!uint(hdrChunk.length) - || !output.writeArray(hdrChunk.type)) - return false; - - if (chunkData.length) - if (!output.writeArray(hdrChunk.data)) - return false; - - if (!output.writeBE!uint(hdrChunk.crc)) - return false; - - return true; - } - - bool writeHeader() - { - PNGHeader hdr; - hdr.width = networkByteOrder(img.width); - hdr.height = networkByteOrder(img.height); - hdr.bitDepth = 8; - if (img.channels == 4) - hdr.colorType = ColorType.RGBA; - else if (img.channels == 3) - hdr.colorType = ColorType.RGB; - else if (img.channels == 2) - hdr.colorType = ColorType.GreyscaleAlpha; - else if (img.channels == 1) - hdr.colorType = ColorType.Greyscale; - hdr.compressionMethod = 0; - hdr.filterMethod = 0; - hdr.interlaceMethod = 0; - - return writeChunk(IHDR, hdr.bytes); - } - - output.writeArray(PNGSignature); - if (!writeHeader()) - return error("savePNG error: write failed (disk full?)"); - - //TODO: filtering - ubyte[] raw = New!(ubyte[])(img.width * img.height * img.channels + img.height); - foreach(y; 0..img.height) - { - auto rowStart = y * (img.width * img.channels + 1); - raw[rowStart] = 0; // No filter - - foreach(x; 0..img.width) - { - auto dataIndex = (y * img.width + x) * img.channels; - auto rawIndex = rowStart + 1 + x * img.channels; - - foreach(ch; 0..img.channels) - raw[rawIndex + ch] = img.data[dataIndex + ch]; - } - } - - ubyte[] buffer = New!(ubyte[])(64 * 1024); - ZlibBufferedEncoder zlibEncoder = ZlibBufferedEncoder(buffer, raw); - while (!zlibEncoder.ended) - { - auto len = zlibEncoder.encode(); - if (len > 0) - writeChunk(IDAT, zlibEncoder.buffer[0..len]); - } - - writeChunk(IEND, []); - - Delete(buffer); - Delete(raw); - - return compound(true, ""); -} -} - -/* - * performs the paeth PNG filter from pixels values: - * a = back - * b = up - * c = up and back - */ -pure ubyte paeth(ubyte a, ubyte b, ubyte c) -{ - int p = a + b - c; - int pa = abs(p - a); - int pb = abs(p - b); - int pc = abs(p - c); - if (pa <= pb && pa <= pc) return a; - else if (pb <= pc) return b; - else return c; -} - -bool filter(PNGHeader* hdr, - uint channels, - bool indexed, - ubyte[] ibuffer, - out ubyte[] obuffer, - out string errorMsg) -{ - uint dataSize = cast(uint)ibuffer.length; - uint scanlineSize; - - uint calculatedSize; - if (indexed) - { - calculatedSize = hdr.width * hdr.height * hdr.bitDepth / 8 + hdr.height; - scanlineSize = hdr.width * hdr.bitDepth / 8 + 1; - } - else - { - calculatedSize = hdr.width * hdr.height * channels + hdr.height; - scanlineSize = hdr.width * channels + 1; - } - - version(PNGDebug) - { - writefln("[filter] dataSize = %s", dataSize); - writefln("[filter] calculatedSize = %s", calculatedSize); - } - - if (dataSize != calculatedSize) - { - errorMsg = "loadPNG error: image size and data mismatch"; - return false; - } - - obuffer = New!(ubyte[])(calculatedSize - hdr.height); - - ubyte pback, pup, pupback, cbyte; - - for (int i = 0; i < hdr.height; ++i) - { - pback = 0; - - // get the first byte of a scanline - ubyte scanFilter = ibuffer[i * scanlineSize]; - - if (indexed) - { - // TODO: support filtering for indexed images - if (scanFilter != FilterMethod.None) - { - errorMsg = "loadPNG error: filtering is not supported for indexed images"; - return false; - } - - for (int j = 1; j < scanlineSize; ++j) - { - ubyte b = ibuffer[(i * scanlineSize) + j]; - obuffer[(i * (scanlineSize-1) + j - 1)] = b; - } - continue; - } - - for (int j = 0; j < hdr.width; ++j) - { - for (int k = 0; k < channels; ++k) - { - if (i == 0) pup = 0; - else pup = obuffer[((i-1) * hdr.width + j) * channels + k]; // (hdr.height-(i-1)-1) - if (j == 0) pback = 0; - else pback = obuffer[(i * hdr.width + j-1) * channels + k]; - if (i == 0 || j == 0) pupback = 0; - else pupback = obuffer[((i-1) * hdr.width + j - 1) * channels + k]; - - // get the current byte from ibuffer - cbyte = ibuffer[i * (hdr.width * channels + 1) + j * channels + k + 1]; - - // filter, then set the current byte in data - switch (scanFilter) - { - case FilterMethod.None: - obuffer[(i * hdr.width + j) * channels + k] = cbyte; - break; - case FilterMethod.Sub: - obuffer[(i * hdr.width + j) * channels + k] = cast(ubyte)(cbyte + pback); - break; - case FilterMethod.Up: - obuffer[(i * hdr.width + j) * channels + k] = cast(ubyte)(cbyte + pup); - break; - case FilterMethod.Average: - obuffer[(i * hdr.width + j) * channels + k] = cast(ubyte)(cbyte + (pback + pup) / 2); - break; - case FilterMethod.Paeth: - obuffer[(i * hdr.width + j) * channels + k] = cast(ubyte)(cbyte + paeth(pback, pup, pupback)); - break; - default: - errorMsg = format("loadPNG error: unknown scanline filter (%s)", scanFilter); - return false; - } - } - } - } - - return true; -} - -uint crc32(R)(R range, uint inCrc = 0) if (isInputRange!R) -{ - uint[256] generateTable() - { - uint[256] table; - uint crc; - for (int i = 0; i < 256; i++) - { - crc = i; - for (int j = 0; j < 8; j++) - crc = crc & 1 ? (crc >> 1) ^ 0xEDB88320UL : crc >> 1; - table[i] = crc; - } - return table; - } - - static const uint[256] table = generateTable(); - - uint crc; - - crc = inCrc ^ 0xFFFFFFFF; - foreach(v; range) - crc = (crc >> 8) ^ table[(crc ^ v) & 0xFF]; - - return (crc ^ 0xFFFFFFFF); -} - -static if (false) { -unittest -{ - import std.base64; - - InputStream png() { - string minimal = - "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADklEQVR42mL4z8AAEGAAAwEBAGb9nyQAAAAASUVORK5CYII="; - - ubyte[] bytes = Base64.decode(minimal); - return new ArrayStream(bytes, bytes.length); - } - - SuperImage img = loadPNG(png()); - - assert(img.width == 1); - assert(img.height == 1); - assert(img.channels == 3); - assert(img.pixelSize == 3); - assert(img.data == [0xff, 0x00, 0x00]); - - createDir("tests", false); - savePNG(img, "tests/minimal.png"); - loadPNG("tests/minimal.png"); -} -} diff --git a/3rdparty/dimage/stream.d b/3rdparty/dimage/stream.d deleted file mode 100644 index aa58d2f7..00000000 --- a/3rdparty/dimage/stream.d +++ /dev/null @@ -1,263 +0,0 @@ -/* -Copyright (c) 2014 Martin Cejp - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - -// dimage is actually stripped out part of dlib - just to support reading PNG and JPEG -//dlib.core.stream -module dimage.stream; - -import std.bitmanip; -import std.stdint; -import std.conv; - -//import dlib.core.memory; - -alias StreamPos = uint64_t; -alias StreamSize = uint64_t; -alias StreamOffset = int64_t; - -class SeekException : Exception -{ - this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null) - { - super(msg, file, line, next); - } -} - -/// Seekable -interface Seekable -{ - // Won't throw on invalid position, may throw on a more serious error. - - StreamPos getPosition() @property; - bool setPosition(StreamPos pos); - StreamSize size(); - - // Throw-on-error wrappers - - final StreamPos position(StreamPos pos) - { - if (!setPosition(pos)) - throw new SeekException("Cannot set Seekable position to " ~ pos.to!string); - - return pos; - } - - final StreamPos position() - { - return getPosition(); - } - - // TODO: Non-throwing version - final StreamPos seek(StreamOffset amount) - { - immutable StreamPos seekTo = getPosition() + amount; - - if (!setPosition(seekTo)) - throw new SeekException("Cannot set Seekable position to " ~ seekTo.to!string); - - return seekTo; - } -} - -/// Stream -interface Stream : Seekable -{ - void close(); - bool seekable(); -} - -interface InputStream : Stream -{ - // Won't throw on EOF, may throw on a more serious error. - - bool readable(); - size_t readBytes(void* buffer, size_t count); - - /// Read array.length elements into an pre-allocated array. - /// Returns: true if all elements were read, false otherwise - final bool fillArray(T)(T[] array) - { - immutable size_t len = array.length * T.sizeof; - return readBytes(array.ptr, len) == len; - } - - /// Read an integer in little-endian encoding - final bool readLE(T)(T* value) - { - ubyte[T.sizeof] buffer; - - if (readBytes(buffer.ptr, buffer.length) != buffer.length) - return false; - - *value = littleEndianToNative!T(buffer); - return true; - } - - /// Read an integer in big-endian encoding - final bool readBE(T)(T* value) - { - ubyte[T.sizeof] buffer; - - if (readBytes(buffer.ptr, buffer.length) != buffer.length) - return false; - - *value = bigEndianToNative!T(buffer); - return true; - } -} - -interface OutputStream : Stream -{ - // Won't throw on full disk, may throw on a more serious error. - - void flush(); - bool writeable(); - size_t writeBytes(const void* buffer, size_t count); - - /// Write array.length elements from array. - /// Returns: true if all elements were written, false otherwise - final bool writeArray(T)(const T[] array) - { - immutable size_t len = array.length * T.sizeof; - return writeBytes(array.ptr, len) == len; - } - - /// Write a string as zero-terminated - /// Returns: true on success, false otherwise - final bool writeStringz(string text) - { - ubyte[1] zero = [0]; - - return writeBytes(text.ptr, text.length) - && writeBytes(zero.ptr, zero.length); - } - - /// Write an integer in little-endian encoding - final bool writeLE(T)(const T value) - { - ubyte[T.sizeof] buffer = nativeToLittleEndian!T(value); - - return writeBytes(buffer.ptr, buffer.length) == buffer.length; - } - - /// Write an integer in big-endian encoding - final bool writeBE(T)(const T value) - { - ubyte[T.sizeof] buffer = nativeToBigEndian!T(value); - - return writeBytes(buffer.ptr, buffer.length) == buffer.length; - } -} - -interface IOStream : InputStream, OutputStream -{ -} - -StreamSize copyFromTo(InputStream input, OutputStream output) -{ - ubyte[0x1000] buffer; - StreamSize total = 0; - - while (input.readable) - { - size_t have = input.readBytes(buffer.ptr, buffer.length); - - if (have == 0) - break; - - output.writeBytes(buffer.ptr, have); - total += have; - } - - return total; -} - -// TODO: Move this? -// TODO: Add OutputStream methods -class ArrayStream : InputStream { - import std.algorithm; - - this() { - } - - this(ubyte[] data, size_t size) { - assert(size_ <= data.length); - - this.size_ = size; - this.data = data; - } - - override void close() { - this.pos = 0; - this.size_ = 0; - this.data = null; - } - - override bool readable() { - return pos < size_; - } - - override size_t readBytes(void* buffer, size_t count) { - import core.stdc.string; - - count = min(count, size_ - pos); - - // whoops, memcpy out of nowhere, can we do better than that? - memcpy(buffer, data.ptr + pos, count); - - pos += count; - return count; - } - - override bool seekable() { - return true; - } - - override StreamPos getPosition() { - return pos; - } - - override bool setPosition(StreamPos pos) { - if (pos > size_) - return false; - - this.pos = cast(size_t)pos; - return true; - } - - override StreamSize size() { - return size; - } - - //mixin ManualModeImpl; - //mixin FreeImpl; - - private: - size_t pos = 0, size_ = 0; - ubyte[] data; // data.length is capacity -} diff --git a/3rdparty/dimage/zlib.d b/3rdparty/dimage/zlib.d deleted file mode 100644 index 07784d83..00000000 --- a/3rdparty/dimage/zlib.d +++ /dev/null @@ -1,165 +0,0 @@ -/* -Copyright (c) 2011-2015 Timur Gafarov - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. -*/ - -// dimage is actually stripped out part of dlib - just to support reading PNG and JPEG -module dimage.zlib; //dlib.coding.zlib - -private -{ - import etc.c.zlib; - import dimage.memory; -} - -struct ZlibBufferedEncoder -{ - z_stream zlibStream; - ubyte[] buffer; - ubyte[] input; - bool ended = true; - - this(ubyte[] buf, ubyte[] inp) - { - buffer = buf; - input = inp; - zlibStream.next_out = buffer.ptr; - zlibStream.avail_out = cast(uint)buffer.length; - zlibStream.data_type = Z_BINARY; - zlibStream.zalloc = null; - zlibStream.zfree = null; - zlibStream.opaque = null; - - zlibStream.next_in = inp.ptr; - zlibStream.avail_in = cast(uint)inp.length; - - deflateInit(&zlibStream, Z_BEST_COMPRESSION); - ended = false; - } - - size_t encode() - { - zlibStream.next_out = buffer.ptr; - zlibStream.avail_out = cast(uint)buffer.length; - zlibStream.total_out = 0; - - while (zlibStream.avail_out > 0) - { - int msg = deflate(&zlibStream, Z_FINISH); - - if (msg == Z_STREAM_END) - { - deflateEnd(&zlibStream); - ended = true; - return zlibStream.total_out; - } - else if (msg != Z_OK) - { - deflateEnd(&zlibStream); - return 0; - } - } - - return zlibStream.total_out; - } -} - -struct ZlibDecoder -{ - z_stream zlibStream; - ubyte[] buffer; - int msg = 0; - - bool isInitialized = false; - bool hasEnded = false; - - this(ubyte[] buf) - { - buffer = buf; - zlibStream.next_out = buffer.ptr; - zlibStream.avail_out = cast(uint)buffer.length; - zlibStream.data_type = Z_BINARY; - } - - bool decode(ubyte[] input) - { - zlibStream.next_in = input.ptr; - zlibStream.avail_in = cast(uint)input.length; - - if (!isInitialized) - { - isInitialized = true; - msg = inflateInit(&zlibStream); - if (msg) - { - inflateEnd(&zlibStream); - return false; - } - } - - while (zlibStream.avail_in) - { - msg = inflate(&zlibStream, Z_NO_FLUSH); - - if (msg == Z_STREAM_END) - { - inflateEnd(&zlibStream); - hasEnded = true; - reallocateBuffer(zlibStream.total_out); - return true; - } - else if (msg != Z_OK) - { - inflateEnd(&zlibStream); - return false; - } - else if (zlibStream.avail_out == 0) - { - reallocateBuffer(buffer.length * 2); - zlibStream.next_out = &buffer[buffer.length / 2]; - zlibStream.avail_out = cast(uint)(buffer.length / 2); - } - } - - return true; - } - - void reallocateBuffer(size_t len) - { - ubyte[] buffer2 = New!(ubyte[])(len); - for(uint i = 0; i < buffer2.length; i++) - if (i < buffer.length) - buffer2[i] = buffer[i]; - Delete(buffer); - buffer = buffer2; - } - - void free() - { - Delete(buffer); - } -} - diff --git a/README.md b/README.md index 15d4b4ea..17a24a2b 100644 --- a/README.md +++ b/README.md @@ -151,9 +151,8 @@ Third party components used * `binbc-opengl` - for OpenGL support * `bindbc-freetype` + FreeType library support under linux and optionally under Windows. * `bindbc-sdl` + SDL2 for cross platform support -* WindowsAPI bindings from http://www.dsource.org/projects/bindings/wiki/WindowsApi (patched) * X11 binding when SDL2 is not used -* PNG and JPEG reading code is based on dlib sources +* `arsd-official` For image reading and XML parsing Hello World diff --git a/dub.json b/dub.json index 31f66a2a..e288afa6 100644 --- a/dub.json +++ b/dub.json @@ -34,7 +34,8 @@ "dependencies": { "inilike": "~>1.2.2", "icontheme": "~>1.2.3", - "arsd-official:dom": "~>10.9.8" + "arsd-official:dom": "~>10.9.10", + "arsd-official:image_files": "~>10.9.10" }, "subPackages": [ diff --git a/src/dlangui/graphics/images.d b/src/dlangui/graphics/images.d index b308cc4a..250f0823 100644 --- a/src/dlangui/graphics/images.d +++ b/src/dlangui/graphics/images.d @@ -23,25 +23,7 @@ module dlangui.graphics.images; public import dlangui.core.config; static if (BACKEND_GUI): -//version = USE_DEIMAGE; -//version = USE_DLIBIMAGE; -version = USE_DIMAGE; - -version (USE_DEIMAGE) { - import devisualization.image; - import devisualization.image.png; -} else version (USE_DIMAGE) { - //import dimage.io; - import dimage.image; - import dimage.png; - import dimage.jpeg; -} else version (USE_DLIBIMAGE) { - import dlib.image.io.io; - import dlib.image.image; - import dlib.image.io.png; - import dlib.image.io.jpeg; - version = ENABLE_DLIBIMAGE_JPEG; -} +import arsd.image; import dlangui.core.logger; import dlangui.core.types; @@ -82,138 +64,16 @@ ColorDrawBuf loadImage(immutable ubyte[] data, string filename) { } } - version (USE_DEIMAGE) { - try { - Image image = imageFromData(extension(filename)[1 ..$], cast(ubyte[])data); //imageFromFile(filename); - int w = cast(int)image.width; - int h = cast(int)image.height; - ColorDrawBuf buf = new ColorDrawBuf(w, h); - Color_RGBA[] pixels = image.rgba.allPixels; - int index = 0; - foreach(y; 0 .. h) { - uint * dstLine = buf.scanLine(y); - foreach(x; 0 .. w) { - Color_RGBA * pixel = &pixels[index + x]; - dstLine[x] = makeRGBA(pixel.r_ubyte, pixel.g_ubyte, pixel.b_ubyte, pixel.a_ubyte); - } - index += w; - } - //destroy(image); - return buf; - } catch (NotAnImageException e) { - Log.e("Failed to load image from file ", filename, " using de_image"); - Log.e(to!string(e)); - return null; - } - } else version (USE_DLIBIMAGE) { - static import dlib.core.stream; - try { - version (ENABLE_DLIBIMAGE_JPEG) { - } else { - // temporary disabling of JPEG support - until DLIB included it - if (filename.endsWith(".jpeg") || filename.endsWith(".jpg") || filename.endsWith(".JPG") || filename.endsWith(".JPEG")) - return null; - } - SuperImage image = null; - dlib.core.stream.ArrayStream dlibstream = new dlib.core.stream.ArrayStream(cast(ubyte[])data, data.length); - switch(filename.extension) - { - case ".jpg", ".JPG", ".jpeg": - image = dlib.image.io.jpeg.loadJPEG(dlibstream); - break; - case ".png", ".PNG": - image = dlib.image.io.png.loadPNG(dlibstream); - break; - default: - break; - } - //SuperImage image = dlib.image.io.io.loadImage(filename); - if (!image) - return null; - ColorDrawBuf buf = importImage(image); - destroy(image); - return buf; - } catch (Exception e) { - Log.e("Failed to load image from file ", filename, " using dlib image"); - Log.e(to!string(e)); - return null; - } - } else version (USE_DIMAGE) { - static import dimage.stream; - try { - SuperImage image = null; - dimage.stream.ArrayStream dlibstream = new dimage.stream.ArrayStream(cast(ubyte[])data, data.length); - switch(filename.extension) - { - case ".jpg", ".JPG", ".jpeg": - image = dimage.jpeg.loadJPEG(dlibstream); - break; - case ".png", ".PNG": - image = dimage.png.loadPNG(dlibstream); - break; - default: - break; - } - //SuperImage image = dlib.image.io.io.loadImage(filename); - if (!image) - return null; - ColorDrawBuf buf = importImage(image); - destroy(image); - return buf; - } catch (Exception e) { - Log.e("Failed to load image from file ", filename, " using dlib image"); - Log.e(to!string(e)); - return null; - } - } else { - try { - std.stream.File f = new std.stream.File(filename); - scope(exit) { f.close(); } - return loadImage(f); - } catch (Exception e) { - Log.e("exception while loading image from file ", filename); - Log.e(to!string(e)); - return null; + auto image = loadImageFromMemory(data); + ColorDrawBuf buf = new ColorDrawBuf(image.width, image.height); + for(int j = 0; j < buf.height; j++) + { + auto scanLine = buf.scanLine(j); + for(int i = 0; i < buf.width; i++) + { + auto color = image.getPixel(i, j); + scanLine[i] = makeRGBA(color.r, color.g, color.b, 255 - color.a); } } - + return buf; } - -version (USE_DLIBIMAGE) { - ColorDrawBuf importImage(SuperImage image) { - int w = image.width; - int h = image.height; - ColorDrawBuf buf = new ColorDrawBuf(w, h); - foreach(y; 0 .. h) { - uint * dstLine = buf.scanLine(y); - foreach(x; 0 .. w) { - auto pixel = image[x, y].convert(8); - dstLine[x] = makeRGBA(pixel.r, pixel.g, pixel.b, 255 - pixel.a); - } - } - return buf; - } -} - -version (USE_DIMAGE) { - ColorDrawBuf importImage(SuperImage image) { - int w = image.width; - int h = image.height; - ColorDrawBuf buf = new ColorDrawBuf(w, h); - foreach(y; 0 .. h) { - uint * dstLine = buf.scanLine(y); - foreach(x; 0 .. w) { - uint pixel = image[x, y]; - dstLine[x] = pixel ^ 0xFF000000; - } - } - return buf; - } -} - -class ImageDecodingException : Exception { - this(string msg) { - super(msg); - } -} -