1 /** 2 * Image module. 3 * 4 * License: 5 * MIT. See LICENSE for full details. 6 */ 7 module tkd.image.image; 8 9 /** 10 * Imports. 11 */ 12 import tkd.element.element; 13 14 /** 15 * The image base class. 16 */ 17 class Image : Element 18 { 19 /** 20 * Construct the image. 21 */ 22 public this() 23 { 24 super(); 25 this._elementId = "image"; 26 27 this._tk.eval("image create photo %s", this.id); 28 } 29 30 /** 31 * This method embeds the image as a base64 encoded string into the 32 * application at compile-time. The path to the image must be passed to the 33 * compiler using the -J switch. 34 * 35 * Params: 36 * filename = The filename to read the data from. 37 * 38 * Returns: 39 * This image to aid method chaining. 40 */ 41 protected auto embedBase64Data(string filename, this T)() 42 { 43 this.setData(base64Encode!(filename)); 44 45 return cast(T) this; 46 } 47 48 /** 49 * Clears the image of all pixel data and effectively makes it transparent. 50 * 51 * Returns: 52 * This image to aid method chaining. 53 */ 54 public auto blank(this T)() 55 { 56 this._tk.eval("%s blank", this.id); 57 58 return cast(T) this; 59 } 60 61 /** 62 * Specifies the contents of the image as a string. The string should 63 * contain binary data or, for some formats, base64-encoded data (this is 64 * currently guaranteed to be supported for PNG and GIF images). A set 65 * file takes precedence over the setting of data. 66 * 67 * Params: 68 * data = The image data. 69 * 70 * Returns: 71 * This image to aid method chaining. 72 */ 73 public auto setData(this T)(string data) 74 { 75 this._tk.eval("%s configure -data {%s}", this.id, data); 76 77 return cast(T) this; 78 } 79 80 /** 81 * Get the image data. 82 * 83 * Returns: 84 * Base64 encoded image data. 85 */ 86 public string getData() 87 { 88 this._tk.eval("%s cget -data", this.id); 89 return this._tk.getResult!(string); 90 } 91 92 /** 93 * Set the image format. 94 * Once set the image only accepts files or data in this format. 95 * 96 * Params: 97 * format = A valid image format. 98 * 99 * Returns: 100 * This image to aid method chaining. 101 * 102 * See_Also: 103 * $(LINK2 ./imageformat.html, tkd.image.imageformat) for supported formats. 104 */ 105 public auto setFormat(this T)(string format) 106 { 107 this._tk.eval("%s configure -format {%s}", this.id, format); 108 109 return cast(T) this; 110 } 111 112 /** 113 * Get the image format. 114 * 115 * Returns: 116 * The image format. 117 * 118 * See_Also: 119 * $(LINK2 ./imageformat.html, tkd.image.imageformat) for returned formats. 120 */ 121 public string getFormat() 122 { 123 this._tk.eval("%s cget -format", this.id); 124 return this._tk.getResult!(string); 125 } 126 127 /** 128 * Set the image file. 129 * 130 * Params: 131 * file = The name of the file. 132 * 133 * Returns: 134 * This image to aid method chaining. 135 */ 136 public auto setFile(this T)(string file) 137 { 138 this._tk.eval("%s configure -file {%s}", this.id, file); 139 140 return cast(T) this; 141 } 142 143 /** 144 * Get the image file. 145 * 146 * Returns: 147 * The file that was loaded for this image. 148 */ 149 public string getFile() 150 { 151 this._tk.eval("%s cget -file", this.id); 152 return this._tk.getResult!(string); 153 } 154 155 /** 156 * Set the image gamma. 157 * 158 * Params: 159 * gamma = The destination gamma. 160 * 161 * Returns: 162 * This image to aid method chaining. 163 */ 164 public auto setGamma(this T)(double gamma) 165 { 166 if (gamma < 0) 167 { 168 gamma = 1; 169 } 170 171 this._tk.eval("%s configure -gamma %s", this.id, gamma); 172 173 return cast(T) this; 174 } 175 176 /** 177 * Get the current image gamma. 178 * 179 * Returns: 180 * A string containing the image gamma setting. 181 */ 182 public string getGamma() 183 { 184 this._tk.eval("%s cget -gamma", this.id); 185 return this._tk.getResult!(string); 186 } 187 188 /** 189 * Set the image height. 190 * 191 * Params: 192 * height = The height to crop the image to. 193 * 194 * Returns: 195 * This image to aid method chaining. 196 */ 197 public auto setHeight(this T)(int height) 198 { 199 this._tk.eval("%s configure -height %s", this.id, height); 200 201 return cast(T) this; 202 } 203 204 /** 205 * Get the current cropped image height. 206 * 207 * Returns: 208 * The current cropped image height. Returns 0 if no cropping is taking place. 209 */ 210 public string getHeight() 211 { 212 this._tk.eval("%s cget -height", this.id); 213 return this._tk.getResult!(string); 214 } 215 216 /** 217 * Set the image palette. This setting set how many levels of color/gray are used. 218 * 219 * Sample_Palettes: 220 * $(UL 221 * $(LI "16" = 16 levels of gray) 222 * $(LI "16/16/16" = 16 levels of RGB) 223 * ) 224 * 225 * Params: 226 * palette = A string describing the palette to use. 227 * 228 * Returns: 229 * This image to aid method chaining. 230 */ 231 public auto setPalette(this T)(string palette) 232 { 233 this._tk.eval("%s configure -palette {%s}", this.id, palette); 234 235 return cast(T) this; 236 } 237 238 /** 239 * Get the current palette. 240 * 241 * Returns: 242 * A string describing the palette. 243 */ 244 public string getPalette() 245 { 246 this._tk.eval("%s cget -palette", this.id); 247 return this._tk.getResult!(string); 248 } 249 250 /** 251 * Set the image width. 252 * 253 * Params: 254 * width = The width to crop the image to. 255 * 256 * Returns: 257 * This image to aid method chaining. 258 */ 259 public auto setWidth(this T)(int width) 260 { 261 this._tk.eval("%s configure -width %s", this.id, width); 262 263 return cast(T) this; 264 } 265 266 /** 267 * Get the current cropped image height. 268 * 269 * Returns: 270 * The current cropped image height. Returns 0 if no cropping is taking place. 271 */ 272 public string getWidth() 273 { 274 this._tk.eval("%s cget -width", this.id); 275 return this._tk.getResult!(string); 276 } 277 278 /** 279 * Destroy this image. 280 * 281 * Caveats: 282 * Once an image is destroyed it can no longer be referenced in your 283 * code or a segmentation fault will occur and potentially crash your 284 * program. 285 */ 286 public void destroy() 287 { 288 this._tk.eval("image delete %s", this.id); 289 super.destroy(); 290 } 291 } 292 293 /** 294 * Template to base64 encode files at compile time. 295 * 296 * Params: 297 * file = The file name to encode and embed. 298 */ 299 private template base64Encode(string file) 300 { 301 import std.base64; 302 303 private string getData() 304 { 305 return Base64.encode(cast(ubyte[])import(file)); 306 } 307 308 enum base64Encode = getData(); 309 }