1 // Written in the D programming language. 2 3 /** 4 This module contains image loading functions. 5 6 Currently uses FreeImage. 7 8 Usage of libpng is not feasible under linux due to conflicts of library and binding versions. 9 10 Synopsis: 11 12 ---- 13 import dlangui.graphics.images; 14 15 ---- 16 17 Copyright: Vadim Lopatin, 2014 18 License: Boost License 1.0 19 Authors: Vadim Lopatin, coolreader.org@gmail.com 20 */ 21 module dlangui.graphics.images; 22 23 public import dlangui.core.config; 24 static if (BACKEND_GUI): 25 26 //version = USE_DEIMAGE; 27 //version = USE_DLIBIMAGE; 28 version = USE_DIMAGE; 29 30 version (USE_DEIMAGE) { 31 import devisualization.image; 32 import devisualization.image.png; 33 } else version (USE_DIMAGE) { 34 //import dimage.io; 35 import dimage.image; 36 import dimage.png; 37 import dimage.jpeg; 38 } else version (USE_DLIBIMAGE) { 39 import dlib.image.io.io; 40 import dlib.image.image; 41 import dlib.image.io.png; 42 import dlib.image.io.jpeg; 43 version = ENABLE_DLIBIMAGE_JPEG; 44 } 45 46 import dlangui.core.logger; 47 import dlangui.core.types; 48 import dlangui.graphics.colors; 49 import dlangui.graphics.drawbuf; 50 import dlangui.core.streams; 51 import std.path; 52 import std.conv : to; 53 54 55 /// load and decode image from file to ColorDrawBuf, returns null if loading or decoding is failed 56 ColorDrawBuf loadImage(string filename) { 57 static import std.file; 58 try { 59 immutable ubyte[] data = cast(immutable ubyte[])std.file.read(filename); 60 return loadImage(data, filename); 61 } catch (Exception e) { 62 Log.e("exception while loading image from file ", filename); 63 Log.e(to!string(e)); 64 return null; 65 } 66 } 67 68 /// load and decode image from input stream to ColorDrawBuf, returns null if loading or decoding is failed 69 ColorDrawBuf loadImage(immutable ubyte[] data, string filename) { 70 Log.d("Loading image from file " ~ filename); 71 72 import std.algorithm : endsWith; 73 if (filename.endsWith(".xpm")) { 74 import dlangui.graphics.xpm.reader : parseXPM; 75 try { 76 return parseXPM(data); 77 } 78 catch(Exception e) { 79 Log.e("Failed to load image from file ", filename); 80 Log.e(to!string(e)); 81 return null; 82 } 83 } 84 85 version (USE_DEIMAGE) { 86 try { 87 Image image = imageFromData(extension(filename)[1 ..$], cast(ubyte[])data); //imageFromFile(filename); 88 int w = cast(int)image.width; 89 int h = cast(int)image.height; 90 ColorDrawBuf buf = new ColorDrawBuf(w, h); 91 Color_RGBA[] pixels = image.rgba.allPixels; 92 int index = 0; 93 foreach(y; 0 .. h) { 94 uint * dstLine = buf.scanLine(y); 95 foreach(x; 0 .. w) { 96 Color_RGBA * pixel = &pixels[index + x]; 97 dstLine[x] = makeRGBA(pixel.r_ubyte, pixel.g_ubyte, pixel.b_ubyte, pixel.a_ubyte); 98 } 99 index += w; 100 } 101 //destroy(image); 102 return buf; 103 } catch (NotAnImageException e) { 104 Log.e("Failed to load image from file ", filename, " using de_image"); 105 Log.e(to!string(e)); 106 return null; 107 } 108 } else version (USE_DLIBIMAGE) { 109 static import dlib.core.stream; 110 try { 111 version (ENABLE_DLIBIMAGE_JPEG) { 112 } else { 113 // temporary disabling of JPEG support - until DLIB included it 114 if (filename.endsWith(".jpeg") || filename.endsWith(".jpg") || filename.endsWith(".JPG") || filename.endsWith(".JPEG")) 115 return null; 116 } 117 SuperImage image = null; 118 dlib.core.stream.ArrayStream dlibstream = new dlib.core.stream.ArrayStream(cast(ubyte[])data, data.length); 119 switch(filename.extension) 120 { 121 case ".jpg", ".JPG", ".jpeg": 122 image = dlib.image.io.jpeg.loadJPEG(dlibstream); 123 break; 124 case ".png", ".PNG": 125 image = dlib.image.io.png.loadPNG(dlibstream); 126 break; 127 default: 128 break; 129 } 130 //SuperImage image = dlib.image.io.io.loadImage(filename); 131 if (!image) 132 return null; 133 ColorDrawBuf buf = importImage(image); 134 destroy(image); 135 return buf; 136 } catch (Exception e) { 137 Log.e("Failed to load image from file ", filename, " using dlib image"); 138 Log.e(to!string(e)); 139 return null; 140 } 141 } else version (USE_DIMAGE) { 142 static import dimage.stream; 143 try { 144 SuperImage image = null; 145 dimage.stream.ArrayStream dlibstream = new dimage.stream.ArrayStream(cast(ubyte[])data, data.length); 146 switch(filename.extension) 147 { 148 case ".jpg", ".JPG", ".jpeg": 149 image = dimage.jpeg.loadJPEG(dlibstream); 150 break; 151 case ".png", ".PNG": 152 image = dimage.png.loadPNG(dlibstream); 153 break; 154 default: 155 break; 156 } 157 //SuperImage image = dlib.image.io.io.loadImage(filename); 158 if (!image) 159 return null; 160 ColorDrawBuf buf = importImage(image); 161 destroy(image); 162 return buf; 163 } catch (Exception e) { 164 Log.e("Failed to load image from file ", filename, " using dlib image"); 165 Log.e(to!string(e)); 166 return null; 167 } 168 } else { 169 try { 170 std.stream.File f = new std.stream.File(filename); 171 scope(exit) { f.close(); } 172 return loadImage(f); 173 } catch (Exception e) { 174 Log.e("exception while loading image from file ", filename); 175 Log.e(to!string(e)); 176 return null; 177 } 178 } 179 180 } 181 182 version (USE_DLIBIMAGE) { 183 ColorDrawBuf importImage(SuperImage image) { 184 int w = image.width; 185 int h = image.height; 186 ColorDrawBuf buf = new ColorDrawBuf(w, h); 187 foreach(y; 0 .. h) { 188 uint * dstLine = buf.scanLine(y); 189 foreach(x; 0 .. w) { 190 auto pixel = image[x, y].convert(8); 191 dstLine[x] = makeRGBA(pixel.r, pixel.g, pixel.b, 255 - pixel.a); 192 } 193 } 194 return buf; 195 } 196 } 197 198 version (USE_DIMAGE) { 199 ColorDrawBuf importImage(SuperImage image) { 200 int w = image.width; 201 int h = image.height; 202 ColorDrawBuf buf = new ColorDrawBuf(w, h); 203 foreach(y; 0 .. h) { 204 uint * dstLine = buf.scanLine(y); 205 foreach(x; 0 .. w) { 206 uint pixel = image[x, y]; 207 dstLine[x] = pixel ^ 0xFF000000; 208 } 209 } 210 return buf; 211 } 212 } 213 214 class ImageDecodingException : Exception { 215 this(string msg) { 216 super(msg); 217 } 218 } 219