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 } 154 ubyte* outputPointer; 155 size_t outputSize = WebPEncodeRGBA( 156 inputImage.data.ptr, 157 img.width(), 158 img.height(), 159 img.width() * 4, 160 quality, 161 &outputPointer); 162 ubyte[] result = outputPointer[0 .. outputSize]; 163 free(outputPointer); 164 return result; 165 } 166 private ubyte[] saveLossy(SuperImage img, int quality) { 167 SuperImage inputImage = img; 168 if (PixelFormat.RGB8 != img.pixelFormat) { 169 inputImage = convert!(Image!(PixelFormat.RGB8))(img); 170 } 171 ubyte* outputPointer; 172 size_t outputSize = WebPEncodeRGB( 173 inputImage.data.ptr, 174 img.width(), 175 img.height(), 176 img.width() * 3, 177 quality, 178 &outputPointer); 179 ubyte[] result = outputPointer[0 .. outputSize]; 180 free(outputPointer); 181 return result; 182 } 183 184 private ubyte[] saveLosslessWithAlpha(SuperImage img) { 185 SuperImage inputImage = img; 186 if (PixelFormat.RGBA8 != img.pixelFormat) { 187 inputImage = convert!(Image!(PixelFormat.RGBA8))(img); 188 } 189 ubyte* outputPointer; 190 size_t outputSize = WebPEncodeLosslessRGBA( 191 inputImage.data.ptr, 192 inputImage.width(), 193 inputImage.height(), 194 inputImage.width() * 4, 195 &outputPointer); 196 ubyte[] result = outputPointer[0 .. outputSize]; 197 free(outputPointer); 198 return result; 199 } 200 private ubyte[] saveLossless(SuperImage img) { 201 SuperImage inputImage = img; 202 if (PixelFormat.RGB8 != img.pixelFormat) { 203 inputImage = convert!(Image!(PixelFormat.RGB8))(img); 204 } 205 ubyte* outputPointer; 206 size_t outputSize = WebPEncodeLosslessRGB( 207 inputImage.data.ptr, 208 inputImage.width(), 209 inputImage.height(), 210 inputImage.width() * 3, 211 &outputPointer); 212 ubyte[] result = outputPointer[0 .. outputSize]; 213 free(outputPointer); 214 return result; 215 }