2020-09-30 17:12:29 +02:00

3870 lines
164 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/****************************************************************************
SCALEBIT.C
$Log: S:\products\wangview\oiwh\display\scalebit.c_v $
*
* Rev 1.32 22 Apr 1996 09:38:58 BEG06016
* Cleaned up error checking.
*
* Rev 1.31 15 Apr 1996 08:25:24 BEG06016
* Fixed a build problem.
*
* Rev 1.30 12 Apr 1996 15:53:10 RC
* Changed the way lines 1 & 2 were set up in scalebwstamp
*
* Rev 1.29 21 Mar 1996 10:49:46 RC
* Changed the way lrrect was passed into functions from value to
* reference (the power pc compiler couldnt handle those cases)
*
* Rev 1.28 07 Feb 1996 09:10:22 BLJ
* Made scaling with a BW scale algorithm with non-BW data an error.
*
* Rev 1.27 02 Jan 1996 12:51:50 BLJ
* Fixed bug in BW_AVG_TO_BW scale algorithm.
*
* Rev 1.26 02 Jan 1996 09:57:30 BLJ
* Changed alot of UINTs to ints.
* Changed IMG structure to include the image data.
* Changed lp prefix to p.
*
* Rev 1.25 22 Dec 1995 11:11:30 BLJ
* Added a parameter for zero init'ing to some memory manager calls.
*
* Rev 1.24 14 Dec 1995 08:39:12 BLJ
* Added BW_AVERAGE_TO_BW scale algorithm.
* Also fixed a problem with BW scaling to gray.
*
* Rev 1.23 29 Nov 1995 11:19:18 BLJ
* Fixed 5436 Distortion of image when scrolled.
*
* Rev 1.22 19 Nov 1995 13:26:56 BLJ
* Fixed 5370. Garbage during BW scale to gray.
*
* Rev 1.21 18 Nov 1995 16:31:24 RC
* Fixed nloopend computation in scalebwtogray
*
* Rev 1.20 07 Nov 1995 09:41:02 BLJ
* Added stack checking pragma.
*
* Rev 1.19 18 Aug 1995 11:06:52 RC
* Initialized pLine1
*
* Rev 1.18 17 Aug 1995 14:56:12 BLJ
* Prevented freeing of non-allocated memory.
*
****************************************************************************/
#include "privdisp.h"
#pragma check_stack(on)
//
/****************************************************************************
FUNCTION: ScaleBits
PURPOSE: Dispatches the scale operation.
*****************************************************************************/
int WINAPI ScaleBits(PIMG pSourceImg, PIMG pDestImg, int nScaleAlgorithm,
int nHScale, int nVScale,
LRECT lrSourceRect, LRECT lrDestRect, LPRGBQUAD pPalette){
int nStatus = 0;
LRECT lrRect;
if (nHScale < 20 || nVScale < 20){
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
if (!pSourceImg){
nStatus = Error(DISPLAY_IMAGETYPENOTSUPPORTED);
goto Exit;
}
SetLRect(lrRect, 0, 0, lrDestRect.right - lrDestRect.left,
lrDestRect.bottom - lrDestRect.top);
switch (pSourceImg->nType){
case ITYPE_BI_LEVEL:
switch (nScaleAlgorithm){
case OI_SCALE_ALG_AVERAGE_TO_GRAY4:
case OI_SCALE_ALG_AVERAGE_TO_GRAY7:
case OI_SCALE_ALG_AVERAGE_TO_GRAY8:
CheckError2( ScaleBWToGray(pSourceImg, pDestImg, nHScale, nVScale,
lrDestRect.left, lrDestRect.top, &lrRect));
break;
case OI_SCALE_ALG_USE_DEFAULT:
case OI_SCALE_ALG_NORMAL:
CheckError2( Scale1BPPDecimate(pSourceImg, pDestImg, nHScale, nVScale,
lrDestRect.left, lrDestRect.top, &lrRect));
break;
case OI_SCALE_ALG_STAMP:
CheckError2( ScaleBWStamp(pSourceImg, pDestImg, nHScale, nVScale,
lrDestRect.left, lrDestRect.top, lrRect));
break;
case OI_SCALE_ALG_BW_KEEP_BLACK:
CheckError2( ScaleBWKeepBlack(pSourceImg, pDestImg, nHScale, nVScale,
lrDestRect.left, lrDestRect.top, &lrRect));
break;
case OI_SCALE_ALG_BW_AVERAGE_TO_BW:
CheckError2( ScaleBWAvgToBW(pSourceImg, pDestImg, nHScale, nVScale,
lrDestRect.left, lrDestRect.top, &lrRect));
break;
case OI_SCALE_ALG_BW_MINORITY:
case OI_SCALE_ALG_BW_MAJORITY:
default:
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
break;
case ITYPE_GRAY4:
switch (nScaleAlgorithm){
case OI_SCALE_ALG_AVERAGE_TO_GRAY4:
case OI_SCALE_ALG_AVERAGE_TO_GRAY7:
case OI_SCALE_ALG_AVERAGE_TO_GRAY8:
CheckError2( ScaleGray4ToGray(pSourceImg, pDestImg, nHScale, nVScale,
lrDestRect.left, lrDestRect.top, &lrRect));
break;
case OI_SCALE_ALG_USE_DEFAULT:
case OI_SCALE_ALG_NORMAL:
CheckError2( Scale4BPPDecimate(pSourceImg, pDestImg, nHScale, nVScale,
lrDestRect.left, lrDestRect.top, lrRect));
break;
case OI_SCALE_ALG_STAMP:
CheckError2( ScaleGray4ToGray(pSourceImg, pDestImg, nHScale, nVScale,
lrDestRect.left, lrDestRect.top, &lrRect));
break;
case OI_SCALE_ALG_BW_KEEP_BLACK:
case OI_SCALE_ALG_BW_MINORITY:
case OI_SCALE_ALG_BW_MAJORITY:
default:
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
break;
case ITYPE_GRAY7:
case ITYPE_GRAY8:
switch (nScaleAlgorithm){
case OI_SCALE_ALG_AVERAGE_TO_GRAY4:
case OI_SCALE_ALG_AVERAGE_TO_GRAY7:
case OI_SCALE_ALG_AVERAGE_TO_GRAY8:
CheckError2( ScaleGray8ToGray(pSourceImg, pDestImg, nHScale, nVScale,
lrDestRect.left, lrDestRect.top, lrRect));
break;
case OI_SCALE_ALG_USE_DEFAULT:
case OI_SCALE_ALG_NORMAL:
CheckError2( Scale8BPPDecimate(pSourceImg, pDestImg, nHScale, nVScale,
lrDestRect.left, lrDestRect.top, lrRect));
break;
case OI_SCALE_ALG_STAMP:
CheckError2( ScaleGray8ToGray(pSourceImg, pDestImg, nHScale, nVScale,
lrDestRect.left, lrDestRect.top, lrRect));
break;
case OI_SCALE_ALG_BW_KEEP_BLACK:
case OI_SCALE_ALG_BW_MINORITY:
case OI_SCALE_ALG_BW_MAJORITY:
default:
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
break;
case ITYPE_PAL4:
switch (nScaleAlgorithm){
case OI_SCALE_ALG_USE_DEFAULT:
case OI_SCALE_ALG_NORMAL:
case OI_SCALE_ALG_STAMP:
CheckError2( Scale4BPPDecimate(pSourceImg, pDestImg, nHScale, nVScale,
lrDestRect.left, lrDestRect.top, lrRect));
break;
case OI_SCALE_ALG_AVERAGE_TO_GRAY4:
case OI_SCALE_ALG_AVERAGE_TO_GRAY7:
case OI_SCALE_ALG_AVERAGE_TO_GRAY8:
CheckError2( ScalePal4ToGray(pSourceImg, pDestImg, nHScale, nVScale,
lrDestRect.left, lrDestRect.top, &lrRect, pPalette));
break;
case OI_SCALE_ALG_BW_KEEP_BLACK:
case OI_SCALE_ALG_BW_MINORITY:
case OI_SCALE_ALG_BW_MAJORITY:
default:
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
break;
case ITYPE_COMPAL8:
case ITYPE_CUSPAL8:
switch (nScaleAlgorithm){
case OI_SCALE_ALG_USE_DEFAULT:
case OI_SCALE_ALG_STAMP:
case OI_SCALE_ALG_NORMAL:
CheckError2( Scale8BPPDecimate(pSourceImg, pDestImg, nHScale, nVScale,
lrDestRect.left, lrDestRect.top, lrRect));
break;
case OI_SCALE_ALG_AVERAGE_TO_GRAY4:
case OI_SCALE_ALG_AVERAGE_TO_GRAY7:
case OI_SCALE_ALG_AVERAGE_TO_GRAY8:
CheckError2( ScalePal8ToGray(pSourceImg, pDestImg, nHScale, nVScale,
lrDestRect.left, lrDestRect.top, lrRect, pPalette));
break;
case OI_SCALE_ALG_BW_KEEP_BLACK:
case OI_SCALE_ALG_BW_MINORITY:
case OI_SCALE_ALG_BW_MAJORITY:
default:
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
break;
case ITYPE_RGB24:
case ITYPE_BGR24:
switch (nScaleAlgorithm){
case OI_SCALE_ALG_AVERAGE_TO_GRAY4:
case OI_SCALE_ALG_AVERAGE_TO_GRAY7:
case OI_SCALE_ALG_AVERAGE_TO_GRAY8:
CheckError2( ScaleRGBToGrayAvg(pSourceImg, pDestImg, nHScale, nVScale,
lrDestRect.left, lrDestRect.top, lrRect));
break;
case OI_SCALE_ALG_USE_DEFAULT:
case OI_SCALE_ALG_STAMP:
case OI_SCALE_ALG_NORMAL:
CheckError2( Scale24BPPDecimate(pSourceImg, pDestImg, nHScale, nVScale,
lrDestRect.left, lrDestRect.top, lrRect));
break;
case OI_SCALE_ALG_BW_KEEP_BLACK:
case OI_SCALE_ALG_BW_MINORITY:
case OI_SCALE_ALG_BW_MAJORITY:
default:
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
break;
default:
nStatus = Error(DISPLAY_IMAGETYPENOTSUPPORTED);
goto Exit;
}
Exit:
return(nStatus);
}
//
/****************************************************************************
FUNCTION: ScaleBWAvgToBW
PURPOSE: Scales BW images to BW via averaging and error diffusion.
*****************************************************************************/
int WINAPI ScaleBWAvgToBW(PIMG pSourceImg, PIMG pDestImg, int nHScale, int nVScale,
int nHDestOffset, int nVDestOffset, LRECT *plrDestRect){
int nStatus = 0;
int nDest[MAX_PIXELS_HANDLED];
int nDestPixel[MAX_BW_BYTES_HANDLED];
int nPixels[MAX_BW_BYTES_HANDLED];
int nMask0[MAX_BW_BYTES_HANDLED];
int nMask1[MAX_BW_BYTES_HANDLED];
int nMask2[MAX_BW_BYTES_HANDLED];
int nMask3[MAX_BW_BYTES_HANDLED];
int nMask4[MAX_BW_BYTES_HANDLED];
int nMask5[MAX_BW_BYTES_HANDLED];
int nMask6[MAX_BW_BYTES_HANDLED];
int nMask7[MAX_BW_BYTES_HANDLED];
int nMask8[MAX_BW_BYTES_HANDLED];
int nGrayScaleTable1[2500];
int nGrayScaleTable2[2500];
int nPixelIndex;
int nDestWidth;
int nDestWidthInts;
int nDestHeight;
int nSourcePixelsPerLinePerPixel;
int nSourceLinesPerPixel;
int nDestLine;
PINT pnSourceLineOffsets = 0; // Table nsed to translate dest line offsets to source line offsets.
PBYTE pSourceLine; // The address of the start of the source line.
PBYTE pSourceByte; // The address of the source byte currently being processed.
PBYTE pDestLine; // The address of the start of the dest line.
int nFirstMask;
int nSourcePixel;
int nScaleDenominator;
int nCountTable[256];
int nSourceWidth;
int nSourceHeight;
int nNumberOfSourceBitsPerDestBit;
int nFirstSourceByte;
int nSourceBytes;
int nSourceByteIndex;
int nDestPixel0;
int nDestPixel1;
int nDestPixel2;
int nDestPixel3;
int nDestPixel4;
int nDestPixel5;
int nDestPixel6;
int nDestPixel7;
int nDestPixel8;
PINT pnLine0 = 0;
PINT pnLine1 = 0;
PINT pnThisLine;
PINT pnNextLine;
PINT pnDestLineGray;
int nBitMask;
int nLineSize;
int nPixel;
int nSourceByte;
int nThreshold;
int nThresholdTimes2;
// Loop variables.
int nLoop;
int nLoop2;
int nSourceLineCount;
int nLoopEnd;
LRECT lrDestRect ;
CopyRect (lrDestRect, *plrDestRect) ;
if (!pDestImg || pDestImg->nType != ITYPE_BI_LEVEL){
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
if (nHScale == 62 || nHScale == 31){
nScaleDenominator = 992;
}else{
nScaleDenominator = SCALE_DENOMINATOR;
}
nDestWidth = (lrDestRect.right - lrDestRect.left);
nDestHeight = (lrDestRect.bottom - lrDestRect.top);
nFirstSourceByte = ((((lrDestRect.left + nHDestOffset) * nScaleDenominator)
/ nHScale) / 8);
nSourceWidth = pSourceImg->nWidth;
nSourceBytes = ((min(nSourceWidth,
(((lrDestRect.right + nHDestOffset) * nScaleDenominator) / nHScale))
+ 7) / 8) - nFirstSourceByte;
if (nSourceBytes * 8 > MAX_PIXELS_HANDLED || nDestWidth > MAX_PIXELS_HANDLED
|| nSourceWidth < (nScaleDenominator / nHScale)){
nStatus = Error(DISPLAY_INVALIDRECT);
goto Exit;
}
memset((PSTR) nDestPixel, 0, sizeof(int) * (nDestWidth / 8));
memset((PSTR) nPixels, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask0, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask1, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask2, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask3, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask4, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask5, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask6, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask7, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask8, 0, sizeof(int) * nSourceBytes);
memset(nGrayScaleTable1, 0, 2500);
memset(nGrayScaleTable2, 0, 2500);
nSourcePixelsPerLinePerPixel = (int)(nScaleDenominator / nHScale);
if (nScaleDenominator % nHScale || !nSourcePixelsPerLinePerPixel){
nSourcePixelsPerLinePerPixel++;
}
nSourceLinesPerPixel = (int)(nScaleDenominator / nVScale);
if ((nScaleDenominator % nVScale) || !nSourceLinesPerPixel){
nSourceLinesPerPixel++;
}
memcpy(nCountTable, nCountTheZerosTable, sizeof(int) * 256);
// Produce scale table.
if (nHScale >= 1000){
for (nLoop = 0; nLoop < nSourceBytes; nLoop++){
nSourcePixel = (nFirstSourceByte + nLoop) << 3;
nDestPixel0 = max(0, ((nSourcePixel * nHScale) / nScaleDenominator) - nHDestOffset);
nDestPixel1 = max(0, (((nSourcePixel + 1) * nHScale) / nScaleDenominator) - nHDestOffset);
nDestPixel2 = max(0, (((nSourcePixel + 2) * nHScale) / nScaleDenominator) - nHDestOffset);
nDestPixel3 = max(0, (((nSourcePixel + 3) * nHScale) / nScaleDenominator) - nHDestOffset);
nDestPixel4 = max(0, (((nSourcePixel + 4) * nHScale) / nScaleDenominator) - nHDestOffset);
nDestPixel5 = max(0, (((nSourcePixel + 5) * nHScale) / nScaleDenominator) - nHDestOffset);
nDestPixel6 = max(0, (((nSourcePixel + 6) * nHScale) / nScaleDenominator) - nHDestOffset);
nDestPixel7 = max(0, (((nSourcePixel + 7) * nHScale) / nScaleDenominator) - nHDestOffset);
nDestPixel8 = max(0, (((nSourcePixel + 8) * nHScale) / nScaleDenominator) - nHDestOffset);
nDestPixel[nLoop] = nDestPixel0;
nMask0[nLoop] = nDestPixel1 - nDestPixel0;
nMask1[nLoop] = nDestPixel2 - nDestPixel1;
nMask2[nLoop] = nDestPixel3 - nDestPixel2;
nMask3[nLoop] = nDestPixel4 - nDestPixel3;
nMask4[nLoop] = nDestPixel5 - nDestPixel4;
nMask5[nLoop] = nDestPixel6 - nDestPixel5;
nMask6[nLoop] = nDestPixel7 - nDestPixel6;
nMask7[nLoop] = nDestPixel8 - nDestPixel7;
}
}else{
// Pixel 0 = 0x80, pixel 7 = 0x01. 0 = black, 1 = white.
switch (nSourcePixelsPerLinePerPixel){
case 1: nFirstMask = 0xff7f; break;
case 2: nFirstMask = 0xff3f; break;
case 3: nFirstMask = 0xff1f; break;
case 4: nFirstMask = 0xff0f; break;
case 5: nFirstMask = 0xff07; break;
case 6: nFirstMask = 0xff03; break;
case 7: nFirstMask = 0xff01; break;
default: nFirstMask = 0xff00; break;
}
for (nLoop = 0; nLoop < nDestWidth; nLoop++){
nSourcePixel = ((nLoop + nHDestOffset + lrDestRect.left) * nScaleDenominator) / nHScale;
if (nSourcePixel + nSourcePixelsPerLinePerPixel > nSourceWidth){
nSourcePixel = nSourceWidth - nSourcePixelsPerLinePerPixel;
}
// First byte.
nSourceByteIndex = (nSourcePixel >> 3) - nFirstSourceByte;
if (!(nPixels[nSourceByteIndex])){
nDestPixel[nSourceByteIndex] = nLoop;
}
switch (nPixels[nSourceByteIndex]){
case 0: nMask0[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
case 1: nMask1[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
case 2: nMask2[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
case 3: nMask3[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
case 4: nMask4[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
case 5: nMask5[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
case 6: nMask6[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
case 7: nMask7[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
case 8: nMask8[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
default: Error(DISPLAY_DATACORRUPTED); goto Exit;
}
nPixels[nSourceByteIndex]++;
nSourcePixel += nSourcePixelsPerLinePerPixel - 1;
if (nLoop2 = ((nSourcePixel >> 3) - (nSourceByteIndex + nFirstSourceByte))){
// Middle bytes.
for (; nLoop2 > 1; nLoop2--){
nSourceByteIndex++;
nDestPixel[nSourceByteIndex] = nLoop;
switch (nPixels[nSourceByteIndex]){
case 0: nMask0[nSourceByteIndex] = 0; break;
case 1: nMask1[nSourceByteIndex] = 0; break;
case 2: nMask2[nSourceByteIndex] = 0; break;
case 3: nMask3[nSourceByteIndex] = 0; break;
case 4: nMask4[nSourceByteIndex] = 0; break;
case 5: nMask5[nSourceByteIndex] = 0; break;
case 6: nMask6[nSourceByteIndex] = 0; break;
case 7: nMask7[nSourceByteIndex] = 0; break;
case 8: nMask8[nSourceByteIndex] = 0; break;
default: Error(DISPLAY_DATACORRUPTED); goto Exit;
}
nPixels[nSourceByteIndex]++;
}
// Last byte.
nSourceByteIndex++;
nDestPixel[nSourceByteIndex] = nLoop;
nMask0[nSourceByteIndex] = (uchar) (0x7f >> (nSourcePixel & 7));
nPixels[nSourceByteIndex]++;
}
}
}
// Produce table of source line offsets.
CheckError2( AllocateMemory(sizeof(int) * nDestHeight, (PPSTR) &pnSourceLineOffsets, ZERO_INIT));
nSourceHeight = pSourceImg->nHeight;
for (nLoop = 0; nLoop < nDestHeight; nLoop++){
pnSourceLineOffsets[nLoop] = (((nLoop + nVDestOffset + lrDestRect.top) * nScaleDenominator) / nVScale);
if (pnSourceLineOffsets[nLoop] + nSourceLinesPerPixel > nSourceHeight){
pnSourceLineOffsets[nLoop] = nSourceHeight - nSourceLinesPerPixel;
}
}
// Generate nGrayScaleTables.
nNumberOfSourceBitsPerDestBit = nSourcePixelsPerLinePerPixel * nSourceLinesPerPixel;
nThreshold = 0x08000 * nNumberOfSourceBitsPerDestBit;
nThresholdTimes2 = nThreshold * 2;
nDestWidthInts = sizeof(int) * nDestWidth;
nLineSize = (nDestWidth + 9) * sizeof(int);
// pnLine0 = (nSourceLine & 1) == 0.
// pnLine1 = (nSourceLine & 1) == 1.
CheckError2( AllocateMemory(nLineSize, (PPSTR) &pnLine0, ZERO_INIT));
CheckError2( AllocateMemory(nLineSize, (PPSTR) &pnLine1, ZERO_INIT));
// Begin scaling the data.
for (nDestLine = 0; nDestLine < nDestHeight; nDestLine++){
memset((PSTR) nDest, 0, nDestWidthInts);
for (nSourceLineCount = nSourceLinesPerPixel; nSourceLineCount; nSourceLineCount--){
pSourceLine = &pSourceImg->bImageData[0] + ((pnSourceLineOffsets[nDestLine]
+ (nSourceLinesPerPixel - nSourceLineCount)) * pSourceImg->nBytesPerLine);
pSourceByte = pSourceLine + nFirstSourceByte;
if (nHScale >= 1000){
nSourceByteIndex = 0;
if ((int) pSourceByte & 3){
nLoopEnd = min(4 - ((int) pSourceByte & 3), nSourceBytes);
}else{
nLoopEnd = 0;
}
while(nSourceByteIndex < nLoopEnd){
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
if (!(nSourceByte & 0x80)){
for (nLoop = nMask0[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask0[nSourceByteIndex];
}
if (!(nSourceByte & 0x40)){
for (nLoop = nMask1[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask1[nSourceByteIndex];
}
if (!(nSourceByte & 0x20)){
for (nLoop = nMask2[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask2[nSourceByteIndex];
}
if (!(nSourceByte & 0x10)){
for (nLoop = nMask3[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask3[nSourceByteIndex];
}
if (!(nSourceByte & 0x08)){
for (nLoop = nMask4[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask4[nSourceByteIndex];
}
if (!(nSourceByte & 0x04)){
for (nLoop = nMask5[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask5[nSourceByteIndex];
}
if (!(nSourceByte & 0x02)){
for (nLoop = nMask6[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask6[nSourceByteIndex];
}
if (!(nSourceByte & 0x01)){
for (nLoop = nMask7[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}
}
nSourceByteIndex++;
}
nLoopEnd = (nSourceBytes - nSourceByteIndex) & -4;
while(nSourceByteIndex < nLoopEnd){
if (*((PDWORD) pSourceByte) == 0xffffffff){
nSourceByteIndex += 4;
pSourceByte += 4;
continue;
}else{
do{
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
if (!(nSourceByte & 0x80)){
for (nLoop = nMask0[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask0[nSourceByteIndex];
}
if (!(nSourceByte & 0x40)){
for (nLoop = nMask1[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask1[nSourceByteIndex];
}
if (!(nSourceByte & 0x20)){
for (nLoop = nMask2[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask2[nSourceByteIndex];
}
if (!(nSourceByte & 0x10)){
for (nLoop = nMask3[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask3[nSourceByteIndex];
}
if (!(nSourceByte & 0x08)){
for (nLoop = nMask4[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask4[nSourceByteIndex];
}
if (!(nSourceByte & 0x04)){
for (nLoop = nMask5[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask5[nSourceByteIndex];
}
if (!(nSourceByte & 0x02)){
for (nLoop = nMask6[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask6[nSourceByteIndex];
}
if (!(nSourceByte & 0x01)){
for (nLoop = nMask7[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}
}
nSourceByteIndex++;
}while((int) pSourceByte & 3);
}
}
while(nSourceByteIndex < nSourceBytes){
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
if (!(nSourceByte & 0x80)){
for (nLoop = nMask0[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask0[nSourceByteIndex];
}
if (!(nSourceByte & 0x40)){
for (nLoop = nMask1[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask1[nSourceByteIndex];
}
if (!(nSourceByte & 0x20)){
for (nLoop = nMask2[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask2[nSourceByteIndex];
}
if (!(nSourceByte & 0x10)){
for (nLoop = nMask3[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask3[nSourceByteIndex];
}
if (!(nSourceByte & 0x08)){
for (nLoop = nMask4[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask4[nSourceByteIndex];
}
if (!(nSourceByte & 0x04)){
for (nLoop = nMask5[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask5[nSourceByteIndex];
}
if (!(nSourceByte & 0x02)){
for (nLoop = nMask6[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask6[nSourceByteIndex];
}
if (!(nSourceByte & 0x01)){
for (nLoop = nMask7[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}
}
nSourceByteIndex++;
}
}else{ // nHScale < 1000.
nSourceByteIndex = 0;
while (((int) pSourceByte & 3) && nSourceByteIndex < nSourceBytes){
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
nDest[nPixelIndex] += nCountTable[nSourceByte | nMask0[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 1){
nDest[nPixelIndex + 1] += nCountTable[nSourceByte | nMask1[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 2){
nDest[nPixelIndex + 2] += nCountTable[nSourceByte | nMask2[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 3){
nDest[nPixelIndex + 3] += nCountTable[nSourceByte | nMask3[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 4){
nDest[nPixelIndex + 4] += nCountTable[nSourceByte | nMask4[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 5){
nDest[nPixelIndex + 5] += nCountTable[nSourceByte | nMask5[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 6){
nDest[nPixelIndex + 6] += nCountTable[nSourceByte | nMask6[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 7){
nDest[nPixelIndex + 7] += nCountTable[nSourceByte | nMask7[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 8){
nDest[nPixelIndex + 8] += nCountTable[nSourceByte | nMask8[nSourceByteIndex]];
} } } } } } } } }
nSourceByteIndex++;
}
nLoopEnd = (nSourceBytes - nSourceByteIndex) & -4;
while(nSourceByteIndex < nLoopEnd){
if (*((PDWORD) pSourceByte) == 0xffffffff){
nSourceByteIndex += 4;
pSourceByte += 4;
continue;
}else{
// Do Byte 1.
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
nDest[nPixelIndex] += nCountTable[nSourceByte | nMask0[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 1){
nDest[nPixelIndex + 1] += nCountTable[nSourceByte | nMask1[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 2){
nDest[nPixelIndex + 2] += nCountTable[nSourceByte | nMask2[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 3){
nDest[nPixelIndex + 3] += nCountTable[nSourceByte | nMask3[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 4){
nDest[nPixelIndex + 4] += nCountTable[nSourceByte | nMask4[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 5){
nDest[nPixelIndex + 5] += nCountTable[nSourceByte | nMask5[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 6){
nDest[nPixelIndex + 6] += nCountTable[nSourceByte | nMask6[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 7){
nDest[nPixelIndex + 7] += nCountTable[nSourceByte | nMask7[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 8){
nDest[nPixelIndex + 8] += nCountTable[nSourceByte | nMask8[nSourceByteIndex]];
} } } } } } } } }
nSourceByteIndex++;
// Do Byte 2.
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
nDest[nPixelIndex] += nCountTable[nSourceByte | nMask0[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 1){
nDest[nPixelIndex + 1] += nCountTable[nSourceByte | nMask1[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 2){
nDest[nPixelIndex + 2] += nCountTable[nSourceByte | nMask2[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 3){
nDest[nPixelIndex + 3] += nCountTable[nSourceByte | nMask3[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 4){
nDest[nPixelIndex + 4] += nCountTable[nSourceByte | nMask4[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 5){
nDest[nPixelIndex + 5] += nCountTable[nSourceByte | nMask5[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 6){
nDest[nPixelIndex + 6] += nCountTable[nSourceByte | nMask6[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 7){
nDest[nPixelIndex + 7] += nCountTable[nSourceByte | nMask7[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 8){
nDest[nPixelIndex + 8] += nCountTable[nSourceByte | nMask8[nSourceByteIndex]];
} } } } } } } } }
nSourceByteIndex++;
// Do Byte 3.
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
nDest[nPixelIndex] += nCountTable[nSourceByte | nMask0[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 1){
nDest[nPixelIndex + 1] += nCountTable[nSourceByte | nMask1[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 2){
nDest[nPixelIndex + 2] += nCountTable[nSourceByte | nMask2[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 3){
nDest[nPixelIndex + 3] += nCountTable[nSourceByte | nMask3[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 4){
nDest[nPixelIndex + 4] += nCountTable[nSourceByte | nMask4[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 5){
nDest[nPixelIndex + 5] += nCountTable[nSourceByte | nMask5[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 6){
nDest[nPixelIndex + 6] += nCountTable[nSourceByte | nMask6[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 7){
nDest[nPixelIndex + 7] += nCountTable[nSourceByte | nMask7[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 8){
nDest[nPixelIndex + 8] += nCountTable[nSourceByte | nMask8[nSourceByteIndex]];
} } } } } } } } }
nSourceByteIndex++;
// Do Byte 4.
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
nDest[nPixelIndex] += nCountTable[nSourceByte | nMask0[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 1){
nDest[nPixelIndex + 1] += nCountTable[nSourceByte | nMask1[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 2){
nDest[nPixelIndex + 2] += nCountTable[nSourceByte | nMask2[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 3){
nDest[nPixelIndex + 3] += nCountTable[nSourceByte | nMask3[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 4){
nDest[nPixelIndex + 4] += nCountTable[nSourceByte | nMask4[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 5){
nDest[nPixelIndex + 5] += nCountTable[nSourceByte | nMask5[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 6){
nDest[nPixelIndex + 6] += nCountTable[nSourceByte | nMask6[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 7){
nDest[nPixelIndex + 7] += nCountTable[nSourceByte | nMask7[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 8){
nDest[nPixelIndex + 8] += nCountTable[nSourceByte | nMask8[nSourceByteIndex]];
} } } } } } } } }
nSourceByteIndex++;
}
}
while(nSourceByteIndex < nSourceBytes){
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
nDest[nPixelIndex] += nCountTable[nSourceByte | nMask0[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 1){
nDest[nPixelIndex + 1] += nCountTable[nSourceByte | nMask1[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 2){
nDest[nPixelIndex + 2] += nCountTable[nSourceByte | nMask2[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 3){
nDest[nPixelIndex + 3] += nCountTable[nSourceByte | nMask3[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 4){
nDest[nPixelIndex + 4] += nCountTable[nSourceByte | nMask4[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 5){
nDest[nPixelIndex + 5] += nCountTable[nSourceByte | nMask5[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 6){
nDest[nPixelIndex + 6] += nCountTable[nSourceByte | nMask6[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 7){
nDest[nPixelIndex + 7] += nCountTable[nSourceByte | nMask7[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 8){
nDest[nPixelIndex + 8] += nCountTable[nSourceByte | nMask8[nSourceByteIndex]];
} } } } } } } } }
nSourceByteIndex++;
}
}
}
// Error diffuse the line to BW.
pDestLine = &pDestImg->bImageData[0] + ((nDestLine + (int)lrDestRect.top)
* pDestImg->nBytesPerLine) + (lrDestRect.left / 8);
if (nDestLine & 1){
pnThisLine = &pnLine1[1];
pnNextLine = pnLine0;
}else{
pnThisLine = &pnLine0[1];
pnNextLine = pnLine1;
}
// memset(pnNextLine, 0, nLineSize);
pnNextLine[0] = 0;
pnNextLine[1] = 0;
nPixelIndex = 0;
pnDestLineGray = &nDest[0];
nLoopEnd = nDestWidth;
// Do first few pixels.
if (lrDestRect.left & 7){
switch (lrDestRect.left & 7){
case 1: nBitMask = 0x40; nLoop = 7; break;
case 2: nBitMask = 0x20; nLoop = 6; break;
case 3: nBitMask = 0x10; nLoop = 5; break;
case 4: nBitMask = 0x08; nLoop = 4; break;
case 5: nBitMask = 0x04; nLoop = 3; break;
case 6: nBitMask = 0x02; nLoop = 2; break;
case 7: nBitMask = 0x01; nLoop = 1; break;
}
nLoop = min(nLoopEnd, nLoop);
nLoopEnd -= nLoop;
nDestPixel0 = *pDestLine;
for (; nLoop; nLoop--){
// *pnDestLineGray = number of black pixels.
nPixel = *pnThisLine + (*(pnDestLineGray++) << 16);
if (nPixel >= nThreshold){
nDestPixel0 &= ~nBitMask;
nPixel = (nPixel - nThresholdTimes2) / 4;
}else{
nDestPixel0 |= nBitMask;
nPixel = nPixel / 4;
}
nBitMask >>= 1;
*(++pnThisLine) += nPixel;
*(pnNextLine++) += nPixel;
*(pnNextLine) += nPixel;
*(pnNextLine + 1) = nPixel;
}
*(pDestLine++) = nDestPixel0;
}
// Do middle bytes.
if (nLoopEnd & ~7){
for (nLoop = nLoopEnd / 8; nLoop; nLoop--){
// Pixel 0.
nPixel = *pnThisLine + (*(pnDestLineGray++) << 16);
if (nPixel >= nThreshold){
nDestPixel0 = 0x7f;
nPixel = (nPixel - nThresholdTimes2) / 4;
}else{
nDestPixel0 = 0xff;
nPixel = nPixel / 4;
}
*(++pnThisLine) += nPixel;
*(pnNextLine++) += nPixel;
*(pnNextLine) += nPixel;
*(pnNextLine + 1) = nPixel;
// Pixel 1.
nPixel = *pnThisLine + (*(pnDestLineGray++) << 16);
if (nPixel >= nThreshold){
nDestPixel0 &= 0xbf;
nPixel = (nPixel - nThresholdTimes2) / 4;
}else{
nPixel = nPixel / 4;
}
*(++pnThisLine) += nPixel;
*(pnNextLine++) += nPixel;
*(pnNextLine) += nPixel;
*(pnNextLine + 1) = nPixel;
// Pixel 2.
nPixel = *pnThisLine + (*(pnDestLineGray++) << 16);
if (nPixel >= nThreshold){
nDestPixel0 &= 0xdf;
nPixel = (nPixel - nThresholdTimes2) / 4;
}else{
nPixel = nPixel / 4;
}
*(++pnThisLine) += nPixel;
*(pnNextLine++) += nPixel;
*(pnNextLine) += nPixel;
*(pnNextLine + 1) = nPixel;
// Pixel 3.
nPixel = *pnThisLine + (*(pnDestLineGray++) << 16);
if (nPixel >= nThreshold){
nDestPixel0 &= 0xef;
nPixel = (nPixel - nThresholdTimes2) / 4;
}else{
nPixel = nPixel / 4;
}
*(++pnThisLine) += nPixel;
*(pnNextLine++) += nPixel;
*(pnNextLine) += nPixel;
*(pnNextLine + 1) = nPixel;
// Pixel 4.
nPixel = *pnThisLine + (*(pnDestLineGray++) << 16);
if (nPixel >= nThreshold){
nDestPixel0 &= 0xf7;
nPixel = (nPixel - nThresholdTimes2) / 4;
}else{
nPixel = nPixel / 4;
}
*(++pnThisLine) += nPixel;
*(pnNextLine++) += nPixel;
*(pnNextLine) += nPixel;
*(pnNextLine + 1) = nPixel;
// Pixel 5.
nPixel = *pnThisLine + (*(pnDestLineGray++) << 16);
if (nPixel >= nThreshold){
nDestPixel0 &= 0xfb;
nPixel = (nPixel - nThresholdTimes2) / 4;
}else{
nPixel = nPixel / 4;
}
*(++pnThisLine) += nPixel;
*(pnNextLine++) += nPixel;
*(pnNextLine) += nPixel;
*(pnNextLine + 1) = nPixel;
// Pixel 6.
nPixel = *pnThisLine + (*(pnDestLineGray++) << 16);
if (nPixel >= nThreshold){
nDestPixel0 &= 0xfd;
nPixel = (nPixel - nThresholdTimes2) / 4;
}else{
nPixel = nPixel / 4;
}
*(++pnThisLine) += nPixel;
*(pnNextLine++) += nPixel;
*(pnNextLine) += nPixel;
*(pnNextLine + 1) = nPixel;
// Pixel 7.
nPixel = *pnThisLine + (*(pnDestLineGray++) << 16);
if (nPixel >= nThreshold){
nDestPixel0 &= 0xfe;
nPixel = (nPixel - nThresholdTimes2) / 4;
}else{
nPixel = nPixel / 4;
}
*(++pnThisLine) += nPixel;
*(pnNextLine++) += nPixel;
*(pnNextLine) += nPixel;
*(pnNextLine + 1) = nPixel;
*(pDestLine++) = nDestPixel0;
}
}
// Do last few pixels.
if (lrDestRect.right & 7){
nBitMask = 0x80;
switch (lrDestRect.right & 7){
case 1: nLoop = 1; break;
case 2: nLoop = 2; break;
case 3: nLoop = 3; break;
case 4: nLoop = 4; break;
case 5: nLoop = 5; break;
case 6: nLoop = 6; break;
case 7: nLoop = 7; break;
}
nDestPixel0 = *pDestLine;
for (; nLoop; nLoop--){
nPixel = *pnThisLine + (*(pnDestLineGray++) << 16);
if (nPixel >= nThreshold){
nDestPixel0 &= ~nBitMask;
nPixel = (nPixel - nThresholdTimes2) / 4;
}else{
nDestPixel0 |= nBitMask;
nPixel = nPixel / 4;
}
nBitMask >>= 1;
*(++pnThisLine) += nPixel;
*(pnNextLine++) += nPixel;
*(pnNextLine) += nPixel;
*(pnNextLine + 1) = nPixel;
}
*pDestLine = nDestPixel0;
}
}
Exit:
if (pnSourceLineOffsets){
FreeMemory((PPSTR) &pnSourceLineOffsets);
}
if (pnLine0){
FreeMemory((PPSTR) &pnLine0);
}
if (pnLine1){
FreeMemory((PPSTR) &pnLine1);
}
return(nStatus);
}
//
/****************************************************************************
FUNCTION: ScaleBWToGray
PURPOSE: Scales BW images to GRAY8/GRAY7/GRAY4.
*****************************************************************************/
int WINAPI ScaleBWToGray(PIMG pSourceImg, PIMG pDestImg, int nHScale, int nVScale,
int nHDestOffset, int nVDestOffset, LRECT *plrDestRect){
int nStatus = 0;
int nDest[MAX_PIXELS_HANDLED];
int nDestPixel[MAX_BW_BYTES_HANDLED];
int nPixels[MAX_BW_BYTES_HANDLED];
int nMask0[MAX_BW_BYTES_HANDLED];
int nMask1[MAX_BW_BYTES_HANDLED];
int nMask2[MAX_BW_BYTES_HANDLED];
int nMask3[MAX_BW_BYTES_HANDLED];
int nMask4[MAX_BW_BYTES_HANDLED];
int nMask5[MAX_BW_BYTES_HANDLED];
int nMask6[MAX_BW_BYTES_HANDLED];
int nMask7[MAX_BW_BYTES_HANDLED];
int nMask8[MAX_BW_BYTES_HANDLED];
int nGrayScaleTable1[2500];
int nGrayScaleTable2[2500];
int nPixelIndex;
int nDestWidth;
int nDestWidthInts;
int nDestHeight;
int nSourcePixelsPerLinePerPixel;
int nSourceLinesPerPixel;
long lMultiplier; // Multiplier for averaging of all lines.
int nDestLine;
PINT pnSourceLineOffsets = 0; // Table nsed to translate dest line offsets to source line offsets.
PBYTE pSourceLine; // The address of the start of the source line.
PBYTE pSourceByte; // The address of the source byte currently being processed.
PBYTE pDestLine; // The address of the start of the dest line.
int nFirstMask;
int nSourcePixel;
int nScaleDenominator;
int nCountTable[256];
int nSourceWidth;
int nSourceHeight;
int nNumberOfSourceBitsPerDestBit;
int nFirstSourceByte;
int nSourceBytes;
int nSourceByteIndex;
int nTemp;
int nDestPixel0;
int nDestPixel1;
int nDestPixel2;
int nDestPixel3;
int nDestPixel4;
int nDestPixel5;
int nDestPixel6;
int nDestPixel7;
int nDestPixel8;
// Loop variables.
int nLoop;
int nLoop2;
int nTempIndex;
int nSourceLineCount;
int nLoopEnd;
int nSourceByte;
LRECT lrDestRect ;
CopyRect (lrDestRect, *plrDestRect) ;
if (!pDestImg && pDestImg->nType != ITYPE_GRAY8
&& pDestImg->nType != ITYPE_GRAY7
&& pDestImg->nType != ITYPE_GRAY4){
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
if (nHScale == 62 || nHScale == 31){
nScaleDenominator = 992;
}else{
nScaleDenominator = SCALE_DENOMINATOR;
}
nDestWidth = (int)(lrDestRect.right - lrDestRect.left);
nDestHeight = (int)(lrDestRect.bottom - lrDestRect.top);
nFirstSourceByte = (int) ((((lrDestRect.left + nHDestOffset) * nScaleDenominator)
/ nHScale) >> 3);
nSourceWidth = pSourceImg->nWidth;
nSourceBytes = ((min(nSourceWidth,
(int) (((lrDestRect.right + nHDestOffset) * nScaleDenominator) / nHScale))
+ 7) >> 3) - nFirstSourceByte;
if (nSourceBytes * 8 > MAX_PIXELS_HANDLED || nDestWidth > MAX_PIXELS_HANDLED
|| nSourceWidth < (INT)(nScaleDenominator / nHScale)){
nStatus = Error(DISPLAY_INVALIDRECT);
goto Exit;
}
memset((PSTR) nDestPixel, 0, sizeof(int) * (nDestWidth / 8));
memset((PSTR) nPixels, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask0, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask1, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask2, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask3, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask4, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask5, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask6, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask7, 0, sizeof(int) * nSourceBytes);
memset((PSTR) nMask8, 0, sizeof(int) * nSourceBytes);
memset(nGrayScaleTable1, 0, 2500);
memset(nGrayScaleTable2, 0, 2500);
nSourcePixelsPerLinePerPixel = (int)(nScaleDenominator / nHScale);
if (nScaleDenominator % nHScale || !nSourcePixelsPerLinePerPixel){
nSourcePixelsPerLinePerPixel++;
}
nSourceLinesPerPixel = (int)(nScaleDenominator / nVScale);
if ((nScaleDenominator % nVScale) || !nSourceLinesPerPixel){
nSourceLinesPerPixel++;
}
memcpy(nCountTable, nCountTheZerosTable, sizeof(int) * 256);
// Produce scale table.
if (nHScale >= 1000){
for (nLoop = 0; nLoop < nSourceBytes; nLoop++){
nSourcePixel = (nFirstSourceByte + nLoop) << 3;
nDestPixel0 = max(0, ((nSourcePixel * nHScale) / nScaleDenominator) - (int) nHDestOffset);
nDestPixel1 = max(0, (((nSourcePixel + 1) * nHScale) / nScaleDenominator) - (int) nHDestOffset);
nDestPixel2 = max(0, (((nSourcePixel + 2) * nHScale) / nScaleDenominator) - (int) nHDestOffset);
nDestPixel3 = max(0, (((nSourcePixel + 3) * nHScale) / nScaleDenominator) - (int) nHDestOffset);
nDestPixel4 = max(0, (((nSourcePixel + 4) * nHScale) / nScaleDenominator) - (int) nHDestOffset);
nDestPixel5 = max(0, (((nSourcePixel + 5) * nHScale) / nScaleDenominator) - (int) nHDestOffset);
nDestPixel6 = max(0, (((nSourcePixel + 6) * nHScale) / nScaleDenominator) - (int) nHDestOffset);
nDestPixel7 = max(0, (((nSourcePixel + 7) * nHScale) / nScaleDenominator) - (int) nHDestOffset);
nDestPixel8 = max(0, (((nSourcePixel + 8) * nHScale) / nScaleDenominator) - (int) nHDestOffset);
nDestPixel[nLoop] = nDestPixel0;
nMask0[nLoop] = nDestPixel1 - nDestPixel0;
nMask1[nLoop] = nDestPixel2 - nDestPixel1;
nMask2[nLoop] = nDestPixel3 - nDestPixel2;
nMask3[nLoop] = nDestPixel4 - nDestPixel3;
nMask4[nLoop] = nDestPixel5 - nDestPixel4;
nMask5[nLoop] = nDestPixel6 - nDestPixel5;
nMask6[nLoop] = nDestPixel7 - nDestPixel6;
nMask7[nLoop] = nDestPixel8 - nDestPixel7;
}
}else{
// Pixel 0 = 0x80, pixel 7 = 0x01. 0 = black, 1 = white.
switch (nSourcePixelsPerLinePerPixel){
case 1: nFirstMask = 0xff7f; break;
case 2: nFirstMask = 0xff3f; break;
case 3: nFirstMask = 0xff1f; break;
case 4: nFirstMask = 0xff0f; break;
case 5: nFirstMask = 0xff07; break;
case 6: nFirstMask = 0xff03; break;
case 7: nFirstMask = 0xff01; break;
default: nFirstMask = 0xff00; break;
}
for (nLoop = 0; nLoop < nDestWidth; nLoop++){
nSourcePixel = ((nLoop + nHDestOffset + lrDestRect.left) * nScaleDenominator) / nHScale;
if (nSourcePixel + nSourcePixelsPerLinePerPixel > nSourceWidth){
nSourcePixel = nSourceWidth - nSourcePixelsPerLinePerPixel;
}
// First byte.
nSourceByteIndex = (int) (nSourcePixel >> 3) - nFirstSourceByte;
if (!(nPixels[nSourceByteIndex])){
nDestPixel[nSourceByteIndex] = nLoop;
}
switch (nPixels[nSourceByteIndex]){
case 0: nMask0[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
case 1: nMask1[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
case 2: nMask2[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
case 3: nMask3[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
case 4: nMask4[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
case 5: nMask5[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
case 6: nMask6[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
case 7: nMask7[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
case 8: nMask8[nSourceByteIndex] = (nFirstMask >> (nSourcePixel & 7)) & 0x0ff; break;
default: Error(DISPLAY_DATACORRUPTED); goto Exit;
}
nPixels[nSourceByteIndex]++;
nSourcePixel += nSourcePixelsPerLinePerPixel - 1;
if (nLoop2 = (int) ((nSourcePixel >> 3) - (nSourceByteIndex + nFirstSourceByte))){
// Middle bytes.
for (; nLoop2 > 1; nLoop2--){
nSourceByteIndex++;
nDestPixel[nSourceByteIndex] = nLoop;
switch (nPixels[nSourceByteIndex]){
case 0: nMask0[nSourceByteIndex] = 0; break;
case 1: nMask1[nSourceByteIndex] = 0; break;
case 2: nMask2[nSourceByteIndex] = 0; break;
case 3: nMask3[nSourceByteIndex] = 0; break;
case 4: nMask4[nSourceByteIndex] = 0; break;
case 5: nMask5[nSourceByteIndex] = 0; break;
case 6: nMask6[nSourceByteIndex] = 0; break;
case 7: nMask7[nSourceByteIndex] = 0; break;
case 8: nMask8[nSourceByteIndex] = 0; break;
default: Error(DISPLAY_DATACORRUPTED); goto Exit;
}
nPixels[nSourceByteIndex]++;
}
// Last byte.
nSourceByteIndex++;
nDestPixel[nSourceByteIndex] = nLoop;
nMask0[nSourceByteIndex] = (uchar) (0x7f >> (nSourcePixel & 7));
nPixels[nSourceByteIndex]++;
}
}
}
// Produce table of source line offsets.
CheckError2( AllocateMemory(sizeof(int) * nDestHeight, (PPSTR) &pnSourceLineOffsets, NO_INIT));
nSourceHeight = pSourceImg->nHeight;
for (nLoop = 0; nLoop < nDestHeight; nLoop++){
pnSourceLineOffsets[nLoop] = (int)(((nLoop + nVDestOffset + lrDestRect.top)
* nScaleDenominator) / nVScale);
if (pnSourceLineOffsets[nLoop] + nSourceLinesPerPixel > nSourceHeight){
pnSourceLineOffsets[nLoop] = nSourceHeight - nSourceLinesPerPixel;
}
}
// Generate nGrayScaleTables.
nNumberOfSourceBitsPerDestBit = nSourcePixelsPerLinePerPixel * nSourceLinesPerPixel;
// Calculate the averaging divisors.
// gray = ((0xff0000 / # of Total pixel) * # of 1's) / 0x10000
// # of 1's = # of Total pixels - # of 0's
// 0xff0000 = 255 * 0x10000
if (pDestImg->nType == ITYPE_GRAY8){
lMultiplier = 0x0ff0000 / nNumberOfSourceBitsPerDestBit;
}else if (pDestImg->nType == ITYPE_GRAY7){
lMultiplier = 0x07f0000 / nNumberOfSourceBitsPerDestBit;
}else{ // ITYPE_GRAY4
lMultiplier = 0x00f0000 / nNumberOfSourceBitsPerDestBit;
}
for (nLoop = 0; nLoop < nNumberOfSourceBitsPerDestBit; nLoop++){
nTemp = (nNumberOfSourceBitsPerDestBit - nLoop) * lMultiplier;
nGrayScaleTable1[nLoop] = ((nTemp >> 16) + ((nTemp >> 15) & 1));
}
if (pDestImg->nType == ITYPE_GRAY4){
for (nLoop = 0; nLoop < nNumberOfSourceBitsPerDestBit; nLoop++){
nGrayScaleTable2[nLoop] = nGrayScaleTable1[nLoop] << 4;
}
}
nDestWidthInts = sizeof(int) * nDestWidth;
// Begin scaling the data.
for (nDestLine = 0; nDestLine < nDestHeight; nDestLine++){
memset((PSTR) nDest, 0, nDestWidthInts);
for (nSourceLineCount = nSourceLinesPerPixel; nSourceLineCount; nSourceLineCount--){
pSourceLine = &pSourceImg->bImageData[0] + ((pnSourceLineOffsets[nDestLine]
+ (nSourceLinesPerPixel - nSourceLineCount)) * pSourceImg->nBytesPerLine);
pSourceByte = pSourceLine + nFirstSourceByte;
if (nHScale >= 1000){
nSourceByteIndex = 0;
if ((int) pSourceByte & 3){
nLoopEnd = min(4 - ((int) pSourceByte & 3), nSourceBytes);
}else{
nLoopEnd = 0;
}
while(nSourceByteIndex < nLoopEnd){
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
if (!(nSourceByte & 0x80)){
for (nLoop = nMask0[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask0[nSourceByteIndex];
}
if (!(nSourceByte & 0x40)){
for (nLoop = nMask1[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask1[nSourceByteIndex];
}
if (!(nSourceByte & 0x20)){
for (nLoop = nMask2[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask2[nSourceByteIndex];
}
if (!(nSourceByte & 0x10)){
for (nLoop = nMask3[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask3[nSourceByteIndex];
}
if (!(nSourceByte & 0x08)){
for (nLoop = nMask4[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask4[nSourceByteIndex];
}
if (!(nSourceByte & 0x04)){
for (nLoop = nMask5[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask5[nSourceByteIndex];
}
if (!(nSourceByte & 0x02)){
for (nLoop = nMask6[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask6[nSourceByteIndex];
}
if (!(nSourceByte & 0x01)){
for (nLoop = nMask7[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}
}
nSourceByteIndex++;
}
nLoopEnd = (nSourceBytes - nSourceByteIndex) & -4;
while(nSourceByteIndex < nLoopEnd){
if (*((PDWORD) pSourceByte) == 0xffffffff){
nSourceByteIndex += 4;
pSourceByte += 4;
continue;
}else{
do{
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
if (!(nSourceByte & 0x80)){
for (nLoop = nMask0[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask0[nSourceByteIndex];
}
if (!(nSourceByte & 0x40)){
for (nLoop = nMask1[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask1[nSourceByteIndex];
}
if (!(nSourceByte & 0x20)){
for (nLoop = nMask2[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask2[nSourceByteIndex];
}
if (!(nSourceByte & 0x10)){
for (nLoop = nMask3[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask3[nSourceByteIndex];
}
if (!(nSourceByte & 0x08)){
for (nLoop = nMask4[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask4[nSourceByteIndex];
}
if (!(nSourceByte & 0x04)){
for (nLoop = nMask5[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask5[nSourceByteIndex];
}
if (!(nSourceByte & 0x02)){
for (nLoop = nMask6[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask6[nSourceByteIndex];
}
if (!(nSourceByte & 0x01)){
for (nLoop = nMask7[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}
}
nSourceByteIndex++;
}while((int) pSourceByte & 3);
}
}
while(nSourceByteIndex < nSourceBytes){
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
if (!(nSourceByte & 0x80)){
for (nLoop = nMask0[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask0[nSourceByteIndex];
}
if (!(nSourceByte & 0x40)){
for (nLoop = nMask1[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask1[nSourceByteIndex];
}
if (!(nSourceByte & 0x20)){
for (nLoop = nMask2[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask2[nSourceByteIndex];
}
if (!(nSourceByte & 0x10)){
for (nLoop = nMask3[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask3[nSourceByteIndex];
}
if (!(nSourceByte & 0x08)){
for (nLoop = nMask4[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask4[nSourceByteIndex];
}
if (!(nSourceByte & 0x04)){
for (nLoop = nMask5[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask5[nSourceByteIndex];
}
if (!(nSourceByte & 0x02)){
for (nLoop = nMask6[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}else{
nPixelIndex += nMask6[nSourceByteIndex];
}
if (!(nSourceByte & 0x01)){
for (nLoop = nMask7[nSourceByteIndex]; nLoop; nLoop--){
nDest[nPixelIndex++]++;
}
}
}
nSourceByteIndex++;
}
}else{ // nHScale < 1000.
nSourceByteIndex = 0;
while (((int) pSourceByte & 3) && nSourceByteIndex < nSourceBytes){
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
nDest[nPixelIndex] += nCountTable[nSourceByte | nMask0[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 1){
nDest[nPixelIndex + 1] += nCountTable[nSourceByte | nMask1[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 2){
nDest[nPixelIndex + 2] += nCountTable[nSourceByte | nMask2[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 3){
nDest[nPixelIndex + 3] += nCountTable[nSourceByte | nMask3[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 4){
nDest[nPixelIndex + 4] += nCountTable[nSourceByte | nMask4[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 5){
nDest[nPixelIndex + 5] += nCountTable[nSourceByte | nMask5[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 6){
nDest[nPixelIndex + 6] += nCountTable[nSourceByte | nMask6[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 7){
nDest[nPixelIndex + 7] += nCountTable[nSourceByte | nMask7[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 8){
nDest[nPixelIndex + 8] += nCountTable[nSourceByte | nMask8[nSourceByteIndex]];
} } } } } } } } }
nSourceByteIndex++;
}
nLoopEnd = (nSourceBytes - nSourceByteIndex) & -4;
while(nSourceByteIndex < nLoopEnd){
if (*((PDWORD) pSourceByte) == 0xffffffff){
nSourceByteIndex += 4;
pSourceByte += 4;
continue;
}else{
// Do Byte 1.
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
nDest[nPixelIndex] += nCountTable[nSourceByte | nMask0[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 1){
nDest[nPixelIndex + 1] += nCountTable[nSourceByte | nMask1[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 2){
nDest[nPixelIndex + 2] += nCountTable[nSourceByte | nMask2[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 3){
nDest[nPixelIndex + 3] += nCountTable[nSourceByte | nMask3[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 4){
nDest[nPixelIndex + 4] += nCountTable[nSourceByte | nMask4[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 5){
nDest[nPixelIndex + 5] += nCountTable[nSourceByte | nMask5[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 6){
nDest[nPixelIndex + 6] += nCountTable[nSourceByte | nMask6[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 7){
nDest[nPixelIndex + 7] += nCountTable[nSourceByte | nMask7[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 8){
nDest[nPixelIndex + 8] += nCountTable[nSourceByte | nMask8[nSourceByteIndex]];
} } } } } } } } }
nSourceByteIndex++;
// Do Byte 2.
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
nDest[nPixelIndex] += nCountTable[nSourceByte | nMask0[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 1){
nDest[nPixelIndex + 1] += nCountTable[nSourceByte | nMask1[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 2){
nDest[nPixelIndex + 2] += nCountTable[nSourceByte | nMask2[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 3){
nDest[nPixelIndex + 3] += nCountTable[nSourceByte | nMask3[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 4){
nDest[nPixelIndex + 4] += nCountTable[nSourceByte | nMask4[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 5){
nDest[nPixelIndex + 5] += nCountTable[nSourceByte | nMask5[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 6){
nDest[nPixelIndex + 6] += nCountTable[nSourceByte | nMask6[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 7){
nDest[nPixelIndex + 7] += nCountTable[nSourceByte | nMask7[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 8){
nDest[nPixelIndex + 8] += nCountTable[nSourceByte | nMask8[nSourceByteIndex]];
} } } } } } } } }
nSourceByteIndex++;
// Do Byte 3.
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
nDest[nPixelIndex] += nCountTable[nSourceByte | nMask0[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 1){
nDest[nPixelIndex + 1] += nCountTable[nSourceByte | nMask1[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 2){
nDest[nPixelIndex + 2] += nCountTable[nSourceByte | nMask2[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 3){
nDest[nPixelIndex + 3] += nCountTable[nSourceByte | nMask3[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 4){
nDest[nPixelIndex + 4] += nCountTable[nSourceByte | nMask4[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 5){
nDest[nPixelIndex + 5] += nCountTable[nSourceByte | nMask5[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 6){
nDest[nPixelIndex + 6] += nCountTable[nSourceByte | nMask6[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 7){
nDest[nPixelIndex + 7] += nCountTable[nSourceByte | nMask7[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 8){
nDest[nPixelIndex + 8] += nCountTable[nSourceByte | nMask8[nSourceByteIndex]];
} } } } } } } } }
nSourceByteIndex++;
// Do Byte 4.
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
nDest[nPixelIndex] += nCountTable[nSourceByte | nMask0[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 1){
nDest[nPixelIndex + 1] += nCountTable[nSourceByte | nMask1[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 2){
nDest[nPixelIndex + 2] += nCountTable[nSourceByte | nMask2[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 3){
nDest[nPixelIndex + 3] += nCountTable[nSourceByte | nMask3[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 4){
nDest[nPixelIndex + 4] += nCountTable[nSourceByte | nMask4[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 5){
nDest[nPixelIndex + 5] += nCountTable[nSourceByte | nMask5[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 6){
nDest[nPixelIndex + 6] += nCountTable[nSourceByte | nMask6[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 7){
nDest[nPixelIndex + 7] += nCountTable[nSourceByte | nMask7[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 8){
nDest[nPixelIndex + 8] += nCountTable[nSourceByte | nMask8[nSourceByteIndex]];
} } } } } } } } }
nSourceByteIndex++;
}
}
while(nSourceByteIndex < nSourceBytes){
if ((nSourceByte = *(pSourceByte++)) != 0xff){
nPixelIndex = nDestPixel[nSourceByteIndex];
nDest[nPixelIndex] += nCountTable[nSourceByte | nMask0[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 1){
nDest[nPixelIndex + 1] += nCountTable[nSourceByte | nMask1[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 2){
nDest[nPixelIndex + 2] += nCountTable[nSourceByte | nMask2[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 3){
nDest[nPixelIndex + 3] += nCountTable[nSourceByte | nMask3[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 4){
nDest[nPixelIndex + 4] += nCountTable[nSourceByte | nMask4[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 5){
nDest[nPixelIndex + 5] += nCountTable[nSourceByte | nMask5[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 6){
nDest[nPixelIndex + 6] += nCountTable[nSourceByte | nMask6[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 7){
nDest[nPixelIndex + 7] += nCountTable[nSourceByte | nMask7[nSourceByteIndex]];
if (nPixels[nSourceByteIndex] > 8){
nDest[nPixelIndex + 8] += nCountTable[nSourceByte | nMask8[nSourceByteIndex]];
} } } } } } } } }
nSourceByteIndex++;
}
}
}
// Average the line to gray.
nPixelIndex = 0;
pDestLine = &pDestImg->bImageData[0] + ((nDestLine + (int)lrDestRect.top) * pDestImg->nBytesPerLine);
if (pDestImg->nType == ITYPE_GRAY8 || pDestImg->nType == ITYPE_GRAY7){
pDestLine += lrDestRect.left;
nTempIndex = nDestWidth + 1;
while(--nTempIndex){
*(pDestLine++) = (BYTE) (nGrayScaleTable1[nDest[nPixelIndex++]]);
}
}else{ // GRAY4.
pDestLine += lrDestRect.left / 2;
nTempIndex = 0;
if (lrDestRect.left & 1){
// Do first pixel.
*pDestLine = (BYTE) ((*pDestLine & 0xf0) | nGrayScaleTable1[nDest[nPixelIndex++]]);
pDestLine++;
nTempIndex++;
}
// Do middle bytes.
nLoopEnd = max (0, (nDestWidth - nTempIndex) >> 1);
nTempIndex += nLoopEnd << 1;
nLoopEnd++;
while(--nLoopEnd){
*(pDestLine++) = (BYTE) (nGrayScaleTable2[nDest[nPixelIndex]]
| nGrayScaleTable1[nDest[nPixelIndex + 1]]);
nPixelIndex += 2;
}
// Do last pixel.
if (nTempIndex < nDestWidth){
*pDestLine = (BYTE) ((*pDestLine & 0x0f) | nGrayScaleTable2[nDest[nPixelIndex++]]);
}
}
}
Exit:
if (pnSourceLineOffsets){
FreeMemory((PPSTR) &pnSourceLineOffsets);
}
return(nStatus);
}
//
/****************************************************************************
FUNCTION: ScaleRGBToGrayAvg
PURPOSE: Scales RGB/BGR images to GRAY8/GRAY7/GRAY4.
*****************************************************************************/
int WINAPI ScaleRGBToGrayAvg(PIMG pSourceImg, PIMG pDestImg,
int nHScale, int nVScale,
int nHDestOffset, int nVDestOffset, LRECT lrDestRect){
int nStatus = 0;
int nDestWidth;
int nDestWidthBytes;
int nDestHeight;
int nSourcePixelsPerLinePerPixel;
int nSourceLinesPerPixel;
int nPerLineDivisor; // Divisor for per line averaging. 1 if not needed.
int nDivisor; // Divisor for averaging of all lines.
int nDestLine;
PINT pnSourceByteOffsets = 0; // Table nsed to translate dest pixel offsets to source byte offsets.
PINT pnSourceLineOffsets = 0; // Table nsed to translate dest line offsets to source line offsets.
int nDestR; // Intermediate averaging value.
int nDestG; // "
int nDestB; // "
PINT pnDestLineR = 0; // Temp buffer nsed to hold one line of average values.
PINT pnDestLineG = 0; // "
PINT pnDestLineB = 0; // "
PBYTE pTempDestLine = 0; // Temp buffer nsed to hold one line of gray scale values.
PBYTE pSourceLine; // The address of the start of the source line.
PBYTE pSourceByte; // The address of the source byte currently being processed.
PBYTE pDestLine; // The address of the start of the dest line.
int nSourceBytes;
int nSourceLines;
int nDestByte;
int nScaleDenominator;
// Loop variables.
int nLoop;
PINT pnTempDestLineR; // Temp pointer nsed in loops.
PINT pnTempDestLineG; // "
PINT pnTempDestLineB; // "
int nTempIndex;
int nSourceLineCount;
int nSourcePixelCount;
if (!pDestImg && pDestImg->nType != ITYPE_GRAY8
&& pDestImg->nType != ITYPE_GRAY7
&& pDestImg->nType != ITYPE_GRAY4){
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
if (lrDestRect.right - lrDestRect.left > 0x7fff
|| lrDestRect.bottom - lrDestRect.top > 0x7fff){
nStatus = Error(DISPLAY_INVALIDRECT);
goto Exit;
}
if (nHScale == 62 || nHScale == 31){
nScaleDenominator = 992;
}else{
nScaleDenominator = SCALE_DENOMINATOR;
}
nDestWidth = (int)(lrDestRect.right - lrDestRect.left);
if (pDestImg->nType == ITYPE_GRAY8 || pDestImg->nType == ITYPE_GRAY7){
nDestWidthBytes = nDestWidth;
}else{ // GRAY4
nDestWidthBytes = nDestWidth / 2;
}
nDestHeight = (int)(lrDestRect.bottom - lrDestRect.top);
nSourcePixelsPerLinePerPixel = nScaleDenominator / nHScale;
if ((nScaleDenominator % nHScale) || !nSourcePixelsPerLinePerPixel){
nSourcePixelsPerLinePerPixel++;
}
nSourceLinesPerPixel = nScaleDenominator / nVScale;
if ((nScaleDenominator % nVScale) || !nSourceLinesPerPixel){
nSourceLinesPerPixel++;
}
CheckError2( AllocateMemory(sizeof(int) * nDestWidth, (PPSTR) &pnDestLineR, NO_INIT));
CheckError2( AllocateMemory(sizeof(int) * nDestWidth, (PPSTR) &pnDestLineG, NO_INIT));
CheckError2( AllocateMemory(sizeof(int) * nDestWidth, (PPSTR) &pnDestLineB, NO_INIT));
CheckError2( AllocateMemory(nDestWidth, (PPSTR) &pTempDestLine, NO_INIT));
// Produce table of source pixel offsets.
CheckError2( AllocateMemory(sizeof(int) * nDestWidth, (PPSTR) &pnSourceByteOffsets, NO_INIT));
nSourceBytes = (int) pSourceImg->nWidth * 3;
for (nLoop = 0; nLoop < nDestWidth; nLoop++){
pnSourceByteOffsets[nLoop] = (int)((((nLoop + nHDestOffset + lrDestRect.left)
* nScaleDenominator) / nHScale) * 3);
if (pnSourceByteOffsets[nLoop] + (nSourcePixelsPerLinePerPixel * 3) >= nSourceBytes){
pnSourceByteOffsets[nLoop] = nSourceBytes - (nSourcePixelsPerLinePerPixel * 3);
}
}
// Produce table of source line offsets.
CheckError2( AllocateMemory(sizeof(int) * nDestHeight, (PPSTR) &pnSourceLineOffsets, NO_INIT));
nSourceLines = (int) pSourceImg->nHeight;
for (nLoop = 0; nLoop < nDestHeight; nLoop++){
pnSourceLineOffsets[nLoop] = (int)(((nLoop + nVDestOffset + lrDestRect.top)
* nScaleDenominator) / nVScale);
if (pnSourceLineOffsets[nLoop] + nSourceLinesPerPixel > nSourceLines){
pnSourceLineOffsets[nLoop] = nSourceLines - nSourceLinesPerPixel;
}
}
// Calculate the averaging divisors.
if (nSourcePixelsPerLinePerPixel >= 16 || nSourceLinesPerPixel >= 16){
nPerLineDivisor = nSourcePixelsPerLinePerPixel;
nDivisor = nSourceLinesPerPixel;
}else{
nPerLineDivisor = 1;
nDivisor = nSourcePixelsPerLinePerPixel * nSourceLinesPerPixel;
}
for (nDestLine = 0; nDestLine < nDestHeight; nDestLine++){
memset(pnDestLineR, 0, sizeof(int) * nDestWidth);
memset(pnDestLineG, 0, sizeof(int) * nDestWidth);
memset(pnDestLineB, 0, sizeof(int) * nDestWidth);
if (pSourceImg->nType == ITYPE_RGB24){
// Average first source line.
for (nSourceLineCount = nSourceLinesPerPixel; nSourceLineCount; nSourceLineCount--){
pSourceLine = &pSourceImg->bImageData[0] + ((pnSourceLineOffsets[nDestLine]
+ (nSourceLinesPerPixel - nSourceLineCount)) * pSourceImg->nBytesPerLine);
pnTempDestLineR = pnDestLineR;
pnTempDestLineG = pnDestLineG;
pnTempDestLineB = pnDestLineB;
for (nTempIndex = 0; nTempIndex < nDestWidth; nTempIndex++){
// Add source pixels for this line.
pSourceByte = pSourceLine + pnSourceByteOffsets[nTempIndex];
nSourcePixelCount = nSourcePixelsPerLinePerPixel;
nDestR = *(pSourceByte++);
nDestG = *(pSourceByte++);
nDestB = *(pSourceByte++);
while(--nSourcePixelCount){
nDestR += *(pSourceByte++);
nDestG += *(pSourceByte++);
nDestB += *(pSourceByte++);
}
if (nPerLineDivisor != 1){
nDestR /= nPerLineDivisor;
nDestG /= nPerLineDivisor;
nDestB /= nPerLineDivisor;
}
*(pnTempDestLineR++) += nDestR;
*(pnTempDestLineG++) += nDestG;
*(pnTempDestLineB++) += nDestB;
}
}
}else{
for (nSourceLineCount = nSourceLinesPerPixel; nSourceLineCount; nSourceLineCount--){
pSourceLine = &pSourceImg->bImageData[0] + ((pnSourceLineOffsets[nDestLine]
+ (nSourceLinesPerPixel - nSourceLineCount)) * pSourceImg->nBytesPerLine);
pnTempDestLineR = pnDestLineR;
pnTempDestLineG = pnDestLineG;
pnTempDestLineB = pnDestLineB;
for (nTempIndex = 0; nTempIndex < nDestWidth; nTempIndex++){
// Add source pixels for this line.
pSourceByte = pSourceLine + pnSourceByteOffsets[nTempIndex];
nSourcePixelCount = nSourcePixelsPerLinePerPixel;
nDestB = *(pSourceByte++);
nDestG = *(pSourceByte++);
nDestR = *(pSourceByte++);
while(--nSourcePixelCount){
nDestB += *(pSourceByte++);
nDestG += *(pSourceByte++);
nDestR += *(pSourceByte++);
}
if (nPerLineDivisor != 1){
nDestR /= nPerLineDivisor;
nDestG /= nPerLineDivisor;
nDestB /= nPerLineDivisor;
}
*(pnTempDestLineR++) += nDestR;
*(pnTempDestLineG++) += nDestG;
*(pnTempDestLineB++) += nDestB;
}
}
}
// Average the line to gray.
pnTempDestLineR = pnDestLineR;
pnTempDestLineG = pnDestLineG;
pnTempDestLineB = pnDestLineB;
pDestLine = &pDestImg->bImageData[0] + ((nDestLine + (int)lrDestRect.top) * pDestImg->nBytesPerLine);
if (pDestImg->nType == ITYPE_GRAY4){
for (nLoop = 0; nLoop < nDestWidthBytes; nLoop++){
nDestByte = (cRedToGray8Table[*(pnTempDestLineR++) / nDivisor]
+ cGreenToGray8Table[*(pnTempDestLineG++) / nDivisor]
+ cBlueToGray8Table[*(pnTempDestLineB++) / nDivisor]) & 0xf0;
*(pDestLine++) = nDestByte | ((cRedToGray8Table[*(pnTempDestLineR++) / nDivisor]
+ cGreenToGray8Table[*(pnTempDestLineG++) / nDivisor]
+ cBlueToGray8Table[*(pnTempDestLineB++) / nDivisor]) >> 4);
}
if (nDestWidth & 1){
*pDestLine = (cRedToGray8Table[*pnTempDestLineR / nDivisor]
+ cGreenToGray8Table[*pnTempDestLineG / nDivisor]
+ cBlueToGray8Table[*pnTempDestLineB / nDivisor]) & 0xf0;
}
}else if (pDestImg->nType == ITYPE_GRAY8){
for (nLoop = 0; nLoop < nDestWidthBytes; nLoop++){
*(pDestLine++) = cRedToGray8Table[*(pnTempDestLineR++) / nDivisor]
+ cGreenToGray8Table[*(pnTempDestLineG++) / nDivisor]
+ cBlueToGray8Table[*(pnTempDestLineB++) / nDivisor];
}
}else{ // GRAY7
for (nLoop = 0; nLoop < nDestWidthBytes; nLoop++){
*(pDestLine++) = (cRedToGray8Table[*(pnTempDestLineR++) / nDivisor]
+ cGreenToGray8Table[*(pnTempDestLineG++) / nDivisor]
+ cBlueToGray8Table[*(pnTempDestLineB++) / nDivisor]) >> 1;
}
}
}
Exit:
if (pnSourceByteOffsets){
FreeMemory((PPSTR) &pnSourceByteOffsets);
}
if (pnSourceLineOffsets){
FreeMemory((PPSTR) &pnSourceLineOffsets);
}
if (pnDestLineR){
FreeMemory((PPSTR) &pnDestLineR);
}
if (pnDestLineG){
FreeMemory((PPSTR) &pnDestLineG);
}
if (pnDestLineB){
FreeMemory((PPSTR) &pnDestLineB);
}
if (pTempDestLine){
FreeMemory((PPSTR) &pTempDestLine);
}
return(nStatus);
}
//
/****************************************************************************
FUNCTION: Scale24BPPDecimate
PURPOSE: Scales 24 BPP (Bit Per Pixel) images nsing decimation.
*****************************************************************************/
int WINAPI Scale24BPPDecimate(PIMG pSourceImg, PIMG pDestImg,
int nHScale, int nVScale,
int nHDestOffset, int nVDestOffset, LRECT lrDestRect){
int nStatus = 0;
int nDestWidth;
int nDestHeight;
int nDestLine;
PINT pnSourceByteOffsets = 0; // Table nsed to translate dest pixel offsets to source byte offsets.
PBYTE pSourceLine; // The address of the start of the source line.
PBYTE pSourceByte; // The address of the source byte currently being processed.
PBYTE pDestLine; // The address of the start of the dest line.
int nSourceBytes;
int nLoop;
int nTempIndex;
int nScaleDenominator;
if (pDestImg->nType != pSourceImg->nType){
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
if (lrDestRect.right - lrDestRect.left > 0x7fff
|| lrDestRect.bottom - lrDestRect.top > 0x7fff){
nStatus = Error(DISPLAY_INVALIDRECT);
goto Exit;
}
if (nHScale == 62 || nHScale == 31){
nScaleDenominator = 992;
}else{
nScaleDenominator = SCALE_DENOMINATOR;
}
nDestWidth = (int)(lrDestRect.right - lrDestRect.left);
nDestHeight = (int)(lrDestRect.bottom - lrDestRect.top);
// Produce table of source pixel offsets.
CheckError2( AllocateMemory(sizeof(int) * nDestWidth, (PPSTR) &pnSourceByteOffsets, NO_INIT));
nSourceBytes = (int) pSourceImg->nWidth * 3;
for (nLoop = 0; nLoop < nDestWidth; nLoop++){
pnSourceByteOffsets[nLoop] = (int)((((nLoop + nHDestOffset + lrDestRect.left)
* nScaleDenominator) / nHScale) * 3);
if (pnSourceByteOffsets[nLoop] >= nSourceBytes){
pnSourceByteOffsets[nLoop] = nSourceBytes - 3;
}
}
for (nDestLine = 0; nDestLine < nDestHeight; nDestLine++){
pDestLine = &pDestImg->bImageData[0] + ((nDestLine + (int)lrDestRect.top) * pDestImg->nBytesPerLine);
pSourceLine = &pSourceImg->bImageData[0] + (((int)(((nDestLine
+ nVDestOffset + (int)lrDestRect.top) * nScaleDenominator) / nVScale)) * pSourceImg->nBytesPerLine);
if (nHScale == 1000){
pSourceByte = pSourceLine + pnSourceByteOffsets[0];
memcpy(pDestLine + (lrDestRect.left * 3), pSourceByte, nDestWidth * 3);
}else{
for (nTempIndex = 0; nTempIndex < nDestWidth; nTempIndex++){
pSourceByte = pSourceLine + pnSourceByteOffsets[nTempIndex];
*(pDestLine++) = *(pSourceByte++);
*(pDestLine++) = *(pSourceByte++);
*(pDestLine++) = *(pSourceByte++);
}
}
}
Exit:
if (pnSourceByteOffsets){
FreeMemory((PPSTR) &pnSourceByteOffsets);
}
return(nStatus);
}
//
/****************************************************************************
FUNCTION: ScaleBWKeepBlack
PURPOSE: Scales BW images to BW keeping black pixels.
*****************************************************************************/
int WINAPI ScaleBWKeepBlack(PIMG pSourceImg, PIMG pDestImg,
int nHScale, int nVScale,
int nHDestOffset, int nVDestOffset, LRECT *plrDestRect){
int nStatus = 0;
typedef struct tagBWKeepBlackScaleTable{
int nFirstByte;
int nFirstMask;
int nBytes;
int nLastMask;
} BW_KEEP_BLACK_SCALE_TABLE;
BW_KEEP_BLACK_SCALE_TABLE ScaleTable[MAX_PIXELS_HANDLED];
int nDestWidth;
int nDestHeight;
int nSourcePixelsPerLinePerPixel;
int nSourceLinesPerPixel;
int nDestLine;
PINT pnSourceLineOffsets = 0; // Table nsed to translate dest line offsets to source line offsets.
PBYTE pSourceLine; // The address of the start of the source line.
PBYTE pSourceByte; // The address of the source byte currently being processed.
PBYTE pDestLine; // The address of the start of the dest line.
PBYTE pDestByte; // The address of the dest byte currently being processed.
int nFirstMask;
int nLastMask;
int nSourcePixel;
int nScaleDenominator;
int nXlatTable[2048];
int *pXlatTable;
int nSourceWidth;
int nSourceHeight;
int nFirstDestByte;
int nFirstDestBit;
int nFirstDestMask;
int nLastDestMask;
int nMiddleDestBytes;
int nSourceByte;
// Loop variables.
int nLoop;
int nTempIndex;
int nSourceLineCount;
int nLoopEnd;
int nDestBit;
LRECT lrDestRect ;
CopyRect (lrDestRect, *plrDestRect) ;
if (pDestImg->nType != ITYPE_BI_LEVEL){
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
if (nHScale == 62 || nHScale == 31){
nScaleDenominator = 992;
}else{
nScaleDenominator = SCALE_DENOMINATOR;
}
if (nHScale >= 1000 || nHScale >= 1000){
nStatus = Scale1BPPDecimate(pSourceImg, pDestImg,
nHScale, nVScale, nHDestOffset, nVDestOffset, &lrDestRect);
goto Exit;
}
if (lrDestRect.right - lrDestRect.left > 0x7fff
|| lrDestRect.bottom - lrDestRect.top > 0x7fff){
nStatus = Error(DISPLAY_INVALIDRECT);
goto Exit;
}
nDestWidth = (int)(lrDestRect.right - lrDestRect.left);
nDestHeight = (int)(lrDestRect.bottom - lrDestRect.top);
nSourcePixelsPerLinePerPixel = (int)(nScaleDenominator / nHScale);
if ((nScaleDenominator % nHScale) || !nSourcePixelsPerLinePerPixel){
nSourcePixelsPerLinePerPixel++;
}
nSourceLinesPerPixel = (int)(nScaleDenominator / nVScale);
if ((nScaleDenominator % nVScale) || !nSourceLinesPerPixel){
nSourceLinesPerPixel++;
}
// Init Scale table.
pXlatTable = &nXlatTable[0];
for (nLoop = 255; nLoop; nLoop--){
*(pXlatTable++) = 0x7f;
}
*(pXlatTable++) = 0xff;
for (nLoop = 255; nLoop; nLoop--){
*(pXlatTable++) = 0xbf;
}
*(pXlatTable++) = 0xff;
for (nLoop = 255; nLoop; nLoop--){
*(pXlatTable++) = 0xdf;
}
*(pXlatTable++) = 0xff;
for (nLoop = 255; nLoop; nLoop--){
*(pXlatTable++) = 0xef;
}
*(pXlatTable++) = 0xff;
for (nLoop = 255; nLoop; nLoop--){
*(pXlatTable++) = 0xf7;
}
*(pXlatTable++) = 0xff;
for (nLoop = 255; nLoop; nLoop--){
*(pXlatTable++) = 0xfb;
}
*(pXlatTable++) = 0xff;
for (nLoop = 255; nLoop; nLoop--){
*(pXlatTable++) = 0xfd;
}
*(pXlatTable++) = 0xff;
for (nLoop = 255; nLoop; nLoop--){
*(pXlatTable++) = 0xfe;
}
*(pXlatTable++) = 0xff;
// Produce scale table.
// Pixel 0 = 0x80, pixel 7 = 0x01. 0 = black, 1 = white.
switch (nSourcePixelsPerLinePerPixel){
case 1: nFirstMask = 0x80; break;
case 2: nFirstMask = 0xc0; break;
case 3: nFirstMask = 0xe0; break;
case 4: nFirstMask = 0xf0; break;
case 5: nFirstMask = 0xf8; break;
case 6: nFirstMask = 0xfc; break;
case 7: nFirstMask = 0xfe; break;
default: nFirstMask = 0xff; break;
}
nSourceWidth = (int) pSourceImg->nWidth;
for (nLoop = 0; nLoop < nDestWidth; nLoop++){
nSourcePixel = ((nLoop + nHDestOffset + lrDestRect.left) * nScaleDenominator) / nHScale;
if (nSourcePixel + nSourcePixelsPerLinePerPixel > nSourceWidth){
nSourcePixel = nSourceWidth - nSourcePixelsPerLinePerPixel;
}
ScaleTable[nLoop].nFirstByte = (int) (nSourcePixel >> 3);
ScaleTable[nLoop].nFirstMask = ~(nFirstMask >> (nSourcePixel & 7)) & 0xff;
nSourcePixel += nSourcePixelsPerLinePerPixel - 1;
if (!((nSourcePixel >> 3) - ScaleTable[nLoop].nFirstByte)){
ScaleTable[nLoop].nBytes = 0;
ScaleTable[nLoop].nLastMask = 0;
}else{
ScaleTable[nLoop].nBytes =
((int)(nSourcePixel >> 3) - ScaleTable[nLoop].nFirstByte) - 1;
ScaleTable[nLoop].nLastMask = ~(0xff80 >> (nSourcePixel & 7)) & 0xff;
}
}
// Produce table of source line offsets.
CheckError2( AllocateMemory(sizeof(int) * lrDestRect.bottom, (PPSTR) &pnSourceLineOffsets, NO_INIT));
nSourceHeight = (int) pSourceImg->nHeight;
for (nLoop = 0; nLoop < nDestHeight; nLoop++){
pnSourceLineOffsets[nLoop] = (int)(((nLoop + nVDestOffset + lrDestRect.top)
* nScaleDenominator) / nVScale);
if (pnSourceLineOffsets[nLoop] + nSourceLinesPerPixel > nSourceHeight){
pnSourceLineOffsets[nLoop] = (int)nSourceHeight - nSourceLinesPerPixel;
}
}
nFirstDestByte = (lrDestRect.left >> 3);
nFirstDestBit = lrDestRect.left & 7;
switch (nFirstDestBit){
case 0: nDestBit = 0x80; break;
case 1: nDestBit = 0x40; break;
case 2: nDestBit = 0x20; break;
case 3: nDestBit = 0x10; break;
case 4: nDestBit = 0x08; break;
case 5: nDestBit = 0x04; break;
case 6: nDestBit = 0x02; break;
case 7: nDestBit = 0x01; break;
}
nFirstDestMask = 0;
for (nLoop = nDestWidth; nLoop && nDestBit; nLoop--){
nFirstDestMask |= nDestBit;
nDestBit >>= 1;
}
nMiddleDestBytes = nLoop >> 3;
nLastDestMask = 0xff;
for (nLoop &= 7; nLoop; nLoop--){
nLastDestMask >>= 1;
}
nLastDestMask = ~nLastDestMask & 0xff;
for (nDestLine = 0; nDestLine < nDestHeight; nDestLine++){
pDestLine = &pDestImg->bImageData[0] + ((nDestLine + (int)lrDestRect.top) * pDestImg->nBytesPerLine);
// Initialize dest line to white.
pDestByte = pDestLine + nFirstDestByte;
*(pDestByte++) |= nFirstDestMask;
if (nMiddleDestBytes){
memset(pDestByte, 0xff, nMiddleDestBytes);
pDestByte += nMiddleDestBytes;
}
*pDestByte |= nLastDestMask;
for (nSourceLineCount = nSourceLinesPerPixel; nSourceLineCount; nSourceLineCount--){
pSourceLine = &pSourceImg->bImageData[0] + ((pnSourceLineOffsets[nDestLine]
+ (nSourceLinesPerPixel - nSourceLineCount)) * pSourceImg->nBytesPerLine);
pSourceByte = pSourceLine + ScaleTable[0].nFirstByte;
pDestByte = pDestLine + nFirstDestByte;
switch (nHScale){
case 500:
// Do first few pixels to align the data.
nDestBit = nFirstDestBit << 8;
nTempIndex = 0;
while(ScaleTable[nTempIndex].nFirstMask != 0x3f
&& nTempIndex < nDestWidth){
*pDestByte &= nXlatTable[nDestBit
+ (*pSourceByte | ScaleTable[nTempIndex].nFirstMask)];
if (!(nDestBit = (nDestBit + 256) & 0x700 )){
pDestByte++;
}
nTempIndex++;
}
if (nTempIndex){
pSourceByte++;
}
// Do middle pixels.
nLoopEnd = (nDestWidth - nTempIndex) >> 2;
for (; nLoopEnd; nLoopEnd--){
nSourceByte = *(pSourceByte++);
*pDestByte &= nXlatTable[nDestBit + (nSourceByte | 0x3f)];
if (!(nDestBit = (nDestBit + 256) & 0x700 )){
pDestByte++;
}
*pDestByte &= nXlatTable[nDestBit + (nSourceByte | 0xcf)];
if (!(nDestBit = (nDestBit + 256) & 0x700 )){
pDestByte++;
}
*pDestByte &= nXlatTable[nDestBit + (nSourceByte | 0xf3)];
if (!(nDestBit = (nDestBit + 256) & 0x700 )){
pDestByte++;
}
*pDestByte &= nXlatTable[nDestBit + (nSourceByte | 0xfc)];
if (!(nDestBit = (nDestBit + 256) & 0x700 )){
pDestByte++;
}
}
// Do last few pixels.
nLoopEnd = (nDestWidth - nTempIndex) & 3;
nLastMask = 0xff3f;
for (; nLoopEnd; nLoopEnd--){
*pDestByte &= nXlatTable[nDestBit + (*pSourceByte | (nLastMask & 0xff))];
if (!(nDestBit = (nDestBit + 256) & 0x700 )){
pDestByte++;
}
nLastMask >> 2;
}
break;
case 250:
// Do first few pixels to align the data.
nDestBit = nFirstDestBit * 256;
nTempIndex = 0;
if (ScaleTable[nTempIndex].nFirstMask != 0x0f){
*pDestByte &= nXlatTable[nDestBit
+ (*pSourceByte | ScaleTable[nTempIndex].nFirstMask)];
if (!(nDestBit = (nDestBit + 256) & 0x700 )){
pDestByte++;
}
nTempIndex++;
pSourceByte++;
}
// Do middle pixels.
nLoopEnd = (nDestWidth - nTempIndex) / 2;
if (nLoopEnd){
for (; nLoopEnd; nLoopEnd--){
*pDestByte &= nXlatTable[nDestBit + (*pSourceByte | 0x0f)];
if (!(nDestBit = (nDestBit + 256) & 0x700 )){
pDestByte++;
}
*pDestByte &= nXlatTable[nDestBit + (*(pSourceByte++) | 0xf0)];
if (!(nDestBit = (nDestBit + 256) & 0x700 )){
pDestByte++;
}
}
}
// Do last few pixels.
nLoopEnd = (nDestWidth - nTempIndex) & 1;
nLastMask = 0xff3f;
for (; nLoopEnd; nLoopEnd--){
*pDestByte &= nXlatTable[nDestBit + (*pSourceByte | (nLastMask & 0xff))];
if (!(nDestBit = (nDestBit + 256) & 0x700 )){
pDestByte++;
}
nLastMask >> 2;
}
break;
case 125:
nLoopEnd = nDestWidth - 1;
nDestBit = nFirstDestBit * 256;
for (; nLoopEnd; nLoopEnd--){
*pDestByte &= nXlatTable[nDestBit + *(pSourceByte++)];
if (!(nDestBit = (nDestBit + 256) & 0x700 )){
pDestByte++;
}
}
// Do last pixel via variable scale because it might start
// to the left because of not enough source pixels.
nTempIndex = nDestWidth - 1;
pSourceByte = pSourceLine + ScaleTable[nTempIndex].nFirstByte;
*pDestByte &= nXlatTable[nDestBit + (*(pSourceByte++) | ScaleTable[nTempIndex].nFirstMask)];
for (nLoop = ScaleTable[nTempIndex].nBytes; nLoop; nLoop--){
*pDestByte &= nXlatTable[nDestBit + *(pSourceByte++)];
}
if (nLastMask = ScaleTable[nTempIndex].nLastMask){
*pDestByte &= nXlatTable[nDestBit + (*(pSourceByte++) | ScaleTable[nTempIndex].nLastMask)];
}
break;
case 62:
nDestBit = nFirstDestBit * 256;
nLoopEnd = nDestWidth - 1;
for (; nLoopEnd; nLoopEnd--){
*pDestByte &= nXlatTable[nDestBit + *(pSourceByte++)];
*pDestByte &= nXlatTable[nDestBit + *(pSourceByte++)];
if (!(nDestBit = (nDestBit + 256) & 0x700 )){
pDestByte++;
}
}
// Do last pixel via variable scale because it might start
// to the left because of not enough source pixels.
nTempIndex = nDestWidth - 1;
pSourceByte = pSourceLine + ScaleTable[nTempIndex].nFirstByte;
*pDestByte &= nXlatTable[nDestBit + (*(pSourceByte++) | ScaleTable[nTempIndex].nFirstMask)];
for (nLoop = ScaleTable[nTempIndex].nBytes; nLoop; nLoop--){
*pDestByte &= nXlatTable[nDestBit + *(pSourceByte++)];
}
if (nLastMask = ScaleTable[nTempIndex].nLastMask){
*pDestByte &= nXlatTable[nDestBit + (*(pSourceByte++) | ScaleTable[nTempIndex].nLastMask)];
}
break;
case 31:
nDestBit = nFirstDestBit * 256;
nLoopEnd = nDestWidth - 1;
for (; nLoopEnd; nLoopEnd--){
*pDestByte &= nXlatTable[nDestBit + *(pSourceByte++)];
*pDestByte &= nXlatTable[nDestBit + *(pSourceByte++)];
*pDestByte &= nXlatTable[nDestBit + *(pSourceByte++)];
*pDestByte &= nXlatTable[nDestBit + *(pSourceByte++)];
if (!(nDestBit = (nDestBit + 256) & 0x700 )){
pDestByte++;
}
}
// Do last pixel via variable scale because it might start
// to the left because of not enough source pixels.
nTempIndex = nDestWidth - 1;
pSourceByte = pSourceLine + ScaleTable[nTempIndex].nFirstByte;
*pDestByte &= nXlatTable[nDestBit + (*(pSourceByte++) | ScaleTable[nTempIndex].nFirstMask)];
for (nLoop = ScaleTable[nTempIndex].nBytes; nLoop; nLoop--){
*pDestByte &= nXlatTable[nDestBit + *(pSourceByte++)];
}
if (nLastMask = ScaleTable[nTempIndex].nLastMask){
*pDestByte &= nXlatTable[nDestBit + (*(pSourceByte++) | ScaleTable[nTempIndex].nLastMask)];
}
break;
default: // Variable scale.
nDestBit = nFirstDestBit * 256;
for (nTempIndex = 0; nTempIndex < nDestWidth; nTempIndex++){
pSourceByte = pSourceLine + ScaleTable[nTempIndex].nFirstByte;
*pDestByte &= nXlatTable[nDestBit + (*(pSourceByte++) | ScaleTable[nTempIndex].nFirstMask)];
for (nLoop = ScaleTable[nTempIndex].nBytes; nLoop; nLoop--){
*pDestByte &= nXlatTable[nDestBit + *(pSourceByte++)];
}
if (nLastMask = ScaleTable[nTempIndex].nLastMask){
*pDestByte &= nXlatTable[nDestBit + (*(pSourceByte++) | ScaleTable[nTempIndex].nLastMask)];
}
if ((nDestBit = (nDestBit + 256) & 0x700 )){
continue;
}
pDestByte++;
}
break;
}
}
}
Exit:
if (pnSourceLineOffsets){
FreeMemory((PPSTR) &pnSourceLineOffsets);
}
return(nStatus);
}
//
/****************************************************************************
FUNCTION: ScaleGray8ToGray
PURPOSE: Scales GRAY8/GRAY7 images to GRAY8/GRAY7/GRAY4.
*****************************************************************************/
int WINAPI ScaleGray8ToGray(PIMG pSourceImg, PIMG pDestImg,
int nHScale, int nVScale,
int nHDestOffset, int nVDestOffset, LRECT lrDestRect){
int nStatus = 0;
int nDestWidth;
int nDestHeight;
int nSourcePixelsPerLinePerPixel;
int nSourceLinesPerPixel;
int nPerLineDivisor; // Divisor for per line averaging. 1 if not needed.
int nDivisor; // Divisor for averaging of all lines.
int nDestLine;
PINT pnSourceByteOffsets = 0; // Table nsed to translate dest pixel offsets to source byte offsets.
PINT pnSourceLineOffsets = 0; // Table nsed to translate dest line offsets to source line offsets.
PINT pnDestLine = 0; // Temp buffer nsed to hold one line of average values.
PBYTE pTempDestLine = 0; // Temp buffer nsed to hold one line of gray scale values.
PBYTE pSourceLine; // The address of the start of the source line.
PBYTE pDestLine; // The address of the start of the dest line.
int nSourceWidth;
int nSourceHeight;
int nScaleDenominator;
// Loop variables.
int nLoop;
PINT pnTempDestLine; // Temp pointer nsed in loops.
int nSourceLineCount;
int nTempIndex;
PBYTE pSourceByte; // The address of the source byte currently being processed.
int nSourcePixelCount;
int nDest; // Intermediate averaging value.
if (pDestImg->nType != ITYPE_GRAY8
&& pDestImg->nType != ITYPE_GRAY7
&& pDestImg->nType != ITYPE_GRAY4){
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
if (lrDestRect.right - lrDestRect.left > 0x7fff
|| lrDestRect.bottom - lrDestRect.top > 0x7fff){
nStatus = Error(DISPLAY_INVALIDRECT);
goto Exit;
}
if (nHScale >= 1000 && nVScale >= 1000 && pSourceImg->nType == pDestImg->nType){
nStatus = Scale8BPPDecimate(pSourceImg, pDestImg,
nHScale, nVScale, nHDestOffset, nVDestOffset, lrDestRect);
goto Exit;
}
if (nHScale == 62 || nHScale == 31){
nScaleDenominator = 992;
}else{
nScaleDenominator = SCALE_DENOMINATOR;
}
nDestWidth = (int)(lrDestRect.right - lrDestRect.left);
nDestHeight = (int)(lrDestRect.bottom - lrDestRect.top);
nSourcePixelsPerLinePerPixel = nScaleDenominator / nHScale;
if ((nScaleDenominator % nHScale) || !nSourcePixelsPerLinePerPixel){
nSourcePixelsPerLinePerPixel++;
}
nSourceLinesPerPixel = nScaleDenominator / nVScale;
if ((nScaleDenominator % nVScale) || !nSourceLinesPerPixel){
nSourceLinesPerPixel++;
}
CheckError2( AllocateMemory(sizeof(int) * nDestWidth, (PPSTR) &pnDestLine, NO_INIT));
CheckError2( AllocateMemory(nDestWidth, (PPSTR) &pTempDestLine, NO_INIT));
// Produce table of source pixel offsets.
CheckError2( AllocateMemory(sizeof(int) * nDestWidth, (PPSTR) &pnSourceByteOffsets, NO_INIT));
nSourceWidth = (int) pSourceImg->nWidth;
for (nLoop = 0; nLoop < nDestWidth; nLoop++){
pnSourceByteOffsets[nLoop] = (int)(((nLoop + nHDestOffset + lrDestRect.left)
* nScaleDenominator) / nHScale);
if (pnSourceByteOffsets[nLoop] + nSourcePixelsPerLinePerPixel > nSourceWidth){
pnSourceByteOffsets[nLoop] = nSourceWidth - nSourcePixelsPerLinePerPixel;
}
}
// Produce table of source line offsets.
CheckError2( AllocateMemory(sizeof(int) * nDestHeight, (PPSTR) &pnSourceLineOffsets, NO_INIT));
nSourceHeight = (int) pSourceImg->nHeight;
for (nLoop = 0; nLoop < nDestHeight; nLoop++){
pnSourceLineOffsets[nLoop] = (int)(((nLoop + nVDestOffset + lrDestRect.top)
* nScaleDenominator) / nVScale);
if (pnSourceLineOffsets[nLoop] + nSourceLinesPerPixel > nSourceHeight){
pnSourceLineOffsets[nLoop] = nSourceHeight - nSourceLinesPerPixel;
}
}
// Calculate the averaging divisors.
if (nSourcePixelsPerLinePerPixel >= 16 || nSourceLinesPerPixel >= 16){
nPerLineDivisor = nSourcePixelsPerLinePerPixel;
if (pDestImg->nType == ITYPE_GRAY8){
nDivisor = nSourceLinesPerPixel;
}else if(pDestImg->nType == ITYPE_GRAY7){
nDivisor = nSourceLinesPerPixel * 2;
}else{ // GRAY4
nDivisor = nSourceLinesPerPixel * 16;
}
}else{
nPerLineDivisor = 1;
if (pDestImg->nType == ITYPE_GRAY8){
nDivisor = nSourcePixelsPerLinePerPixel * nSourceLinesPerPixel;
}else if(pDestImg->nType == ITYPE_GRAY7){
nDivisor = nSourcePixelsPerLinePerPixel * nSourceLinesPerPixel * 2;
}else{ // GRAY4
nDivisor = nSourcePixelsPerLinePerPixel * nSourceLinesPerPixel * 16;
}
}
for (nDestLine = 0; nDestLine < nDestHeight; nDestLine++){
memset(pnDestLine, 0, sizeof(int) * nDestWidth);
for (nSourceLineCount = nSourceLinesPerPixel; nSourceLineCount; nSourceLineCount--){
pSourceLine = &pSourceImg->bImageData[0] + ((pnSourceLineOffsets[nDestLine + lrDestRect.top]
+ (nSourceLinesPerPixel - nSourceLineCount)) * pSourceImg->nBytesPerLine);
pnTempDestLine = pnDestLine;
for (nLoop = 0; nLoop < nDestWidth; nLoop++){
pSourceByte = pSourceLine + pnSourceByteOffsets[nLoop];
nSourcePixelCount = nSourcePixelsPerLinePerPixel;
nDest = *(pSourceByte++);
while(--nSourcePixelCount){
nDest += *(pSourceByte++);
}
if (nPerLineDivisor != 1){
nDest /= nPerLineDivisor;
}
*(pnTempDestLine++) += nDest;
}
}
// Average the line to gray.
pnTempDestLine = pnDestLine;
pDestLine = &pDestImg->bImageData[0] + ((nDestLine + (int)lrDestRect.top) * pDestImg->nBytesPerLine);
if (pDestImg->nType == ITYPE_GRAY4){
pDestLine += lrDestRect.left / 2;
nTempIndex = nDestWidth;
if (lrDestRect.left & 1){
// Do first pixel.
*pDestLine = (*pDestLine & 0xf0) | (*(pnTempDestLine++) / nDivisor);
pDestLine++;
nTempIndex--;
}
// Do middle bytes.
for (nLoop = nTempIndex / 2; nLoop; nLoop--){
*pDestLine = *(pnTempDestLine++) / nDivisor << 4;
*(pDestLine++) |= (*(pnTempDestLine++) / nDivisor);
}
if (nTempIndex & 1){
*pDestLine = *pnTempDestLine / nDivisor << 4;
}
}else{ // Dest == Gray 7/8.
pDestLine += lrDestRect.left;
for (nLoop = nDestWidth; nLoop; nLoop--){
*(pDestLine++) = *(pnTempDestLine++) / nDivisor;
}
}
}
Exit:
if (pnSourceByteOffsets){
FreeMemory((PPSTR) &pnSourceByteOffsets);
}
if (pnSourceLineOffsets){
FreeMemory((PPSTR) &pnSourceLineOffsets);
}
if (pnDestLine){
FreeMemory((PPSTR) &pnDestLine);
}
if (pTempDestLine){
FreeMemory((PPSTR) &pTempDestLine);
}
return(nStatus);
}
//
/****************************************************************************
FUNCTION: Scale8BPPDecimate
PURPOSE: Scales 8 BPP (Bit Per Pixel) images nsing decimation.
*****************************************************************************/
int WINAPI Scale8BPPDecimate(PIMG pSourceImg, PIMG pDestImg,
int nHScale, int nVScale,
int nHDestOffset, int nVDestOffset, LRECT lrDestRect){
int nStatus = 0;
int nDestWidth;
int nDestHeight;
int nDestLine;
PINT pnSourceByteOffsets = 0; // Table nsed to translate dest pixel offsets to source byte offsets.
PBYTE pSourceLine; // The address of the start of the source line.
PBYTE pSourceByte; // The address of the source byte currently being processed.
PBYTE pDestLine; // The address of the start of the dest line.
int nSourceByteAdder;
int nSourceWidth;
int nFirstPixels;
int nMiddlePixels;
int nLastPixels;
int nScaleDenominator;
// Loop variables.
int nLoop;
if (pDestImg->nType != pSourceImg->nType){
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
if (lrDestRect.right - lrDestRect.left > 0x7fff
|| lrDestRect.bottom - lrDestRect.top > 0x7fff){
nStatus = Error(DISPLAY_INVALIDRECT);
goto Exit;
}
if (nHScale == 62 || nHScale == 31){
nScaleDenominator = 992;
}else{
nScaleDenominator = SCALE_DENOMINATOR;
}
nDestWidth = (int)(lrDestRect.right - lrDestRect.left);
nDestHeight = (int)(lrDestRect.bottom - lrDestRect.top);
// Produce table of source pixel offsets.
CheckError2( AllocateMemory(sizeof(int) * nDestWidth, (PPSTR) &pnSourceByteOffsets, NO_INIT));
nSourceWidth = (int) pSourceImg->nWidth;
for (nLoop = 0; nLoop < nDestWidth; nLoop++){
pnSourceByteOffsets[nLoop] = (int)((((nLoop + nHDestOffset)
* nScaleDenominator) / nHScale));
if (pnSourceByteOffsets[nLoop] >= nSourceWidth){
pnSourceByteOffsets[nLoop] = nSourceWidth - 1;
}
}
// Put stuff here that you only have to do once.
switch (nHScale){
case 8000:
nFirstPixels = min(nDestWidth, (8 - ((int)nHDestOffset + (int)lrDestRect.left)) & 7);
nMiddlePixels = (nDestWidth - nFirstPixels) >> 3;
nLastPixels = nDestWidth - nFirstPixels - (nMiddlePixels << 3);
break;
case 4000:
nFirstPixels = min(nDestWidth, (4 - ((int)nHDestOffset + (int)lrDestRect.left)) & 3);
nMiddlePixels = (nDestWidth - nFirstPixels) >> 2;
nLastPixels = nDestWidth - nFirstPixels - (nMiddlePixels << 2);
break;
case 2000:
nFirstPixels = min(nDestWidth, (2 - ((int)nHDestOffset + (int)lrDestRect.left)) & 1);
nMiddlePixels = (nDestWidth - nFirstPixels) >> 1;
nLastPixels = nDestWidth - nFirstPixels - (nMiddlePixels << 1);
break;
default:
break;
}
for (nDestLine = 0; nDestLine < nDestHeight; nDestLine++){
pDestLine = &pDestImg->bImageData[0] + ((nDestLine + (int)lrDestRect.top) * pDestImg->nBytesPerLine);
pDestLine += lrDestRect.left;
pSourceLine = &pSourceImg->bImageData[0] + (((int)(((nDestLine + nVDestOffset + lrDestRect.top)
* nScaleDenominator) / nVScale)) * pSourceImg->nBytesPerLine);
switch (nHScale){
case 8000:
pSourceByte = pSourceLine + pnSourceByteOffsets[0];
if (nFirstPixels){
for (nLoop = nFirstPixels; nLoop; nLoop--){
*(pDestLine++) = *pSourceByte;
}
pSourceByte++;
}
for (nLoop = nMiddlePixels; nLoop; nLoop--){
*(pDestLine++) = *(pSourceByte);
*(pDestLine++) = *(pSourceByte);
*(pDestLine++) = *(pSourceByte);
*(pDestLine++) = *(pSourceByte);
*(pDestLine++) = *(pSourceByte);
*(pDestLine++) = *(pSourceByte);
*(pDestLine++) = *(pSourceByte);
*(pDestLine++) = *(pSourceByte++);
}
for (nLoop = nLastPixels; nLoop; nLoop--){
*(pDestLine++) = *(pSourceByte);
}
break;
case 4000:
pSourceByte = pSourceLine + pnSourceByteOffsets[0];
if (nFirstPixels){
for (nLoop = nFirstPixels; nLoop; nLoop--){
*(pDestLine++) = *pSourceByte;
}
pSourceByte++;
}
for (nLoop = nMiddlePixels; nLoop; nLoop--){
*(pDestLine++) = *(pSourceByte);
*(pDestLine++) = *(pSourceByte);
*(pDestLine++) = *(pSourceByte);
*(pDestLine++) = *(pSourceByte++);
}
for (nLoop = nLastPixels; nLoop; nLoop--){
*(pDestLine++) = *(pSourceByte);
}
break;
case 2000:
pSourceByte = pSourceLine + pnSourceByteOffsets[0];
if (nFirstPixels){
for (nLoop = nFirstPixels; nLoop; nLoop--){
*(pDestLine++) = *pSourceByte;
}
pSourceByte++;
}
for (nLoop = nMiddlePixels; nLoop; nLoop--){
*(pDestLine++) = *(pSourceByte);
*(pDestLine++) = *(pSourceByte++);
}
for (nLoop = nLastPixels; nLoop; nLoop--){
*(pDestLine++) = *(pSourceByte);
}
break;
case 1000:
pSourceByte = pSourceLine + pnSourceByteOffsets[0];
memcpy(pDestLine, pSourceByte, nDestWidth);
break;
case 500:
case 250:
case 125:
case 62:
case 31:
pSourceByte = pSourceLine + pnSourceByteOffsets[0];
nSourceByteAdder = 1000 / nHScale;
for (nLoop = nDestWidth; nLoop; nLoop--){
*(pDestLine++) = *pSourceByte;
pSourceByte += nSourceByteAdder;
}
break;
default: // Variable scale.
for (nLoop = 0; nLoop < nDestWidth; nLoop++){
*(pDestLine++) = *(pSourceLine + pnSourceByteOffsets[nLoop]);
}
break;
}
}
Exit:
if (pnSourceByteOffsets){
FreeMemory((PPSTR) &pnSourceByteOffsets);
}
return(nStatus);
}
//
/****************************************************************************
FUNCTION: Scale8BPPToGray
PURPOSE: Scales CUSPAL8/COMPAL8 images to GRAY8/GRAY7/GRAY4.
*****************************************************************************/
int WINAPI ScalePal8ToGray(PIMG pSourceImg, PIMG pDestImg,
int nHScale, int nVScale,
int nHDestOffset, int nVDestOffset,
LRECT lrDestRect, LPRGBQUAD pPalette){
int nStatus = 0;
int nDestWidth;
int nDestHeight;
int nSourcePixelsPerLinePerPixel;
int nSourceLinesPerPixel;
int nPerLineDivisor; // Divisor for per line averaging. 1 if not needed.
int nDivisor; // Divisor for averaging of all lines.
int nDestLine;
PINT pnSourceByteOffsets = 0; // Table nsed to translate dest pixel offsets to source byte offsets.
PINT pnSourceLineOffsets = 0; // Table nsed to translate dest line offsets to source line offsets.
PINT pnDestLine = 0; // Temp buffer nsed to hold one line of average values.
PBYTE pTempDestLine = 0; // Temp buffer nsed to hold one line of gray scale values.
PBYTE pSourceLine; // The address of the start of the source line.
PBYTE pDestLine; // The address of the start of the dest line.
int nSourceWidth;
int nSourceHeight;
BYTE cPal8ToGray8Table[256];
int nScaleDenominator;
// Loop variables.
int nLoop;
PINT pnTempDestLine; // Temp pointer nsed in loops.
int nSourceLineCount;
int nTempIndex;
PBYTE pSourceByte; // The address of the source byte currently being processed.
int nSourcePixelCount;
int nDest; // Intermediate averaging value.
if (pDestImg->nType != ITYPE_GRAY8
&& pDestImg->nType != ITYPE_GRAY7
&& pDestImg->nType != ITYPE_GRAY4){
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
if (lrDestRect.right - lrDestRect.left > 0x7fff
|| lrDestRect.bottom - lrDestRect.top > 0x7fff){
nStatus = Error(DISPLAY_INVALIDRECT);
goto Exit;
}
if (nHScale == 62 || nHScale == 31){
nScaleDenominator = 992;
}else{
nScaleDenominator = SCALE_DENOMINATOR;
}
nDestWidth = (int)(lrDestRect.right - lrDestRect.left);
nDestHeight = (int)(lrDestRect.bottom - lrDestRect.top);
nSourcePixelsPerLinePerPixel = nScaleDenominator / nHScale;
if ((nScaleDenominator % nHScale) || !nSourcePixelsPerLinePerPixel){
nSourcePixelsPerLinePerPixel++;
}
nSourceLinesPerPixel = nScaleDenominator / nVScale;
if ((nScaleDenominator % nVScale) || !nSourceLinesPerPixel){
nSourceLinesPerPixel++;
}
CheckError2( AllocateMemory(sizeof(int) * nDestWidth, (PPSTR) &pnDestLine, NO_INIT));
CheckError2( AllocateMemory(nDestWidth, (PPSTR) &pTempDestLine, NO_INIT));
// Produce table of source pixel offsets.
CheckError2( AllocateMemory(sizeof(int) * nDestWidth, (PPSTR) &pnSourceByteOffsets, NO_INIT));
nSourceWidth = (int) pSourceImg->nWidth;
for (nLoop = 0; nLoop < nDestWidth; nLoop++){
pnSourceByteOffsets[nLoop] = (int)(((nLoop + nHDestOffset + lrDestRect.left)
* nScaleDenominator) / nHScale);
if (pnSourceByteOffsets[nLoop] + nSourcePixelsPerLinePerPixel > nSourceWidth){
pnSourceByteOffsets[nLoop] = nSourceWidth - nSourcePixelsPerLinePerPixel;
}
}
// Produce table of source line offsets.
CheckError2( AllocateMemory(sizeof(int) * nDestHeight, (PPSTR) &pnSourceLineOffsets, NO_INIT));
nSourceHeight = (int) pSourceImg->nHeight;
for (nLoop = 0; nLoop < nDestHeight; nLoop++){
pnSourceLineOffsets[nLoop] = (int)(((nLoop + nVDestOffset + lrDestRect.top)
* nScaleDenominator) / nVScale);
if (pnSourceLineOffsets[nLoop] + nSourceLinesPerPixel > nSourceHeight){
pnSourceLineOffsets[nLoop] = nSourceHeight - nSourceLinesPerPixel;
}
}
// Calculate the averaging divisors.
if (nSourcePixelsPerLinePerPixel >= 16 || nSourceLinesPerPixel >= 16){
nPerLineDivisor = nSourcePixelsPerLinePerPixel;
if (pDestImg->nType == ITYPE_GRAY8){
nDivisor = nSourceLinesPerPixel;
}else if(pDestImg->nType == ITYPE_GRAY7){
nDivisor = nSourceLinesPerPixel * 2;
}else{ // GRAY4
nDivisor = nSourceLinesPerPixel * 16;
}
}else{
nPerLineDivisor = 1;
if (pDestImg->nType == ITYPE_GRAY8){
nDivisor = nSourcePixelsPerLinePerPixel * nSourceLinesPerPixel;
}else if(pDestImg->nType == ITYPE_GRAY7){
nDivisor = nSourcePixelsPerLinePerPixel * nSourceLinesPerPixel * 2;
}else{ // GRAY4
nDivisor = nSourcePixelsPerLinePerPixel * nSourceLinesPerPixel * 16;
}
}
// Generate palette to gray8 conversion table.
// 74 = 256 * .29
// 144 = 256 * .56
// 38 = 256 * .15
for (nLoop = 0; nLoop < 256; nLoop++){
cPal8ToGray8Table[nLoop] = ((pPalette[nLoop].rgbRed * 74)
+ (pPalette[nLoop].rgbGreen * 144) + (pPalette[nLoop].rgbBlue * 38)) >> 8;
}
for (nDestLine = 0; nDestLine < nDestHeight; nDestLine++){
memset(pnDestLine, 0, sizeof(int) * nDestWidth);
for (nSourceLineCount = nSourceLinesPerPixel; nSourceLineCount; nSourceLineCount--){
pSourceLine = &pSourceImg->bImageData[0] + ((pnSourceLineOffsets[nDestLine + lrDestRect.top]
+ (nSourceLinesPerPixel - nSourceLineCount)) * pSourceImg->nBytesPerLine);
pnTempDestLine = pnDestLine;
if (nPerLineDivisor == 1){
for (nLoop = 0; nLoop < nDestWidth; nLoop++){
pSourceByte = pSourceLine + pnSourceByteOffsets[nLoop];
nSourcePixelCount = nSourcePixelsPerLinePerPixel;
nDest = cPal8ToGray8Table[*(pSourceByte++)];
while(--nSourcePixelCount){
nDest += cPal8ToGray8Table[*(pSourceByte++)];
}
*(pnTempDestLine++) += nDest;
}
}else{
for (nLoop = 0; nLoop < nDestWidth; nLoop++){
pSourceByte = pSourceLine + pnSourceByteOffsets[nLoop];
nSourcePixelCount = nSourcePixelsPerLinePerPixel;
nDest = cPal8ToGray8Table[*(pSourceByte++)];
while(--nSourcePixelCount){
nDest += cPal8ToGray8Table[*(pSourceByte++)];
}
nDest /= nPerLineDivisor;
*(pnTempDestLine++) += nDest;
}
}
}
// Average the line to gray.
pnTempDestLine = pnDestLine;
pDestLine = &pDestImg->bImageData[0] + ((nDestLine + (int)lrDestRect.top) * pDestImg->nBytesPerLine);
if (pDestImg->nType == ITYPE_GRAY4){
pDestLine += lrDestRect.left / 2;
nTempIndex = nDestWidth;
if (lrDestRect.left & 1){
// Do first pixel.
*pDestLine = (*pDestLine & 0xf0) | (*(pnTempDestLine++) / nDivisor);
pDestLine++;
nTempIndex--;
}
// Do middle bytes.
for (nLoop = nTempIndex / 2; nLoop; nLoop--){
*pDestLine = *(pnTempDestLine++) / nDivisor << 4;
*(pDestLine++) |= (*(pnTempDestLine++) / nDivisor);
}
if (nTempIndex & 1){
*pDestLine = *pnTempDestLine / nDivisor << 4;
}
}else{ // Dest == Gray 7/8.
pDestLine += lrDestRect.left;
for (nLoop = nDestWidth; nLoop; nLoop--){
*(pDestLine++) = *(pnTempDestLine++) / nDivisor;
}
}
}
Exit:
if (pnSourceByteOffsets){
FreeMemory((PPSTR) &pnSourceByteOffsets);
}
if (pnSourceLineOffsets){
FreeMemory((PPSTR) &pnSourceLineOffsets);
}
if (pnDestLine){
FreeMemory((PPSTR) &pnDestLine);
}
if (pTempDestLine){
FreeMemory((PPSTR) &pTempDestLine);
}
return(nStatus);
}
//
/****************************************************************************
FUNCTION: ScaleGray4ToGray
PURPOSE: Scales GRAY4 images to GRAY8/GRAY7/GRAY4.
*****************************************************************************/
int WINAPI ScaleGray4ToGray(PIMG pSourceImg, PIMG pDestImg,
int nHScale, int nVScale,
int nHDestOffset, int nVDestOffset, LRECT *plrDestRect){
int nStatus = 0;
int nFirstByte[MAX_PIXELS_HANDLED];
int nFirstMask[MAX_PIXELS_HANDLED];
int nBytes[MAX_PIXELS_HANDLED];
int nLastMask[MAX_PIXELS_HANDLED];
int nDestWidth;
int nDestHeight;
int nSourcePixelsPerLinePerPixel;
int nSourceLinesPerPixel;
int nDivisor; // Divisor for averaging of all lines.
int nDestLineNumber;
int nDestLine[MAX_PIXELS_HANDLED]; // Temp buffer nsed to hold one line of average values.
PINT pnSourceLineOffsets = 0; // Table nsed to translate dest line offsets to source line offsets.
PBYTE pSourceLine; // The address of the start of the source line.
PBYTE pDestLine; // The address of the start of the dest line.
int nByteMask;
long lSourcePixel;
int nSourceWidth;
int nSourceHeight;
PBYTE pSourceByte; // The address of the source byte currently being processed.
int nDest; // Intermediate averaging value.
int nScaleDenominator;
// Loop variables.
int nLoop;
int nTempIndex;
int nSourceLineCount;
int nLoopEnd;
LRECT lrDestRect ;
CopyRect (lrDestRect, *plrDestRect) ;
if (pDestImg->nType != ITYPE_GRAY8
&& pDestImg->nType != ITYPE_GRAY7
&& pDestImg->nType != ITYPE_GRAY4){
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
if (lrDestRect.right - lrDestRect.left > 0x7fff
|| lrDestRect.bottom - lrDestRect.top > 0x7fff){
nStatus = Error(DISPLAY_INVALIDRECT);
goto Exit;
}
if (nHScale >= 1000 && nVScale >= 1000 && pSourceImg->nType == pDestImg->nType){
nStatus = Scale4BPPDecimate(pSourceImg, pDestImg,
nHScale, nVScale, nHDestOffset, nVDestOffset, lrDestRect);
goto Exit;
}
if (nHScale == 62 || nHScale == 31){
nScaleDenominator = 992;
}else{
nScaleDenominator = SCALE_DENOMINATOR;
}
nDestWidth = (int)(lrDestRect.right - lrDestRect.left);
nDestHeight = (int)(lrDestRect.bottom - lrDestRect.top);
nSourcePixelsPerLinePerPixel = nScaleDenominator / nHScale;
if ((nScaleDenominator % nHScale) || !nSourcePixelsPerLinePerPixel){
nSourcePixelsPerLinePerPixel++;
}
nSourceLinesPerPixel = nScaleDenominator / nVScale;
if ((nScaleDenominator % nVScale) || !nSourceLinesPerPixel){
nSourceLinesPerPixel++;
}
// Produce scale table.
// Pixel 0 = 0xf0, pixel 1 = 0x0f. 0 = black, f = white.
if (nSourcePixelsPerLinePerPixel <= 1){
nByteMask = 0xf0;
}else{
nByteMask = 0xff;
}
nSourceWidth = (int) pSourceImg->nWidth;
for (nLoop = 0; nLoop < nDestWidth; nLoop++){
lSourcePixel = ((nLoop + nHDestOffset + lrDestRect.left) * nScaleDenominator) / nHScale;
if (lSourcePixel + nSourcePixelsPerLinePerPixel > nSourceWidth){
lSourcePixel = nSourceWidth - nSourcePixelsPerLinePerPixel;
}
nFirstByte[nLoop] = (int) (lSourcePixel >> 1);
if (lSourcePixel & 1){
nFirstMask[nLoop] = 0x0f;
}else{
nFirstMask[nLoop] = nByteMask;
}
lSourcePixel += nSourcePixelsPerLinePerPixel;
if (!((lSourcePixel >> 1) - nFirstByte[nLoop])){
nBytes[nLoop] = 0;
nLastMask[nLoop] = 0;
}else{
nBytes[nLoop] =
((int)(lSourcePixel >> 1) - nFirstByte[nLoop]) - 1;
if (lSourcePixel & 1){
nLastMask[nLoop] = 0xf0;
}else{
nLastMask[nLoop] = 0;
}
}
}
// Produce table of source line offsets.
CheckError2( AllocateMemory(sizeof(int) * nDestHeight, (PPSTR) &pnSourceLineOffsets, NO_INIT));
nSourceHeight = (int) pSourceImg->nHeight;
for (nLoop = 0; nLoop < nDestHeight; nLoop++){
pnSourceLineOffsets[nLoop] = (int)(((nLoop + nVDestOffset + (int)lrDestRect.top)
* nScaleDenominator) / nVScale);
if (pnSourceLineOffsets[nLoop] + nSourceLinesPerPixel > nSourceHeight){
pnSourceLineOffsets[nLoop] = nSourceHeight - nSourceLinesPerPixel;
}
}
// Calculate the averaging divisors.
if (pDestImg->nType == ITYPE_GRAY8){
nDivisor = nSourcePixelsPerLinePerPixel * nSourceLinesPerPixel;
}else if(pDestImg->nType == ITYPE_GRAY7){
nDivisor = nSourcePixelsPerLinePerPixel * nSourceLinesPerPixel * 2;
}else{ // GRAY4
nDivisor = nSourcePixelsPerLinePerPixel * nSourceLinesPerPixel * 16;
}
for (nDestLineNumber = 0; nDestLineNumber < nDestHeight; nDestLineNumber++){
memset(&nDestLine[0], 0, sizeof(int) * nDestWidth);
for (nSourceLineCount = nSourceLinesPerPixel; nSourceLineCount; nSourceLineCount--){
pSourceLine = &pSourceImg->bImageData[0] + ((pnSourceLineOffsets[nDestLineNumber]
+ (nSourceLinesPerPixel - nSourceLineCount)) * pSourceImg->nBytesPerLine);
for (nTempIndex = 0; nTempIndex < nDestWidth; nTempIndex++){
// Add source pixels for this line.
pSourceByte = pSourceLine + nFirstByte[nTempIndex];
nDest = cGray4AddTable[*(pSourceByte++) & nFirstMask[nTempIndex]];
for (nLoop = nBytes[nTempIndex]; nLoop; nLoop--){
nDest += cGray4AddTable[*(pSourceByte++)];
}
if (nLastMask[nTempIndex]){
nDest += cGray4AddTable[*(pSourceByte++) & nLastMask[nTempIndex]];
}
nDestLine[nTempIndex] += nDest;
}
}
// Average the line to gray.
pDestLine = &pDestImg->bImageData[0] + ((nDestLineNumber + (int)lrDestRect.top) * pDestImg->nBytesPerLine);
if (pDestImg->nType == ITYPE_GRAY4){
pDestLine += lrDestRect.left / 2;
nTempIndex = 0;
if (lrDestRect.left & 1){
// Do first pixel.
*(pDestLine++) = (*pDestLine & 0xf0) | ((nDestLine[nTempIndex++] << 4) / nDivisor);
}
// Do middle bytes.
nLoopEnd = ((nDestWidth - nTempIndex) & -2) + nTempIndex;
for (; nTempIndex < nLoopEnd;){
*pDestLine = (nDestLine[nTempIndex++] << 8) / nDivisor & 0xf0;
*(pDestLine++) |= (nDestLine[nTempIndex++] << 4) / nDivisor;
}
if (nTempIndex < nDestWidth){
*pDestLine = (*pDestLine & 0x0f) | ((nDestLine[nTempIndex] << 8) / nDivisor & 0xf0);
}
}else{ // Dest = Gray 7/8.
pDestLine += lrDestRect.left;
for (nTempIndex = 0; nTempIndex < nDestWidth;){
*(pDestLine++) = (nDestLine[nTempIndex++] << 4) / nDivisor;
}
}
}
Exit:
if (pnSourceLineOffsets){
FreeMemory((PPSTR) &pnSourceLineOffsets);
}
return(nStatus);
}
//
/****************************************************************************
FUNCTION: Scale4BPPDecimate
PURPOSE: Scales 4 BPP (Bit Per Pixel) images nsing decimation.
*****************************************************************************/
int WINAPI Scale4BPPDecimate(PIMG pSourceImg, PIMG pDestImg,
int nHScale, int nVScale,
int nHDestOffset, int nVDestOffset, LRECT lrDestRect){
int nStatus = 0;
typedef struct tagGray4DecimateScaleTable{
int nByte;
int nMask;
} GRAY4_DECIMATE_SCALE_TABLE, *PGRAY4_DECIMATE_SCALE_TABLE;
PGRAY4_DECIMATE_SCALE_TABLE pScaleTable = 0;
PGRAY4_DECIMATE_SCALE_TABLE pScaleTable1;
uchar c4BPPTo0TableLocal[256]; // Table that moves the pixel to pixel 0 in the byte.
uchar c4BPPTo1TableLocal[256]; // Table that moves the pixel to pixel 1 in the byte.
int nDestLine;
PBYTE pSourceLine; // The address of the start of the source line.
PBYTE pSourceByte; // The address of the source byte currently being processed.
PBYTE pDestLine; // The address of the start of the dest line.
int nSourcePixel;
int nSourceWidth;
int nDestWidth;
int nTempIndex;
int nMiddleBytes;
int nScaleDenominator;
// Loop variables.
int nLoop;
int nDestByte;
int nSourceByteAdder;
if (pSourceImg->nType != pDestImg->nType){
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
if (lrDestRect.right - lrDestRect.left > 0x7fff
|| lrDestRect.bottom - lrDestRect.top > 0x7fff){
nStatus = Error(DISPLAY_INVALIDRECT);
goto Exit;
}
if (nHScale == 62 || nHScale == 31){
nScaleDenominator = 992;
}else{
nScaleDenominator = SCALE_DENOMINATOR;
}
nDestWidth = (int)(lrDestRect.right - lrDestRect.left);
// Produce scale table .
memcpy(c4BPPTo0TableLocal, c4BPPTo0Table, 256);
memcpy(c4BPPTo1TableLocal, c4BPPTo1Table, 256);
CheckError2( AllocateMemory(sizeof(GRAY4_DECIMATE_SCALE_TABLE) * nDestWidth,
(PPSTR) &pScaleTable, NO_INIT));
// Pixel 0 = 0xf0, pixel 1 = 0x0f. 0 = black, f = white.
nSourceWidth = (int) pSourceImg->nWidth;
for (nLoop = 0; nLoop < nDestWidth; nLoop++){
nSourcePixel = (int)(((nLoop + nHDestOffset + lrDestRect.left) * nScaleDenominator) / nHScale);
if (nSourcePixel > nSourceWidth){
nSourcePixel = nSourceWidth - 1;
}
pScaleTable[nLoop].nByte = (int) (nSourcePixel >> 1);
if (nSourcePixel & 1){
pScaleTable[nLoop].nMask = 0x0f;
}else{
pScaleTable[nLoop].nMask = 0xf0;
}
}
for (nDestLine = (int)lrDestRect.top; nDestLine < (int)lrDestRect.bottom; nDestLine++){
pDestLine = &pDestImg->bImageData[0] + (nDestLine * pDestImg->nBytesPerLine);
pDestLine += lrDestRect.left / 2;
pSourceLine = &pSourceImg->bImageData[0] + (((int)(((nDestLine + nVDestOffset)
* nScaleDenominator) / nVScale)) * pSourceImg->nBytesPerLine);
// Do first pixel.
pSourceByte = pSourceLine + pScaleTable[0].nByte;
pScaleTable1 = pScaleTable;
nTempIndex = nDestWidth;
if (lrDestRect.left & 1){
*pDestLine = *pDestLine | c4BPPTo1TableLocal[*(pSourceLine
+ pScaleTable1->nByte) & pScaleTable1->nMask];
pSourceByte = pSourceLine + pScaleTable[1].nByte;
pScaleTable1++;
pDestLine++;
nTempIndex--;
}
// Do middle bytes.
nMiddleBytes = nTempIndex / 2;
if (nHScale == 1000 && !(nHDestOffset & 1)){
memcpy(pDestLine, pSourceByte, nMiddleBytes);
pDestLine += nMiddleBytes;
pSourceByte += nMiddleBytes;
}else{
switch (nHScale){
case 500:
case 250:
case 125:
case 62:
case 31:
nSourceByteAdder = (int)((1000 / nHScale) / 2);
if (!(nHDestOffset & 1)){
for (nLoop = nMiddleBytes; nLoop; nLoop--){
nDestByte = *pSourceByte & 0xf0;
pSourceByte += nSourceByteAdder;
*(pDestLine++) = nDestByte | (*pSourceByte >> 4);
pSourceByte += nSourceByteAdder;
}
}else{
for (nLoop = nMiddleBytes; nLoop; nLoop--){
nDestByte = (*pSourceByte << 4);
pSourceByte += nSourceByteAdder;
*(pDestLine++) = nDestByte | *pSourceByte & 0x0f;
pSourceByte += nSourceByteAdder;
}
}
break;
default: // Variable Scale.
for (nLoop = nMiddleBytes; nLoop; nLoop--){
nDestByte = c4BPPTo0TableLocal[*(pSourceLine + pScaleTable1->nByte)
& pScaleTable1->nMask];
pScaleTable1++;
*(pDestLine++) = nDestByte | c4BPPTo1TableLocal[*(pSourceLine + pScaleTable1->nByte)
& pScaleTable1->nMask];
pScaleTable1++;
}
break;
}
}
// Do last pixel.
if (nTempIndex & 1){
pScaleTable1 = &pScaleTable[nDestWidth - 1];
*pDestLine = (*pDestLine & 0x0f)
| c4BPPTo0TableLocal[*(pSourceLine + pScaleTable1->nByte) & pScaleTable1->nMask];
}
}
Exit:
if (pScaleTable){
FreeMemory((PPSTR) &pScaleTable);
}
return(nStatus);
}
//
/****************************************************************************
FUNCTION: ScalePAL4ToGray
PURPOSE: Scales PAL4 images to GRAY8/GRAY7/GRAY4.
*****************************************************************************/
int WINAPI ScalePal4ToGray(PIMG pSourceImg, PIMG pDestImg,
int nHScale, int nVScale,
int nHDestOffset, int nVDestOffset,
LRECT *plrDestRect, LPRGBQUAD pPalette){
int nStatus = 0;
int nDestLineInts[MAX_PIXELS_HANDLED];
PINT pnDestLine = &nDestLineInts[0];
int nFirstByte[MAX_PIXELS_HANDLED];
BOOL bDoFirst[MAX_PIXELS_HANDLED];
int nBytes[MAX_PIXELS_HANDLED];
BOOL bDoLast[MAX_PIXELS_HANDLED];
BYTE cPal4ToGray8Table[256];
int nDestWidth;
int nDestHeight;
int nSourcePixelsPerLinePerPixel;
int nSourceLinesPerPixel;
int nPerLineDivisor; // Divisor for per line averaging. 1 if not needed.
int nDivisor; // Divisor for averaging of all lines.
int nDestLine;
PINT pnSourceLineOffsets = 0; // Table nsed to translate dest line offsets to source line offsets.
PBYTE pSourceLine; // The address of the start of the source line.
PBYTE pDestLine; // The address of the start of the dest line.
long lSourcePixel;
int nSourceWidth;
int nSourceHeight;
int nPixels;
int nScaleDenominator;
// Loop variables.
int nLoop;
PINT pnTempDestLine; // Temp pointer nsed in loops.
int nTempIndex;
int nSourceLineCount;
PBYTE pSourceByte; // The address of the source byte currently being processed.
int nDest; // Intermediate averaging value.
LRECT lrDestRect ;
CopyRect (lrDestRect, *plrDestRect) ;
if (pDestImg->nType != ITYPE_GRAY8
&& pDestImg->nType != ITYPE_GRAY7
&& pDestImg->nType != ITYPE_GRAY4){
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
if (nHScale >= 1000 && nVScale >= 1000 && pSourceImg->nType == pDestImg->nType){
nStatus = Scale4BPPDecimate(pSourceImg, pDestImg,
nHScale, nVScale, nHDestOffset, nVDestOffset, lrDestRect);
goto Exit;
}
if (lrDestRect.right - lrDestRect.left > MAX_PIXELS_HANDLED
|| lrDestRect.bottom - lrDestRect.top > 0x7fff){
nStatus = Error(DISPLAY_INVALIDRECT);
goto Exit;
}
if (nHScale == 62 || nHScale == 31){
nScaleDenominator = 992;
}else{
nScaleDenominator = SCALE_DENOMINATOR;
}
nDestWidth = (lrDestRect.right - lrDestRect.left);
nDestHeight = (lrDestRect.bottom - lrDestRect.top);
nSourcePixelsPerLinePerPixel = nScaleDenominator / nHScale;
if ((nScaleDenominator % nHScale) || !nSourcePixelsPerLinePerPixel){
nSourcePixelsPerLinePerPixel++;
}
nSourceLinesPerPixel = nScaleDenominator / nVScale;
if ((nScaleDenominator % nVScale) || !nSourceLinesPerPixel){
nSourceLinesPerPixel++;
}
// Generate palette to gray8 conversion table.
// 74 = 256 * .29
// 144 = 256 * .56
// 38 = 256 * .15
for (nLoop = 0; nLoop < 16; nLoop++){
cPal4ToGray8Table[nLoop] = ((pPalette[nLoop].rgbRed * 74)
+ (pPalette[nLoop].rgbGreen * 144) + (pPalette[nLoop].rgbBlue * 38)) >> 8;
cPal4ToGray8Table[nLoop << 4] = cPal4ToGray8Table[nLoop];
}
// Produce scale table.
// Pixel 0 = 0xf0, pixel 1 = 0x0f.
nSourceWidth = pSourceImg->nWidth;
for (nLoop = 0; nLoop < nDestWidth; nLoop++){
lSourcePixel = ((nLoop + nHDestOffset + lrDestRect.left) * nScaleDenominator) / nHScale;
if (lSourcePixel + nSourcePixelsPerLinePerPixel > nSourceWidth){
lSourcePixel = nSourceWidth - nSourcePixelsPerLinePerPixel;
}
nFirstByte[nLoop] = lSourcePixel >> 1;
nPixels = nSourcePixelsPerLinePerPixel;
if (lSourcePixel & 1){
bDoFirst[nLoop] = 1;
nPixels--;
}else{
bDoFirst[nLoop] = 0;
}
nBytes[nLoop] = nPixels >> 1;
bDoLast[nLoop] = nPixels & 1;
}
// Produce table of source line offsets.
CheckError2( AllocateMemory(sizeof(int) * nDestHeight, (PPSTR) &pnSourceLineOffsets, NO_INIT));
nSourceHeight = pSourceImg->nHeight;
for (nLoop = 0; nLoop < nDestHeight; nLoop++){
pnSourceLineOffsets[nLoop] = (((nLoop + nVDestOffset + lrDestRect.top)
* nScaleDenominator) / nVScale);
if (pnSourceLineOffsets[nLoop] + nSourceLinesPerPixel > nSourceHeight){
pnSourceLineOffsets[nLoop] = nSourceHeight - nSourceLinesPerPixel;
}
}
// Calculate the averaging divisors.
if (nSourcePixelsPerLinePerPixel >= 16 || nSourceLinesPerPixel >= 16){
nPerLineDivisor = nSourcePixelsPerLinePerPixel;
if (pDestImg->nType == ITYPE_GRAY8){
nDivisor = nSourceLinesPerPixel;
}else if(pDestImg->nType == ITYPE_GRAY7){
nDivisor = nSourceLinesPerPixel * 2;
}else{ // GRAY4
nDivisor = nSourceLinesPerPixel * 16;
}
}else{
nPerLineDivisor = 1;
if (pDestImg->nType == ITYPE_GRAY8){
nDivisor = nSourcePixelsPerLinePerPixel * nSourceLinesPerPixel;
}else if(pDestImg->nType == ITYPE_GRAY7){
nDivisor = nSourcePixelsPerLinePerPixel * nSourceLinesPerPixel * 2;
}else{ // GRAY4
nDivisor = nSourcePixelsPerLinePerPixel * nSourceLinesPerPixel * 16;
}
}
for (nDestLine = 0; nDestLine < nDestHeight; nDestLine++){
memset(pnDestLine, 0, sizeof(int) * nDestWidth);
for (nSourceLineCount = nSourceLinesPerPixel; nSourceLineCount; nSourceLineCount--){
pSourceLine = &pSourceImg->bImageData[0] + ((pnSourceLineOffsets[nDestLine]
+ (nSourceLinesPerPixel - nSourceLineCount)) * pSourceImg->nBytesPerLine);
pnTempDestLine = pnDestLine;
if (nPerLineDivisor == 1){
for (nTempIndex = 0; nTempIndex < nDestWidth; nTempIndex++){
// Add source pixels for this line.
pSourceByte = pSourceLine + nFirstByte[nTempIndex];
nDest = 0;
if (bDoFirst[nTempIndex]){
nDest += cPal4ToGray8Table[*(pSourceByte++) & 0x0f];
}
for (nLoop = nBytes[nTempIndex]; nLoop; nLoop--){
nDest += cPal4ToGray8Table[*pSourceByte & 0xf0];
nDest += cPal4ToGray8Table[*(pSourceByte++) & 0x0f];
}
if (bDoLast[nTempIndex]){
nDest += cPal4ToGray8Table[*pSourceByte & 0xf0];
}
*(pnTempDestLine++) += nDest;
}
}else{
for (nTempIndex = 0; nTempIndex < nDestWidth; nTempIndex++){
// Add source pixels for this line.
pSourceByte = pSourceLine + nFirstByte[nTempIndex];
nDest = 0;
if (bDoFirst[nTempIndex]){
nDest += cPal4ToGray8Table[*(pSourceByte++) & 0x0f];
}
for (nLoop = nBytes[nTempIndex]; nLoop; nLoop--){
nDest += cPal4ToGray8Table[*pSourceByte & 0xf0];
nDest += cPal4ToGray8Table[*(pSourceByte++) & 0x0f];
}
if (bDoLast[nTempIndex]){
nDest += cPal4ToGray8Table[*pSourceByte & 0xf0];
}
*(pnTempDestLine++) += nDest / nPerLineDivisor;
}
}
}
// Average the line to gray.
pnTempDestLine = pnDestLine;
pDestLine = &pDestImg->bImageData[0] + ((nDestLine + lrDestRect.top) * pDestImg->nBytesPerLine);
if (pDestImg->nType == ITYPE_GRAY4){
pDestLine += lrDestRect.left / 2;
nTempIndex = nDestWidth;
if (lrDestRect.left & 1){
// Do first pixel.
*pDestLine = (*pDestLine & 0xf0) | (*(pnTempDestLine++) / nDivisor);
pDestLine++;
nTempIndex--;
}
// Do middle bytes.
for (nLoop = nTempIndex / 2; nLoop; nLoop--){
*pDestLine = (*(pnTempDestLine++) / nDivisor) << 4;
*(pDestLine++) |= *(pnTempDestLine++) / nDivisor;
}
if (nTempIndex & 1){
*(pDestLine++) = (*(pnTempDestLine++) / nDivisor) << 4;
}
}else{ // Dest = Gray 7/8.
pDestLine += lrDestRect.left;
for (nLoop = nDestWidth; nLoop; nLoop--){
*(pDestLine++) = *(pnTempDestLine++) / nDivisor;
}
}
}
Exit:
if (pnSourceLineOffsets){
FreeMemory((PPSTR) &pnSourceLineOffsets);
}
return(nStatus);
}
//
/****************************************************************************
FUNCTION: ScaleBWStamp
PURPOSE: Scales BW images via Stamp.
*****************************************************************************/
int WINAPI ScaleBWStamp(PIMG pSourceImg, PIMG pDestImg,
int nHScale, int nVScale,
int nHDestOffset, int nVDestOffset, LRECT lrDestRect){
int nStatus = 0;
typedef struct tagBWToStampScaleTable{
int nFirstByte;
int nFirstMask;
int nBytes;
int nLastMask;
} BW_TO_STAMP_SCALE_TABLE, *PBW_TO_STAMP_SCALE_TABLE;
PBW_TO_STAMP_SCALE_TABLE pScaleTable = 0;
int nDestWidth;
int nDestHeight;
int nDestByte; // Dest byte.
PBYTE pDestByte; // The address of the dest byte.
PBYTE pLine1=0; // The address of the first source line.
PBYTE pLine2; // The address of the second source line.
PBYTE pLine3; // The address of the third source line.
PBYTE pTempLine1; // The address of the current pixel -1 for line 1.
PBYTE pTempLine2; // The address of the current pixel -1 for line 2.
PBYTE pTempLine3; // The address of the current pixel -1 for line 3.
PBYTE pBuffer[3]; // The address of the temporary buffers.
int nNextTempBuffer = 0; // The index to the next temp buffer to nse.
PIMG pImg = 0;
int nPixel;
LRECT lrRect;
int nNeighbors; // The average of all neighboring pixels.
int nDestMask; // Mask for setting bits in the dest byte.
int nLines;
// Loop variables.
int nLoop;
int nLoopEnd;
int nDestLine;
pBuffer[0] = 0;
pBuffer[1] = 0;
pBuffer[2] = 0;
if (nHScale >= 1000 && nVScale >= 1000){
nStatus = Scale1BPPDecimate(pSourceImg, pDestImg,
nHScale, nVScale, nHDestOffset, nVDestOffset, &lrDestRect);
goto Exit;
}
if (pDestImg->nType != ITYPE_BI_LEVEL){
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
if (lrDestRect.right - lrDestRect.left > 0x7fff
|| lrDestRect.bottom - lrDestRect.top > 0x7fff){
nStatus = Error(DISPLAY_INVALIDRECT);
goto Exit;
}
nDestWidth = (int)(lrDestRect.right - lrDestRect.left);
nDestHeight = (int)(lrDestRect.bottom - lrDestRect.top);
CheckError2( CreateAnyImgBuf(&pImg, nDestWidth, nDestHeight, ITYPE_GRAY8));
SetLRect(lrRect, 0, 0, nDestWidth, nDestHeight);
CheckError2( ScaleBWToGray(pSourceImg, pImg, nHScale, nVScale,
nHDestOffset + lrDestRect.left, nVDestOffset + lrDestRect.top, &lrRect));
// Convert the Gray8 img into a B + W stamp image.
CheckError2( AllocateMemory(nDestWidth, (PPSTR) &pBuffer[0], NO_INIT));
CheckError2( AllocateMemory(nDestWidth, (PPSTR) &pBuffer[1], NO_INIT));
CheckError2( AllocateMemory(nDestWidth, (PPSTR) &pBuffer[2], NO_INIT));
// Init pointers to lines 1 and 2.
pLine2 = pBuffer[0];
pLine3 = pBuffer[1];
nNextTempBuffer = 2;
memcpy(pLine2, &pImg->bImageData[0], nDestWidth);
if (pImg->nHeight > 1){
memcpy(pLine3, &pImg->bImageData[nDestWidth], nDestWidth);
}else{
memcpy(pLine3, &pImg->bImageData[0], nDestWidth);
}
for (nDestLine = 0; nDestLine < nDestHeight; nDestLine++){
pDestByte = &pDestImg->bImageData[0] + ((nDestLine + (int)lrDestRect.top) * pDestImg->nBytesPerLine);
pLine1 = pLine2;
pLine2 = pLine3;
if (nDestLine != (nDestHeight - 1)){
pLine3 = &pImg->bImageData[0] + ((nDestLine + 1) * pImg->nBytesPerLine);
nLines = pImg->nHeight - (nDestLine + 1);
if (nLines < 3){
memcpy(pBuffer[nNextTempBuffer], pLine3, nDestWidth);
pLine3 = pBuffer[nNextTempBuffer++];
if (nNextTempBuffer >= 3){
nNextTempBuffer = 0;
}
}
}
pTempLine1 = pLine1;
pTempLine2 = pLine2;
pTempLine3 = pLine3;
// Pixel 0 = 0x80, pixel 7 = 0x01. 0 = black, 1 = white.
// Do first pixel.
nNeighbors = pTempLine1[0];
nNeighbors += pTempLine1[1];
nNeighbors += pTempLine2[1];
nNeighbors += pTempLine3[0];
nNeighbors += pTempLine3[1];
nNeighbors /= 5;
nPixel = pTempLine2[0];
if (nPixel > nNeighbors){
nDestByte = 0x80;
}else if(nPixel < nNeighbors){
nDestByte = 0x00;
}else if(nPixel >= 0x80){
nDestByte = 0x80;
}else{
nDestByte = 0x00;
}
nDestMask = 0x40;
// Do middle pixels.
nLoopEnd = nDestWidth - 2;
for (nLoop = 0; nLoop < nLoopEnd; nLoop++){
nNeighbors = pTempLine1[0];
nNeighbors += pTempLine1[1];
nNeighbors += pTempLine1[2];
nNeighbors += pTempLine2[0];
nNeighbors += pTempLine2[2];
nNeighbors += pTempLine3[0];
nNeighbors += pTempLine3[1];
nNeighbors += pTempLine3[2];
nNeighbors >>= 3;
nPixel = pTempLine2[1];
if (nPixel > nNeighbors){
nDestByte |= nDestMask;
}else if(nPixel == nNeighbors && nPixel >= 0x80){
nDestByte |= nDestMask;
}
nDestMask >>= 1;
if (!nDestMask){
*(pDestByte++) = nDestByte;
nDestByte = 0;
nDestMask = 0x80;
}
pTempLine1++;
pTempLine2++;
pTempLine3++;
}
// Do last pixel.
nNeighbors = pTempLine1[0];
nNeighbors += pTempLine1[1];
nNeighbors += pTempLine2[0];
nNeighbors += pTempLine3[0];
nNeighbors += pTempLine3[1];
nNeighbors /= 5;
nPixel = pTempLine2[1];
if (nPixel > nNeighbors){
nDestByte |= nDestMask;
}else if(nPixel == nNeighbors && nPixel >= 0x80){
nDestByte |= nDestMask;
}
nDestMask >> 1;
*pDestByte = nDestByte;
}
Exit:
if (pBuffer[0]){
FreeMemory((PPSTR) &pBuffer[0]);
}
if (pBuffer[1]){
FreeMemory((PPSTR) &pBuffer[1]);
}
if (pBuffer[2]){
FreeMemory((PPSTR) &pBuffer[2]);
}
FreeImgBuf(&pImg);
return(nStatus);
}