-
Notifications
You must be signed in to change notification settings - Fork 0
/
dotify.c
133 lines (106 loc) · 3.17 KB
/
dotify.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
* dotify.c - Gimp plugin to dither an image.
* Pretty redundant, as the effect can also be achieved
* with existing plugins/filters.
*
* Andreas Textor <textor.andreas@googlemail.com>
*/
#include <libgimp/gimp.h>
#include <stdlib.h>
void run(const gchar *name,
gint nparams,
const GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals);
static void query();
GimpPlugInInfo PLUG_IN_INFO = {
NULL, //init
NULL, //quit
query,
run
};
MAIN()
static void blur (GimpDrawable *drawable) {
gint i, j, k, channels;
gint x1, y1, x2, y2;
GimpPixelRgn rgn_in, rgn_out;
guchar *row1, *row2, *row3;
guchar *outrow;
gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
channels = gimp_drawable_bpp (drawable->drawable_id);
gimp_pixel_rgn_init (&rgn_in, drawable, x1, y1, x2 - x1, y2 - y1, FALSE, FALSE);
gimp_pixel_rgn_init (&rgn_out, drawable, x1, y1, x2 - x1, y2 - y1, TRUE, TRUE);
/* Initialise enough memory for row1, row2, row3, outrow */
row1 = g_new (guchar, channels * (x2 - x1));
outrow = g_new (guchar, channels * (x2 - x1));
for (i = y1; i < y2; i++) {
/* Get row i-1, i, i+1 */
gimp_pixel_rgn_get_row (&rgn_in, row1, x1, MAX (y1, i - 1), x2 - x1);
for (j = x1; j < x2; j++) {
/* For each layer, compute the average of the nine pixels */
for (k = 0; k < channels; k++) {
int in = row1[channels * (j - x1) + k];
int a = (1.0 - (in / 255.0)) * 100.0;
int r = rand() % 100;
outrow[channels * (j - x1) + k] = r < a ? 0 : 255;
}
}
gimp_pixel_rgn_set_row (&rgn_out, outrow, x1, i, x2 - x1);
if (i % 10 == 0)
gimp_progress_update ((gdouble) (i - y1) / (gdouble) (y2 - y1));
}
g_free (row1);
g_free (outrow);
gimp_drawable_flush (drawable);
gimp_drawable_merge_shadow (drawable->drawable_id, TRUE);
gimp_drawable_update (drawable->drawable_id, x1, y1, x2 - x1, y2 - y1);
}
void run(const gchar *name,
gint nparams,
const GimpParam *param,
gint *nreturn_vals,
GimpParam **return_vals) {
static GimpParam values[1];
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
GimpRunMode run_mode;
GimpDrawable *drawable;
/* Setting mandatory output values */
*nreturn_vals = 1;
*return_vals = values;
values[0].type = GIMP_PDB_STATUS;
values[0].data.d_status = status;
/* Getting run_mode - we won't display a dialog if
* we are in NONINTERACTIVE mode */
run_mode = param[0].data.d_int32;
/* Get the specified drawable */
drawable = gimp_drawable_get(param[2].data.d_drawable);
gimp_progress_init("Dotify...");
/* Let's time blur
*
* GTimer timer = g_timer_new time();
*/
srand(time(NULL));
blur(drawable);
gimp_displays_flush();
gimp_drawable_detach(drawable);
}
static void query() {
static GimpParamDef args[] = {
{ GIMP_PDB_INT32, "run-mode", "Run mode" },
{ GIMP_PDB_IMAGE, "image", "Input image" },
{ GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }
};
gimp_install_procedure(
"plug-in-dotify",
"Dotify",
"Creates the appearance of an image drawn by black dots only",
"Andreas Textor",
"Copyright Andreas Textor",
"2009",
"_Dotify...",
"GRAY*",
GIMP_PLUGIN,
G_N_ELEMENTS(args), 0,
args, NULL);
gimp_plugin_menu_register("plug-in-dotify", "<Image>/Filters/Distorts");
}