#include "ET++.ph" #ifdef __GNUG__ #pragma implementation #endif #include "ColorMapper.h" #include "Class.h" #include "DevBitmap.h" #include "WindowColorMap.h" #include "ET_stdio.h" bool gDither= TRUE; //---- ColorMapper ------------------------------------------------------------- NewMetaImpl(ColorMapper,RefCounted, (T(id), T(cnt))); int ColorMapper::cnt= 0; ColorMapper::ColorMapper() { id= ColorMapper::cnt++; } void ColorMapper::Pixel2RGB(u_long, RGB*) { AbstractMethod("Pixel2RGB"); } bool ColorMapper::RGB2Pixel(RGB*, u_long*) { AbstractMethod("RGB2Pixel"); return FALSE; } bool ColorMapper::ChangeRGB(u_long, RGB*) { AbstractMethod("ChangeRGB"); return TRUE; } bool ColorMapper::IsGrey() { return FALSE; } u_long ColorMapper::MaxPixel() { return 0; } bool ColorMapper::HasMask() { return FALSE; } OStream& ColorMapper::PrintOn(OStream &os) { Object::PrintOn(os); return os << id SP; } IStream& ColorMapper::ReadFrom(IStream &is) { Object::ReadFrom(is); return is >> id; } DevBitmap *ColorMapper::MapColors(WindowColorMap*, DevBitmap*, int) { return 0; } //---- MonoMapper -------------------------------------------------------------- NewMetaImpl0(MonoMapper,ColorMapper); MonoMapper::MonoMapper() { } void MonoMapper::Pixel2RGB(u_long pixel, RGB *result) { if (pixel == 0) { result->red= result->green= result->blue= 255; result->alpha= 0; } else if (pixel == 1) { result->red= result->green= result->blue= 0; result->alpha= 1; } } bool MonoMapper::RGB2Pixel(RGB *rgb, u_long *pixel) { if (rgb->red == rgb->green && rgb->green == rgb->blue) { if (rgb->red == 255) { *pixel= 0; return TRUE; } if (rgb->red == 0) { *pixel= 1; return TRUE; } } return FALSE; } bool MonoMapper::ChangeRGB(u_long, RGB*) { return TRUE; } bool MonoMapper::IsGrey() { return TRUE; } u_long MonoMapper::MaxPixel() { return 1; } //---- ColorMap ---------------------------------------------------------------- NewMetaImpl(IndexMapper,ColorMapper, (TV(map,size), T(maxsize), TB(mask))); IndexMapper::IndexMapper(int mx) { maxsize= mx; size= 0; map= 0; mask= FALSE; } IndexMapper::~IndexMapper() { SafeDelete(map); } void IndexMapper::Expand(int sz) { if (sz > size) { map= (RGB*) Storage::ReAlloc(map, sz*sizeof(RGB)); size= sz; } } bool IndexMapper::RGB2Pixel(RGB *rgb, u_long *pixel) { for (u_long i= 0; i < size; i++) { if (map[i] == *rgb) { *pixel= i; return TRUE; } } if (ChangeRGB(i, rgb)) { *pixel= i; return TRUE; } return FALSE; } bool IndexMapper::ChangeRGB(u_long pixel, RGB *rgb) { if (pixel >= maxsize) return FALSE; Expand((int)(pixel+1)); map[pixel]= *rgb; if (rgb->alpha != 255) mask= TRUE; return TRUE; } void IndexMapper::Pixel2RGB(u_long pixel, RGB *result) { if (pixel < size) *result= map[pixel]; else fprintf(stderr, "IndexMapper::Pixel2RGB: index (%d) out of range\n", pixel); } u_long IndexMapper::MaxPixel() { return size-1; } bool IndexMapper::HasMask() { return mask; } OStream& IndexMapper::PrintOn(OStream &os) { ColorMapper::PrintOn(os); os << size SP << maxsize NL; if (size > 0) { for (int i= 0; i < size; i++) os << map[i]; } return os; } IStream& IndexMapper::ReadFrom(IStream &is) { int sz; ColorMapper::ReadFrom(is); mask= FALSE; size= 0; is >> sz >> maxsize; if (sz > 0) { Expand(sz); for (int i= 0; i < size; i++) { is >> map[i]; if (map[i].alpha != 255) mask= TRUE; } } return is; } bool IndexMapper::IsGrey() { for (int i= 0; i < size; i++) if (! map[i].IsGrey()) return FALSE; return TRUE; } DevBitmap *IndexMapper::MapColors(WindowColorMap *wcm, DevBitmap *from, int d) { DevBitmap *to= from->DevAllocBitmap(from->Size(), d); if (gDither && ((IsGrey() && MaxPixel() > 16 && !HasMask()) || wcm->IsGrey())) { to->DevHalftone(wcm, from, this); } else { register int x, l= (int) MaxPixel()+1; register u_long *map= new u_long[l]; RGB c; for (x= 0; x < l; x++) { Pixel2RGB(x, &c); if (c.alpha == 0) map[x]= 0; else map[x]= wcm->RGB2Index(&c); } to->DevMapColors(from, map); delete map; } return to; } //---- DirectMapper ------------------------------------------------------------ NewMetaImpl0(DirectMapper,ColorMapper); DirectMapper::DirectMapper() { } u_long DirectMapper::MaxPixel() { return 0x00ffffff; } bool DirectMapper::IsGrey() { return FALSE; } static union { struct { u_int a : 8; u_int b : 8; u_int g : 8; u_int r : 8; } rgb; u_long pixel; } cv; void DirectMapper::Pixel2RGB(u_long pixel, RGB *result) { /* result->alpha= (short) ((pixel & 0xff000000) >> 24); result->blue= (short) ((pixel & 0x00ff0000) >> 16); result->green= (short) ((pixel & 0x0000ff00) >> 8); result->red= (short) (pixel & 0x000000ff); */ cv.pixel= pixel; result->alpha= cv.rgb.a; result->blue= cv.rgb.b; result->green= cv.rgb.g; result->red= cv.rgb.r; } bool DirectMapper::RGB2Pixel(RGB *rgb, u_long *pixel) { cv.rgb.a= rgb->alpha; cv.rgb.b= rgb->blue; cv.rgb.g= rgb->green; cv.rgb.r= rgb->red; *pixel= cv.pixel; // *pixel= ((((rgb->alpha << 8 + rgb->blue) << 8) + rgb->green) << 8) + rgb->red; // *pixel= (((rgb->blue << 8) + rgb->green) << 8) + rgb->red; return TRUE; } DevBitmap *DirectMapper::MapColors(WindowColorMap *wcm, DevBitmap *from, int d) { DevBitmap *to= from->DevAllocBitmap(from->Size(), d); if (gDither && !HasMask()) to->DevFloydSteinberg(wcm, from, this); else to->DevMapDirect(wcm, from, this); return to; }