📄 dpen4.c
字号:
/*************************************************************************/
/* */
/* Copyright (c) 1997 - 1999 Accelerated Technology, Inc. */
/* */
/* PROPRIETARY RIGHTS of Accelerated Technology are involved in the */
/* subject matter of this material. All manufacturing, reproduction, */
/* use, and sales rights pertaining to this subject matter are governed */
/* by the license agreement. The recipient of this software implicitly */
/* accepts the terms of the license. */
/* */
/*************************************************************************/
/*************************************************************************/
/* */
/* FILE NAME VERSION */
/* */
/* DPEN4.c 1.9 */
/* */
/* COMPONENT */
/* */
/* All */
/* */
/* DESCRIPTION */
/* */
/* This file contains the FindClosestRGB function. */
/* */
/* AUTHOR */
/* */
/* Robert G. Burrill, Accelerated Technology, Inc. */
/* */
/* DATA STRUCTURES */
/* */
/* None */
/* */
/* FUNCTIONS */
/* */
/* None */
/* */
/* DEPENDENCIES */
/* */
/* None */
/* */
/* HISTORY */
/* */
/* NAME DATE REMARKS */
/* */
/* */
/*************************************************************************/
#include "meta_wnd.h"
#include "metconst.h" /* MetaWINDOW Constant & Stucture Definitions */
#include "metports.h" /* MetaWINDOW Port & Bitmap Definitions */
#include "grafdata.h"
#define MAX_DEFWIN_X 640
/* Function FindClosestRGB returns the palette index of the color closest
to the specified target RGB value. RGBCOLOR is an RGB value stored
in a single "palData" palette record.
FindClosestRGB uses the Pythagorean distance formula to locate the
index in the RGBPALETTE array closest matching the RGBCOLOR value. */
int FindClosestRGB(palData *RGBCOLOR, palData *RGBPALETTE)
{
int QueryColors(void);
unsigned long minDistSq; /* closest distance, squared */
unsigned long tDistSq;
int minDistIndex; /* closest index */
int maxColor; /* max color index */
word red; /* 8 bit RGB target values */
word green;
word blue;
int i;
int j;
red = RGBCOLOR->palRed >> 8; /* scale RGBCOLOR components down to 8 bits */
green = RGBCOLOR->palGreen >> 8;
blue = RGBCOLOR->palBlue >> 8;
maxColor = QueryColors();
minDistSq = 0xfffffff;
minDistIndex = 0;
for (i = 0; i <= maxColor; i++) /* search for closest value in RGBPALETTE array */
{
j = (RGBPALETTE[i].palRed >> 8) - red;
tDistSq = j * j;
j = (RGBPALETTE[i].palGreen >> 8) - green;
tDistSq += (j * j);
j = (RGBPALETTE[i].palBlue >> 8) - blue;
tDistSq += (j * j);
if (tDistSq < minDistSq)
{ /* save the index and smallest distance (squared) */
minDistSq = tDistSq;
minDistIndex = i;
}
}
return (minDistIndex);
}
void ColorDiffusionDither(image *imgIn, palData *imgPal,
image *imgOut, palData *palPtr)
{
byte *imgInDataPtr, *imgOutDataPtr;
palData imgData;
int irow, icol, npal, iwidth, iheight, imgInData;
long colorErr, tempImgRed, tempImgGreen, tempImgBlue;
long rerr1[MAX_DEFWIN_X], rerr2[MAX_DEFWIN_X];
long gerr1[MAX_DEFWIN_X], gerr2[MAX_DEFWIN_X];
long berr1[MAX_DEFWIN_X], berr2[MAX_DEFWIN_X];
/* copy image header */
imgOut->imWidth = imgIn->imWidth; /* Image pixel width (X) */
imgOut->imHeight = imgIn->imHeight; /* Image pixel height (Y) */
imgOut->imAlign = imgIn->imAlign; /* Image alignment */
imgOut->imFlags = imgIn->imFlags; /* Image flags */
imgOut->imBytes = imgIn->imBytes; /* Image bytes per row */
imgOut->imBits = imgIn->imBits; /* Image bits per pixel */
imgOut->imPlanes = imgIn->imPlanes; /* Image planes per pixel */
/* get image values */
imgInDataPtr = imgIn->imData;
imgOutDataPtr = imgOut->imData;
iwidth = imgIn->imWidth - 1;
iheight = imgIn->imHeight - 1;
/* get the data and convert it */
/* get first pixel */
imgInData = *imgInDataPtr++;
imgData.palRed = (imgPal[imgInData].palRed);
imgData.palGreen = (imgPal[imgInData].palGreen);
imgData.palBlue = (imgPal[imgInData].palBlue);
npal = FindClosestRGB(&imgData, palPtr);
*imgOutDataPtr++ = npal; /* first pixel has no correction */
/* calculate corrections for surrounding points */
colorErr = ((imgData.palRed - palPtr[npal].palRed) >> 4);
rerr1[0] = 0;
rerr2[1] = colorErr;
rerr1[1] = (7 * colorErr);
rerr2[0] = (5 * colorErr);
colorErr = ((imgData.palGreen - palPtr[npal].palGreen) >> 4);
gerr1[0] = 0;
gerr2[1] = colorErr;
gerr1[1] = (7 * colorErr);
gerr2[0] = (5 * colorErr);
colorErr = ((imgData.palBlue - palPtr[npal].palBlue) >> 4);
berr1[0] = 0;
berr2[1] = colorErr;
berr1[1] = (7 * colorErr);
berr2[0] = (5 * colorErr);
/* do rest of first row */
for (icol = 1; icol < iwidth; icol++)
{
imgInData = *imgInDataPtr++;
tempImgRed = (imgPal[imgInData].palRed) + rerr1[icol];
if (tempImgRed < 0)
{
imgData.palRed = 0;
}
else
{
if (tempImgRed > 0xff00)
{
imgData.palRed = 0xff00;
}
else
{
imgData.palRed = (word) tempImgRed;
}
}
tempImgGreen = (imgPal[imgInData].palGreen) + gerr1[icol];
if (tempImgGreen < 0)
{
imgData.palGreen = 0;
}
else
{
if (tempImgGreen > 0xff00)
{
imgData.palGreen = 0xff00;
}
else
{
imgData.palGreen = (word) tempImgGreen;
}
}
tempImgBlue = (imgPal[imgInData].palBlue) + berr1[icol];
if (tempImgBlue < 0)
{
imgData.palBlue = 0;
}
else
{
if (tempImgBlue > 0xff00)
{
imgData.palBlue = 0xff00;
}
else
{
imgData.palBlue = (word) tempImgBlue;
}
}
npal = FindClosestRGB(&imgData, palPtr);
*imgOutDataPtr++ = npal; /* store corrected value */
/* calculate corrections for surrounding points */
colorErr = ((imgPal[imgInData].palRed - palPtr[npal].palRed) >> 4);
rerr2[icol+1] = colorErr;
rerr1[icol+1] = (7 * colorErr);
rerr2[icol-1] += (3 * colorErr);
rerr2[icol] += (5 * colorErr);
colorErr = ((imgPal[imgInData].palGreen - palPtr[npal].palGreen) >> 4);
gerr2[icol+1] = colorErr;
gerr1[icol+1] = (7 * colorErr);
gerr2[icol-1] += (3 * colorErr);
gerr2[icol] += (5 * colorErr);
colorErr = ((imgPal[imgInData].palBlue - palPtr[npal].palBlue) >> 4);
berr2[icol+1] = colorErr;
berr1[icol+1] = (7 * colorErr);
berr2[icol-1] += (3 * colorErr);
berr2[icol] += (5 * colorErr);
}
/* do last pixel */
imgInData = *imgInDataPtr++;
tempImgRed = (imgPal[imgInData].palRed) + rerr1[icol];
if (tempImgRed < 0)
{
imgData.palRed = 0;
}
else
{
if (tempImgRed > 0xff00)
{
imgData.palRed = 0xff00;
}
else
{
imgData.palRed = (word) tempImgRed;
}
}
tempImgGreen = (imgPal[imgInData].palGreen) + gerr1[icol];
if (tempImgGreen < 0)
{
imgData.palGreen = 0;
}
else
{
if (tempImgGreen > 0xff00)
{
imgData.palGreen = 0xff00;
}
else
{
imgData.palGreen = (word) tempImgGreen;
}
}
tempImgBlue = (imgPal[imgInData].palBlue) + berr1[icol];
if (tempImgBlue < 0)
{
imgData.palBlue = 0;
}
else
{
if (tempImgBlue > 0xff00)
{
imgData.palBlue = 0xff00;
}
else
{
imgData.palBlue = (word) tempImgBlue;
}
}
npal = FindClosestRGB(&imgData, palPtr);
*imgOutDataPtr++ = npal; /* store corrected value */
/* calculate corrections for surrounding points */
colorErr = ((imgPal[imgInData].palRed - palPtr[npal].palRed) >> 4);
rerr2[icol-1] += (3 * colorErr);
rerr2[icol] += (5 * colorErr);
colorErr = ((imgPal[imgInData].palGreen - palPtr[npal].palGreen) >> 4);
gerr2[icol-1] += (3 * colorErr);
gerr2[icol] += (5 * colorErr);
colorErr = ((imgPal[imgInData].palBlue - palPtr[npal].palBlue) >> 4);
berr2[icol-1] += (3 * colorErr);
berr2[icol] += (5 * colorErr);
/* do remaining rows */
for (irow = 1; irow < iheight; irow++)
{
/* get first pixel */
imgInData = *imgInDataPtr++;
tempImgRed = (imgPal[imgInData].palRed) + rerr2[icol];
if (tempImgRed < 0)
{
imgData.palRed = 0;
}
else
{
if (tempImgRed > 0xff00)
{
imgData.palRed = 0xff00;
}
else
{
imgData.palRed = (word) tempImgRed;
}
}
tempImgGreen = (imgPal[imgInData].palGreen) + gerr2[icol];
if (tempImgGreen < 0)
{
imgData.palGreen = 0;
}
else
{
if (tempImgGreen > 0xff00)
{
imgData.palGreen = 0xff00;
}
else
{
imgData.palGreen = (word) tempImgGreen;
}
}
tempImgBlue = (imgPal[imgInData].palBlue) + berr2[icol];
if (tempImgBlue < 0)
{
imgData.palBlue = 0;
}
else
{
if (tempImgBlue > 0xff00)
{
imgData.palBlue = 0xff00;
}
else
{
imgData.palBlue = (word) tempImgBlue;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -