1/* 2 * Copyright (c) 1996, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * 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) gray ramp. The error diffusion technique requires that the 33 * input color information be delivered in a special order from the top 34 * 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 "Gray" 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 DeclareGrayDitherVars 55#define InitDither InitGrayDither 56#define StartDitherLine StartGrayDitherLine 57#define DitherPixel GrayDitherPixel 58#define DitherBufComplete GrayDitherBufComplete 59#endif 60 61typedef struct { 62 int gray; 63} GrayDitherError; 64 65#define DeclareGrayDitherVars \ 66 extern unsigned char img_grays[256]; \ 67 extern unsigned char img_bwgamma[256]; \ 68 int egray; \ 69 GrayDitherError *gep; 70 71#define InitGrayDither(cvdata, clrdata, dstTW) \ 72 do { \ 73 if (cvdata->fserrors == 0) { \ 74 int size = (dstTW + 2) * sizeof(GrayDitherError); \ 75 gep = (GrayDitherError *) sysMalloc(size); \ 76 if (gep == 0) { \ 77 SignalError(0, JAVAPKG "OutOfMemoryError", 0); \ 78 return SCALEFAILURE; \ 79 } \ 80 memset(gep, 0, size); \ 81 cvdata->fserrors = (void *) gep; \ 82 } \ 83 } while (0) 84 85 86#define StartGrayDitherLine(cvdata, dstX1, dstY) \ 87 do { \ 88 gep = cvdata->fserrors; \ 89 if (dstX1) { \ 90 egray = gep[0].gray; \ 91 gep += dstX1; \ 92 } else { \ 93 egray = 0; \ 94 } \ 95 } while (0) 96 97#define GrayDitherPixel(dstX, dstY, pixel, red, green, blue) \ 98 do { \ 99 int e1, e2, e3; \ 100 \ 101 /* convert to gray value */ \ 102 e2 = RGBTOGRAY(red, green, blue); \ 103 \ 104 /* add previous errors */ \ 105 e2 += gep[1].gray; \ 106 \ 107 /* bounds checking */ \ 108 e2 = ComponentBound(e2); \ 109 \ 110 /* Store the closest color in the destination pixel */ \ 111 e2 = img_bwgamma[e2]; \ 112 pixel = img_grays[e2]; \ 113 GetPixelRGB(pixel, red, green, blue); \ 114 \ 115 /* Set the error from the previous lap */ \ 116 gep[1].gray = egray; \ 117 \ 118 /* compute the errors */ \ 119 egray = e2 - red; \ 120 \ 121 /* distribute the errors */ \ 122 DitherDist(gep, e1, e2, e3, egray, gray); \ 123 gep++; \ 124 } while (0) 125 126#define GrayDitherBufComplete(cvdata, dstX1) \ 127 do { \ 128 if (dstX1) { \ 129 gep = cvdata->fserrors; \ 130 gep[0].gray = egray; \ 131 } \ 132 } while (0) 133