26
26
#include <stdlib.h>
30
28
#include <libgimp/gimp.h>
31
29
#include <libgimp/gimpui.h>
33
31
#include "libgimp/stdplugins-intl.h"
34
#define PLUG_IN_PROC "plug-in-filter-pack"
35
#define PLUG_IN_BINARY "fp"
35
37
#define MAX_PREVIEW_SIZE 125
36
38
#define MAX_ROUGHNESS 128
37
39
#define RANGE_HEIGHT 15
38
40
#define PR_BX_BRDR 4
42
#define HELP_ID "plug-in-filter-pack"
44
43
#define RANGE_ADJUST_MASK GDK_EXPOSURE_MASK | \
45
GDK_ENTER_NOTIFY_MASK | \
46
GDK_BUTTON_PRESS_MASK | \
47
GDK_BUTTON_RELEASE_MASK | \
48
GDK_BUTTON1_MOTION_MASK | \
49
GDK_POINTER_MOTION_HINT_MASK
44
GDK_ENTER_NOTIFY_MASK | \
45
GDK_BUTTON_PRESS_MASK | \
46
GDK_BUTTON_RELEASE_MASK | \
47
GDK_BUTTON1_MOTION_MASK | \
48
GDK_POINTER_MOTION_HINT_MASK
317
317
GimpParamDef args[] =
319
{ GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
319
{ GIMP_PDB_INT32, "run-mode", "Interactive, non-interactive" },
320
320
{ GIMP_PDB_IMAGE, "image", "Input image (used for indexed images)" },
321
{ GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
321
{ GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }
324
gimp_install_procedure ("plug_in_filter_pack",
325
"Allows the user to change H, S, or C with many previews",
324
gimp_install_procedure (PLUG_IN_PROC,
325
N_("Interactively modify the image colors"),
326
"Interactively modify the image colors.",
327
327
"Pavel Grinfeld (pavel@ml.com)",
328
328
"Pavel Grinfeld (pavel@ml.com)",
329
329
"27th March 1997",
1065
1077
fpvals.touched[fpvals.value_by] = 1;
1067
if (data == (gpointer) hue_red) {
1068
update_current_fp (HUE, RED);
1069
} else if (data == (gpointer) hue_green) {
1070
update_current_fp (HUE, GREEN);
1071
} else if (data == (gpointer) hue_blue) {
1072
update_current_fp (HUE, BLUE);
1073
} else if (data == (gpointer) hue_cyan) {
1074
update_current_fp (HUE, CYAN);
1075
} else if (data == (gpointer) hue_yellow) {
1076
update_current_fp (HUE, YELLOW);
1077
} else if (data == (gpointer) hue_magenta) {
1078
update_current_fp (HUE, MAGENTA);
1079
} else if (data == (gpointer) val_darker) {
1080
update_current_fp (VALUE, DOWN);
1081
} else if (data == (gpointer) val_lighter) {
1082
update_current_fp (VALUE, UP);
1083
} else if (data == (gpointer) sat_more) {
1084
update_current_fp (SATURATION, UP);
1085
} else if (data == (gpointer) sat_less) {
1086
update_current_fp (SATURATION, DOWN);
1079
if (data == (gpointer) hue_red)
1081
update_current_fp (HUE, RED);
1083
else if (data == (gpointer) hue_green)
1085
update_current_fp (HUE, GREEN);
1087
else if (data == (gpointer) hue_blue)
1089
update_current_fp (HUE, BLUE);
1091
else if (data == (gpointer) hue_cyan)
1093
update_current_fp (HUE, CYAN);
1095
else if (data == (gpointer) hue_yellow)
1097
update_current_fp (HUE, YELLOW);
1099
else if (data == (gpointer) hue_magenta)
1101
update_current_fp (HUE, MAGENTA);
1103
else if (data == (gpointer) val_darker)
1105
update_current_fp (VALUE, DOWN);
1107
else if (data == (gpointer) val_lighter)
1109
update_current_fp (VALUE, UP);
1111
else if (data == (gpointer) sat_more)
1113
update_current_fp (SATURATION, UP);
1115
else if (data == (gpointer) sat_less)
1117
update_current_fp (SATURATION, DOWN);
1089
1120
fp_refresh_previews (fpvals.visible_frames);
1173
1207
GtkWidget *control;
1174
1208
GtkWidget *table;
1176
reduced = fp_reduce_image (drawable,mask,
1177
fpvals.preview_size,
1178
fpvals.selection_only);
1180
gimp_ui_init ("fp", TRUE);
1182
dlg = gimp_dialog_new (_("Filter Pack Simulation"), "fp",
1210
reduced = fp_reduce_image (drawable, mask,
1211
fpvals.preview_size,
1212
fpvals.selection_only);
1214
gimp_ui_init (PLUG_IN_BINARY, TRUE);
1216
dlg = gimp_dialog_new (_("Filter Pack Simulation"), PLUG_IN_BINARY,
1184
gimp_standard_help_func, HELP_ID,
1218
gimp_standard_help_func, PLUG_IN_PROC,
1186
1220
GIMP_STOCK_RESET, RESPONSE_RESET,
1187
1221
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1222
1264
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
1224
1266
gtk_table_attach (GTK_TABLE (table), control, 1, 2, 1, 3,
1225
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
1267
GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0);
1227
1269
gtk_table_attach (GTK_TABLE (table), rough, 1, 2, 3, 4,
1228
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
1270
GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0);
1230
1272
gtk_table_attach (GTK_TABLE (table), show, 0, 1, 1, 2,
1231
GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
1273
GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0);
1233
1275
gtk_table_attach (GTK_TABLE (table), range, 0, 1, 2, 3,
1234
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
1276
GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0);
1236
1278
gtk_table_attach (GTK_TABLE (table), pixelsBy, 0, 1, 3, 4,
1237
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
1279
GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0);
1239
1281
gtk_widget_show (dlg);
1618
1661
static ReducedImage *
1619
fp_reduce_image (GimpDrawable *drawable,
1662
fp_reduce_image (GimpDrawable *drawable,
1620
1663
GimpDrawable *mask,
1621
1664
gint longer_size,
1622
1665
gint selection)
1624
gint RH, RW, width, height, bytes=drawable->bpp;
1625
ReducedImage *temp = (ReducedImage *) malloc (sizeof (ReducedImage));
1667
gint RH, RW, bytes = drawable->bpp;
1668
gint x, y, width, height;
1669
ReducedImage *temp = g_new0 (ReducedImage, 1);
1626
1670
guchar *tempRGB, *src_row, *tempmask, *src_mask_row, R, G, B;
1627
gint i, j, whichcol, whichrow, x1, x2, y1, y2;
1671
gint i, j, whichcol, whichrow;
1628
1672
GimpPixelRgn srcPR, srcMask;
1629
gboolean NoSelectionMade = TRUE;
1630
1673
gdouble *tempHSV;
1634
gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
1638
if (width != drawable->width && height != drawable->height)
1639
NoSelectionMade = FALSE;
1644
x2 = drawable->width;
1646
y2 = drawable->height;
1648
else if (selection == 2)
1650
x1 = MAX (0, x1 - width / 2.0);
1651
x2 = MIN (drawable->width, x2 + width / 2.0);
1652
y1 = MAX (0, y1 - height / 2.0);
1653
y2 = MIN (drawable->height, y2 + height / 2.0);
1681
width = drawable->width;
1683
height = drawable->height;
1687
if (! gimp_drawable_mask_intersect (drawable->drawable_id,
1688
&x, &y, &width, &height))
1693
if (! gimp_drawable_mask_intersect (drawable->drawable_id,
1694
&x, &y, &width, &height) ||
1695
! gimp_rectangle_intersect (x - width / 2, y - height / 2,
1696
2 * width, 2 * height,
1697
0, 0, drawable->width, drawable->height,
1698
&x, &y, &width, &height))
1659
1706
if (width > height)
1667
1714
RW = (gdouble) width * (gdouble) longer_size / (gdouble) height;
1670
tempRGB = (guchar *) malloc (RW * RH * bytes);
1671
tempHSV = (gdouble *) malloc (RW * RH * bytes * sizeof (gdouble));
1672
tempmask = (guchar *) malloc (RW * RH);
1674
gimp_pixel_rgn_init (&srcPR, drawable, x1, y1, width, height, FALSE, FALSE);
1675
gimp_pixel_rgn_init (&srcMask, mask, x1, y1, width, height, FALSE, FALSE);
1677
src_row = (guchar *) malloc (width * bytes);
1678
src_mask_row = (guchar *) malloc (width * bytes);
1717
tempRGB = g_new (guchar, RW * RH * bytes);
1718
tempHSV = g_new (gdouble, RW * RH * bytes);
1719
tempmask = g_new (guchar, RW * RH);
1721
gimp_pixel_rgn_init (&srcPR, drawable, x, y, width, height, FALSE, FALSE);
1722
gimp_pixel_rgn_init (&srcMask, mask, x, y, width, height, FALSE, FALSE);
1724
src_row = g_new (guchar, width * bytes);
1725
src_mask_row = g_new (guchar, width * bytes);
1680
1727
for (i = 0; i < RH; i++)
1682
1729
whichrow = (gdouble) i * (gdouble) height / (gdouble) RH;
1684
gimp_pixel_rgn_get_row (&srcPR, src_row, x1, y1 + whichrow, width);
1685
gimp_pixel_rgn_get_row (&srcMask, src_mask_row, x1, y1 + whichrow, width);
1731
gimp_pixel_rgn_get_row (&srcPR, src_row, x, y + whichrow, width);
1732
gimp_pixel_rgn_get_row (&srcMask, src_mask_row, x, y + whichrow, width);
1687
1734
for (j = 0; j < RW; j++)
1689
1736
whichcol = (gdouble) j * (gdouble) width / (gdouble) RW;
1691
if (NoSelectionMade)
1692
tempmask[i * RW + j] = 255;
1694
tempmask[i * RW + j] = src_mask_row[whichcol];
1738
tempmask[i * RW + j] = src_mask_row[whichcol];
1696
1740
R = src_row[whichcol * bytes + 0];
1697
1741
G = src_row[whichcol * bytes + 1];
1740
1787
gint tempSat[JUDGE_BY][256];
1742
a = g_new (guchar, 4*RW*RH);
1789
a = g_new (guchar, 4 * RW * RH);
1744
if (change_what==SATURATION)
1791
if (change_what == SATURATION)
1745
1792
for (k = 0; k < 256; k++)
1747
1794
for (JudgeBy = BY_HUE; JudgeBy < JUDGE_BY; JudgeBy++)
1748
1795
tempSat[JudgeBy][k] = 0;
1749
tempSat[fpvals.value_by][k] += change_which * nudgeArray[(k + fpvals.offset) % 256];
1797
tempSat[fpvals.value_by][k] +=
1798
change_which * nudgeArray[(k + fpvals.offset) % 256];
1752
1801
for (i = 0; i < RH; i++)
1754
1803
for (j = 0; j < RW; j++)
1756
backupP[0] = P[0] = (int) reduced->rgb[i * RW * bytes + j * bytes + 0];
1757
backupP[1] = P[1] = (int) reduced->rgb[i * RW * bytes + j * bytes + 1];
1758
backupP[2] = P[2] = (int) reduced->rgb[i * RW * bytes + j * bytes + 2];
1760
m = MIN (MIN (P[0], P[1]), P[2]);
1761
M = MAX (MAX (P[0], P[1]), P[2]);
1763
middle = (M + m) / 2;
1765
for (k = 0; k < 3; k++)
1766
if (P[k] != m && P[k] != M) middle = P[k];
1768
partial = reduced->mask[i * RW + j] / 255.0;
1770
for (JudgeBy = BY_HUE; JudgeBy < JUDGE_BY; JudgeBy++)
1772
if (!fpvals.touched[JudgeBy]) continue;
1774
Inten = reduced->hsv[i * RW * bytes + j * bytes + JudgeBy] * 255.0;
1776
/*DO SATURATION FIRST*/
1777
if (change_what != NONEATALL)
1781
for (k = 0; k < 3; k++)
1782
if (backupP[k] == M)
1783
P[k] = MAX (P[k] + partial * fpvals.sat_adjust[JudgeBy][Inten],
1785
else if (backupP[k] == m)
1786
P[k] = MIN (P[k] - partial * fpvals.sat_adjust[JudgeBy][Inten],
1790
P[0] += partial * fpvals.red_adjust[JudgeBy][Inten];
1791
P[1] += partial * fpvals.green_adjust[JudgeBy][Inten];
1792
P[2] += partial * fpvals.blue_adjust[JudgeBy][Inten];
1796
Inten = reduced->hsv[i * RW * bytes + j * bytes + fpvals.value_by] * 255.0;
1797
nudge = partial * nudgeArray[(Inten + fpvals.offset) % 256];
1799
switch (change_what)
1802
P[0] += colorSign[RED][change_which] * nudge;
1803
P[1] += colorSign[GREEN][change_which] * nudge;
1804
P[2] += colorSign[BLUE][change_which] * nudge;
1805
backupP[0] = P[0] = reduced->rgb[i * RW * bytes + j * bytes + 0];
1806
backupP[1] = P[1] = reduced->rgb[i * RW * bytes + j * bytes + 1];
1807
backupP[2] = P[2] = reduced->rgb[i * RW * bytes + j * bytes + 2];
1809
m = MIN (MIN (P[0], P[1]), P[2]);
1810
M = MAX (MAX (P[0], P[1]), P[2]);
1812
middle = (M + m) / 2;
1814
for (k = 0; k < 3; k++)
1815
if (P[k] != m && P[k] != M) middle = P[k];
1817
partial = reduced->mask[i * RW + j] / 255.0;
1808
1819
for (JudgeBy = BY_HUE; JudgeBy < JUDGE_BY; JudgeBy++)
1809
for (k = 0; k < 3; k++)
1821
if (!fpvals.touched[JudgeBy])
1825
reduced->hsv[i * RW * bytes + j * bytes + JudgeBy] * 255.0;
1827
/*DO SATURATION FIRST*/
1828
if (change_what != NONEATALL)
1812
if (backupP[k] == M)
1813
P[k] = MAX (P[k] + partial * tempSat[JudgeBy][Inten],
1815
else if (backupP[k] == m)
1816
P[k] = MIN (P[k]- partial * tempSat[JudgeBy][Inten],
1822
P[0] += change_which * nudge;
1823
P[1] += change_which * nudge;
1824
P[2] += change_which * nudge;
1831
a[(i * RW + j) * 4 + 0] = CLAMP0255(P[0]);
1832
a[(i * RW + j) * 4 + 1] = CLAMP0255(P[1]);
1833
a[(i * RW + j) * 4 + 2] = CLAMP0255(P[2]);
1836
a[(i * RW + j) * 4 + 3] = reduced->rgb[i * RW * bytes + j * bytes + 3];
1838
a[(i * RW + j) * 4 + 3] = 255;
1832
for (k = 0; k < 3; k++)
1833
if (backupP[k] == M)
1835
partial * fpvals.sat_adjust[JudgeBy][Inten],
1837
else if (backupP[k] == m)
1839
partial * fpvals.sat_adjust[JudgeBy][Inten],
1843
P[0] += partial * fpvals.red_adjust[JudgeBy][Inten];
1844
P[1] += partial * fpvals.green_adjust[JudgeBy][Inten];
1845
P[2] += partial * fpvals.blue_adjust[JudgeBy][Inten];
1850
reduced->hsv[i * RW * bytes + j * bytes + fpvals.value_by] * 255.0;
1851
nudge = partial * nudgeArray[(Inten + fpvals.offset) % 256];
1853
switch (change_what)
1856
P[0] += colorSign[RED][change_which] * nudge;
1857
P[1] += colorSign[GREEN][change_which] * nudge;
1858
P[2] += colorSign[BLUE][change_which] * nudge;
1862
for (JudgeBy = BY_HUE; JudgeBy < JUDGE_BY; JudgeBy++)
1863
for (k = 0; k < 3; k++)
1866
if (backupP[k] == M)
1867
P[k] = MAX (P[k] + partial * tempSat[JudgeBy][Inten],
1869
else if (backupP[k] == m)
1870
P[k] = MIN (P[k]- partial * tempSat[JudgeBy][Inten],
1876
P[0] += change_which * nudge;
1877
P[1] += change_which * nudge;
1878
P[2] += change_which * nudge;
1885
a[(i * RW + j) * 4 + 0] = CLAMP0255(P[0]);
1886
a[(i * RW + j) * 4 + 1] = CLAMP0255(P[1]);
1887
a[(i * RW + j) * 4 + 2] = CLAMP0255(P[2]);
1890
a[(i * RW + j) * 4 + 3] = reduced->rgb[i * RW * bytes + j * bytes + 3];
1892
a[(i * RW + j) * 4 + 3] = 255;