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