/* /-------------------------------------------------------------------- | | $Id: plbmpbase.cpp,v 1.12 2004/10/02 22:23:12 uzadow Exp $ | | Copyright (c) 1996-2002 Ulrich von Zadow | \-------------------------------------------------------------------- */ #include "plbmpbase.h" #include "planybmp.h" #include "Filter/plfilter.h" #include "Filter/plfilterquantize.h" #include using namespace std; template void createTrueColorCopy (PLBmp & DestBmp, const PLBmpBase & SrcBmp, DestPixelC Dummy); // Creates an empty bitmap. PLBmpBase::PLBmpBase () : m_DitherPaletteType(PLDTHPAL_MEDIAN), // defaults for 8Bit color quantization m_DitherType(PLDTH_ORDERED), m_pClrTab(0) { } PLBmpBase::~PLBmpBase () { } bool const PLBmpBase::operator == ( PLBmpBase const &Other ) { return AlmostEqual (Other, 0); } #ifdef _DEBUG void PLBmpBase::AssertValid () const { if (m_Size != PLPoint(0,0)) { // Color table only if 8 bpp. PLASSERT ((GetBitsPerPixel() > 8) == (m_pClrTab == NULL)); PLASSERT (m_Size.y >= 0); PLASSERT (m_Size.x >= 0); // Greyscale only if 8 bpp PLASSERT ((GetBitsPerPixel() <= 8) || !IsGreyscale()); } } #endif ///////////////////////////////////////////////////////////////////// // PLBmpBase manipulation void PLBmpBase::SetQuantizationMode (int DitherType, int DitherPaletteType) { PLASSERT_VALID (this); m_DitherType = DitherType; m_DitherPaletteType = DitherPaletteType; } // The dummy parameter is nessesary to work around an MSVC bug. If it isn't // there, the function will only get instantiated once :-(. template void createTrueColorCopy (PLBmpBase & DestBmp, const PLBmpBase & SrcBmp, DestPixelC Dummy) { // Make sure we're using the right template. PLASSERT (DestBmp.GetBitsPerPixel() == sizeof (DestPixelC)*8); int BPPSrc = SrcBmp.GetBitsPerPixel(); PLBYTE ** pSrcLines = SrcBmp.GetLineArray(); DestPixelC ** pDstLines = (DestPixelC**) DestBmp.GetLineArray(); int Height = min(SrcBmp.GetHeight(), DestBmp.GetHeight()); int Width = min(SrcBmp.GetWidth(), DestBmp.GetWidth()); for (int y = 0; y> (x & 7))) // black pixel *pDstPixel = blackDot; else *pDstPixel = whiteDot; pDstPixel++; } } break; default: PLASSERT (false); } } } void PLBmpBase::CopyPixels ( const PLBmpBase& SrcBmp ) { if (SrcBmp.GetPixelFormat() == GetPixelFormat()) { if (&SrcBmp != this) { PLBYTE ** pSrcLines = SrcBmp.GetLineArray(); PLBYTE ** pDstLines = GetLineArray(); int Height = min(SrcBmp.GetHeight(), GetHeight()); int Width = min(SrcBmp.GetWidth(), GetWidth()); int LineLen = Width*GetBitsPerPixel()/8; for (int y = 0; yGetBitsPerPixel() == 8); // The two bitmaps must have the same dimensions PLASSERT (pAlphaBmp->GetWidth() == GetWidth()); PLASSERT (pAlphaBmp->GetHeight() == GetHeight()); pLineArray = GetLineArray32(); pAlphaLineArray = pAlphaBmp->GetLineArray(); for (y=0; y < GetHeight(); y++) { PLPixel32 * pLine = pLineArray[y]; pAlphaLine = pAlphaLineArray[y]; for (x=0; x < GetWidth(); x++) { pLine[x].SetA(pAlphaLine[x]); } } m_pf = m_pf.UseAlpha(true); PLASSERT_VALID (this); } PLBYTE PLBmpBase::FindNearestColor (PLPixel32 col) { PLPixel32 * pPalette = GetPalette(); PLASSERT (pPalette); int d1; int dMin = 100000; int i; int index; for (i = 0; i epsilon) return false; break; case 16: if (((PLPixel16*)(ppLines1[y]))[x] != ((PLPixel16*)(ppLines2[y]))[x]) return false; break; case 24: if (abs (ppLines1[y][x*3+PL_RGBA_RED] - ppLines2[y][x*3+PL_RGBA_RED]) > epsilon || abs (ppLines1[y][x*3+PL_RGBA_GREEN] - ppLines2[y][x*3+PL_RGBA_GREEN]) > epsilon || abs (ppLines1[y][x*3+PL_RGBA_BLUE] - ppLines2[y][x*3+PL_RGBA_BLUE]) > epsilon) return false; break; case 32: if (abs (ppLines1[y][x*4+PL_RGBA_RED] - ppLines2[y][x*4+PL_RGBA_RED]) > epsilon || abs (ppLines1[y][x*4+PL_RGBA_GREEN] - ppLines2[y][x*4+PL_RGBA_GREEN]) > epsilon || abs (ppLines1[y][x*4+PL_RGBA_BLUE] - ppLines2[y][x*4+PL_RGBA_BLUE]) > epsilon) return false; if (HasAlpha() && abs (ppLines1[y][x*4+3] - ppLines2[y][x*4+3]) > epsilon) return false; break; default: // Unsupported BPP. PLASSERT (false); } // Test if the palettes are the same for paletted bitmaps. if (GetBitsPerPixel() == 8) { int i; PLPixel32 * pPal1 = GetPalette(); PLPixel32 * pPal2 = Bmp.GetPalette(); for (i=0; i<255; i++) { if (abs (pPal1[i].GetR() - pPal2[i].GetR()) > epsilon || abs (pPal1[i].GetG() - pPal2[i].GetG()) > epsilon || abs (pPal1[i].GetB() - pPal2[i].GetB()) > epsilon) return false; } } return true; } void PLBmpBase::Dump () { cerr << AsString() << endl; cerr << " Pixel data: \n"; PLBYTE ** ppLines = GetLineArray(); int y,x; for (y=0; y8 BPP { PLFilterQuantize Filter (m_DitherPaletteType, m_DitherType); PLAnyBmp TempBmp; Filter.Apply (&(const_cast(rSrcBmp)), &TempBmp); SetPalette(TempBmp.GetPalette()); CopyPixels(TempBmp); } else // 1 -> 8 { PLPixel32 *pPal = rSrcBmp.GetPalette(); // if bi-tonal "palette" exists, use it... if (pPal) { PLBYTE *pWhite = (PLBYTE *) pPal; PLBYTE *pBlack = (PLBYTE *) (pPal+1); SetPaletteEntry(0, pWhite[PL_RGBA_RED], pWhite[PL_RGBA_GREEN], pWhite[PL_RGBA_BLUE], 255); SetPaletteEntry(1, pBlack[PL_RGBA_RED], pBlack[PL_RGBA_GREEN], pBlack[PL_RGBA_BLUE], 255); } else { SetPaletteEntry(0,255,255,255,255); SetPaletteEntry(1,0,0,0,255); } // assume msb is leftmost for (int y = 0; y> (x & 7)) ? 1 : 0; } } } void PLBmpBase::create1BPPCopy (const PLBmpBase & rSrcBmp) { int BPPSrc = rSrcBmp.GetBitsPerPixel(); PLBYTE ** pSrcLines = rSrcBmp.GetLineArray(); PLBYTE ** pDstLines = GetLineArray(); int Height = min(rSrcBmp.GetHeight(), GetHeight()); int Width = min(rSrcBmp.GetWidth(), GetWidth()); SetPaletteEntry(0,255,255,255,255); SetPaletteEntry(1,0,0,0,255); // downgrade to monochrome PLPixel32 *pPal = rSrcBmp.GetPalette(); PLBYTE *pRGBA; int DstLineLen = (Width+7)/8; for (int y = 0; y < Height; ++y) { // For each line PLBYTE * pSrcPixel = pSrcLines[y]; PLBYTE * pDstPixel = pDstLines[y]; // fill with background (index 0) color memset(pDstPixel,0,DstLineLen); for (int x = 0; x < Width; ++x) // For each pixel { pRGBA = BPPSrc == 8 ? (PLBYTE*) &pPal[*pSrcPixel] : pSrcPixel; // the following criterion supposedly finds "dark" pixels; it may // need some twiddling and maybe use the alpha channel as well if (pRGBA[PL_RGBA_RED] < 128 && pRGBA[PL_RGBA_GREEN] < 128 && pRGBA[PL_RGBA_BLUE] < 128 ) pDstPixel[x / 8] |= 128 >> (x & 7); pSrcPixel += BPPSrc == 8 ? 1 : sizeof(PLPixel32); } } } /* /-------------------------------------------------------------------- | | $Log: plbmpbase.cpp,v $ | Revision 1.12 2004/10/02 22:23:12 uzadow | - configure and Makefile cleanups\n- Pixelformat enhancements for several filters\n- Added PLBmpBase:Dump\n- Added PLBmpBase::GetPixelNn()-methods\n- Changed default unix byte order to BGR | | Revision 1.11 2004/09/15 14:52:09 artcom | - added PLPixelformatTest | - added DICOM Decoder | | Revision 1.10 2004/09/11 12:41:35 uzadow | removed plstdpch.h | | Revision 1.9 2004/09/11 10:30:40 uzadow | Linux build fixes, automake dependency fixes. | | Revision 1.8 2004/09/09 16:52:49 artcom | refactored PixelFormat | | Revision 1.7 2004/08/04 14:53:29 uzadow | Added PLFilterColorize. | | Revision 1.6 2004/08/03 13:26:50 uzadow | Fixed copy bug when bitmaps have different sizes. | | Revision 1.5 2004/06/20 16:59:34 uzadow | Added PLBmpBase::CopyPixels() and PLInPlaceFilter | | Revision 1.4 2004/06/19 16:49:07 uzadow | Changed GetImage so it works with PLBmpBase | | Revision 1.3 2004/06/15 14:17:11 uzadow | First working version of PLSubBmp. | | Revision 1.2 2004/06/15 11:18:17 uzadow | First working version of PLBmpBase. | | Revision 1.1 2004/06/15 10:46:41 uzadow | Initial nonfunctioning version of plbmpbase. | | \-------------------------------------------------------------------- */