1 /** 2 * A class to expose ImageInfo QuantizeInfo and DrawInfo 3 * 4 * Copyright: Mike Wey 2011 5 * License: zlib (See accompanying LICENSE file) 6 * Authors: Mike Wey 7 */ 8 9 module dmagick.Options; 10 11 import std.conv; 12 import std.math; 13 import std..string; 14 import core.stdc.stdio; 15 import core.stdc..string; 16 17 import dmagick.Color; 18 import dmagick.Geometry; 19 import dmagick.Image; 20 import dmagick.Utils; 21 22 import dmagick.c.cacheView; 23 import dmagick.c.colorspace; 24 import dmagick.c.compress; 25 import dmagick.c.draw; 26 import dmagick.c.geometry; 27 import dmagick.c.image; 28 import dmagick.c.list; 29 import dmagick.c.magickType; 30 import dmagick.c.memory; 31 import dmagick.c.option; 32 import dmagick.c.quantize; 33 import dmagick.c.quantum; 34 import dmagick.c.type; 35 36 /// See_Also: $(CXREF quantize, _DitherMethod) 37 public alias dmagick.c.quantize.DitherMethod DitherMethod; 38 39 //These symbols are publicly imported by dmagick.Image. 40 private alias dmagick.c.geometry.AffineMatrix AffineMatrix; 41 private alias dmagick.c.colorspace.ColorspaceType ColorspaceType; 42 private alias dmagick.c.compress.CompressionType CompressionType; 43 private alias dmagick.c.quantum.EndianType EndianType; 44 private alias dmagick.c.image.ImageType ImageType; 45 private alias dmagick.c.image.InterlaceType InterlaceType; 46 private alias dmagick.c.image.ResolutionType ResolutionType; 47 private alias dmagick.c.cacheView.VirtualPixelMethod VirtualPixelMethod; 48 49 /** 50 * A class that wraps ImageInfo, DrawInfo and QuantizeInfo 51 */ 52 class Options 53 { 54 ImageInfo* imageInfo; 55 QuantizeInfo* quantizeInfo; 56 DrawInfo* drawInfo; 57 58 this() 59 { 60 imageInfo = cast(ImageInfo*)AcquireMagickMemory(ImageInfo.sizeof); 61 quantizeInfo = cast(QuantizeInfo*)AcquireMagickMemory(QuantizeInfo.sizeof); 62 drawInfo = cast(DrawInfo*)AcquireMagickMemory(DrawInfo.sizeof); 63 64 //Initialize with defaults. 65 GetImageInfo(imageInfo); 66 GetDrawInfo(imageInfo, drawInfo); 67 GetQuantizeInfo(quantizeInfo); 68 69 //In D strings are UTF encoded. 70 textEncoding("UTF-8"); 71 } 72 73 this(const(ImageInfo)* imageInfo, const(QuantizeInfo)* quantizeInfo, const(DrawInfo)* drawInfo) 74 { 75 this.imageInfo = CloneImageInfo(imageInfo); 76 this.quantizeInfo = CloneQuantizeInfo(quantizeInfo); 77 this.drawInfo = CloneDrawInfo(imageInfo, drawInfo); 78 } 79 80 ~this() 81 { 82 imageInfo = DestroyImageInfo(imageInfo); 83 quantizeInfo = DestroyQuantizeInfo(quantizeInfo); 84 drawInfo = DestroyDrawInfo(drawInfo); 85 } 86 87 Options clone() const 88 { 89 return new Options(imageInfo, quantizeInfo, drawInfo); 90 } 91 92 /+*************************************************************** 93 * ImageInfo fields 94 ***************************************************************+/ 95 96 /** 97 * Join images into a single multi-image file. 98 */ 99 void adjoin(bool flag) 100 { 101 imageInfo.adjoin = flag; 102 } 103 ///ditto 104 bool adjoin() const 105 { 106 return imageInfo.adjoin == 1; 107 } 108 109 /** 110 * Set the image background color. The default is "white". 111 */ 112 void backgroundColor(string color) 113 { 114 backgroundColor = new Color(color); 115 } 116 ///ditto 117 void backgroundColor(Color color) 118 { 119 imageInfo.background_color = color.pixelPacket; 120 } 121 ///ditto 122 Color backgroundColor() const 123 { 124 return new Color(imageInfo.background_color); 125 } 126 127 /** 128 * Set a texture to tile onto the image background. 129 * Corresponds to the -texture option to ImageMagick's 130 * convert and mogrify commands. 131 */ 132 void backgroundTexture(string str) 133 { 134 copyString(imageInfo.texture, str); 135 } 136 ///ditto 137 string backgroundTexture() const 138 { 139 return to!(string)(imageInfo.texture); 140 } 141 142 /** 143 * Set the image border color. The default is "#dfdfdf". 144 */ 145 void borderColor(string color) 146 { 147 borderColor = new Color(color); 148 } 149 ///ditto 150 void borderColor(Color color) 151 { 152 imageInfo.border_color = color.pixelPacket; 153 drawInfo.border_color = color.pixelPacket; 154 } 155 ///ditto 156 Color borderColor() const 157 { 158 return new Color(imageInfo.border_color); 159 } 160 161 /** 162 * Specifies the image pixel interpretation. 163 */ 164 void colorspace(ColorspaceType space) 165 { 166 imageInfo.colorspace = space; 167 } 168 ///ditto 169 ColorspaceType colorspace() const 170 { 171 return imageInfo.colorspace; 172 } 173 174 /** 175 * Specifies the type of _compression used when writing the image. 176 * Only some image formats support _compression. For those that do, 177 * only some _compression types are supported. If you specify an 178 * _compression type that is not supported, the default _compression 179 * type (usually NoCompression) is used instead. 180 */ 181 void compression(CompressionType compress) 182 { 183 imageInfo.compression = compress; 184 } 185 ///ditto 186 CompressionType compression() const 187 { 188 return imageInfo.compression; 189 } 190 191 //void ddebug(bool d) 192 //{ 193 // 194 //} 195 //ditto 196 //bool ddebug() 197 //{ 198 // 199 //} 200 201 /** 202 * Define an option. Use this method to set options for 203 * reading or writing certain image formats. The list of 204 * supported options changes from release to release. 205 * For a list of the valid image formats, keys, and values, 206 * refer to the documentation for the -define option for the 207 * release of ImageMagick installed on your system. 208 * Params: 209 * format = An image format name such as "ps" or "tiff". 210 * key = A string that identifies the option. 211 * vaule = The value of the option. 212 */ 213 void define(string format, string key, string value = "") 214 { 215 string option = format ~":"~ key ~ "\0"; 216 217 SetImageOption(imageInfo, option.ptr, toStringz(value)); 218 } 219 220 //TODO: opindex / opiindexassign for the options. 221 222 /** 223 * Delete an option definition set by define. 224 * This is not the same as setting the option to a null value. 225 * The undefine method removes the option name from the list 226 * of options for the specified format. 227 * format = An image format name such as "ps" or "tiff". 228 * key = A string that identifies the option. 229 */ 230 void undefine(string format, string key) 231 { 232 string option = format ~":"~ key ~ "\0"; 233 234 DeleteImageOption(imageInfo, option.ptr); 235 } 236 237 /** 238 * Specifies the vertical and horizontal resolution in pixels. 239 * The default _density is "72.0x72.0". This attribute can be used 240 * when writing JBIG, PCL, PS, PS2, and PS3 format images. 241 * 242 * This attribute can also be used to specify the width and height 243 * of HISTOGRAM format images. For HISTOGRAM, the default is 256x200. 244 */ 245 void density(string str) 246 { 247 copyString(imageInfo.density, str); 248 } 249 ///ditto 250 void density(Geometry geometry) 251 { 252 density(geometry.toString()); 253 } 254 ///ditto 255 Geometry density() const 256 { 257 return Geometry( to!(string)(imageInfo.density) ); 258 } 259 260 /** 261 * Specifies the image _depth 262 * 263 * Either 8, 16, or 32. You can specify 16 and 32 264 * only when ImageMagick was compiled with a QuantumDepth 265 * that allows these _depth values. 266 */ 267 void depth(size_t d) 268 { 269 imageInfo.depth = d; 270 } 271 ///ditto 272 size_t depth() const 273 { 274 return imageInfo.depth; 275 } 276 277 /** 278 * This attribute can be used when writing GIF images. 279 * 280 * Apply Floyd/Steinberg error diffusion to the image. 281 * The basic strategy of dithering is to trade intensity 282 * resolution for spatial resolution by averaging the intensities 283 * of several neighboring pixels. Images which suffer from severe 284 * contouring when reducing colors can be improved with this option. 285 */ 286 void dither(bool d) 287 { 288 imageInfo.dither = d; 289 quantizeInfo.dither = d; 290 } 291 ///ditto 292 size_t dither() const 293 { 294 return imageInfo.dither; 295 } 296 297 /** 298 * Specify the endianess of the image when reading the image file. 299 */ 300 void endian(EndianType type) 301 { 302 imageInfo.endian = type; 303 } 304 ///ditto 305 EndianType endian() const 306 { 307 return imageInfo.endian; 308 } 309 310 /** 311 * Image _file descriptor. 312 */ 313 void file(FILE* f) 314 { 315 imageInfo.file = f; 316 } 317 ///ditto 318 FILE* file() 319 { 320 return imageInfo.file; 321 } 322 323 /** 324 * Image _filename/path. 325 */ 326 void filename(string str) 327 { 328 copyString(imageInfo.filename, str); 329 } 330 ///ditto 331 string filename() const 332 { 333 return imageInfo.filename[0 .. strlen(imageInfo.filename.ptr)].idup; 334 } 335 336 /** 337 * The _font name or filename. 338 * You can tag a _font to specify whether it is a Postscript, 339 * Truetype, or OPTION1 _font. For example, Arial.ttf is a 340 * Truetype _font, ps:helvetica is Postscript, and x:fixed is OPTION1. 341 * 342 * The _font name can be a complete filename such as 343 * "/mnt/windows/windows/fonts/Arial.ttf". The _font name can 344 * also be a fully qualified X font name such as 345 * "-urw-times-medium-i-normal--0-0-0-0-p-0-iso8859-13". 346 */ 347 void font(string str) 348 { 349 copyString(imageInfo.font, str); 350 copyString(drawInfo.font, str); 351 } 352 ///ditto 353 string font() const 354 { 355 return to!(string)(drawInfo.font); 356 } 357 358 /** 359 * Text rendering font point size 360 */ 361 void fontSize(double size) 362 { 363 imageInfo.pointsize = size; 364 drawInfo.pointsize = size; 365 } 366 ///ditto 367 double fontSize() const 368 { 369 return drawInfo.pointsize; 370 } 371 372 /** 373 * Colors within this distance are considered equal. 374 * A number of algorithms search for a target color. 375 * By default the color must be exact. Use this option to match 376 * colors that are close to the target color in RGB space. 377 */ 378 void fuzz(double f) 379 { 380 imageInfo.fuzz = f; 381 } 382 ///ditto 383 double fuzz() const 384 { 385 return imageInfo.fuzz; 386 } 387 388 /** 389 * Specify the _type of interlacing scheme for raw image formats 390 * such as RGB or YUV. NoInterlace means do not _interlace, 391 * LineInterlace uses scanline interlacing, and PlaneInterlace 392 * uses plane interlacing. PartitionInterlace is like PlaneInterlace 393 * except the different planes are saved to individual files 394 * (e.g. image.R, image.G, and image.B). Use LineInterlace or 395 * PlaneInterlace to create an interlaced GIF or 396 * progressive JPEG image. The default is NoInterlace. 397 */ 398 void interlace(InterlaceType type) 399 { 400 imageInfo.interlace = type; 401 } 402 ///ditto 403 InterlaceType interlace() const 404 { 405 return imageInfo.interlace; 406 } 407 408 /** 409 * Image format (e.g. "GIF") 410 */ 411 void magick(string str) 412 { 413 copyString(imageInfo.magick, str); 414 } 415 ///ditto 416 string magick() const 417 { 418 return imageInfo.magick[0 .. strlen(imageInfo.magick.ptr)].idup; 419 } 420 421 /** 422 * Set the image transparent color. The default is "#bdbdbd". 423 */ 424 void matteColor(string color) 425 { 426 matteColor = new Color(color); 427 } 428 ///ditto 429 void matteColor(Color color) 430 { 431 imageInfo.matte_color = color.pixelPacket; 432 } 433 ///ditto 434 Color matteColor() const 435 { 436 return new Color(imageInfo.matte_color); 437 } 438 439 /** 440 * Transform the image to black and white on input. 441 * Only the EPT, PDF, and PS formats respect this attribute. 442 */ 443 void monochrome(bool m) 444 { 445 imageInfo.monochrome = m; 446 } 447 ///ditto 448 bool monochrome() const 449 { 450 return imageInfo.monochrome == 1; 451 } 452 453 /** 454 * Use this option to specify the dimensions and position 455 * of the Postscript _page in dots per inch or in pixels. 456 * This option is typically used in concert with density. 457 * 458 * Page may also be used to position a GIF image 459 * (such as for a scene in an animation) 460 * The default is "612x792" 461 */ 462 void page(string str) 463 { 464 copyString(imageInfo.page, str); 465 } 466 ///ditto 467 void page(Geometry geometry) 468 { 469 page(geometry.toString()); 470 } 471 ///ditto 472 Geometry page() const 473 { 474 return Geometry( to!(string)(imageInfo.page) ); 475 } 476 477 /** 478 * The compression level for JPEG, MPEG, JPEG-2000, 479 * MIFF, MNG, and PNG image format. 480 * The default is 75 481 */ 482 void quality(size_t q) 483 { 484 imageInfo.quality = q; 485 } 486 ///ditto 487 size_t quality() const 488 { 489 return imageInfo.quality; 490 } 491 492 /** 493 * Units of image resolution. 494 */ 495 void resolutionUnits(ResolutionType type) 496 { 497 imageInfo.units = type; 498 } 499 ///ditto 500 ResolutionType resolutionUnits() const 501 { 502 return imageInfo.units; 503 } 504 505 /** 506 * sampling factors used by JPEG or MPEG-2 encoder and 507 * YUV decoder/encoder. 508 * 509 * This attribute specifies the sampling factors to be used 510 * by the JPEG encoder for chroma downsampling. 511 * If this attribute is omitted, the JPEG library will use its 512 * own default values. When reading or writing the YUV format and 513 * when writing the M2V (MPEG-2) format, use sampling-factor="2x1" 514 * to specify the 4:2:2 downsampling method. 515 */ 516 void samplingFactor(string str) 517 { 518 copyString(imageInfo.sampling_factor, str); 519 } 520 ///ditto 521 string samplingFactor() const 522 { 523 return to!(string)(imageInfo.sampling_factor); 524 } 525 526 /** 527 * Set the width and height of the image when reading a 528 * built-in image format that does not have an inherent _size, 529 * or when reading an image from a multi-resolution file format 530 * such as Photo CD, JBIG, or JPEG. 531 */ 532 void size(string str) 533 { 534 copyString(imageInfo.size, str); 535 } 536 ///ditto 537 void size(Geometry geometry) 538 { 539 size(geometry.toString()); 540 } 541 ///ditto 542 Geometry size() const 543 { 544 return Geometry( to!(string)(imageInfo.size) ); 545 } 546 547 /** 548 * Subimage of an image sequence 549 */ 550 void subImage(size_t num) 551 { 552 imageInfo.scene = num; 553 } 554 ///ditto 555 size_t subImage() const 556 { 557 return imageInfo.scene; 558 } 559 560 /** 561 * Number of images relative to the base image 562 */ 563 void subRange(size_t num) 564 { 565 imageInfo.number_scenes = num; 566 } 567 ///ditto 568 size_t subRange() const 569 { 570 return imageInfo.number_scenes; 571 } 572 573 /** 574 * Image _type. 575 */ 576 void type(ImageType t) 577 { 578 imageInfo.type = t; 579 } 580 ///ditto 581 ImageType type() const 582 { 583 return imageInfo.type; 584 } 585 586 /** 587 * Print detailed information about the image. 588 */ 589 void verbose(bool v) 590 { 591 imageInfo.verbose = v; 592 } 593 ///ditto 594 bool verbose() const 595 { 596 return imageInfo.verbose == 1; 597 } 598 599 /** 600 * FlashPix viewing parameters. 601 */ 602 void view(string str) 603 { 604 copyString(imageInfo.view, str); 605 } 606 ///ditto 607 string view() const 608 { 609 return to!(string)(imageInfo.view); 610 } 611 612 /** 613 * Image virtual pixel _method. 614 */ 615 void virtualPixelMethod(VirtualPixelMethod method) 616 { 617 imageInfo.virtual_pixel_method = method; 618 } 619 ///ditto 620 VirtualPixelMethod virtualPixelMethod() const 621 { 622 return imageInfo.virtual_pixel_method; 623 } 624 625 /** 626 * X11 display to display to obtain fonts from or, to capture image from. 627 */ 628 void x11Display(string str) 629 { 630 copyString(imageInfo.server_name, str); 631 drawInfo.server_name = imageInfo.server_name; 632 } 633 ///ditto 634 string x11Display() const 635 { 636 return to!(string)(imageInfo.server_name); 637 } 638 639 //OrientationType orientation; 640 //MagickBooleanType temporary, 641 //MagickBooleanType affirm, 642 //MagickBooleanType antialias; 643 //char* extract, 644 //char* scenes; 645 //size_t colors; 646 //PreviewType preview_type; 647 //ssize_t group; 648 //MagickBooleanType ping, 649 //char* authenticate; 650 //ChannelType channel; 651 //void* options; 652 //MagickProgressMonitor progress_monitor; 653 //void* client_data, 654 //void* cache; 655 //StreamHandler stream; 656 //void* blob; 657 //size_t length; 658 //char[MaxTextExtent] unique, 659 //char[MaxTextExtent] zero, 660 //size_t signature; 661 //PixelPacket transparent_color; 662 //void* profile; 663 //MagickBooleanType synchronize; 664 665 /+*************************************************************** 666 * DrawInfo fields 667 ***************************************************************+/ 668 669 void affine(AffineMatrix affine) 670 { 671 drawInfo.affine = affine; 672 } 673 AffineMatrix affine() const 674 { 675 return drawInfo.affine; 676 } 677 678 /** 679 * Origin of coordinate system to use when annotating or drawing 680 */ 681 void transformOrigin (double tx, double ty) 682 { 683 AffineMatrix affine; 684 affine.sx = 1.0; 685 affine.rx = 0.0; 686 affine.ry = 0.0; 687 affine.sy = 1.0; 688 affine.tx = tx; 689 affine.ty = ty; 690 691 drawInfo.affine = multiplyMatrix(drawInfo.affine, affine); 692 } 693 694 /** 695 * Rotation to use when annotating or drawing 696 */ 697 void transformRotation(double angle) 698 { 699 AffineMatrix affine; 700 affine.sx = cos(degreesToRadians(angle % 360.0)); 701 affine.rx = sin(degreesToRadians(angle % 360.0)); 702 affine.ry = -affine.rx; 703 affine.sy = affine.sx; 704 affine.tx = 0.0; 705 affine.ty = 0.0; 706 707 drawInfo.affine = multiplyMatrix(drawInfo.affine, affine); 708 } 709 710 /** 711 * Scale to use when annotating or drawing 712 */ 713 void transformScale(double sx, double sy) 714 { 715 AffineMatrix affine; 716 affine.sx = sx; 717 affine.rx = 0.0; 718 affine.ry = 0.0; 719 affine.sy = sy; 720 affine.tx = 0.0; 721 affine.ty = 0.0; 722 723 drawInfo.affine = multiplyMatrix(drawInfo.affine, affine); 724 } 725 726 /** 727 * Shear to use in X axis when annotating or drawing 728 */ 729 void transformShearX(double skewx) 730 { 731 AffineMatrix affine; 732 affine.sx = 1.0; 733 affine.rx = 0.0; 734 affine.ry = tan(degreesToRadians(skewx % 360.0)); 735 affine.sy = 1.0; 736 affine.tx = 0.0; 737 affine.ty = 0.0; 738 739 drawInfo.affine = multiplyMatrix(drawInfo.affine, affine); 740 } 741 742 /** 743 * Shear to use in X axis when annotating or drawing 744 */ 745 void transformShearY(double skewy) 746 { 747 AffineMatrix affine; 748 affine.sx = 1.0; 749 affine.rx = tan(degreesToRadians(skewy % 360.0)); 750 affine.ry = 0.0; 751 affine.sy = 1.0; 752 affine.tx = 0.0; 753 affine.ty = 0.0; 754 755 drawInfo.affine = multiplyMatrix(drawInfo.affine, affine); 756 } 757 758 /** 759 * Reset transformation parameters to default 760 */ 761 void transformReset() 762 { 763 drawInfo.affine.sx = 1.0; 764 drawInfo.affine.rx = 0.0; 765 drawInfo.affine.ry = 0.0; 766 drawInfo.affine.sy = 1.0; 767 drawInfo.affine.tx = 0.0; 768 drawInfo.affine.ty = 0.0; 769 } 770 771 /** 772 * Returns the product of two Affine matrices 773 * The AffineMatrix looks like this: 774 * ----------- 775 * | sx rx 0 | 776 * | ry sy 0 | 777 * | tx ty 1 | 778 * ----------- 779 */ 780 AffineMatrix multiplyMatrix(AffineMatrix a, AffineMatrix b) 781 { 782 AffineMatrix result; 783 784 result.sx = a.sx * b.sx + a.rx * b.ry; 785 result.rx = a.sx * b.rx + a.rx * b.sy; 786 result.ry = a.ry * b.sx + a.sy * b.ry; 787 result.sy = a.ry * b.rx + a.sy * b.sy; 788 result.tx = a.tx * b.sx + a.ty * b.ry + b.tx; 789 result.ty = a.tx * b.rx + a.ty * b.sy + b.ty; 790 791 return result; 792 } 793 794 /** 795 * Control antialiasing of rendered Postscript 796 * and Postscript or TrueType fonts. The default is true. 797 */ 798 void antialias(bool antialias) 799 { 800 drawInfo.text_antialias = antialias; 801 } 802 ///ditto 803 bool antialias() const 804 { 805 return drawInfo.text_antialias == 1; 806 } 807 808 /** 809 * If set, causes the text to be drawn over a box of the specified color. 810 */ 811 void boxColor(string color) 812 { 813 boxColor = new Color(color); 814 } 815 ///ditto 816 void boxColor(Color color) 817 { 818 drawInfo.undercolor = color.pixelPacket; 819 } 820 ///ditto 821 Color boxColor() const 822 { 823 return new Color(drawInfo.undercolor); 824 } 825 826 /** 827 * Color to use when filling drawn objects. 828 * The default is "black". 829 */ 830 void fillColor(string color) 831 { 832 fillColor = new Color(color); 833 } 834 ///ditto 835 void fillColor(Color color) 836 { 837 drawInfo.fill = color.pixelPacket; 838 } 839 ///ditto 840 Color fillColor() const 841 { 842 return new Color(drawInfo.fill); 843 } 844 845 /** 846 * Pattern image to use when filling drawn objects. 847 */ 848 //TODO: investigate if we need to clone the image. 849 void fillPattern(dmagick.Image.Image pattern) 850 { 851 if (drawInfo.fill_pattern) 852 drawInfo.fill_pattern = DestroyImageList(drawInfo.fill_pattern); 853 854 drawInfo.fill_pattern = ReferenceImage(pattern.imageRef); 855 } 856 ///ditto 857 const(dmagick.Image.Image) fillPattern() const 858 { 859 return new dmagick.Image.Image(ReferenceImage((cast(DrawInfo*)drawInfo).fill_pattern)); 860 } 861 862 /** 863 * Rule to use when filling drawn objects. 864 */ 865 void fillRule(FillRule rule) 866 { 867 drawInfo.fill_rule = rule; 868 } 869 ///ditto 870 FillRule fillRule() const 871 { 872 return drawInfo.fill_rule; 873 } 874 875 /** 876 * Specify the font family, such as "arial" or "helvetica". 877 */ 878 void fontFamily(string type) 879 { 880 copyString(drawInfo.family, type); 881 } 882 ///ditto 883 string fontFamily() const 884 { 885 return to!(string)(drawInfo.family); 886 } 887 888 /** 889 * Specify the spacing between text characters. 890 */ 891 void fontStretch(StretchType type) 892 { 893 drawInfo.stretch = type; 894 } 895 ///ditto 896 StretchType fontStretch() const 897 { 898 return drawInfo.stretch; 899 } 900 901 /** 902 * Specify the font style, i.e. italic, oblique, or normal. 903 */ 904 void fontStyle(StyleType type) 905 { 906 drawInfo.style = type; 907 } 908 ///ditto 909 StyleType fontStyle() const 910 { 911 return drawInfo.style; 912 } 913 914 /** 915 * Specify the font weight. 916 */ 917 void fontWeight(size_t weight) 918 { 919 drawInfo.weight = type; 920 } 921 ///ditto 922 size_t fontWeight() const 923 { 924 return drawInfo.weight; 925 } 926 927 /** 928 * Enable or disable anti-aliasing when drawing object outlines. 929 */ 930 void strokeAntialias(bool antialias) 931 { 932 drawInfo.stroke_antialias = antialias; 933 } 934 ///ditto 935 bool strokeAntialias() const 936 { 937 return drawInfo.stroke_antialias == 1; 938 } 939 940 /** 941 * Color to use when drawing object outlines. 942 */ 943 void strokeColor(string color) 944 { 945 strokeColor = new Color(color); 946 } 947 ///ditto 948 void strokeColor(Color color) 949 { 950 drawInfo.stroke = color.pixelPacket; 951 } 952 ///ditto 953 Color strokeColor() const 954 { 955 return new Color(drawInfo.stroke); 956 } 957 958 /** 959 * The initial distance into the dash pattern. The units are pixels. 960 */ 961 void strokeDashOffset(double offset) 962 { 963 drawInfo.dash_offset = offset; 964 } 965 ///ditto 966 double strokeDashOffset() const 967 { 968 return drawInfo.dash_offset; 969 } 970 971 /** 972 * Describe a _pattern of dashes to be used when stroking paths. 973 * The arguments are a list of pixel widths of 974 * alternating dashes and gaps. 975 * All elements must be > 0. 976 */ 977 void strokeDashPattern(const(double)[] pattern) 978 { 979 if ( drawInfo.dash_pattern !is null ) 980 RelinquishMagickMemory(drawInfo.dash_pattern); 981 982 if ( pattern is null ) 983 return; 984 985 drawInfo.dash_pattern = cast(double*)AcquireMagickMemory((pattern.length+1) * double.sizeof); 986 drawInfo.dash_pattern[0 .. pattern.length] = pattern; 987 drawInfo.dash_pattern[pattern.length] = 0.0; 988 } 989 ///ditto 990 double[] strokeDashPattern() const 991 { 992 size_t x; 993 for (x = 0; drawInfo.dash_pattern[x] == 0.0; x++ ) {} 994 995 double[] pattern = new double[x]; 996 pattern[] = drawInfo.dash_pattern[0 .. x]; 997 998 return pattern; 999 } 1000 1001 /** 1002 * Specify how the line ends should be drawn. 1003 */ 1004 void strokeLineCap(LineCap cap) 1005 { 1006 drawInfo.linecap = cap; 1007 } 1008 ///ditto 1009 LineCap strokeLineCap() const 1010 { 1011 return drawInfo.linecap; 1012 } 1013 1014 /** 1015 * Specify how corners are drawn. 1016 */ 1017 void strokeLineJoin(LineJoin join) 1018 { 1019 drawInfo.linejoin = join; 1020 } 1021 ///ditto 1022 LineJoin lineJoin() const 1023 { 1024 return drawInfo.linejoin; 1025 } 1026 1027 /** 1028 * Specify a constraint on the length of the "miter" 1029 * formed by two lines meeting at an angle. If the angle 1030 * if very sharp, the miter could be very long relative 1031 * to the line thickness. The miter _limit is a _limit on 1032 * the ratio of the miter length to the line width. 1033 * The default is 4. 1034 */ 1035 void strokeMiterlimit(size_t limit) 1036 { 1037 drawInfo.miterlimit = limit; 1038 } 1039 ///ditto 1040 size_t strokeMiterlimit() const 1041 { 1042 return drawInfo.miterlimit; 1043 } 1044 1045 /** 1046 * Pattern image to use while drawing object stroke 1047 */ 1048 //TODO: investigate if we need to clone the image. 1049 void strokePattern(dmagick.Image.Image pattern) 1050 { 1051 if (drawInfo.stroke_pattern) 1052 drawInfo.stroke_pattern = DestroyImageList(drawInfo.stroke_pattern); 1053 1054 drawInfo.stroke_pattern = ReferenceImage(pattern.imageRef); 1055 } 1056 ///ditto 1057 const(dmagick.Image.Image) strokePattern() const 1058 { 1059 return new dmagick.Image.Image(ReferenceImage((cast(DrawInfo*)drawInfo).stroke_pattern)); 1060 } 1061 1062 /** 1063 * Stroke _width for use when drawing vector objects 1064 */ 1065 void strokeWidth(double width) 1066 { 1067 drawInfo.stroke_width = width; 1068 } 1069 ///ditto 1070 double strokeWidth() const 1071 { 1072 return drawInfo.stroke_width; 1073 } 1074 1075 /** 1076 * The text density in the x and y directions. The default is "72x72". 1077 */ 1078 void textDensity(string str) 1079 { 1080 copyString(imageInfo.density, str); 1081 } 1082 ///ditto 1083 void textDensity(Geometry geometry) 1084 { 1085 textDensity(geometry.toString); 1086 } 1087 ///ditto 1088 Geometry textDensity() const 1089 { 1090 return Geometry( to!(string)(imageInfo.density) ); 1091 } 1092 1093 /** 1094 * Specify the code set to use for text annotations. 1095 * The only character encoding which may be specified at 1096 * this time is "UTF-8" for representing Unicode as a 1097 * sequence of bytes. Specify an empty string to use 1098 * ASCII encoding. Successful text annotation using 1099 * Unicode may require fonts designed to support Unicode. 1100 * The default is "UTF-8" 1101 */ 1102 void textEncoding(string str) 1103 { 1104 copyString(drawInfo.encoding, str); 1105 } 1106 ///ditto 1107 string textEncoding() const 1108 { 1109 return to!(string)(drawInfo.encoding); 1110 } 1111 1112 //char* primitive, 1113 //char* geometry; 1114 //RectangleInfo viewbox; 1115 //GravityType gravity; 1116 //GradientInfo gradient; 1117 //MagickBooleanType tile, 1118 //DecorationType decorate; 1119 //CompositeOperator compose; 1120 //char* text; 1121 //size_t face; 1122 //char* metrics, 1123 //AlignType align; 1124 //char* clip_mask; 1125 //SegmentInfo bounds; 1126 //ClipPathUnits clip_units; 1127 //Quantum opacity; 1128 //MagickBooleanType render; 1129 //ElementReference element_reference; 1130 //MagickBooleanType ddebug; 1131 //size_t signature; 1132 //double kerning, 1133 //double interword_spacing, 1134 //double interline_spacing; 1135 //DirectionType direction; 1136 1137 /+*************************************************************** 1138 * QuantizeInfo fields 1139 ***************************************************************+/ 1140 1141 1142 /** 1143 * Preferred number of _colors in the image. 1144 * The actual number of _colors in the image may be less 1145 * than your request, but never more. Images with less 1146 * unique _colors than specified with this option will have 1147 * any duplicate or unused _colors removed. 1148 */ 1149 void quantizeColors(size_t colors) 1150 { 1151 quantizeInfo.number_colors = colors; 1152 } 1153 ///ditto 1154 size_t quantizeColors() const 1155 { 1156 return quantizeInfo.number_colors; 1157 } 1158 1159 /** 1160 * Colorspace to quantize colors in. 1161 * Empirical evidence suggests that distances in color spaces 1162 * such as YUV or YIQ correspond to perceptual color differences 1163 * more closely than do distances in RGB space. These color spaces 1164 * may give better results when color reducing an image. 1165 * The default is RGB 1166 */ 1167 void quantizeColorSpace(ColorspaceType type) 1168 { 1169 quantizeInfo.colorspace = type; 1170 } 1171 ///ditto 1172 ColorspaceType quantizeColorSpace() const 1173 { 1174 return quantizeInfo.colorspace; 1175 } 1176 1177 /** 1178 * The basic strategy of dithering is to trade intensity resolution for 1179 * spatial resolution by averaging the intensities of several neighboring 1180 * pixels. Images which suffer from severe contouring when reducing 1181 * colors can be improved with this option. 1182 */ 1183 void quantizeDitherMethod(DitherMethod method) 1184 { 1185 quantizeInfo.dither_method = method; 1186 } 1187 ///ditto 1188 DitherMethod quantizeDitherMethod() const 1189 { 1190 return quantizeInfo.dither_method; 1191 } 1192 1193 /** 1194 * Depth of the quantization color classification tree. 1195 * Values of 0 or 1 allow selection of the optimal tree _depth 1196 * for the color reduction algorithm. Values between 2 and 8 1197 * may be used to manually adjust the tree _depth. 1198 */ 1199 void quantizeTreeDepth(size_t depth) 1200 { 1201 quantizeInfo.tree_depth = depth; 1202 } 1203 ///ditto 1204 size_t quantizeTreeDepth() const 1205 { 1206 return quantizeInfo.tree_depth; 1207 } 1208 1209 //MagickBooleanType measure_error; 1210 //size_t signature; 1211 }