void ReplaceColorFilter::applyToGrayscale(FilterManager* filterMgr) { const uint16_t* src_address = (uint16_t*)filterMgr->getSourceAddress(); uint16_t* dst_address = (uint16_t*)filterMgr->getDestinationAddress(); int w = filterMgr->getWidth(); int src_k, src_a; int dst_k, dst_a; int x, c; dst_k = _graya_getv(m_from); dst_a = _graya_geta(m_from); for (x=0; x<w; x++) { if (filterMgr->skipPixel()) { ++src_address; ++dst_address; continue; } c = *(src_address++); src_k = _graya_getv(c); src_a = _graya_geta(c); if ((ABS(src_k-dst_k) <= m_tolerance) && (ABS(src_a-dst_a) <= m_tolerance)) *(dst_address++) = m_to; else *(dst_address++) = c; } }
static bool is_same_pixel(PixelFormat pixelFormat, int pixel1, int pixel2) { switch (pixelFormat) { case IMAGE_RGB: if (_rgba_geta(pixel1) == 0 && _rgba_geta(pixel2) == 0) return true; break; case IMAGE_GRAYSCALE: if (_graya_geta(pixel1) == 0 && _graya_geta(pixel2) == 0) return true; break; } return pixel1 == pixel2; }
// static Color Color::fromImage(PixelFormat pixelFormat, int c) { Color color = Color::fromMask(); switch (pixelFormat) { case IMAGE_RGB: if (_rgba_geta(c) > 0) { color = Color::fromRgb(_rgba_getr(c), _rgba_getg(c), _rgba_getb(c)); } break; case IMAGE_GRAYSCALE: if (_graya_geta(c) > 0) { color = Color::fromGray(_graya_getv(c)); } break; case IMAGE_INDEXED: color = Color::fromIndex(c); break; } return color; }
void InvertColorFilter::applyToGrayscale(FilterManager* filterMgr) { const uint16_t* src_address = (uint16_t*)filterMgr->getSourceAddress(); uint16_t* dst_address = (uint16_t*)filterMgr->getDestinationAddress(); int w = filterMgr->getWidth(); Target target = filterMgr->getTarget(); int x, c, k, a; for (x=0; x<w; x++) { if (filterMgr->skipPixel()) { ++src_address; ++dst_address; continue; } c = *(src_address++); k = _graya_getv(c); a = _graya_geta(c); if (target & TARGET_GRAY_CHANNEL) k ^= 0xff; if (target & TARGET_ALPHA_CHANNEL) a ^= 0xff; *(dst_address++) = _graya(k, a); } }
static inline bool color_equal_16(uint16_t c1, uint16_t c2, int tolerance) { if (tolerance == 0) return (c1 == c2) || (_graya_geta(c1) == 0 && _graya_geta(c2) == 0); else { int k1 = _graya_getv(c1); int a1 = _graya_geta(c1); int k2 = _graya_getv(c2); int a2 = _graya_geta(c2); if (a1 == 0 && a2 == 0) return true; return ((ABS(k1-k2) <= tolerance) && (ABS(a1-a2) <= tolerance)); } }
void write_scanline(GrayscaleTraits::address_t address, int w, uint8_t* buffer) { for (int x=0; x<w; ++x) { *(buffer++) = _graya_getv(*address); *(buffer++) = _graya_geta(*address); ++address; } }
inline void operator()(RgbTraits::address_t& scanline_address, RgbTraits::address_t& dst_address, GrayscaleTraits::address_t& src_address, int opacity) { if (*src_address != m_mask_color) { int v = _graya_getv(*src_address); *scanline_address = (*m_blend_color)(*dst_address, _rgba(v, v, v, _graya_geta(*src_address)), opacity); } else *scanline_address = *dst_address; }
void ConvolutionMatrixFilter::applyToGrayscale(FilterManager* filterMgr) { if (!m_matrix) return; const Image* src = filterMgr->getSourceImage(); uint16_t* dst_address = (uint16_t*)filterMgr->getDestinationAddress(); Target target = filterMgr->getTarget(); uint16_t color; GetPixelsDelegateGrayscale delegate; int x = filterMgr->getX(); int x2 = x+filterMgr->getWidth(); int y = filterMgr->getY(); for (; x<x2; ++x) { // Avoid the non-selected region if (filterMgr->skipPixel()) { ++dst_address; continue; } delegate.reset(m_matrix); get_neighboring_pixels<GrayscaleTraits>(src, x, y, m_matrix->getWidth(), m_matrix->getHeight(), m_matrix->getCenterX(), m_matrix->getCenterY(), m_tiledMode, delegate); color = image_getpixel_fast<GrayscaleTraits>(src, x, y); if (delegate.div == 0) { *(dst_address++) = color; continue; } if (target & TARGET_GRAY_CHANNEL) { delegate.v = delegate.v / delegate.div + m_matrix->getBias(); delegate.v = MID(0, delegate.v, 255); } else delegate.v = _graya_getv(color); if (target & TARGET_ALPHA_CHANNEL) { delegate.a = delegate.a / m_matrix->getDiv() + m_matrix->getBias(); delegate.a = MID(0, delegate.a, 255); } else delegate.a = _graya_geta(color); *(dst_address++) = _graya(delegate.v, delegate.a); } }
void MedianFilter::applyToGrayscale(FilterManager* filterMgr) { const Image* src = filterMgr->getSourceImage(); uint16_t* dst_address = (uint16_t*)filterMgr->getDestinationAddress(); Target target = filterMgr->getTarget(); int color, k, a; GetPixelsDelegateGrayscale delegate(m_channel); int x = filterMgr->getX(); int x2 = x+filterMgr->getWidth(); int y = filterMgr->getY(); for (; x<x2; ++x) { // Avoid the non-selected region if (filterMgr->skipPixel()) { ++dst_address; continue; } delegate.reset(); get_neighboring_pixels<GrayscaleTraits>(src, x, y, m_width, m_height, m_width/2, m_height/2, m_tiledMode, delegate); color = image_getpixel_fast<GrayscaleTraits>(src, x, y); if (target & TARGET_GRAY_CHANNEL) { std::sort(m_channel[0].begin(), m_channel[0].end()); k = m_channel[0][m_ncolors/2]; } else k = _graya_getv(color); if (target & TARGET_ALPHA_CHANNEL) { std::sort(m_channel[1].begin(), m_channel[1].end()); a = m_channel[1][m_ncolors/2]; } else a = _graya_geta(color); *(dst_address++) = _graya(k, a); } }
bool StandbyState::onUpdateStatusBar(Editor* editor) { tools::Tool* current_tool = editor->getCurrentEditorTool(); Sprite* sprite = editor->getSprite(); int x, y; editor->screenToEditor(jmouse_x(0), jmouse_y(0), &x, &y); if (!sprite) { app_get_statusbar()->clearText(); } // For eye-dropper else if (current_tool->getInk(0)->isEyedropper()) { int imgtype = sprite->getImgType(); uint32_t pixel = sprite->getPixel(x, y); Color color = Color::fromImage(imgtype, pixel); int alpha = 255; switch (imgtype) { case IMAGE_RGB: alpha = _rgba_geta(pixel); break; case IMAGE_GRAYSCALE: alpha = _graya_geta(pixel); break; } char buf[256]; usprintf(buf, "- Pos %d %d", x, y); app_get_statusbar()->showColor(0, buf, color, alpha); } else { Mask* mask = editor->getDocument()->getMask(); app_get_statusbar()->setStatusText (0, "Pos %d %d, Size %d %d, Frame %d", x, y, ((mask && mask->bitmap)? mask->w: sprite->getWidth()), ((mask && mask->bitmap)? mask->h: sprite->getHeight()), sprite->getCurrentFrame()+1); } return true; }
/** * Resizes the source image @a src to the destination image @a dst. * * @warning If you are using the RESIZE_METHOD_BILINEAR, it is * recommended to use @ref image_fixup_transparent_colors function * over the source image @a src before using this routine. */ void image_resize(const Image* src, Image* dst, ResizeMethod method, const Palette* pal, const RgbMap* rgbmap) { switch (method) { // TODO optimize this case RESIZE_METHOD_NEAREST_NEIGHBOR: { uint32_t color; double u, v, du, dv; int x, y; u = v = 0.0; du = src->w * 1.0 / dst->w; dv = src->h * 1.0 / dst->h; for (y=0; y<dst->h; ++y) { for (x=0; x<dst->w; ++x) { color = src->getpixel(MID(0, u, src->w-1), MID(0, v, src->h-1)); dst->putpixel(x, y, color); u += du; } u = 0.0; v += dv; } break; } // TODO optimize this case RESIZE_METHOD_BILINEAR: { uint32_t color[4], dst_color = 0; double u, v, du, dv; int u_floor, u_floor2; int v_floor, v_floor2; int x, y; u = v = 0.0; du = (src->w-1) * 1.0 / (dst->w-1); dv = (src->h-1) * 1.0 / (dst->h-1); for (y=0; y<dst->h; ++y) { for (x=0; x<dst->w; ++x) { u_floor = floor(u); v_floor = floor(v); if (u_floor > src->w-1) { u_floor = src->w-1; u_floor2 = src->w-1; } else if (u_floor == src->w-1) u_floor2 = u_floor; else u_floor2 = u_floor+1; if (v_floor > src->h-1) { v_floor = src->h-1; v_floor2 = src->h-1; } else if (v_floor == src->h-1) v_floor2 = v_floor; else v_floor2 = v_floor+1; // get the four colors color[0] = src->getpixel(u_floor, v_floor); color[1] = src->getpixel(u_floor2, v_floor); color[2] = src->getpixel(u_floor, v_floor2); color[3] = src->getpixel(u_floor2, v_floor2); // calculate the interpolated color double u1 = u - u_floor; double v1 = v - v_floor; double u2 = 1 - u1; double v2 = 1 - v1; switch (dst->getPixelFormat()) { case IMAGE_RGB: { int r = ((_rgba_getr(color[0])*u2 + _rgba_getr(color[1])*u1)*v2 + (_rgba_getr(color[2])*u2 + _rgba_getr(color[3])*u1)*v1); int g = ((_rgba_getg(color[0])*u2 + _rgba_getg(color[1])*u1)*v2 + (_rgba_getg(color[2])*u2 + _rgba_getg(color[3])*u1)*v1); int b = ((_rgba_getb(color[0])*u2 + _rgba_getb(color[1])*u1)*v2 + (_rgba_getb(color[2])*u2 + _rgba_getb(color[3])*u1)*v1); int a = ((_rgba_geta(color[0])*u2 + _rgba_geta(color[1])*u1)*v2 + (_rgba_geta(color[2])*u2 + _rgba_geta(color[3])*u1)*v1); dst_color = _rgba(r, g, b, a); break; } case IMAGE_GRAYSCALE: { int v = ((_graya_getv(color[0])*u2 + _graya_getv(color[1])*u1)*v2 + (_graya_getv(color[2])*u2 + _graya_getv(color[3])*u1)*v1); int a = ((_graya_geta(color[0])*u2 + _graya_geta(color[1])*u1)*v2 + (_graya_geta(color[2])*u2 + _graya_geta(color[3])*u1)*v1); dst_color = _graya(v, a); break; } case IMAGE_INDEXED: { int r = ((_rgba_getr(pal->getEntry(color[0]))*u2 + _rgba_getr(pal->getEntry(color[1]))*u1)*v2 + (_rgba_getr(pal->getEntry(color[2]))*u2 + _rgba_getr(pal->getEntry(color[3]))*u1)*v1); int g = ((_rgba_getg(pal->getEntry(color[0]))*u2 + _rgba_getg(pal->getEntry(color[1]))*u1)*v2 + (_rgba_getg(pal->getEntry(color[2]))*u2 + _rgba_getg(pal->getEntry(color[3]))*u1)*v1); int b = ((_rgba_getb(pal->getEntry(color[0]))*u2 + _rgba_getb(pal->getEntry(color[1]))*u1)*v2 + (_rgba_getb(pal->getEntry(color[2]))*u2 + _rgba_getb(pal->getEntry(color[3]))*u1)*v1); int a = (((color[0] == 0 ? 0: 255)*u2 + (color[1] == 0 ? 0: 255)*u1)*v2 + ((color[2] == 0 ? 0: 255)*u2 + (color[3] == 0 ? 0: 255)*u1)*v1); dst_color = a > 127 ? rgbmap->mapColor(r, g, b): 0; break; } case IMAGE_BITMAP: { int g = ((255*color[0]*u2 + 255*color[1]*u1)*v2 + (255*color[2]*u2 + 255*color[3]*u1)*v1); dst_color = g > 127 ? 1: 0; break; } } dst->putpixel(x, y, dst_color); u += du; } u = 0.0; v += dv; } break; } } }
/** * This routine does not modify the image to the human eye, but * internally tries to fixup all colors that are completelly * transparent (alpha = 0) with the average of its 4-neighbors. */ void image_fixup_transparent_colors(Image* image) { int x, y, u, v; switch (image->getPixelFormat()) { case IMAGE_RGB: { uint32_t c; int r, g, b, count; for (y=0; y<image->h; ++y) { for (x=0; x<image->w; ++x) { c = image_getpixel_fast<RgbTraits>(image, x, y); // if this is a completelly-transparent pixel... if (_rgba_geta(c) == 0) { count = 0; r = g = b = 0; for (v=y-1; v<=y+1; ++v) { for (u=x-1; u<=x+1; ++u) { if ((u >= 0) && (v >= 0) && (u < image->w) && (v < image->h)) { c = image_getpixel_fast<RgbTraits>(image, u, v); if (_rgba_geta(c) > 0) { r += _rgba_getr(c); g += _rgba_getg(c); b += _rgba_getb(c); ++count; } } } } if (count > 0) { r /= count; g /= count; b /= count; image_putpixel_fast<RgbTraits>(image, x, y, _rgba(r, g, b, 0)); } } } } break; } case IMAGE_GRAYSCALE: { uint16_t c; int k, count; for (y=0; y<image->h; ++y) { for (x=0; x<image->w; ++x) { c = image_getpixel_fast<GrayscaleTraits>(image, x, y); // if this is a completelly-transparent pixel... if (_graya_geta(c) == 0) { count = 0; k = 0; for (v=y-1; v<=y+1; ++v) { for (u=x-1; u<=x+1; ++u) { if ((u >= 0) && (v >= 0) && (u < image->w) && (v < image->h)) { c = image_getpixel_fast<GrayscaleTraits>(image, u, v); if (_graya_geta(c) > 0) { k += _graya_getv(c); ++count; } } } } if (count > 0) { k /= count; image_putpixel_fast<GrayscaleTraits>(image, x, y, _graya(k, 0)); } } } } break; } } }
void write_pixel(FILE* f, GrayscaleTraits::pixel_t c) { fputc(_graya_getv(c), f); fputc(_graya_geta(c), f); }