1 module dlibwebp.impl; 2 3 import api = dlibwebp.api; 4 5 import dlib.image; 6 import webp.encode; 7 import webp.decode; 8 import dlib.core.compound; 9 import dlib.core.stream; 10 import dlib.filesystem.local; 11 import core.stdc.stdlib : free; 12 import std.array; 13 import exceptions; 14 15 16 17 package SuperImage loadWEBP(string filename) { 18 InputStream input = openForInput(filename); 19 auto img = loadWEBP(input); 20 input.close(); 21 return img; 22 } 23 24 package SuperImage loadWEBP(InputStream input) { 25 auto fileContent = appender!(ubyte[])(); 26 ubyte[0x1000] buffer; 27 while (input.readable) { 28 size_t count = input.readBytes(buffer.ptr, buffer.length); 29 if (count == 0) { 30 break; 31 } 32 for (int i = 0; i < count; i++) { 33 fileContent.put(buffer[i]); 34 } 35 } 36 return loadWEBP(fileContent.data); 37 } 38 39 package SuperImage loadWEBP(in ubyte[] webp) { 40 int width; 41 int height; 42 ubyte* argbPointer = WebPDecodeRGBA(webp.ptr, webp.length, &width, &height); 43 ubyte[] argbArray = argbPointer[0 .. (width * height * 4)]; 44 45 SuperImage rgbaImage = defaultImageFactory.createImage(width, height, 4, 8); 46 foreach(i, v; argbArray) { 47 rgbaImage.data[i] = v; 48 } 49 free(argbPointer); 50 return rgbaImage; 51 } 52 53 54 package void saveWEBP(SuperImage img, int quality, string filename) { 55 OutputStream output; 56 try { 57 output = openForOutput(filename); 58 } catch (Exception e) { 59 throw new IOException("Could now open file for write.", e); 60 } 61 62 Compound!(bool, string) res = saveWEBP(img, quality, output); 63 output.close(); 64 65 if (!res[0]) { 66 throw new api.WEBPLoadException(res[1]); 67 } 68 } 69 package void saveLosslessWEBP(SuperImage img, string filename) { 70 OutputStream output; 71 try { 72 output = openForOutput(filename); 73 } catch (Exception e) { 74 throw new IOException("Could now open file for write.", e); 75 } 76 77 Compound!(bool, string) res = saveLosslessWEBP(img, output); 78 output.close(); 79 80 if (!res[0]) { 81 throw new api.WEBPLoadException(res[1]); 82 } 83 } 84 85 package Compound!(bool, string) saveWEBP(SuperImage img, int quality, OutputStream output) { 86 ubyte[] result; 87 try { 88 result = saveWEBPToArray(img, quality); 89 } catch (api.WEBPLoadException e) { 90 if (e.msg.empty) { 91 return compound(false, "Exception occurred during to saving to the array."); 92 } else { 93 return compound(false, e.msg); 94 } 95 } 96 if (result.length < 1) { 97 return compound(false, "Empty result."); 98 } 99 if (!output.writeArray(result)) { 100 /// By some reason, `writeArray` returns `false` on Travis CI. 101 // return compound(false, "Could not write the result to the output stream."); 102 } 103 return compound(true, ""); 104 } 105 package Compound!(bool, string) saveLosslessWEBP(SuperImage img, OutputStream output) { 106 ubyte[] result; 107 try { 108 result = saveLosslessWEBPToArray(img); 109 } catch (api.WEBPLoadException e) { 110 if (e.msg.empty) { 111 return compound(false, "Exception occurred during to saving to the array."); 112 } else { 113 return compound(false, e.msg); 114 } 115 } 116 if (result.length < 1) { 117 return compound(false, "Empty result."); 118 } 119 if (!output.writeArray(result)) { 120 /// By some reason, `writeArray` returns `false` on Travis CI. 121 // return compound(false, "Could not write the result to the output stream."); 122 } 123 return compound(true, ""); 124 } 125 126 package ubyte[] saveWEBPToArray(SuperImage img, int quality) { 127 if (PixelFormat.L8 == img.pixelFormat || 128 PixelFormat.RGB8 == img.pixelFormat || 129 PixelFormat.L16 == img.pixelFormat || 130 PixelFormat.RGB16 == img.pixelFormat) { 131 return saveLossy(img, quality); 132 } else { 133 return saveLossyWithAlpha(img, quality); 134 } 135 } 136 package ubyte[] saveLosslessWEBPToArray(SuperImage img) { 137 if (PixelFormat.L8 == img.pixelFormat || 138 PixelFormat.RGB8 == img.pixelFormat || 139 PixelFormat.L16 == img.pixelFormat || 140 PixelFormat.RGB16 == img.pixelFormat) { 141 return saveLossless(img); 142 } else { 143 return saveLosslessWithAlpha(img); 144 } 145 } 146 147 148 149 private ubyte[] saveLossyWithAlpha(SuperImage img, int quality) { 150 SuperImage inputImage = img; 151 if (PixelFormat.RGBA8 != img.pixelFormat) { 152 inputImage = convert!(Image!(PixelFormat.RGBA8))(img); 153 assert(inputImage.width == img.width); 154 assert(inputImage.height == img.height); 155 } 156 ubyte* outputPointer; 157 size_t outputSize = WebPEncodeRGBA( 158 inputImage.data.ptr, 159 img.width(), 160 img.height(), 161 img.width() * 4, 162 quality, 163 &outputPointer); 164 ubyte[] result = outputPointer[0 .. outputSize]; 165 free(outputPointer); 166 return result; 167 } 168 private ubyte[] saveLossy(SuperImage img, int quality) { 169 SuperImage inputImage = img; 170 if (PixelFormat.RGB8 != img.pixelFormat) { 171 inputImage = convert!(Image!(PixelFormat.RGB8))(img); 172 assert(inputImage.width == img.width); 173 assert(inputImage.height == img.height); 174 } 175 ubyte* outputPointer; 176 size_t outputSize = WebPEncodeRGB( 177 inputImage.data.ptr, 178 img.width(), 179 img.height(), 180 img.width() * 3, 181 quality, 182 &outputPointer); 183 ubyte[] result = outputPointer[0 .. outputSize]; 184 free(outputPointer); 185 return result; 186 } 187 188 private ubyte[] saveLosslessWithAlpha(SuperImage img) { 189 SuperImage inputImage = img; 190 if (PixelFormat.RGBA8 != img.pixelFormat) { 191 inputImage = convert!(Image!(PixelFormat.RGBA8))(img); 192 assert(inputImage.width == img.width); 193 assert(inputImage.height == img.height); 194 } 195 ubyte* outputPointer; 196 size_t outputSize = WebPEncodeLosslessRGBA( 197 inputImage.data.ptr, 198 inputImage.width(), 199 inputImage.height(), 200 inputImage.width() * 4, 201 &outputPointer); 202 ubyte[] result = outputPointer[0 .. outputSize]; 203 free(outputPointer); 204 return result; 205 } 206 private ubyte[] saveLossless(SuperImage img) { 207 SuperImage inputImage = img; 208 if (PixelFormat.RGB8 != img.pixelFormat) { 209 inputImage = convert!(Image!(PixelFormat.RGB8))(img); 210 assert(inputImage.width == img.width); 211 assert(inputImage.height == img.height); 212 } 213 ubyte* outputPointer; 214 size_t outputSize = WebPEncodeLosslessRGB( 215 inputImage.data.ptr, 216 inputImage.width(), 217 inputImage.height(), 218 inputImage.width() * 3, 219 &outputPointer); 220 ubyte[] result = outputPointer[0 .. outputSize]; 221 free(outputPointer); 222 return result; 223 }