0N/A/*
2362N/A * Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/*
0N/A * This file contains macro definitions for the Encoding category of
0N/A * the macros used by the generic scaleloop function.
0N/A *
0N/A * This implementation uses a Floyd-Steinberg error diffusion technique
0N/A * to produce a very high quality version of an image with only an 8-bit
0N/A * (or less) RGB colormap. The error diffusion technique requires that
0N/A * the input color information be delivered in a special order from the
0N/A * top row to the bottom row and then left to right within each row, thus
0N/A * it is only valid in cases where the ImageProducer has specified the
0N/A * TopDownLeftRight delivery hint. If the data is not read in that order,
0N/A * no mathematical or memory access errors should occur, but the dithering
0N/A * error will be spread through the pixels of the output image in an
0N/A * unpleasant manner.
0N/A */
0N/A
0N/A#include "img_fsutil.h"
0N/A
0N/A/*
0N/A * These definitions vector the standard macro names to the "Color"
0N/A * versions of those macros only if the "DitherDeclared" keyword has
0N/A * not yet been defined elsewhere. The "DitherDeclared" keyword is
0N/A * also defined here to claim ownership of the primary implementation
0N/A * even though this file does not rely on the definitions in any other
0N/A * files.
0N/A */
0N/A#ifndef DitherDeclared
0N/A#define DitherDeclared
0N/A#define DeclareDitherVars DeclareColorDitherVars
0N/A#define InitDither InitColorDither
0N/A#define StartDitherLine StartColorDitherLine
0N/A#define DitherPixel ColorDitherPixel
0N/A#define DitherBufComplete ColorDitherBufComplete
0N/A#endif
0N/A
0N/Atypedef struct {
0N/A int r, g, b;
0N/A} ColorDitherError;
0N/A
0N/A#define DeclareColorDitherVars \
0N/A int er, eg, eb; \
0N/A ColorDitherError *cep;
0N/A
0N/A#define InitColorDither(cvdata, clrdata, dstTW) \
0N/A do { \
0N/A if (cvdata->fserrors == 0) { \
0N/A int size = (dstTW + 2) * sizeof(ColorDitherError); \
0N/A cep = (ColorDitherError *) sysMalloc(size); \
0N/A if (cep == 0) { \
0N/A SignalError(0, JAVAPKG "OutOfMemoryError", 0); \
0N/A return SCALEFAILURE; \
0N/A } \
0N/A memset(cep, 0, size); \
0N/A cvdata->fserrors = (void *) cep; \
0N/A } \
0N/A } while (0)
0N/A
0N/A#define StartColorDitherLine(cvdata, dstX1, dstY) \
0N/A do { \
0N/A cep = (ColorDitherError *) cvdata->fserrors; \
0N/A if (dstX1) { \
0N/A er = cep[0].r; \
0N/A eg = cep[0].g; \
0N/A eb = cep[0].b; \
0N/A cep += dstX1; \
0N/A } else { \
0N/A er = eg = eb = 0; \
0N/A } \
0N/A } while (0)
0N/A
0N/A#define ColorDitherPixel(dstX, dstY, pixel, red, green, blue) \
0N/A do { \
0N/A int e1, e2, e3; \
0N/A \
0N/A /* add previous errors */ \
0N/A red += cep[1].r; \
0N/A green += cep[1].g; \
0N/A blue += cep[1].b; \
0N/A \
0N/A /* bounds checking */ \
0N/A e1 = ComponentBound(red); \
0N/A e2 = ComponentBound(green); \
0N/A e3 = ComponentBound(blue); \
0N/A \
0N/A /* Store the closest color in the destination pixel */ \
0N/A pixel = ColorCubeFSMap(e1, e2, e3); \
0N/A GetPixelRGB(pixel, red, green, blue); \
0N/A \
0N/A /* Set the error from the previous lap */ \
0N/A cep[1].r = er; cep[1].g = eg; cep[1].b = eb; \
0N/A \
0N/A /* compute the errors */ \
0N/A er = e1 - red; eg = e2 - green; eb = e3 - blue; \
0N/A \
0N/A /* distribute the errors */ \
0N/A DitherDist(cep, e1, e2, e3, er, r); \
0N/A DitherDist(cep, e1, e2, e3, eg, g); \
0N/A DitherDist(cep, e1, e2, e3, eb, b); \
0N/A cep++; \
0N/A } while (0)
0N/A
0N/A#define ColorDitherBufComplete(cvdata, dstX1) \
0N/A do { \
0N/A if (dstX1) { \
0N/A cep = (ColorDitherError *) cvdata->fserrors; \
0N/A cep[0].r = er; \
0N/A cep[0].g = eg; \
0N/A cep[0].b = eb; \
0N/A } \
0N/A } while (0)