blob: e0fef36fb3d7b7a97be276ae6bae83799f8d5e7b [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1996 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26/*
27 * This file contains macro definitions for the Encoding category of
28 * the macros used by the generic scaleloop function.
29 *
30 * This implementation uses a Floyd-Steinberg error diffusion technique
31 * to produce a very high quality version of an image with only an 8-bit
32 * (or less) RGB colormap. The error diffusion technique requires that
33 * the input color information be delivered in a special order from the
34 * top row to the bottom row and then left to right within each row, thus
35 * it is only valid in cases where the ImageProducer has specified the
36 * TopDownLeftRight delivery hint. If the data is not read in that order,
37 * no mathematical or memory access errors should occur, but the dithering
38 * error will be spread through the pixels of the output image in an
39 * unpleasant manner.
40 */
41
42#include "img_fsutil.h"
43
44/*
45 * These definitions vector the standard macro names to the "Color"
46 * versions of those macros only if the "DitherDeclared" keyword has
47 * not yet been defined elsewhere. The "DitherDeclared" keyword is
48 * also defined here to claim ownership of the primary implementation
49 * even though this file does not rely on the definitions in any other
50 * files.
51 */
52#ifndef DitherDeclared
53#define DitherDeclared
54#define DeclareDitherVars DeclareColorDitherVars
55#define InitDither InitColorDither
56#define StartDitherLine StartColorDitherLine
57#define DitherPixel ColorDitherPixel
58#define DitherBufComplete ColorDitherBufComplete
59#endif
60
61typedef struct {
62 int r, g, b;
63} ColorDitherError;
64
65#define DeclareColorDitherVars \
66 int er, eg, eb; \
67 ColorDitherError *cep;
68
69#define InitColorDither(cvdata, clrdata, dstTW) \
70 do { \
71 if (cvdata->fserrors == 0) { \
72 int size = (dstTW + 2) * sizeof(ColorDitherError); \
73 cep = (ColorDitherError *) sysMalloc(size); \
74 if (cep == 0) { \
75 SignalError(0, JAVAPKG "OutOfMemoryError", 0); \
76 return SCALEFAILURE; \
77 } \
78 memset(cep, 0, size); \
79 cvdata->fserrors = (void *) cep; \
80 } \
81 } while (0)
82
83#define StartColorDitherLine(cvdata, dstX1, dstY) \
84 do { \
85 cep = (ColorDitherError *) cvdata->fserrors; \
86 if (dstX1) { \
87 er = cep[0].r; \
88 eg = cep[0].g; \
89 eb = cep[0].b; \
90 cep += dstX1; \
91 } else { \
92 er = eg = eb = 0; \
93 } \
94 } while (0)
95
96#define ColorDitherPixel(dstX, dstY, pixel, red, green, blue) \
97 do { \
98 int e1, e2, e3; \
99 \
100 /* add previous errors */ \
101 red += cep[1].r; \
102 green += cep[1].g; \
103 blue += cep[1].b; \
104 \
105 /* bounds checking */ \
106 e1 = ComponentBound(red); \
107 e2 = ComponentBound(green); \
108 e3 = ComponentBound(blue); \
109 \
110 /* Store the closest color in the destination pixel */ \
111 pixel = ColorCubeFSMap(e1, e2, e3); \
112 GetPixelRGB(pixel, red, green, blue); \
113 \
114 /* Set the error from the previous lap */ \
115 cep[1].r = er; cep[1].g = eg; cep[1].b = eb; \
116 \
117 /* compute the errors */ \
118 er = e1 - red; eg = e2 - green; eb = e3 - blue; \
119 \
120 /* distribute the errors */ \
121 DitherDist(cep, e1, e2, e3, er, r); \
122 DitherDist(cep, e1, e2, e3, eg, g); \
123 DitherDist(cep, e1, e2, e3, eb, b); \
124 cep++; \
125 } while (0)
126
127#define ColorDitherBufComplete(cvdata, dstX1) \
128 do { \
129 if (dstX1) { \
130 cep = (ColorDitherError *) cvdata->fserrors; \
131 cep[0].r = er; \
132 cep[0].g = eg; \
133 cep[0].b = eb; \
134 } \
135 } while (0)