1 /** \file 2 * \brief Image Manipulation 3 * 4 * See Copyright Notice in im_lib.h 5 */ 6 module im.im_image; 7 8 version(IM) : 9 10 import core.stdc.config : c_long; 11 import im.im : imFile, IM_RGB; 12 13 //version(DigitalMars) version(Windows) { pragma(lib, "im.lib"); } // required anyway 14 15 @nogc nothrow : 16 extern(C) { 17 18 /** \defgroup imgclass imImage 19 * 20 * \par 21 * Base definitions and functions for image representation. \n 22 * Only the image processing operations depends on these definitions, 23 * Image Storage and Image Capture are completely independent. 24 * \par 25 * You can also initialize a structure with your own memory buffer, see \ref imImageInit. 26 * To release the structure without releasing the buffer, 27 * set "data[0]" to NULL before calling imImageDestroy. 28 * \par 29 * See \ref im_image.h 30 * \ingroup imagerep */ 31 32 33 34 /** \brief Image Representation Structure 35 * 36 * \par 37 * An image representation than supports all the color spaces, 38 * but planes are always unpacked and the orientation is always bottom up. 39 * \ingroup imgclass */ 40 struct _imImage // typedef struct _imImage imImage; 41 { 42 /* main parameters */ 43 int width; /**< Number of columns. image:Width() -> width: number [in Lua 5]. */ 44 int height; /**< Number of lines. image:Height() -> height: number [in Lua 5]. */ 45 int color_space; /**< Color space descriptor. See also \ref imColorSpace. image:ColorSpace() -> color_space: number [in Lua 5]. */ 46 int data_type; /**< Data type descriptor. See also \ref imDataType. image:DataType() -> data_type: number [in Lua 5]. */ 47 int has_alpha; /**< Indicates that there is an extra channel with alpha. image:HasAlpha() -> has_alpha: boolean [in Lua 5]. \n 48 It will not affect the secondary parameters, i.e. the number of planes will be in fact depth+1. \n 49 It is always 0 unless imImageAddAlpha is called. Alpha is automatically added in image loading functions. */ 50 51 /* secondary parameters */ 52 int depth; /**< Number of planes (ColorSpaceDepth) image:Depth() -> depth: number [in Lua 5]. */ 53 int line_size; /**< Number of bytes per line in one plane (width * DataTypeSize) */ 54 int plane_size; /**< Number of bytes per plane. (line_size * height) */ 55 int size; /**< Number of bytes occupied by the image (plane_size * depth) */ 56 int count; /**< Number of pixels per plane (width * height) */ 57 58 /* image data */ 59 void** data; /**< Image data organized as a 2D matrix with several planes. \n 60 But plane 0 is also a pointer to the full data. \n 61 The remaining planes are: "data[i] = data[0] + i*plane_size". \n 62 In Lua, data indexing is possible using: "image[plane][line][column]". \n 63 Also in Lua, is possible to set all pixels using a table calling "image:SetPixels(table)" 64 and get all pixels using "table = image:GetPixels()" (Since 3.9). */ 65 66 /* image attributes */ 67 c_long *palette; /**< Color palette. image:GetPalette() -> palette: imPalette [in Lua 5]. \n 68 Used only when depth=1. Otherwise is NULL. */ 69 int palette_count; /**< The palette is always 256 colors allocated, but can have less colors used. */ 70 71 void* attrib_table; /**< in fact is an imAttribTable, but we hide this here */ 72 } 73 alias imImage = _imImage; 74 75 /** Creates a new image. 76 * See also \ref imDataType and \ref imColorSpace. Image data is cleared as \ref imImageClear. \n 77 * In Lua the IM image metatable name is "imImage". 78 * When converted to a string will return "imImage(%p) [width=%d,height=%d,color_space=%s,data_type=%s,depth=%d]" where %p is replaced by the userdata address, 79 * and other values are replaced by the respective attributes. 80 * If the image is already destroyed by im.ImageDestroy, then it will return also the suffix "-destroyed". 81 * 82 * \verbatim im.ImageCreate(width: number, height: number, color_space: number, data_type: number) -> image: imImage [in Lua 5] \endverbatim 83 * \ingroup imgclass */ 84 imImage* imImageCreate(int width, int height, int color_space, int data_type); 85 86 /** Initializes the image structure but does not allocates image data. 87 * See also \ref imDataType and \ref imColorSpace. 88 * The only addtional flag thar color_mode can has here is IM_ALPHA. 89 * To release the image structure without releasing the buffer, 90 * set "data[0]" to NULL before calling imImageDestroy. 91 * \ingroup imgclass */ 92 imImage* imImageInit(int width, int height, int color_mode, int data_type, void* data_buffer, c_long* palette, int palette_count); 93 94 /** Creates a new image based on an existing one. \n 95 * If the addicional parameters are -1, the given image parameters are used. \n 96 * The image atributes always are copied. HasAlpha is copied. 97 * See also \ref imDataType and \ref imColorSpace. 98 * 99 * \verbatim im.ImageCreateBased(image: imImage, [width: number], [height: number], [color_space: number], [data_type: number]) -> image: imImage [in Lua 5] \endverbatim 100 * The addicional parameters in Lua can be nil, 101 * and they can also be functions with the based image as a parameter to return the respective value. 102 * \ingroup imgclass */ 103 imImage* imImageCreateBased(const(imImage)* image, int width, int height, int color_space, int data_type); 104 105 /** Destroys the image and frees the memory used. 106 * image data is destroyed only if its data[0] is not NULL. \n 107 * In Lua if this function is not called, the image is destroyed by the garbage collector. 108 * 109 * \verbatim im.ImageDestroy(image: imImage) [in Lua 5] \endverbatim 110 * \verbatim image:Destroy() [in Lua 5] \endverbatim 111 * \ingroup imgclass */ 112 void imImageDestroy(imImage* image); 113 114 /** Adds an alpha channel plane and sets its value to 0 (transparent). 115 * 116 * \verbatim image:AddAlpha() [in Lua 5] \endverbatim 117 * \ingroup imgclass */ 118 void imImageAddAlpha(imImage* image); 119 120 /** Sets the alpha channel plane to a constant. 121 * 122 * \verbatim image:SetAlpha(alpha: number) [in Lua 5] \endverbatim 123 * \ingroup imgclass */ 124 void imImageSetAlpha(imImage* image, float alpha); 125 126 /** Removes the alpha channel plane if any. 127 * 128 * \verbatim image:RemoveAlpha() [in Lua 5] \endverbatim 129 * \ingroup imgclass */ 130 void imImageRemoveAlpha(imImage* image); 131 132 /** Changes the buffer size. Reallocate internal buffers if the new size is larger than the original. 133 * 134 * \verbatim image:Reshape(width: number, height: number) [in Lua 5] \endverbatim 135 * \ingroup imgclass */ 136 void imImageReshape(imImage* image, int width, int height); 137 138 /** Copy image data and attributes from one image to another. \n 139 * Images must have the same size and type. 140 * 141 * \verbatim image:Copy(dst_image: imImage) [in Lua 5] \endverbatim 142 * \ingroup imgclass */ 143 void imImageCopy(const(imImage)* src_image, imImage* dst_image); 144 145 /** Copy image data only fom one image to another. \n 146 * Images must have the same size and type. 147 * 148 * \verbatim image:CopyData(dst_image: imImage) [in Lua 5] \endverbatim 149 * \ingroup imgclass */ 150 void imImageCopyData(const(imImage)* src_image, imImage* dst_image); 151 152 /** Copies the image attributes from src to dst. 153 * Includes the pallete if defined in both images. 154 * 155 * \verbatim image:CopyAttributes(dst_image: imImage) [in Lua 5] \endverbatim 156 * \ingroup imgclass */ 157 void imImageCopyAttributes(const(imImage)* src_image, imImage* dst_image); 158 159 /** Merges the image attributes from src to dst. \n 160 * Attributes that exist in dst are not replaced. 161 * Doens NOT include the pallete. 162 * 163 * \verbatim image:MergeAttributes(dst_image: imImage) [in Lua 5] \endverbatim 164 * \ingroup imgclass */ 165 void imImageMergeAttributes(const(imImage)* src_image, imImage* dst_image); 166 167 /** Copy one image plane fom one image to another. \n 168 * Images must have the same size and type. 169 * 170 * \verbatim image:CopyPlane(src_plane: number, dst_image: imImage, dst_plane: number) [in Lua 5] \endverbatim 171 * \ingroup imgclass */ 172 void imImageCopyPlane(const(imImage)* src_image, int src_plane, imImage* dst_image, int dst_plane); 173 174 /** Creates a copy of the image. 175 * 176 * \verbatim image:Duplicate() -> new_image: imImage [in Lua 5] \endverbatim 177 * \ingroup imgclass */ 178 imImage* imImageDuplicate(const(imImage)* image); 179 180 /** Creates a clone of the image. i.e. same attributes but ignore contents. 181 * 182 * \verbatim image:Clone() -> new_image: imImage [in Lua 5] \endverbatim 183 * \ingroup imgclass */ 184 imImage* imImageClone(const(imImage)* image); 185 186 /** Changes an extended attribute. \n 187 * The data will be internally duplicated. \n 188 * If data is NULL and count==0 the attribute is removed. \n 189 * If count is -1 and data_type is IM_BYTE then data is zero terminated. 190 * See also \ref imDataType. 191 * 192 * \verbatim image:SetAttribute(attrib: string, data_type: number, data: table of numbers or string) [in Lua 5] \endverbatim 193 * If data_type is IM_BYTE, a string can be used as data. 194 * \ingroup imgclass */ 195 void imImageSetAttribute(const(imImage)* image, const(char)* attrib, int data_type, int count, const(void)* data); 196 197 /** Changes an extended attribute as an integer. 198 * 199 * \verbatim image:SetAttribInteger(attrib: string, data_type: number, value: number) [in Lua 5] \endverbatim 200 * \ingroup imgclass */ 201 void imImageSetAttribInteger(const(imImage)* image, const(char)* attrib, int data_type, int value); 202 203 /** Changes an extended attribute as a real. 204 * 205 * \verbatim image:SetAttribReal(attrib: string, data_type: number, value: number) [in Lua 5] \endverbatim 206 * \ingroup imgclass */ 207 void imImageSetAttribReal(const(imImage)* image, const(char)* attrib, int data_type, double value); 208 209 /** Changes an extended attribute as a string. 210 * 211 * \verbatim image:SetAttribString(attrib: string, value: string) [in Lua 5] \endverbatim 212 * \ingroup imgclass */ 213 void imImageSetAttribString(const(imImage)* image, const(char)* attrib, const(char)* value); 214 215 /** Returns an extended attribute. \n 216 * Returns NULL if not found. 217 * See also \ref imDataType. 218 * 219 * \verbatim image:GetAttribute(attrib: string, [as_string: boolean]) -> data: table of numbers or string, data_type: number [in Lua 5] \endverbatim 220 * If data_type is IM_BYTE, as_string can be used to return a string instead of a table. 221 * \ingroup imgclass */ 222 const(void)* imImageGetAttribute(const(imImage)* image, const(char)* attrib, int* data_type, int* count); 223 224 /** Returns an extended attribute as an integer. 225 * 226 * \verbatim image:GetAttribInteger(attrib: string, [index: number]) -> value: number [in Lua 5] \endverbatim 227 * \ingroup imgclass */ 228 int imImageGetAttribInteger(const(imImage)* image, const(char)* attrib, int index); 229 230 /** Returns an extended attribute as a real. 231 * 232 * \verbatim image:GetAttribReal(attrib: string, [index: number]) -> value: number [in Lua 5] \endverbatim 233 * \ingroup imgclass */ 234 double imImageGetAttribReal(const(imImage)* image, const(char)* attrib, int index); 235 236 /** Returns an extended attribute as a string. 237 * 238 * \verbatim image:GetAttribString(attrib: string) -> value: string [in Lua 5] \endverbatim 239 * \ingroup imgclass */ 240 const(char)* imImageGetAttribString(const(imImage)* image, const(char)* attrib); 241 242 /** Returns a list of the attribute names. \n 243 * "attrib" must contain room enough for "attrib_count" names. Use "attrib=NULL" to return only the count. 244 * 245 * \verbatim image:GetAttributeList() -> data: table of strings [in Lua 5] \endverbatim 246 * \ingroup imgclass */ 247 void imImageGetAttributeList(const(imImage)* image, char** attrib, int* attrib_count); 248 249 /** Sets all image data to zero. But if color space is YCBCR, LAB or LUV, and data type is BYTE or USHORT, then 250 * data is initialized with 128 or 32768 accordingly. Alpha is initialized as transparent (0). 251 * 252 * \verbatim image:Clear() [in Lua 5] \endverbatim 253 * \ingroup imgclass */ 254 void imImageClear(imImage* image); 255 256 /** Indicates that the image can be viewed in common graphic devices. 257 * Data type must be IM_BYTE. Color mode can be IM_RGB, IM_MAP, IM_GRAY or IM_BINARY. 258 * 259 * \verbatim image:IsBitmap() -> is_bitmap: boolean [in Lua 5] \endverbatim 260 * \ingroup imgclass */ 261 int imImageIsBitmap(const(imImage)* image); 262 263 /** Changes the image palette. 264 * This will destroy the existing palette and replace it with the given palette pointer. 265 * Only the pointer is stored, so the palette should be a new palette and it can not be a static array. 266 * 267 * \verbatim image:SetPalette(palette: imPalette) [in Lua 5] \endverbatim 268 * \ingroup imgclass */ 269 void imImageSetPalette(imImage* image, c_long* palette, int palette_count); 270 271 /** Returns 1 if the images match width and height. Returns 0 otherwise. 272 * 273 * \verbatim image:MatchSize(image2: imImage) -> match: boolean [in Lua 5] \endverbatim 274 * \ingroup imgclass */ 275 int imImageMatchSize(const(imImage)* image1, const(imImage)* image2); 276 277 /** Returns 1 if the images match color mode and data type. Returns 0 otherwise. 278 * 279 * \verbatim image:MatchColor(image2: imImage) -> match: boolean [in Lua 5] \endverbatim 280 * \ingroup imgclass */ 281 int imImageMatchColor(const(imImage)* image1, const(imImage)* image2); 282 283 /** Returns 1 if the images match width, height and data type. Returns 0 otherwise. 284 * 285 * \verbatim image:MatchDataType(image2: imImage) -> match: boolean [in Lua 5] \endverbatim 286 * \ingroup imgclass */ 287 int imImageMatchDataType(const(imImage)* image1, const(imImage)* image2); 288 289 /** Returns 1 if the images match width, height and color space. Returns 0 otherwise. 290 * 291 * \verbatim image:MatchColorSpace(image2: imImage) -> match: boolean [in Lua 5] \endverbatim 292 * \ingroup imgclass */ 293 int imImageMatchColorSpace(const(imImage)* image1, const(imImage)* image2); 294 295 /** Returns 1 if the images match in width, height, data type and color space. Returns 0 otherwise. 296 * 297 * \verbatim image:Match(image2: imImage) -> match: boolean [in Lua 5] \endverbatim 298 * \ingroup imgclass */ 299 int imImageMatch(const(imImage)* image1, const(imImage)* image2); 300 301 /** Changes the image color space to map 302 * by just changing color_space. \n 303 * Image must be BINARY or GRAY/BYTE. 304 * 305 * \verbatim image:SetMap() [in Lua 5] \endverbatim 306 * \ingroup imgclass */ 307 void imImageSetMap(imImage* image); 308 309 /** Changes the image color space to binary 310 * by just changing color_space and the palette. 311 * Image must be MAP or GRAY/BYTE. 312 * 313 * \verbatim image:SetBinary() [in Lua 5] \endverbatim 314 * \ingroup imgclass */ 315 void imImageSetBinary(imImage* image); 316 317 /** Changes the image color space to gray 318 * by just changing color_space and the palette. 319 * Image must be BINARY or MAP. Palette is changed only if image was BINARY. 320 * 321 * \verbatim image:SetGray() [in Lua 5] \endverbatim 322 * \ingroup imgclass */ 323 void imImageSetGray(imImage* image); 324 325 /** Changes a gray BYTE data (0,255) into a binary data (0,1), done in-place. 326 * Color space is not changed. Data type must be IM_BYTE. 327 * 328 * \verbatim image:MakeBinary() [in Lua 5] \endverbatim 329 * \ingroup imgclass */ 330 void imImageMakeBinary(imImage* image); 331 332 /** Changes a binary data (0,1) into a gray BYTE data (0,255), done in-place. 333 * Color space is not changed. Data type must be IM_BYTE. 334 * 335 * \verbatim image:MakeGray() [in Lua 5] \endverbatim 336 * \ingroup imgclass */ 337 void imImageMakeGray(imImage* image); 338 339 340 341 /** \defgroup imgfile imImage Storage 342 * 343 * \par 344 * Functions to simplify the process of reading and writting imImage structures. 345 * Will also load and save the alpha planes when possible. 346 * \par 347 * See \ref im_image.h 348 * \ingroup file */ 349 350 351 /** Loads an image from an already open file. Returns NULL if failed. \n 352 * This will call \ref imFileReadImageInfo and \ref imFileReadImageData. \n 353 * index specifies the image number between 0 and image_count-1. \n 354 * The returned image will be of the same color_space and data_type of the image in the file. \n 355 * Attributes from the file will be stored at the image. 356 * See also \ref imErrorCodes. 357 * 358 * \verbatim ifile:LoadImage([index: number]) -> image: imImage, error: number [in Lua 5] \endverbatim 359 * Default index is 0. 360 * \ingroup imgfile */ 361 imImage* imFileLoadImage(imFile* ifile, int index, int* error); 362 363 /** Loads an image from an already open file. Returns NULL if failed. \n 364 * This function assumes that the image in the file has the same parameters as the given image. \n 365 * This will call \ref imFileReadImageInfo and \ref imFileReadImageData. \n 366 * index specifies the image number between 0 and image_count-1. \n 367 * The returned image will be of the same color_space and data_type of the image in the file. \n 368 * Attributes from the file will be stored at the image. 369 * See also \ref imErrorCodes. 370 * 371 * \verbatim ifile:LoadImageFrame(index: number, image: imImage) -> error: number [in Lua 5] \endverbatim 372 * Default index is 0. 373 * \ingroup imgfile */ 374 void imFileLoadImageFrame(imFile* ifile, int index, imImage* image, int* error); 375 376 /** Loads an image from an already open file, but forces the image to be a bitmap.\n 377 * The returned imagem will be always a Bitmap image, with color_space RGB, MAP, GRAY or BINARY, and data_type IM_BYTE. \n 378 * index specifies the image number between 0 and image_count-1. \n 379 * Returns NULL if failed. 380 * Attributes from the file will be stored at the image. 381 * See also \ref imErrorCodes. 382 * 383 * \verbatim ifile:LoadBitmap([index: number]) -> image: imImage, error: number [in Lua 5] \endverbatim 384 * Default index is 0. 385 * \ingroup imgfile */ 386 imImage* imFileLoadBitmap(imFile* ifile, int index, int* error); 387 388 /** Loads an image region from an already open file. Returns NULL if failed. \n 389 * This will call \ref imFileReadImageInfo and \ref imFileReadImageData. \n 390 * index specifies the image number between 0 and image_count-1. \n 391 * The returned image will be of the same color_space and data_type of the image in the file, 392 * or will be a Bitmap image. \n 393 * Attributes from the file will be stored at the image. 394 * See also \ref imErrorCodes. \n 395 * For now, it works only for the ECW file format. 396 * 397 * \verbatim ifile:LoadRegion(index, bitmap, xmin, xmax, ymin, ymax, width, height: number) -> image: imImage, error: number [in Lua 5] \endverbatim 398 * Default index is 0. 399 * \ingroup imgfile */ 400 imImage* imFileLoadImageRegion(imFile* ifile, int index, int bitmap, int* error, 401 int xmin, int xmax, int ymin, int ymax, int width, int height); 402 403 /** Loads an image from an already open file, but forces the image to be a bitmap.\n 404 * This function assumes that the image in the file has the same parameters as the given image. \n 405 * The imagem must be a Bitmap image, with color_space RGB, MAP, GRAY or BINARY, and data_type IM_BYTE. \n 406 * index specifies the image number between 0 and image_count-1. \n 407 * Returns NULL if failed. 408 * Attributes from the file will be stored at the image. 409 * See also \ref imErrorCodes. 410 * 411 * \verbatim ifile:LoadBitmapFrame(index: number, image: imImage) -> error: number [in Lua 5] \endverbatim 412 * Default index is 0. 413 * \ingroup imgfile */ 414 void imFileLoadBitmapFrame(imFile* ifile, int index, imImage* image, int* error); 415 416 /** Saves the image to an already open file. \n 417 * This will call \ref imFileWriteImageInfo and \ref imFileWriteImageData. \n 418 * Attributes from the image will be stored at the file. 419 * Returns error code. 420 * 421 * \verbatim ifile:SaveImage(image: imImage) -> error: number [in Lua 5] \endverbatim 422 * \ingroup imgfile */ 423 int imFileSaveImage(imFile* ifile, const(imImage)* image); 424 425 /** Loads an image from file. Open, loads and closes the file. \n 426 * index specifies the image number between 0 and image_count-1. \n 427 * Returns NULL if failed. 428 * Attributes from the file will be stored at the image. 429 * See also \ref imErrorCodes. 430 * 431 * \verbatim im.FileImageLoad(file_name: string, [index: number]) -> image: imImage, error: number [in Lua 5] \endverbatim 432 * Default index is 0. 433 * \ingroup imgfile */ 434 imImage* imFileImageLoad(const(char)* file_name, int index, int* error); 435 436 /** Loads an image from file, but forces the image to be a bitmap. Open, loads and closes the file. \n 437 * index specifies the image number between 0 and image_count-1. \n 438 * Returns NULL if failed. 439 * Attributes from the file will be stored at the image. 440 * See also \ref imErrorCodes. 441 * 442 * \verbatim im.FileImageLoadBitmap(file_name: string, [index: number]) -> image: imImage, error: number [in Lua 5] \endverbatim 443 * Default index is 0. 444 * \ingroup imgfile */ 445 imImage* imFileImageLoadBitmap(const(char)* file_name, int index, int* error); 446 447 /** Loads an image region from file. Open, loads and closes the file. \n 448 * index specifies the image number between 0 and image_count-1. \n 449 * Returns NULL if failed. 450 * Attributes from the file will be stored at the image. 451 * See also \ref imErrorCodes. \n 452 * For now, it works only for the ECW file format. 453 * 454 * \verbatim im.FileImageLoadRegion(file_name: string, index, bitmap, xmin, xmax, ymin, ymax, width, height: number, ) -> image: imImage, error: number [in Lua 5] \endverbatim 455 * Default index is 0. 456 * \ingroup imgfile */ 457 imImage* imFileImageLoadRegion(const(char)* file_name, int index, int bitmap, int* error, 458 int xmin, int xmax, int ymin, int ymax, int width, int height); 459 460 /** Saves the image to file. Open, saves and closes the file. \n 461 * Returns error code. \n 462 * Attributes from the image will be stored at the file. 463 * 464 * \verbatim im.FileImageSave(file_name: string, format: string, image: imImage) -> error: number [in Lua 5] \endverbatim 465 * \verbatim image:Save(file_name: string, format: string) -> error: number [in Lua 5] \endverbatim 466 * \ingroup imgfile */ 467 int imFileImageSave(const(char)* file_name, const(char)* format, const(imImage)* image); 468 469 } // extern(C) 470 471 version(CD) { 472 import cd.cd : cdCanvas, cdCanvasPutImageRectRGB, cdCanvasPutImageRectRGBA, cdCanvasPutImageRectMap; 473 474 /** Utility macro to draw the image in a CD library canvas. 475 * Works only for data_type IM_BYTE, and color spaces: IM_RGB, IM_MAP, IMGRAY and IM_BINARY. 476 * \ingroup imgclass */ // C origin was a #define : doesn't need to have C-linkage 477 void imcdCanvasPutImage(cdCanvas* _canvas, imImage* _image, int _x, int _y, int _w, int _h, int _xmin, int _xmax, int _ymin, int _ymax) 478 { 479 if (_image.color_space == IM_RGB) 480 { 481 if (_image.has_alpha) 482 cdCanvasPutImageRectRGBA(_canvas, _image.width, _image.height, 483 cast(ubyte*)_image.data[0], 484 cast(ubyte*)_image.data[1], 485 cast(ubyte*)_image.data[2], 486 cast(ubyte*)_image.data[3], 487 _x, _y, _w, _h, _xmin, _xmax, _ymin, _ymax); 488 else 489 cdCanvasPutImageRectRGB(_canvas, _image.width, _image.height, 490 cast(ubyte*)_image.data[0], 491 cast(ubyte*)_image.data[1], 492 cast(ubyte*)_image.data[2], 493 _x, _y, _w, _h, _xmin, _xmax, _ymin, _ymax); 494 } 495 else 496 cdCanvasPutImageRectMap(_canvas, _image.width, _image.height, 497 cast(ubyte*)_image.data[0], _image.palette, 498 _x, _y, _w, _h, _xmin, _xmax, _ymin, _ymax); 499 } 500 501 } // version(CD)