rmagick 1.7.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rmagick might be problematic. Click here for more details.

Files changed (239) hide show
  1. data/ChangeLog +232 -0
  2. data/Makefile.in +28 -0
  3. data/README.html +404 -0
  4. data/README.txt +397 -0
  5. data/configure +8554 -0
  6. data/configure.ac +497 -0
  7. data/doc/comtasks.html +241 -0
  8. data/doc/constants.html +1195 -0
  9. data/doc/css/doc.css +299 -0
  10. data/doc/css/popup.css +34 -0
  11. data/doc/draw.html +3108 -0
  12. data/doc/ex/Adispatch.rb +43 -0
  13. data/doc/ex/Zconstitute.rb +9 -0
  14. data/doc/ex/adaptive_threshold.rb +19 -0
  15. data/doc/ex/add_noise.rb +18 -0
  16. data/doc/ex/affine.rb +48 -0
  17. data/doc/ex/affine_transform.rb +20 -0
  18. data/doc/ex/arc.rb +47 -0
  19. data/doc/ex/arcpath.rb +33 -0
  20. data/doc/ex/average.rb +15 -0
  21. data/doc/ex/axes.rb +64 -0
  22. data/doc/ex/bilevel_channel.rb +20 -0
  23. data/doc/ex/blur_image.rb +12 -0
  24. data/doc/ex/border.rb +10 -0
  25. data/doc/ex/bounding_box.rb +48 -0
  26. data/doc/ex/cbezier1.rb +40 -0
  27. data/doc/ex/cbezier2.rb +40 -0
  28. data/doc/ex/cbezier3.rb +40 -0
  29. data/doc/ex/cbezier4.rb +41 -0
  30. data/doc/ex/cbezier5.rb +41 -0
  31. data/doc/ex/cbezier6.rb +51 -0
  32. data/doc/ex/channel.rb +26 -0
  33. data/doc/ex/channel_threshold.rb +48 -0
  34. data/doc/ex/charcoal.rb +12 -0
  35. data/doc/ex/chop.rb +29 -0
  36. data/doc/ex/circle.rb +31 -0
  37. data/doc/ex/clip_path.rb +56 -0
  38. data/doc/ex/coalesce.rb +60 -0
  39. data/doc/ex/color_fill_to_border.rb +29 -0
  40. data/doc/ex/color_floodfill.rb +28 -0
  41. data/doc/ex/color_histogram.rb +60 -0
  42. data/doc/ex/color_reset.rb +11 -0
  43. data/doc/ex/colorize.rb +16 -0
  44. data/doc/ex/colors.rb +65 -0
  45. data/doc/ex/composite.rb +135 -0
  46. data/doc/ex/contrast.rb +37 -0
  47. data/doc/ex/crop.rb +31 -0
  48. data/doc/ex/crop_with_gravity.rb +46 -0
  49. data/doc/ex/cycle_colormap.rb +21 -0
  50. data/doc/ex/demo.rb +324 -0
  51. data/doc/ex/drawcomp.rb +42 -0
  52. data/doc/ex/drop_shadow.rb +60 -0
  53. data/doc/ex/edge.rb +11 -0
  54. data/doc/ex/ellipse.rb +43 -0
  55. data/doc/ex/emboss.rb +11 -0
  56. data/doc/ex/enhance.rb +28 -0
  57. data/doc/ex/equalize.rb +11 -0
  58. data/doc/ex/flatten_images.rb +38 -0
  59. data/doc/ex/flip.rb +11 -0
  60. data/doc/ex/flop.rb +11 -0
  61. data/doc/ex/fonts.rb +20 -0
  62. data/doc/ex/frame.rb +12 -0
  63. data/doc/ex/gaussian_blur.rb +11 -0
  64. data/doc/ex/get_multiline_type_metrics.rb +53 -0
  65. data/doc/ex/get_pixels.rb +48 -0
  66. data/doc/ex/get_type_metrics.rb +140 -0
  67. data/doc/ex/gradientfill.rb +27 -0
  68. data/doc/ex/grav.rb +44 -0
  69. data/doc/ex/gravity.rb +80 -0
  70. data/doc/ex/hatchfill.rb +27 -0
  71. data/doc/ex/images/Ballerina.jpg +0 -0
  72. data/doc/ex/images/Ballerina3.jpg +0 -0
  73. data/doc/ex/images/Button_0.gif +0 -0
  74. data/doc/ex/images/Button_1.gif +0 -0
  75. data/doc/ex/images/Button_2.gif +0 -0
  76. data/doc/ex/images/Button_3.gif +0 -0
  77. data/doc/ex/images/Button_4.gif +0 -0
  78. data/doc/ex/images/Button_5.gif +0 -0
  79. data/doc/ex/images/Button_6.gif +0 -0
  80. data/doc/ex/images/Button_7.gif +0 -0
  81. data/doc/ex/images/Button_8.gif +0 -0
  82. data/doc/ex/images/Button_9.gif +0 -0
  83. data/doc/ex/images/Button_A.gif +0 -0
  84. data/doc/ex/images/Button_B.gif +0 -0
  85. data/doc/ex/images/Button_C.gif +0 -0
  86. data/doc/ex/images/Button_D.gif +0 -0
  87. data/doc/ex/images/Button_E.gif +0 -0
  88. data/doc/ex/images/Button_F.gif +0 -0
  89. data/doc/ex/images/Button_G.gif +0 -0
  90. data/doc/ex/images/Button_H.gif +0 -0
  91. data/doc/ex/images/Button_I.gif +0 -0
  92. data/doc/ex/images/Button_J.gif +0 -0
  93. data/doc/ex/images/Button_K.gif +0 -0
  94. data/doc/ex/images/Button_L.gif +0 -0
  95. data/doc/ex/images/Button_M.gif +0 -0
  96. data/doc/ex/images/Button_N.gif +0 -0
  97. data/doc/ex/images/Button_O.gif +0 -0
  98. data/doc/ex/images/Button_P.gif +0 -0
  99. data/doc/ex/images/Button_Q.gif +0 -0
  100. data/doc/ex/images/Button_R.gif +0 -0
  101. data/doc/ex/images/Button_S.gif +0 -0
  102. data/doc/ex/images/Button_T.gif +0 -0
  103. data/doc/ex/images/Button_U.gif +0 -0
  104. data/doc/ex/images/Button_V.gif +0 -0
  105. data/doc/ex/images/Button_W.gif +0 -0
  106. data/doc/ex/images/Button_X.gif +0 -0
  107. data/doc/ex/images/Button_Y.gif +0 -0
  108. data/doc/ex/images/Button_Z.gif +0 -0
  109. data/doc/ex/images/Cheetah.jpg +0 -0
  110. data/doc/ex/images/Coffee.wmf +0 -0
  111. data/doc/ex/images/Flower_Hat.jpg +0 -0
  112. data/doc/ex/images/Gold_Statue.jpg +0 -0
  113. data/doc/ex/images/Hot_Air_Balloons.jpg +0 -0
  114. data/doc/ex/images/Hot_Air_Balloons_H.jpg +0 -0
  115. data/doc/ex/images/No.wmf +0 -0
  116. data/doc/ex/images/Polynesia.jpg +0 -0
  117. data/doc/ex/images/Red_Rocks.jpg +0 -0
  118. data/doc/ex/images/Shorts.jpg +0 -0
  119. data/doc/ex/images/Snake.wmf +0 -0
  120. data/doc/ex/images/Violin.jpg +0 -0
  121. data/doc/ex/images/graydient230x6.gif +0 -0
  122. data/doc/ex/images/logo400x83.gif +0 -0
  123. data/doc/ex/images/model.miff +0 -0
  124. data/doc/ex/images/notimplemented.gif +0 -0
  125. data/doc/ex/images/smile.miff +0 -0
  126. data/doc/ex/images/spin.gif +0 -0
  127. data/doc/ex/implode.rb +32 -0
  128. data/doc/ex/level.rb +12 -0
  129. data/doc/ex/level_channel.rb +33 -0
  130. data/doc/ex/line.rb +40 -0
  131. data/doc/ex/map.rb +28 -0
  132. data/doc/ex/map_f.rb +15 -0
  133. data/doc/ex/matte_fill_to_border.rb +42 -0
  134. data/doc/ex/matte_floodfill.rb +35 -0
  135. data/doc/ex/matte_replace.rb +42 -0
  136. data/doc/ex/median_filter.rb +28 -0
  137. data/doc/ex/modulate.rb +11 -0
  138. data/doc/ex/mono.rb +23 -0
  139. data/doc/ex/morph.rb +26 -0
  140. data/doc/ex/mosaic.rb +35 -0
  141. data/doc/ex/motion_blur.rb +11 -0
  142. data/doc/ex/negate.rb +11 -0
  143. data/doc/ex/negate_channel.rb +19 -0
  144. data/doc/ex/normalize.rb +11 -0
  145. data/doc/ex/oil_paint.rb +11 -0
  146. data/doc/ex/opacity.rb +38 -0
  147. data/doc/ex/opaque.rb +14 -0
  148. data/doc/ex/ordered_dither.rb +11 -0
  149. data/doc/ex/path.rb +62 -0
  150. data/doc/ex/pattern1.rb +25 -0
  151. data/doc/ex/pattern2.rb +26 -0
  152. data/doc/ex/polygon.rb +24 -0
  153. data/doc/ex/polyline.rb +23 -0
  154. data/doc/ex/posterize.rb +19 -0
  155. data/doc/ex/preview.rb +16 -0
  156. data/doc/ex/qbezierpath.rb +49 -0
  157. data/doc/ex/quantize-m.rb +25 -0
  158. data/doc/ex/radial_blur.rb +19 -0
  159. data/doc/ex/raise.rb +11 -0
  160. data/doc/ex/random_channel_threshold.rb +17 -0
  161. data/doc/ex/random_threshold_channel.rb +18 -0
  162. data/doc/ex/rectangle.rb +33 -0
  163. data/doc/ex/reduce_noise.rb +28 -0
  164. data/doc/ex/roll.rb +9 -0
  165. data/doc/ex/rotate.rb +43 -0
  166. data/doc/ex/rotate_f.rb +14 -0
  167. data/doc/ex/roundrect.rb +32 -0
  168. data/doc/ex/rubyname.rb +31 -0
  169. data/doc/ex/segment.rb +11 -0
  170. data/doc/ex/shade.rb +11 -0
  171. data/doc/ex/shave.rb +15 -0
  172. data/doc/ex/shear.rb +10 -0
  173. data/doc/ex/skewx.rb +50 -0
  174. data/doc/ex/skewy.rb +45 -0
  175. data/doc/ex/smile.rb +124 -0
  176. data/doc/ex/solarize.rb +11 -0
  177. data/doc/ex/splice.rb +16 -0
  178. data/doc/ex/spread.rb +11 -0
  179. data/doc/ex/stegano.rb +50 -0
  180. data/doc/ex/stroke_dasharray.rb +41 -0
  181. data/doc/ex/stroke_linecap.rb +44 -0
  182. data/doc/ex/stroke_linejoin.rb +48 -0
  183. data/doc/ex/stroke_width.rb +47 -0
  184. data/doc/ex/swirl.rb +17 -0
  185. data/doc/ex/text.rb +32 -0
  186. data/doc/ex/text_align.rb +36 -0
  187. data/doc/ex/text_antialias.rb +33 -0
  188. data/doc/ex/text_undercolor.rb +26 -0
  189. data/doc/ex/texture_fill_to_border.rb +34 -0
  190. data/doc/ex/texture_floodfill.rb +31 -0
  191. data/doc/ex/texturefill.rb +25 -0
  192. data/doc/ex/threshold.rb +13 -0
  193. data/doc/ex/to_blob.rb +14 -0
  194. data/doc/ex/translate.rb +37 -0
  195. data/doc/ex/transparent.rb +38 -0
  196. data/doc/ex/trim.rb +25 -0
  197. data/doc/ex/unsharp_mask.rb +28 -0
  198. data/doc/ex/viewex.rb +36 -0
  199. data/doc/ex/wave.rb +9 -0
  200. data/doc/ilist.html +1592 -0
  201. data/doc/image1.html +3009 -0
  202. data/doc/image2.html +2169 -0
  203. data/doc/image3.html +2815 -0
  204. data/doc/imageattrs.html +1319 -0
  205. data/doc/imusage.html +403 -0
  206. data/doc/index.html +418 -0
  207. data/doc/info.html +949 -0
  208. data/doc/magick.html +439 -0
  209. data/doc/scripts/doc.js +9 -0
  210. data/doc/struct.html +1334 -0
  211. data/doc/usage.html +1318 -0
  212. data/examples/describe.rb +44 -0
  213. data/examples/histogram.rb +289 -0
  214. data/examples/image_opacity.rb +29 -0
  215. data/examples/import_export.rb +31 -0
  216. data/examples/pattern_fill.rb +38 -0
  217. data/examples/rotating_text.rb +47 -0
  218. data/examples/thumbnail.rb +65 -0
  219. data/examples/vignette.rb +79 -0
  220. data/ext/RMagick/MANIFEST +239 -0
  221. data/ext/RMagick/extconf.rb.in +21 -0
  222. data/ext/RMagick/rmagick.h +938 -0
  223. data/ext/RMagick/rmagick_config.h.in +170 -0
  224. data/ext/RMagick/rmdraw.c +1308 -0
  225. data/ext/RMagick/rmfill.c +609 -0
  226. data/ext/RMagick/rmilist.c +685 -0
  227. data/ext/RMagick/rmimage.c +7980 -0
  228. data/ext/RMagick/rminfo.c +982 -0
  229. data/ext/RMagick/rmmain.c +1497 -0
  230. data/ext/RMagick/rmutil.c +2685 -0
  231. data/install.rb +1015 -0
  232. data/lib/RMagick.rb +1486 -0
  233. data/metaconfig.in +6 -0
  234. data/post-clean.rb +12 -0
  235. data/post-install.rb +36 -0
  236. data/post-setup.rb +245 -0
  237. data/rmagick.gemspec +22 -0
  238. data/uninstall.rb +71 -0
  239. metadata +286 -0
@@ -0,0 +1,609 @@
1
+ /* $Id: rmfill.c,v 1.10 2004/12/17 22:44:06 rmagick Exp $ */
2
+ /*============================================================================\
3
+ | Copyright (C) 2004 by Timothy P. Hunter
4
+ | Name: rmfill.c
5
+ | Author: Tim Hunter
6
+ | Purpose: GradientFill, TextureFill class definitions for RMagick
7
+ \============================================================================*/
8
+
9
+ #include "rmagick.h"
10
+
11
+ typedef struct
12
+ {
13
+ double x1, y1, x2, y2;
14
+ PixelPacket start_color;
15
+ PixelPacket stop_color;
16
+ } GradientFill;
17
+
18
+ typedef struct
19
+ {
20
+ Image *texture;
21
+ } TextureFill;
22
+
23
+ /*
24
+ Static: free_Fill
25
+ Purpose: free Fill or Fill subclass object (except for
26
+ TextureFill)
27
+ */
28
+ static void free_Fill(void *fill)
29
+ {
30
+ xfree(fill);
31
+ }
32
+
33
+ /*
34
+ Extern: GradientFill.new(x1, y1, x2, y2, start_color, stop_color)
35
+ Purpose: Create new GradientFill object
36
+ */
37
+ #if !defined(HAVE_RB_DEFINE_ALLOC_FUNC)
38
+ VALUE
39
+ GradientFill_new(
40
+ VALUE class,
41
+ VALUE x1,
42
+ VALUE y1,
43
+ VALUE x2,
44
+ VALUE y2,
45
+ VALUE start_color,
46
+ VALUE stop_color)
47
+ {
48
+ GradientFill *fill;
49
+ volatile VALUE new_fill;
50
+ VALUE argv[6];
51
+
52
+ argv[0] = x1;
53
+ argv[1] = y1;
54
+ argv[2] = x2;
55
+ argv[3] = y2;
56
+ argv[4] = start_color;
57
+ argv[5] = stop_color;
58
+
59
+ new_fill = Data_Make_Struct(class
60
+ , GradientFill
61
+ , NULL
62
+ , free_Fill
63
+ , fill);
64
+
65
+ rb_obj_call_init((VALUE)new_fill, 6, argv);
66
+ return new_fill;
67
+ }
68
+ #else
69
+ VALUE
70
+ GradientFill_alloc(VALUE class)
71
+ {
72
+ GradientFill *fill;
73
+
74
+ return Data_Make_Struct(class, GradientFill, NULL, free_Fill, fill);
75
+ }
76
+ #endif
77
+
78
+ /*
79
+ Extern: GradientFill#initialize(start_color, stop_color)
80
+ Purpose: store the vector points and the start and stop colors
81
+ */
82
+ VALUE
83
+ GradientFill_initialize(
84
+ VALUE self,
85
+ VALUE x1,
86
+ VALUE y1,
87
+ VALUE x2,
88
+ VALUE y2,
89
+ VALUE start_color,
90
+ VALUE stop_color)
91
+ {
92
+ GradientFill *fill;
93
+
94
+ Data_Get_Struct(self, GradientFill, fill);
95
+
96
+ fill->x1 = NUM2DBL(x1);
97
+ fill->y1 = NUM2DBL(y1);
98
+ fill->x2 = NUM2DBL(x2);
99
+ fill->y2 = NUM2DBL(y2);
100
+ Color_to_PixelPacket(&fill->start_color, start_color);
101
+ Color_to_PixelPacket(&fill->stop_color, stop_color);
102
+
103
+ return self;
104
+ }
105
+
106
+ /*
107
+ Static: point_fill
108
+ Purpose: do a gradient that radiates from a point
109
+ */
110
+ static void
111
+ point_fill(
112
+ Image *image,
113
+ double x0,
114
+ double y0,
115
+ PixelPacket *start_color,
116
+ PixelPacket *stop_color)
117
+ {
118
+ double steps, distance;
119
+ long x, y;
120
+ double red_step, green_step, blue_step;
121
+
122
+ steps = sqrt((double)((image->columns-x0)*(image->columns-x0)
123
+ + (image->rows-y0)*(image->rows-y0)));
124
+ red_step = ((double)(stop_color->red - start_color->red)) / steps;
125
+ green_step = ((double)(stop_color->green - start_color->green)) / steps;
126
+ blue_step = ((double)(stop_color->blue - start_color->blue)) / steps;
127
+
128
+ for (y = 0; y < image->rows; y++)
129
+ {
130
+ PixelPacket *row_pixels;
131
+
132
+ if (!(row_pixels = SetImagePixels(image, 0, y, image->columns, 1)))
133
+ {
134
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
135
+ }
136
+ for (x = 0; x < image->columns; x++)
137
+ {
138
+ distance = sqrt((double)((x-x0)*(x-x0)+(y-y0)*(y-y0)));
139
+ row_pixels[x].red = start_color->red + (distance * red_step);
140
+ row_pixels[x].green = start_color->green + (distance * green_step);
141
+ row_pixels[x].blue = start_color->blue + (distance * blue_step);
142
+ row_pixels[x].opacity = OpaqueOpacity;
143
+ }
144
+ if (!SyncImagePixels(image))
145
+ {
146
+ rb_raise(Class_ImageMagickError, "can't set image pixels");
147
+ }
148
+ }
149
+ }
150
+
151
+ /*
152
+ Static: vertical_fill
153
+ Purpose: do a gradient fill that proceeds from a vertical line to the
154
+ right and left sides of the image
155
+ */
156
+ static void
157
+ vertical_fill(
158
+ Image *image,
159
+ double x1,
160
+ PixelPacket *start_color,
161
+ PixelPacket *stop_color)
162
+ {
163
+ double steps;
164
+ long x, y;
165
+ volatile PixelPacket *master;
166
+ double red_step, green_step, blue_step;
167
+
168
+ // Keep in mind that x1 could be < 0 or > image->columns. If steps
169
+ // is negative, swap the start and end colors and use the absolute
170
+ // value.
171
+ steps = fmax(x1, ((long)image->columns)-x1);
172
+ if (steps < 0)
173
+ {
174
+ PixelPacket t = *start_color;
175
+ *start_color = *stop_color;
176
+ *stop_color = t;
177
+ steps = -steps;
178
+ }
179
+
180
+ // If x is to the left of the x-axis, add that many steps so that
181
+ // the color at the right side will be that many steps away from
182
+ // the stop color.
183
+ if (x1 < 0)
184
+ {
185
+ steps -= x1;
186
+ }
187
+
188
+ red_step = (stop_color->red - start_color->red) / steps;
189
+ green_step = (stop_color->green - start_color->green) / steps;
190
+ blue_step = (stop_color->blue - start_color->blue) / steps;
191
+
192
+ // All the rows are the same. Make a "master row" and simply copy
193
+ // it to each actual row.
194
+ master = ALLOC_N(PixelPacket, image->columns);
195
+
196
+ for (x = 0; x < image->columns; x++)
197
+ {
198
+ double distance = fabs(x1 - x);
199
+ master[x].red = start_color->red + (red_step * distance);
200
+ master[x].green = start_color->green + (green_step * distance);
201
+ master[x].blue = start_color->blue + (blue_step * distance);
202
+ master[x].opacity = OpaqueOpacity;
203
+ }
204
+
205
+ // Now copy the master row to each actual row.
206
+ for (y = 0; y < image->rows; y++)
207
+ {
208
+ PixelPacket *row_pixels;
209
+
210
+ if (!(row_pixels = SetImagePixels(image, 0, y, image->columns, 1)))
211
+ {
212
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
213
+ }
214
+
215
+ memcpy(row_pixels, (PixelPacket *)master, image->columns * sizeof(PixelPacket));
216
+ if (!SyncImagePixels(image))
217
+ {
218
+ rb_raise(Class_ImageMagickError, "can't set image pixels");
219
+ }
220
+ }
221
+
222
+ xfree((PixelPacket *)master);
223
+ }
224
+
225
+ /*
226
+ Static: horizontal_fill
227
+ Purpose: do a gradient fill that starts from a horizontal line
228
+ */
229
+ static void
230
+ horizontal_fill(
231
+ Image *image,
232
+ double y1,
233
+ PixelPacket *start_color,
234
+ PixelPacket *stop_color)
235
+ {
236
+ double steps;
237
+ long x, y;
238
+ volatile PixelPacket *master;
239
+ double red_step, green_step, blue_step;
240
+
241
+ // Bear in mind that y1 could be < 0 or > image->rows. If steps is
242
+ // negative, swap the start and end colors and use the absolute value.
243
+ steps = fmax(y1, ((long)image->rows)-y1);
244
+ if (steps < 0)
245
+ {
246
+ PixelPacket t = *start_color;
247
+ *start_color = *stop_color;
248
+ *stop_color = t;
249
+ steps = -steps;
250
+ }
251
+
252
+ // If the line is below the y-axis, add that many steps so the color
253
+ // at the bottom of the image is that many steps away from the stop color
254
+ if (y1 < 0)
255
+ {
256
+ steps -= y1;
257
+ }
258
+
259
+ red_step = (stop_color->red - start_color->red) / steps;
260
+ green_step = (stop_color->green - start_color->green) / steps;
261
+ blue_step = (stop_color->blue - start_color->blue) / steps;
262
+
263
+ // All the columns are the same, so make a master column and copy it to
264
+ // each of the "real" columns.
265
+ master = ALLOC_N(volatile PixelPacket, image->rows);
266
+
267
+ for (y = 0; y < image->rows; y++)
268
+ {
269
+ double distance = fabs(y1 - y);
270
+ master[y].red = start_color->red + (distance * red_step);
271
+ master[y].green = start_color->green + (distance * green_step);
272
+ master[y].blue = start_color->blue + (distance * blue_step);
273
+ master[y].opacity = OpaqueOpacity;
274
+ }
275
+
276
+ for (x = 0; x < image->columns; x++)
277
+ {
278
+ PixelPacket *col_pixels;
279
+
280
+ if (!(col_pixels = SetImagePixels(image, x, 0, 1, image->rows)))
281
+ {
282
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
283
+ }
284
+ memcpy(col_pixels, (PixelPacket *)master, image->rows * sizeof(PixelPacket));
285
+ if (!SyncImagePixels(image))
286
+ {
287
+ rb_raise(Class_ImageMagickError, "can't set image pixels");
288
+ }
289
+ }
290
+
291
+ xfree((PixelPacket *)master);
292
+ }
293
+
294
+ /*
295
+ Static: v_diagonal_fill
296
+ Purpose: do a gradient fill that starts from a diagonal line and
297
+ ends at the top and bottom of the image
298
+ */
299
+ static void
300
+ v_diagonal_fill(
301
+ Image *image,
302
+ double x1,
303
+ double y1,
304
+ double x2,
305
+ double y2,
306
+ PixelPacket *start_color,
307
+ PixelPacket *stop_color)
308
+ {
309
+ long x, y;
310
+ double red_step, green_step, blue_step;
311
+ double m, b, steps = 0.0;
312
+ double d1, d2;
313
+
314
+ // Compute the equation of the line: y=mx+b
315
+ m = ((double)(y2 - y1))/((double)(x2 - x1));
316
+ b = y1 - (m * x1);
317
+
318
+ // The number of steps is the greatest distance between the line and
319
+ // the top or bottom of the image between x=0 and x=image->columns
320
+ // When x=0, y=b. When x=image->columns, y = m*image->columns+b
321
+ d1 = b;
322
+ d2 = m * image->columns + b;
323
+
324
+ if (d1 < 0 && d2 < 0)
325
+ {
326
+ steps += fmax(fabs(d1),fabs(d2));
327
+ }
328
+ else if (d1 > image->rows && d2 > image->rows)
329
+ {
330
+ steps += fmax(d1-image->rows, d2-image->rows);
331
+ }
332
+
333
+ d1 = fmax(b, image->rows-b);
334
+ d2 = fmax(d2, image->rows-d2);
335
+ steps += fmax(d1, d2);
336
+
337
+ // If the line is entirely > image->rows, swap the start & end color
338
+ if (steps < 0)
339
+ {
340
+ PixelPacket t = *stop_color;
341
+ *stop_color = *start_color;
342
+ *start_color = t;
343
+ steps = -steps;
344
+ }
345
+
346
+ red_step = (stop_color->red - start_color->red) / steps;
347
+ green_step = (stop_color->green - start_color->green) / steps;
348
+ blue_step = (stop_color->blue - start_color->blue) / steps;
349
+
350
+ for (y = 0; y < image->rows; y++)
351
+ {
352
+ PixelPacket *row_pixels;
353
+
354
+ if (!(row_pixels = SetImagePixels(image, 0, y, image->columns, 1)))
355
+ {
356
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
357
+ }
358
+ for (x = 0; x < image->columns; x++)
359
+ {
360
+ double distance = fabs(y-(m * x + b));
361
+ row_pixels[x].red = start_color->red + (distance * red_step);
362
+ row_pixels[x].green = start_color->green + (distance * green_step);
363
+ row_pixels[x].blue = start_color->blue + (distance * blue_step);
364
+ row_pixels[x].opacity = OpaqueOpacity;
365
+ }
366
+ if (!SyncImagePixels(image))
367
+ {
368
+ rb_raise(Class_ImageMagickError, "can't set image pixels");
369
+ }
370
+ }
371
+ }
372
+
373
+ /*
374
+ Static: h_diagonal_fill
375
+ Purpose: do a gradient fill that starts from a diagonal line and
376
+ ends at the sides of the image
377
+ */
378
+ static void
379
+ h_diagonal_fill(
380
+ Image *image,
381
+ double x1,
382
+ double y1,
383
+ double x2,
384
+ double y2,
385
+ PixelPacket *start_color,
386
+ PixelPacket *stop_color)
387
+ {
388
+ long x, y;
389
+ double m, b, steps = 0.0;
390
+ double red_step, green_step, blue_step;
391
+ double d1, d2;
392
+
393
+ // Compute the equation of the line: y=mx+b
394
+ m = ((double)(y2 - y1))/((double)(x2 - x1));
395
+ b = y1 - (m * x1);
396
+
397
+ // The number of steps is the greatest distance between the line and
398
+ // the left or right side of the image between y=0 and y=image->rows.
399
+ // When y=0, x=-b/m. When y=image->rows, x = (image->rows-b)/m.
400
+ d1 = -b/m;
401
+ d2 = (image->rows-b)/m;
402
+
403
+ // If the line is entirely to the right or left of the image, increase
404
+ // the number of steps.
405
+ if (d1 < 0 && d2 < 0)
406
+ {
407
+ steps += fmax(fabs(d1),fabs(d2));
408
+ }
409
+ else if (d1 > image->columns && d2 > image->columns)
410
+ {
411
+ steps += fmax(fabs(image->columns-d1),fabs(image->columns-d2));
412
+ }
413
+
414
+ d1 = fmax(d1, image->columns-d1);
415
+ d2 = fmax(d2, image->columns-d2);
416
+ steps += fmax(d1, d2);
417
+
418
+ // If the line is entirely > image->columns, swap the start & end color
419
+ if (steps < 0)
420
+ {
421
+ PixelPacket t = *stop_color;
422
+ *stop_color = *start_color;
423
+ *start_color = t;
424
+ steps = -steps;
425
+ }
426
+
427
+ red_step = (stop_color->red - start_color->red) / steps;
428
+ green_step = (stop_color->green - start_color->green) / steps;
429
+ blue_step = (stop_color->blue - start_color->blue) / steps;
430
+
431
+ for (y = 0; y < image->rows; y++)
432
+ {
433
+ PixelPacket *row_pixels;
434
+
435
+ if (!(row_pixels = SetImagePixels(image, 0, y, image->columns, 1)))
436
+ {
437
+ rb_raise(rb_eNoMemError, "not enough memory to continue");
438
+ }
439
+ for (x = 0; x < image->columns; x++)
440
+ {
441
+ double distance = fabs(x-((y-b)/m));
442
+ row_pixels[x].red = start_color->red + (distance * red_step);
443
+ row_pixels[x].green = start_color->green + (distance * green_step);
444
+ row_pixels[x].blue = start_color->blue + (distance * blue_step);
445
+ row_pixels[x].opacity = OpaqueOpacity;
446
+ }
447
+ if (!SyncImagePixels(image))
448
+ {
449
+ rb_raise(Class_ImageMagickError, "can't set image pixels");
450
+ }
451
+ }
452
+ }
453
+
454
+ /*
455
+ Extern: GradientFill_fill(image_obj)
456
+ Purpose: the GradientFill#fill method - call GradientFill with the
457
+ start and stop colors specified when this fill object
458
+ was created.
459
+ */
460
+ VALUE
461
+ GradientFill_fill(VALUE self, VALUE image_obj)
462
+ {
463
+ GradientFill *fill;
464
+ Image *image;
465
+ PixelPacket start_color, stop_color;
466
+ double x1, y1, x2, y2; // points on the line
467
+
468
+ Data_Get_Struct(self, GradientFill, fill);
469
+ Data_Get_Struct(image_obj, Image, image);
470
+
471
+ x1 = fill->x1;
472
+ y1 = fill->y1;
473
+ x2 = fill->x2;
474
+ y2 = fill->y2;
475
+ start_color = fill->start_color;
476
+ stop_color = fill->stop_color;
477
+
478
+ if (fabs(x2-x1) < 0.5) // vertical?
479
+ {
480
+ // If the x1,y1 and x2,y2 points are essentially the same
481
+ if (fabs(y2-y1) < 0.5)
482
+ {
483
+ point_fill(image, x1, y1, &start_color, &stop_color);
484
+ }
485
+
486
+ // A vertical line is a special case. (Yes, really do pass x1
487
+ // as both the 2nd and 4th arguments!)
488
+ else
489
+ {
490
+ vertical_fill(image, x1, &start_color, &stop_color);
491
+ }
492
+ }
493
+
494
+ // A horizontal line is a special case.
495
+ else if (fabs(y2-y1) < 0.5)
496
+ {
497
+ // Pass y1 as both the 3rd and 5th arguments!
498
+ horizontal_fill(image, y1, &start_color, &stop_color);
499
+ }
500
+
501
+ // This is the general case - a diagonal line. If the line is more horizontal
502
+ // than vertical, use the top and bottom of the image as the ends of the
503
+ // gradient, otherwise use the sides of the image.
504
+ else
505
+ {
506
+ double m = ((double)(y2 - y1))/((double)(x2 - x1));
507
+ double diagonal = ((double)image->rows)/image->columns;
508
+ if (fabs(m) <= diagonal)
509
+ {
510
+ v_diagonal_fill(image, x1, y1, x2, y2, &start_color, &stop_color);
511
+ }
512
+ else
513
+ {
514
+ h_diagonal_fill(image, x1, y1, x2, y2, &start_color, &stop_color);
515
+ }
516
+ }
517
+
518
+ return self;
519
+ }
520
+
521
+
522
+ /*
523
+ Static: free_TextureFill
524
+ Purpose: free the TextureFill struct and the texture image it points to
525
+ Notes: called from GC
526
+ */
527
+ static void
528
+ free_TextureFill(void *fill_obj)
529
+ {
530
+ TextureFill *fill = (TextureFill *)fill_obj;
531
+
532
+ DestroyImage(fill->texture);
533
+ xfree(fill);
534
+ }
535
+
536
+ /*
537
+ Extern: TextureFill.new(texture)
538
+ Purpose: Create new TextureFill object
539
+ Notes: the texture is an Image or Image *object
540
+ */
541
+ #if !defined(HAVE_RB_DEFINE_ALLOC_FUNC)
542
+ VALUE
543
+ TextureFill_new(VALUE class, VALUE texture)
544
+ {
545
+ TextureFill *fill;
546
+ VALUE argv[1];
547
+ volatile VALUE new_fill;
548
+
549
+ new_fill = Data_Make_Struct(class
550
+ , TextureFill
551
+ , NULL
552
+ , free_TextureFill
553
+ , fill);
554
+ argv[0] = texture;
555
+ rb_obj_call_init((VALUE)new_fill, 1, argv);
556
+ return new_fill;
557
+ }
558
+ #else
559
+ VALUE
560
+ TextureFill_alloc(VALUE class)
561
+ {
562
+ TextureFill *fill;
563
+ return Data_Make_Struct(class
564
+ , TextureFill
565
+ , NULL
566
+ , free_TextureFill
567
+ , fill);
568
+ }
569
+ #endif
570
+
571
+ /*
572
+ Extern: TextureFill#initialize
573
+ Purpose: Store the texture image
574
+ */
575
+ VALUE
576
+ TextureFill_initialize(VALUE self, VALUE texture_arg)
577
+ {
578
+ TextureFill *fill;
579
+ Image *texture;
580
+ volatile VALUE texture_image;
581
+
582
+ Data_Get_Struct(self, TextureFill, fill);
583
+
584
+ texture_image = ImageList_cur_image(texture_arg);
585
+
586
+ // Bump the reference count on the texture image.
587
+ Data_Get_Struct(texture_image, Image, texture);
588
+ ReferenceImage(texture);
589
+
590
+ fill->texture = texture;
591
+ return self;
592
+ }
593
+
594
+ /*
595
+ Extern: TextureFill_fill(image_obj)
596
+ Purpose: the TextureFill#fill method
597
+ */
598
+ VALUE
599
+ TextureFill_fill(VALUE self, VALUE image_obj)
600
+ {
601
+ TextureFill *fill;
602
+ Image *image;
603
+
604
+ Data_Get_Struct(image_obj, Image, image);
605
+ Data_Get_Struct(self, TextureFill, fill);
606
+
607
+ TextureImage(image, fill->texture);
608
+ return self;
609
+ }