📄 filterhpa.cpp
字号:
/*****************************************************************************\ filterhpa.cpp : Implimentation for the TErnieFilter class Copyright (c) 1996 - 2001, Hewlett-Packard Co. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of Hewlett-Packard nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\*****************************************************************************/#if defined(APDK_DJ9xxVIP) && defined(APDK_VIP_COLORFILTERING)#include "header.h"// copied from vob \di_research on 10/31/00// MODIFICATIONS BY GE:// 0. remove Windows header references// 1. define assert// 2. set iRastersReady, iRastersDelivered in submitrowtofilter// 3. (constructor) allocate (and delete in destructor) buffers for fRowPtr// (instead of setting it to input buffers, since we reuse input buffers)// 4. copy data into fRowPtr in submitrowtofilter//#define assert ASSERT#include "ernieplatform.h"#include "filterhpa.h"#if kGatherStats == 1extern int blockStats[];#endif#if ((kMemWritesOptimize != 1) && (kMemWritesOptimize != 0))#error "kMemWritesOptimize must be 0 or 1"#endifAPDK_BEGIN_NAMESPACEinline void AverageNRound(bool roundGreenDown, int &rFinal, int &r0, int &r1, int &gFinal, int &g0, int &g1, int &bFinal, int &b0, int &b1);inline void AverageNRound(bool roundGreenDown, int &rFinal, int &r0, int &r1, int &gFinal, int &g0, int &g1, int &bFinal, int &b0, int &b1){ // By rounding G in the other direction than R and B L* variations are minimized while mathematically alternate rounding is accomplished. EGW 2 Dec. 1999. if (roundGreenDown) { rFinal = (r0 + r1 + 1) / 2; gFinal = (g0 + g1) / 2; bFinal = (b0 + b1 + 1) / 2; } else { rFinal = (r0 + r1) / 2; gFinal = (g0 + g1 + 1) / 2; bFinal = (b0 + b1) / 2; }}// Filter1RawRow. To be used to filter an odd row for which we don't have a pair,// found at the bottom of bands that aren't divisable by 2. This routine// filters its row horizontally forming 4x1 and 2x1 blocks.void TErnieFilter::Filter1RawRow(unsigned char *currPtr, int rowWidthInPixels, unsigned int *flagsPtr){ ASSERT(currPtr); ASSERT(rowWidthInPixels > 0); int R0, G0, B0, R1, G1, B1, lastR, lastG, lastB; const unsigned int maxErrorForFourPixels = fMaxErrorForTwoPixels / 2;// const unsigned int maxErrorForEightPixels = maxErrorForFourPixels / 2;// int currPixel, lastPixel; uint32_t currPixel, lastPixel; bool lastPairAveraged = false; bool last2by2Averaged = false; for (int pixelNum = 0; pixelNum < rowWidthInPixels; pixelNum++) { if ((pixelNum & 0x03) == 0x00) // 0,4,8... { last2by2Averaged = false; // Reinitialize every four columns; } currPixel = get4Pixel(currPtr); flagsPtr[0] = (e11n|e11s); // Initialize in case nothing is found for this column if (isWhite(currPixel)) { flagsPtr[0] = eDone;#if kGatherStats == 1 blockStats[esWhiteFound]++;#endif } // Currently we bail entirely if there is white. Later we may still do RLE on the non white pixel if one is present. if (flagsPtr[0] == (e11n|e11s)) { R1 = GetRed(currPixel); G1 = GetGreen(currPixel); B1 = GetBlue(currPixel); // Can only horizontally average every other pixel, much like the 2x2 blocks. if (isOdd(pixelNum)) { // do horizontal on current raster lastPixel = get4Pixel(currPtr,-1); lastR = GetRed(lastPixel); lastG = GetGreen(lastPixel); lastB = GetBlue(lastPixel); if ((fMaxErrorForTwoPixels >= 3) && (NewDeltaE(lastR, R1, lastG, G1, lastB, B1, fMaxErrorForTwoPixels))) { /* - - | | build 2x1 - - */ int didNotBuild4by1 = true;#if kGatherStats == 1 blockStats[es21nw]++;#endif AverageNRound(isOdd(pixelNum), lastR, lastR, R1, lastG, lastG, G1, lastB, lastB, B1); if ((pixelNum >= 3) && (flagsPtr[-3] & e21nw)) // 4,5,6,7,12,13,14,15,20... { // Look for a 4x1 ASSERT(!((flagsPtr[-3] | flagsPtr[-2] | flagsPtr[-1] | flagsPtr[0]) & eTheRest)); // no vertical blocks lastPixel = get4Pixel(currPtr,-3); R0 = GetRed(lastPixel); G0 = GetGreen(lastPixel); B0 = GetBlue(lastPixel); if ((maxErrorForFourPixels >= 3) && (NewDeltaE(lastR, R0, lastG, G0, lastB, B0, maxErrorForFourPixels))) { /* - - - - | | build 4x1 - - - - */#if kGatherStats == 1 blockStats[es41ni]++;#endif didNotBuild4by1 = false; AverageNRound((pixelNum & 0x04)== 0x04, lastR, lastR, R0, lastG, lastG, G0, lastB, lastB, B0); // 4,5,6,7,12,13,14,15,20... if(littleEndian) currPixel = (lastR<<16) + (lastG<<8) + lastB; else if(bigEndian) currPixel = (lastR<<24) + (lastG<<16) + (lastB<<8);#if kMemWritesOptimize == 0 put4Pixel(currPtr, -3, currPixel); put4Pixel(currPtr, -2, currPixel); put4Pixel(currPtr, -1, currPixel); put4Pixel(currPtr, 0, currPixel);#else put4Pixel(currPtr, -3, currPixel);#endif flagsPtr[-3] = (flagsPtr[-3] & ~eNorths) | e41ni; flagsPtr[-2] = (flagsPtr[-2] & ~eNorths) | e41n; flagsPtr[-1] = (flagsPtr[-1] & ~eNorths) | e41n; flagsPtr[0] = (flagsPtr[0] & ~eNorths) | e41n; } } if (didNotBuild4by1) // Not a 4x1 so output 2x1. { ASSERT(!((flagsPtr[-1] | flagsPtr[0]) & eTheRest)); // no vertical blocks if(littleEndian) currPixel = (lastR<<16) + (lastG<<8) + lastB; else if(bigEndian) currPixel = (lastR<<24) + (lastG<<16) + (lastB<<8);#if kMemWritesOptimize == 0 put4Pixel(currPtr, -1, currPixel); put4Pixel(currPtr, 0, currPixel);#else put4Pixel(currPtr, -1, currPixel);#endif flagsPtr[-1] = (flagsPtr[-1] & ~eNorths) | e21nw; flagsPtr[0] = (flagsPtr[0] & ~eNorths) | e21ne; } } // If DeltaE... Looking for two by one } // IsOdd(pixelNum) } else // no flag bits set. { lastPairAveraged = false; // EGW Fixes bug on business graphics. 11/24/97 } currPtr += eBufferedPixelWidthInBytes; flagsPtr++; } // for each pixel...}// Filter2RawRows: Looks filter two raw rows together to form blocks. Vertical// blocks are prefered over horizontal ones. The routine will create 1x2 blocks// before it will create 4x1's. In total this routine will create 1x2, 2x2, 4x2,// 4x1, and 2x1 blocks sizes, with the potential for two seperate 4x1's or 2x1's// in the upper and lower rasters.void TErnieFilter::Filter2RawRows(unsigned char *currPtr, unsigned char *upPtr, int rowWidthInPixels, unsigned int *flagsPtr){ ASSERT(currPtr); ASSERT(upPtr); ASSERT(rowWidthInPixels > 0); int R0, G0, B0, R1, G1, B1, lastR, lastG, lastB; const unsigned int maxErrorForFourPixels = fMaxErrorForTwoPixels / 2; const unsigned int maxErrorForEightPixels = maxErrorForFourPixels / 2;// int currPixel, upPixel, lastPixel; uint32_t currPixel, upPixel, lastPixel; bool lastPairAveraged = false; bool last2by2Averaged = false; for (int pixelNum = 0; pixelNum < rowWidthInPixels; pixelNum++) { if ((pixelNum & 0x03) == 0x00) // 0,4,8... { last2by2Averaged = false; // Reinitialize every four columns; } upPixel = get4Pixel(upPtr); currPixel = get4Pixel(currPtr); flagsPtr[0] = (e11n|e11s); // Initialize in case nothing is found for this column if (isWhite(upPixel) && isWhite(currPixel)) // both white? { flagsPtr[0] = eDone;#if kGatherStats == 1 blockStats[esWhiteFound]++;#endif } // Do vertical average on the current 2 pixel high column // Currently we bail entirely if there is white. Later we may still do RLE on the non white pixel if one is present. if (flagsPtr[0] == (e11n|e11s)) { R1 = GetRed(currPixel); G1 = GetGreen(currPixel); B1 = GetBlue(currPixel); R0 = GetRed(upPixel); G0 = GetGreen(upPixel); B0 = GetBlue(upPixel); if ((fMaxErrorForTwoPixels >= 3) && (NewDeltaE(R0, R1, G0, G1, B0, B1, fMaxErrorForTwoPixels))) { /* _ | | build 1x2 | | - */ ASSERT(flagsPtr[0] == (e11n|e11s)); flagsPtr[0] = e12;#if kGatherStats == 1 blockStats[es12]++;#endif R1 = GetRed(currPixel); G1 = GetGreen(currPixel); B1 = GetBlue(currPixel); R0 = GetRed(upPixel); G0 = GetGreen(upPixel); B0 = GetBlue(upPixel); AverageNRound(isOdd(pixelNum), R1, R1, R0, G1, G1, G0, B1, B1, B0); // look for a 2x2 block average on every other column if (isOdd(pixelNum)) { // It looks like we are at the end of a 2x2 block if (lastPairAveraged) { // Last pair was averaged so it's ok to try to make a 2x2 block if ((maxErrorForFourPixels >= 3) && (NewDeltaE(lastR, R1, lastG, G1,lastB, B1, maxErrorForFourPixels))) { /* - - | | build 2x2 | | - - */ ASSERT(flagsPtr[-1] == e12); int didNotBuild4by2 = true;#if kGatherStats == 1 blockStats[es22w]++;#endif flagsPtr[-1] = e22w; flagsPtr[0] = e22e; AverageNRound((pixelNum & 0x02) == 0x02, R1, R1, lastR, G1, G1, lastG, B1, B1, lastB); // 2,3,6,7... Alternate between rounding up and down for these 2x2 blocks if ((pixelNum & 0x03) == 0x03) // 3,7,11,15... Looking for a 4x2 block to average { if (last2by2Averaged) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -