| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| typedef enum { |
| ST_NIL, |
| ST_RGBM, |
| ST_RGBM64 |
| } ST_TYPE; |
| |
| |
| |
| |
| |
| template <class P> |
| class CSTPic |
| { |
| string m_cacheId; |
| TRasterImageP m_picP; |
| |
| public: |
| int m_lX, m_lY; |
| P *m_pic; |
| const RASTER *m_ras; |
| |
| CSTPic(void) : m_cacheId(TImageCache::instance()->getUniqueId()), |
| m_lX(0), m_lY(0), m_pic(0), m_ras(0) {} |
| |
| void nullPic() |
| { |
| |
| unlock(); |
| TImageCache::instance()->remove(m_cacheId); |
| } |
| |
| |
| void lock() |
| { |
| m_picP = TImageCache::instance()->get(m_cacheId, true); |
| m_pic = (P *)m_picP->getRaster()->getRawData(); |
| } |
| |
| |
| void unlock() |
| { |
| m_picP = 0; |
| m_pic = 0; |
| } |
| |
| CSTPic(const int lX, const int lY) : |
| m_cacheId(TImageCache::instance()->getUniqueId()), |
| m_lX(lX), m_lY(lY), |
| m_pic(0), m_ras(0) |
| { |
| try { |
| initPic(); |
| } catch (SMemAllocError) { |
| null(); |
| throw; |
| } |
| } |
| |
| CSTPic(const CSTPic<P> &sp) : |
| m_lX(sp.m_lX), |
| m_lY(sp.m_lY), |
| m_pic(0), m_ras(sp.m_ras) |
| { |
| try { |
| initPic(); |
| copyPic(sp); |
| } catch (SMemAllocError) { |
| null(); |
| throw; |
| } |
| } |
| |
| ~CSTPic(void) |
| { |
| null(); |
| } |
| |
| |
| |
| |
| void initPic() |
| { |
| nullPic(); |
| if (m_lX > 0 && m_lY > 0) { |
| |
| TRasterGR8P ras(m_lX * m_lY * sizeof(P), 1); |
| if (!ras) |
| throw SMemAllocError("in initPic"); |
| TImageCache::instance()->add(m_cacheId, TRasterImageP(ras)); |
| lock(); |
| } else { |
| char s[200]; |
| sprintf(s, "in initPic lXY=(%d,%d)\n", m_lX, m_lY); |
| throw SMemAllocError(s); |
| } |
| } |
| |
| void null() |
| { |
| nullPic(); |
| m_lX = m_lY = 0; |
| m_ras = 0; |
| } |
| |
| |
| void drawRect(const P &ip) |
| { |
| SRECT rect = {0, 0, m_lX - 1, m_lY - 1}; |
| drawRect(rect, ip); |
| } |
| |
| |
| |
| |
| |
| |
| ST_TYPE getType() const |
| { |
| if (!m_pic) |
| return ST_NIL; |
| if (sizeof(m_pic->r) == sizeof(UCHAR)) |
| return ST_RGBM; |
| if (sizeof(m_pic->r) == sizeof(USHORT)) |
| return ST_RGBM64; |
| return ST_NIL; |
| } |
| |
| |
| |
| void copyPic(const CSTPic<P> &sp) |
| { |
| P p; |
| for (int y = 0; y < m_lY && y < sp.m_lY; y++) |
| for (int x = 0; x < m_lX && x < sp.m_lX; x++) { |
| sp.getPixel(x, y, p); |
| setRGBM(x, y, p); |
| } |
| } |
| |
| |
| |
| void copyPic(const CSTPic<P> &sp, const SRECT &r, const SPOINT &p) |
| { |
| P ip; |
| int xs, ys, xd, yd; |
| for (ys = r.y0, yd = p.y; ys <= r.y1; ys++, yd++) |
| for (xs = r.x0, xd = p.x; xs <= r.x1; xs++, xd++) { |
| sp.getPixel(xs, ys, ip); |
| setRGBM(xd, yd, ip); |
| } |
| } |
| |
| |
| void drawRect(const SRECT &rect, const P &ip) |
| { |
| for (int x = rect.x0; x <= rect.x1; x++) { |
| setRGBM(x, rect.y0, ip); |
| setRGBM(x, rect.y1, ip); |
| } |
| for (int y = rect.y0; y <= rect.y1; y++) { |
| setRGBM(rect.x0, y, ip); |
| setRGBM(rect.x1, y, ip); |
| } |
| } |
| |
| void erease() |
| { |
| P p = {0, 0, 0, 0}; |
| fill(p); |
| } |
| |
| void fill(const P &ip) |
| { |
| for (int y = 0; y < m_lY; y++) |
| for (int x = 0; x < m_lX; x++) |
| setRGBM(x, y, ip); |
| } |
| |
| |
| inline bool isInPic(const int x, const int y) const |
| { |
| return (m_pic && x >= 0 && x < m_lX && y >= 0 && y < m_lY); |
| } |
| |
| |
| void setRGB(const int x, const int y, const P &ip) |
| { |
| if (ISINPIC(x, y)) { |
| P *p = m_pic + y * m_lX + x; |
| p->r = ip.r; |
| p->g = ip.g; |
| p->b = ip.b; |
| } |
| } |
| |
| void setRGBM(const int x, const int y, const P &ip) |
| { |
| if (ISINPIC(x, y)) { |
| P *p = m_pic + y * m_lX + x; |
| p->r = ip.r; |
| p->g = ip.g; |
| p->b = ip.b; |
| p->m = ip.m; |
| } |
| } |
| |
| |
| void setRGB(const int x, const int y, const I_PIXEL &ip) |
| { |
| if (ISINPIC(x, y)) { |
| P *p = m_pic + y * m_lX + x; |
| if (getType() == ST_RGBM) { |
| p->r = (UCHAR)I_CUT_0_255(ip.r); |
| p->g = (UCHAR)I_CUT_0_255(ip.g); |
| p->b = (UCHAR)I_CUT_0_255(ip.b); |
| } else if (getType() == ST_RGBM64) { |
| p->r = (USHORT)I_CUT_0_65535(ip.r); |
| p->g = (USHORT)I_CUT_0_65535(ip.g); |
| p->b = (USHORT)I_CUT_0_65535(ip.b); |
| } |
| } |
| } |
| |
| void setRGBM(const int x, const int y, const I_PIXEL &ip) |
| { |
| if (ISINPIC(x, y)) { |
| P *p = m_pic + y * m_lX + x; |
| if (getType() == ST_RGBM) { |
| p->r = (UCHAR)I_CUT_0_255(ip.r); |
| p->g = (UCHAR)I_CUT_0_255(ip.g); |
| p->b = (UCHAR)I_CUT_0_255(ip.b); |
| p->m = (UCHAR)I_CUT_0_255(ip.m); |
| } else if (getType() == ST_RGBM64) { |
| p->r = I_CUT_0_65535(ip.r); |
| p->g = I_CUT_0_65535(ip.g); |
| p->b = I_CUT_0_65535(ip.b); |
| p->m = I_CUT_0_65535(ip.m); |
| } |
| } |
| } |
| |
| |
| void getPixel(const int x, const int y, P &ip) const |
| { |
| if (ISINPIC(x, y)) { |
| const P *p = m_pic + y * m_lX + x; |
| ASSIGN_PIXEL(&ip, p); |
| return; |
| } |
| ip.r = ip.g = ip.b = ip.m = 0; |
| } |
| |
| void getPixel(const int x, const int y, I_PIXEL &ip) const |
| { |
| if (ISINPIC(x, y)) { |
| const P *p = m_pic + y * m_lX + x; |
| ip.r = (int)p->r; |
| ip.g = (int)p->g; |
| ip.b = (int)p->b; |
| ip.m = (int)p->m; |
| return; |
| } |
| ip.r = ip.g = ip.b = ip.m = 0; |
| } |
| |
| |
| |
| |
| void getRasterPixel(const RASTER *ras, const int x, const int y, |
| I_PIXEL &ip) const |
| { |
| if (x >= 0 && x < ras->lx && y >= 0 && y < ras->ly && ras->buffer) { |
| LPIXEL *pL; |
| LPIXEL pLL; |
| SPIXEL *pS; |
| UD44_CMAPINDEX32 *ci32; |
| |
| UD44_PIXEL32 *col; |
| switch (ras->type) { |
| case (RAS_RGBM): |
| pL = (LPIXEL *)(ras->buffer) + y * ras->wrap + x; |
| ip.r = (int)pL->r; |
| ip.g = (int)pL->g; |
| ip.b = (int)pL->b; |
| ip.m = (int)pL->m; |
| break; |
| case (RAS_RGBM64): |
| pS = (SPIXEL *)(ras->buffer) + y * ras->wrap + x; |
| ip.r = (int)pS->r; |
| ip.g = (int)pS->g; |
| ip.b = (int)pS->b; |
| ip.m = (int)pS->m; |
| break; |
| case (RAS_CM32): |
| ci32 = (UD44_CMAPINDEX32 *)(ras->buffer) + y * ras->wrap + x; |
| col = (UD44_PIXEL32 *)(ras->cmap.buffer); |
| PIX_CM32_MAP_TO_RGBM(*ci32, col, pLL) |
| ip.r = (int)pLL.r; |
| ip.g = (int)pLL.g; |
| ip.b = (int)pLL.b; |
| ip.m = (int)pLL.m; |
| break; |
| } |
| } else |
| ip.r = ip.g = ip.b = ip.m = 0; |
| } |
| |
| void getRasterPixel(const int x, const int y, |
| I_PIXEL &ip) const |
| { |
| if (m_ras) |
| getRasterPixel(m_ras, x, y, ip); |
| else |
| ip.r = ip.g = ip.b = ip.m = 0; |
| } |
| |
| |
| |
| |
| |
| void setRasterPixel(RASTER *ras, const int x, const int y, |
| const I_PIXEL &ip) const |
| { |
| if (x >= 0 && x < ras->lx && y >= 0 && y < ras->ly && ras->buffer) { |
| LPIXEL *pL; |
| SPIXEL *pS; |
| switch (ras->type) { |
| case (RAS_RGBM): |
| pL = (LPIXEL *)(ras->buffer) + y * ras->wrap + x; |
| pL->r = (UCHAR)ip.r; |
| pL->g = (UCHAR)ip.g; |
| pL->b = (UCHAR)ip.b; |
| pL->m = (UCHAR)ip.m; |
| break; |
| case (RAS_RGBM64): |
| pS = (SPIXEL *)(ras->buffer) + y * ras->wrap + x; |
| pS->r = (USHORT)ip.r; |
| pS->g = (USHORT)ip.g; |
| pS->b = (USHORT)ip.b; |
| pS->m = (USHORT)ip.m; |
| break; |
| } |
| } |
| } |
| |
| bool copy_raster(const RASTER *ir, RASTER *out_r, |
| const int xBeg, const int yBeg, |
| const int xEnd, const int yEnd, |
| const int ox, const int oy) |
| |
| { |
| if ((ir->lx <= 0) || (ir->ly <= 0) || (out_r->lx <= 0) || (out_r->ly <= 0)) |
| return false; |
| if (ir->buffer == NULL || out_r->buffer == NULL) |
| return false; |
| if (out_r->type == RAS_CM32) |
| return false; |
| if (ir->type == RAS_CM32 && |
| (ir->cmap.buffer == NULL)) |
| return false; |
| |
| for (int y = yBeg, yy = oy; y <= yEnd; y++, yy++) |
| for (int x = xBeg, xx = ox; x <= xEnd; x++, xx++) { |
| I_PIXEL ip; |
| getRasterPixel(ir, x, y, ip); |
| if (xx >= 0 && yy >= 0 && xx < out_r->lx && yy < out_r->ly) { |
| LPIXEL *pL; |
| SPIXEL *pS; |
| if (out_r->type == RAS_RGBM && |
| (ir->type == RAS_RGBM || ir->type == RAS_CM32)) { |
| pL = (LPIXEL *)(out_r->buffer) + yy * out_r->wrap + xx; |
| pL->r = (UCHAR)ip.r; |
| pL->g = (UCHAR)ip.g; |
| pL->b = (UCHAR)ip.b; |
| pL->m = (UCHAR)ip.m; |
| } else if (out_r->type == RAS_RGBM && |
| ir->type == RAS_RGBM64) { |
| pL = (LPIXEL *)(out_r->buffer) + yy * out_r->wrap + xx; |
| pL->r = PIX_BYTE_FROM_USHORT((USHORT)ip.r); |
| pL->g = PIX_BYTE_FROM_USHORT((USHORT)ip.g); |
| pL->b = PIX_BYTE_FROM_USHORT((USHORT)ip.b); |
| pL->m = PIX_BYTE_FROM_USHORT((USHORT)ip.m); |
| } else if (out_r->type == RAS_RGBM64 && |
| (ir->type == RAS_RGBM || ir->type == RAS_CM32)) { |
| pS = (SPIXEL *)(out_r->buffer) + yy * out_r->wrap + xx; |
| pS->r = PIX_USHORT_FROM_BYTE((UCHAR)ip.r); |
| pS->g = PIX_USHORT_FROM_BYTE((UCHAR)ip.g); |
| pS->b = PIX_USHORT_FROM_BYTE((UCHAR)ip.b); |
| pS->m = PIX_USHORT_FROM_BYTE((UCHAR)ip.m); |
| } else if (out_r->type == RAS_RGBM64 && |
| ir->type == RAS_RGBM64) { |
| pS = (SPIXEL *)(out_r->buffer) + yy * out_r->wrap + xx; |
| pS->r = (USHORT)ip.r; |
| pS->g = (USHORT)ip.g; |
| pS->b = (USHORT)ip.b; |
| pS->m = (USHORT)ip.m; |
| } |
| } |
| } |
| return true; |
| } |
| |
| |
| |
| |
| virtual void read(const RASTER *ras) |
| { |
| try { |
| null(); |
| if (((ras->type == RAS_RGBM || ras->type == RAS_RGBM64) && |
| ras->buffer && ras->lx > 0 && ras->ly > 0) || |
| (ras->type == RAS_CM32 && ras->buffer && |
| ras->cmap.buffer && ras->lx > 0 && ras->ly > 0)) { |
| m_lX = ras->lx; |
| m_lY = ras->ly; |
| m_ras = ras; |
| initPic(); |
| lock(); |
| ST_TYPE type = getType(); |
| P *p = m_pic; |
| I_PIXEL ip; |
| memset(&ip, 0, sizeof(I_PIXEL)); |
| for (int y = 0; y < m_lY; y++) |
| for (int x = 0; x < m_lX; x++, p++) { |
| getRasterPixel(ras, x, y, ip); |
| switch (type) { |
| case (ST_RGBM): |
| if (ras->type == RAS_RGBM64) { |
| |
| p->r = PIX_BYTE_FROM_USHORT((USHORT)ip.r); |
| p->g = PIX_BYTE_FROM_USHORT((USHORT)ip.g); |
| p->b = PIX_BYTE_FROM_USHORT((USHORT)ip.b); |
| p->m = PIX_BYTE_FROM_USHORT((USHORT)ip.m); |
| } else { |
| |
| p->r = (UCHAR)ip.r; |
| p->g = (UCHAR)ip.g; |
| p->b = (UCHAR)ip.b; |
| p->m = (UCHAR)ip.m; |
| } |
| break; |
| case (ST_RGBM64): |
| if (ras->type == RAS_RGBM64) { |
| |
| p->r = ip.r; |
| p->g = ip.g; |
| p->b = ip.b; |
| p->m = ip.m; |
| } else { |
| |
| p->r = PIX_USHORT_FROM_BYTE((UCHAR)ip.r); |
| p->g = PIX_USHORT_FROM_BYTE((UCHAR)ip.g); |
| p->b = PIX_USHORT_FROM_BYTE((UCHAR)ip.b); |
| p->m = PIX_USHORT_FROM_BYTE((UCHAR)ip.m); |
| } |
| break; |
| } |
| } |
| } |
| } catch (SMemAllocError) { |
| null(); |
| throw; |
| } |
| } |
| |
| const CSTPic<P> &operator=(const CSTPic<P> &sp) |
| { |
| try { |
| null(); |
| m_lX = sp.m_lX; |
| m_lY = sp.m_lY; |
| m_ras = sp.m_ras; |
| initPic(); |
| copyPic(sp); |
| } catch (SMemAllocError) { |
| null(); |
| throw; |
| } |
| |
| return (*this); |
| } |
| |
| |
| virtual void write(RASTER *ras) const |
| { |
| if ((ras->type == RAS_RGBM || ras->type == RAS_RGBM64) && |
| ras->lx > 0 && ras->ly > 0 && ras->buffer) { |
| int x, y; |
| I_PIXEL ip; |
| const P *p; |
| for (y = 0; y < m_lY && y < ras->ly; y++) |
| for (x = 0; x < m_lX && x < ras->lx; x++) { |
| p = m_pic + y * m_lX + x; |
| ip.r = (int)p->r; |
| ip.g = (int)p->g; |
| ip.b = (int)p->b; |
| ip.m = (int)p->m; |
| setRasterPixel(ras, x, y, ip); |
| } |
| } else |
| throw SWriteRasterError("(bad Raster type)"); |
| } |
| |
| |
| virtual void write(RASTER *ras, const SRECT &r, const SPOINT &p) const |
| |
| { |
| if (ras->type == RAS_RGBM || ras->type == RAS_RGBM64) { |
| int xs, ys, xd, yd; |
| P pp; |
| I_PIXEL ip; |
| for (ys = r.y0, yd = p.y; ys <= r.y1; ys++, yd++) |
| for (xs = r.x0, xd = p.x; xs <= r.x1; xs++, xd++) { |
| getPixel(xs, ys, pp); |
| ip.r = (int)pp.r; |
| ip.g = (int)pp.g; |
| ip.b = (int)pp.b; |
| ip.m = (int)pp.m; |
| setRasterPixel(ras, xd, yd, ip); |
| } |
| } else |
| throw SWriteRasterError("(bad Raster type)"); |
| } |
| |
| virtual void writeOutBorder(const RASTER *rasin, const int border, RASTER *ras, const SRECT &r, const SPOINT &p) const |
| |
| { |
| assert(rasin->type == RAS_CM32); |
| UD44_PIXEL32 *col = (UD44_PIXEL32 *)(rasin->cmap.buffer); |
| |
| if (ras->type == RAS_RGBM || ras->type == RAS_RGBM64) { |
| int xs, ys, xd, yd; |
| |
| I_PIXEL ip; |
| for (ys = r.y0, yd = p.y; ys <= r.y1; ys++, yd++) |
| for (xs = r.x0, xd = p.x; xs <= r.x1; xs++, xd++) { |
| int x = xd - border; |
| int y = yd - border; |
| if (x >= 0 && y >= 0 && x < rasin->lx && y < rasin->ly) { |
| UD44_CMAPINDEX32 pixel = *(((UD44_CMAPINDEX32 *)rasin->buffer) + y * rasin->wrap + x); |
| |
| |
| if ((pixel & 0xff) == 0 || ((pixel >> 8) & 0xfff) != 0) { |
| LPIXEL pLL; |
| PIX_CM32_MAP_TO_RGBM(pixel, col, pLL) |
| ip.r = (int)pLL.r; |
| ip.g = (int)pLL.g; |
| ip.b = (int)pLL.b; |
| ip.m = (int)pLL.m; |
| setRasterPixel(ras, xd, yd, ip); |
| continue; |
| } |
| } |
| |
| P pp; |
| getPixel(xs, ys, pp); |
| ip.r = (int)pp.r; |
| ip.g = (int)pp.g; |
| ip.b = (int)pp.b; |
| ip.m = (int)pp.m; |
| setRasterPixel(ras, xd, yd, ip); |
| } |
| } else |
| throw SWriteRasterError("(bad Raster type)"); |
| } |
| |
| void convertToCurrentType(P &d, const I_PIXEL &s) const |
| { |
| if (getType() == ST_RGBM) { |
| d.r = (UCHAR)s.r; |
| d.g = (UCHAR)s.g; |
| d.b = (UCHAR)s.b; |
| d.m = (UCHAR)s.m; |
| } |
| if (getType() == ST_RGBM64) { |
| d.r = (USHORT)s.r; |
| d.g = (USHORT)s.g; |
| d.b = (USHORT)s.b; |
| d.m = (USHORT)s.m; |
| } |
| } |
| |
| bool isSameColor(const P *a, const P *b) const |
| { |
| if (a->r == b->r && a->g == b->g && a->b == b->b) |
| return true; |
| return false; |
| } |
| |
| void colorNoise(const I_PIXEL &cc1, const I_PIXEL &cc2, const double d) |
| { |
| P c1, c2; |
| |
| if (d <= 0) |
| return; |
| |
| convertToCurrentType(c1, cc1); |
| convertToCurrentType(c2, cc2); |
| int xy = m_lX * m_lY; |
| P *pPic = m_pic; |
| for (int i = 0; i < xy; i++, pPic++) |
| if (isSameColor(&c1, pPic)) { |
| double q = (rand() % 101) / 100.0; |
| q = d * q; |
| q = q > 1.0 ? 1.0 : q; |
| double r = (1.0 - q) * (double)c1.r + q * (double)c2.r; |
| double g = (1.0 - q) * (double)c1.g + q * (double)c2.g; |
| double b = (1.0 - q) * (double)c1.b + q * (double)c2.b; |
| r = D_CUT_0_255(r); |
| g = D_CUT_0_255(g); |
| b = D_CUT_0_255(b); |
| pPic->r = UC_ROUND(r); |
| pPic->g = UC_ROUND(g); |
| pPic->b = UC_ROUND(b); |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| void rgb2hls(UCHAR r, UCHAR g, UCHAR b, |
| double *h, double *l, double *s) |
| { |
| double ma, mi, delta, sum; |
| double rf, gf, bf; |
| |
| rf = (double)r / 255.0; |
| gf = (double)g / 255.0; |
| bf = (double)b / 255.0; |
| |
| ma = rf > gf ? rf : gf; |
| ma = ma > bf ? ma : bf; |
| mi = rf < gf ? rf : gf; |
| mi = mi < bf ? mi : bf; |
| sum = ma + mi; |
| delta = ma - mi; |
| *l = sum / 2.0; |
| if (fabs(delta) < 0.000001) { |
| *s = 0.0; |
| *h = UNDEFINED; |
| } else { |
| *s = *l <= 0.5 ? delta / sum : delta / (2.0 - sum); |
| *h = fabs((rf - ma)) < 0.000001 ? (gf - bf) / delta : (fabs((gf - ma)) < 0.000001 ? 2.0 + (bf - rf) / delta : 4.0 + (rf - gf) / delta); |
| *h *= 60; |
| *h = *h < 0.0 ? *h + 360.0 : *h; |
| } |
| } |
| |
| double fromHue(double n1, double n2, double hue) |
| { |
| double v, h; |
| |
| h = hue > 360.0 ? hue - 360.0 : hue; |
| h = h < 0.0 ? h + 360.0 : h; |
| |
| if (h < 60.0) { |
| v = n1 + (n2 - n1) * h / 60.0; |
| } else if (h < 180.0) { |
| v = n2; |
| } else if (h < 240.0) { |
| v = n1 + (n2 - n1) * (240.0 - h) / 60.0; |
| } else |
| v = n1; |
| return (v); |
| } |
| |
| void hls2rgb(double h, double l, double s, |
| UCHAR *r, UCHAR *g, UCHAR *b) |
| { |
| double rf, gf, bf; |
| double m1, m2; |
| |
| m2 = l <= 0.5 ? l * (1.0 + s) : l + s - l * s; |
| m1 = 2 * l - m2; |
| if (fabs(s - 0.0) < 0.000001) { |
| if (fabs(h - UNDEFINED) < 0.000001) { |
| rf = gf = bf = l * 255.0; |
| } else |
| rf = gf = bf = 0.0; |
| } else { |
| rf = fromHue(m1, m2, h + 120.0) * 255.0; |
| gf = fromHue(m1, m2, h) * 255.0; |
| bf = fromHue(m1, m2, h - 120.0) * 255.0; |
| } |
| rf = D_CUT_0_255(rf); |
| gf = D_CUT_0_255(gf); |
| bf = D_CUT_0_255(bf); |
| *r = UC_ROUND(rf); |
| *g = UC_ROUND(gf); |
| *b = UC_ROUND(bf); |
| } |
| }; |
| |
| |