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.
- data/ChangeLog +232 -0
- data/Makefile.in +28 -0
- data/README.html +404 -0
- data/README.txt +397 -0
- data/configure +8554 -0
- data/configure.ac +497 -0
- data/doc/comtasks.html +241 -0
- data/doc/constants.html +1195 -0
- data/doc/css/doc.css +299 -0
- data/doc/css/popup.css +34 -0
- data/doc/draw.html +3108 -0
- data/doc/ex/Adispatch.rb +43 -0
- data/doc/ex/Zconstitute.rb +9 -0
- data/doc/ex/adaptive_threshold.rb +19 -0
- data/doc/ex/add_noise.rb +18 -0
- data/doc/ex/affine.rb +48 -0
- data/doc/ex/affine_transform.rb +20 -0
- data/doc/ex/arc.rb +47 -0
- data/doc/ex/arcpath.rb +33 -0
- data/doc/ex/average.rb +15 -0
- data/doc/ex/axes.rb +64 -0
- data/doc/ex/bilevel_channel.rb +20 -0
- data/doc/ex/blur_image.rb +12 -0
- data/doc/ex/border.rb +10 -0
- data/doc/ex/bounding_box.rb +48 -0
- data/doc/ex/cbezier1.rb +40 -0
- data/doc/ex/cbezier2.rb +40 -0
- data/doc/ex/cbezier3.rb +40 -0
- data/doc/ex/cbezier4.rb +41 -0
- data/doc/ex/cbezier5.rb +41 -0
- data/doc/ex/cbezier6.rb +51 -0
- data/doc/ex/channel.rb +26 -0
- data/doc/ex/channel_threshold.rb +48 -0
- data/doc/ex/charcoal.rb +12 -0
- data/doc/ex/chop.rb +29 -0
- data/doc/ex/circle.rb +31 -0
- data/doc/ex/clip_path.rb +56 -0
- data/doc/ex/coalesce.rb +60 -0
- data/doc/ex/color_fill_to_border.rb +29 -0
- data/doc/ex/color_floodfill.rb +28 -0
- data/doc/ex/color_histogram.rb +60 -0
- data/doc/ex/color_reset.rb +11 -0
- data/doc/ex/colorize.rb +16 -0
- data/doc/ex/colors.rb +65 -0
- data/doc/ex/composite.rb +135 -0
- data/doc/ex/contrast.rb +37 -0
- data/doc/ex/crop.rb +31 -0
- data/doc/ex/crop_with_gravity.rb +46 -0
- data/doc/ex/cycle_colormap.rb +21 -0
- data/doc/ex/demo.rb +324 -0
- data/doc/ex/drawcomp.rb +42 -0
- data/doc/ex/drop_shadow.rb +60 -0
- data/doc/ex/edge.rb +11 -0
- data/doc/ex/ellipse.rb +43 -0
- data/doc/ex/emboss.rb +11 -0
- data/doc/ex/enhance.rb +28 -0
- data/doc/ex/equalize.rb +11 -0
- data/doc/ex/flatten_images.rb +38 -0
- data/doc/ex/flip.rb +11 -0
- data/doc/ex/flop.rb +11 -0
- data/doc/ex/fonts.rb +20 -0
- data/doc/ex/frame.rb +12 -0
- data/doc/ex/gaussian_blur.rb +11 -0
- data/doc/ex/get_multiline_type_metrics.rb +53 -0
- data/doc/ex/get_pixels.rb +48 -0
- data/doc/ex/get_type_metrics.rb +140 -0
- data/doc/ex/gradientfill.rb +27 -0
- data/doc/ex/grav.rb +44 -0
- data/doc/ex/gravity.rb +80 -0
- data/doc/ex/hatchfill.rb +27 -0
- data/doc/ex/images/Ballerina.jpg +0 -0
- data/doc/ex/images/Ballerina3.jpg +0 -0
- data/doc/ex/images/Button_0.gif +0 -0
- data/doc/ex/images/Button_1.gif +0 -0
- data/doc/ex/images/Button_2.gif +0 -0
- data/doc/ex/images/Button_3.gif +0 -0
- data/doc/ex/images/Button_4.gif +0 -0
- data/doc/ex/images/Button_5.gif +0 -0
- data/doc/ex/images/Button_6.gif +0 -0
- data/doc/ex/images/Button_7.gif +0 -0
- data/doc/ex/images/Button_8.gif +0 -0
- data/doc/ex/images/Button_9.gif +0 -0
- data/doc/ex/images/Button_A.gif +0 -0
- data/doc/ex/images/Button_B.gif +0 -0
- data/doc/ex/images/Button_C.gif +0 -0
- data/doc/ex/images/Button_D.gif +0 -0
- data/doc/ex/images/Button_E.gif +0 -0
- data/doc/ex/images/Button_F.gif +0 -0
- data/doc/ex/images/Button_G.gif +0 -0
- data/doc/ex/images/Button_H.gif +0 -0
- data/doc/ex/images/Button_I.gif +0 -0
- data/doc/ex/images/Button_J.gif +0 -0
- data/doc/ex/images/Button_K.gif +0 -0
- data/doc/ex/images/Button_L.gif +0 -0
- data/doc/ex/images/Button_M.gif +0 -0
- data/doc/ex/images/Button_N.gif +0 -0
- data/doc/ex/images/Button_O.gif +0 -0
- data/doc/ex/images/Button_P.gif +0 -0
- data/doc/ex/images/Button_Q.gif +0 -0
- data/doc/ex/images/Button_R.gif +0 -0
- data/doc/ex/images/Button_S.gif +0 -0
- data/doc/ex/images/Button_T.gif +0 -0
- data/doc/ex/images/Button_U.gif +0 -0
- data/doc/ex/images/Button_V.gif +0 -0
- data/doc/ex/images/Button_W.gif +0 -0
- data/doc/ex/images/Button_X.gif +0 -0
- data/doc/ex/images/Button_Y.gif +0 -0
- data/doc/ex/images/Button_Z.gif +0 -0
- data/doc/ex/images/Cheetah.jpg +0 -0
- data/doc/ex/images/Coffee.wmf +0 -0
- data/doc/ex/images/Flower_Hat.jpg +0 -0
- data/doc/ex/images/Gold_Statue.jpg +0 -0
- data/doc/ex/images/Hot_Air_Balloons.jpg +0 -0
- data/doc/ex/images/Hot_Air_Balloons_H.jpg +0 -0
- data/doc/ex/images/No.wmf +0 -0
- data/doc/ex/images/Polynesia.jpg +0 -0
- data/doc/ex/images/Red_Rocks.jpg +0 -0
- data/doc/ex/images/Shorts.jpg +0 -0
- data/doc/ex/images/Snake.wmf +0 -0
- data/doc/ex/images/Violin.jpg +0 -0
- data/doc/ex/images/graydient230x6.gif +0 -0
- data/doc/ex/images/logo400x83.gif +0 -0
- data/doc/ex/images/model.miff +0 -0
- data/doc/ex/images/notimplemented.gif +0 -0
- data/doc/ex/images/smile.miff +0 -0
- data/doc/ex/images/spin.gif +0 -0
- data/doc/ex/implode.rb +32 -0
- data/doc/ex/level.rb +12 -0
- data/doc/ex/level_channel.rb +33 -0
- data/doc/ex/line.rb +40 -0
- data/doc/ex/map.rb +28 -0
- data/doc/ex/map_f.rb +15 -0
- data/doc/ex/matte_fill_to_border.rb +42 -0
- data/doc/ex/matte_floodfill.rb +35 -0
- data/doc/ex/matte_replace.rb +42 -0
- data/doc/ex/median_filter.rb +28 -0
- data/doc/ex/modulate.rb +11 -0
- data/doc/ex/mono.rb +23 -0
- data/doc/ex/morph.rb +26 -0
- data/doc/ex/mosaic.rb +35 -0
- data/doc/ex/motion_blur.rb +11 -0
- data/doc/ex/negate.rb +11 -0
- data/doc/ex/negate_channel.rb +19 -0
- data/doc/ex/normalize.rb +11 -0
- data/doc/ex/oil_paint.rb +11 -0
- data/doc/ex/opacity.rb +38 -0
- data/doc/ex/opaque.rb +14 -0
- data/doc/ex/ordered_dither.rb +11 -0
- data/doc/ex/path.rb +62 -0
- data/doc/ex/pattern1.rb +25 -0
- data/doc/ex/pattern2.rb +26 -0
- data/doc/ex/polygon.rb +24 -0
- data/doc/ex/polyline.rb +23 -0
- data/doc/ex/posterize.rb +19 -0
- data/doc/ex/preview.rb +16 -0
- data/doc/ex/qbezierpath.rb +49 -0
- data/doc/ex/quantize-m.rb +25 -0
- data/doc/ex/radial_blur.rb +19 -0
- data/doc/ex/raise.rb +11 -0
- data/doc/ex/random_channel_threshold.rb +17 -0
- data/doc/ex/random_threshold_channel.rb +18 -0
- data/doc/ex/rectangle.rb +33 -0
- data/doc/ex/reduce_noise.rb +28 -0
- data/doc/ex/roll.rb +9 -0
- data/doc/ex/rotate.rb +43 -0
- data/doc/ex/rotate_f.rb +14 -0
- data/doc/ex/roundrect.rb +32 -0
- data/doc/ex/rubyname.rb +31 -0
- data/doc/ex/segment.rb +11 -0
- data/doc/ex/shade.rb +11 -0
- data/doc/ex/shave.rb +15 -0
- data/doc/ex/shear.rb +10 -0
- data/doc/ex/skewx.rb +50 -0
- data/doc/ex/skewy.rb +45 -0
- data/doc/ex/smile.rb +124 -0
- data/doc/ex/solarize.rb +11 -0
- data/doc/ex/splice.rb +16 -0
- data/doc/ex/spread.rb +11 -0
- data/doc/ex/stegano.rb +50 -0
- data/doc/ex/stroke_dasharray.rb +41 -0
- data/doc/ex/stroke_linecap.rb +44 -0
- data/doc/ex/stroke_linejoin.rb +48 -0
- data/doc/ex/stroke_width.rb +47 -0
- data/doc/ex/swirl.rb +17 -0
- data/doc/ex/text.rb +32 -0
- data/doc/ex/text_align.rb +36 -0
- data/doc/ex/text_antialias.rb +33 -0
- data/doc/ex/text_undercolor.rb +26 -0
- data/doc/ex/texture_fill_to_border.rb +34 -0
- data/doc/ex/texture_floodfill.rb +31 -0
- data/doc/ex/texturefill.rb +25 -0
- data/doc/ex/threshold.rb +13 -0
- data/doc/ex/to_blob.rb +14 -0
- data/doc/ex/translate.rb +37 -0
- data/doc/ex/transparent.rb +38 -0
- data/doc/ex/trim.rb +25 -0
- data/doc/ex/unsharp_mask.rb +28 -0
- data/doc/ex/viewex.rb +36 -0
- data/doc/ex/wave.rb +9 -0
- data/doc/ilist.html +1592 -0
- data/doc/image1.html +3009 -0
- data/doc/image2.html +2169 -0
- data/doc/image3.html +2815 -0
- data/doc/imageattrs.html +1319 -0
- data/doc/imusage.html +403 -0
- data/doc/index.html +418 -0
- data/doc/info.html +949 -0
- data/doc/magick.html +439 -0
- data/doc/scripts/doc.js +9 -0
- data/doc/struct.html +1334 -0
- data/doc/usage.html +1318 -0
- data/examples/describe.rb +44 -0
- data/examples/histogram.rb +289 -0
- data/examples/image_opacity.rb +29 -0
- data/examples/import_export.rb +31 -0
- data/examples/pattern_fill.rb +38 -0
- data/examples/rotating_text.rb +47 -0
- data/examples/thumbnail.rb +65 -0
- data/examples/vignette.rb +79 -0
- data/ext/RMagick/MANIFEST +239 -0
- data/ext/RMagick/extconf.rb.in +21 -0
- data/ext/RMagick/rmagick.h +938 -0
- data/ext/RMagick/rmagick_config.h.in +170 -0
- data/ext/RMagick/rmdraw.c +1308 -0
- data/ext/RMagick/rmfill.c +609 -0
- data/ext/RMagick/rmilist.c +685 -0
- data/ext/RMagick/rmimage.c +7980 -0
- data/ext/RMagick/rminfo.c +982 -0
- data/ext/RMagick/rmmain.c +1497 -0
- data/ext/RMagick/rmutil.c +2685 -0
- data/install.rb +1015 -0
- data/lib/RMagick.rb +1486 -0
- data/metaconfig.in +6 -0
- data/post-clean.rb +12 -0
- data/post-install.rb +36 -0
- data/post-setup.rb +245 -0
- data/rmagick.gemspec +22 -0
- data/uninstall.rb +71 -0
- 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
|
+
}
|