示例#1
0
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;
  }
}
示例#2
0
// 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;
}
示例#3
0
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);
    }
}
示例#4
0
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));
  }
}
示例#5
0
 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;
   }
 }
示例#6
0
 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);
  }
}
示例#8
0
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);
  }
}
示例#9
0
/**
 * 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;
    }

  }
}
示例#10
0
/**
 * 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;
    }

  }
}
示例#11
0
 void write_pixel(FILE* f, GrayscaleTraits::pixel_t c) {
   fputc(_graya_getv(c), f);
   fputc(_graya_geta(c), f);
 }
示例#12
0
bool JpegFormat::onSave(FileOp* fop)
{
  struct jpeg_compress_struct cinfo;
  struct error_mgr jerr;
  Image *image = fop->seq.image;
  FILE *file;
  JSAMPARRAY buffer;
  JDIMENSION buffer_height;
  SharedPtr<JpegOptions> jpeg_options = fop->seq.format_options;
  int c;

  // Open the file for write in it.
  file = fopen(fop->filename.c_str(), "wb");
  if (!file) {
    fop_error(fop, "Error creating file.\n");
    return false;
  }

  // Allocate and initialize JPEG compression object.
  jerr.fop = fop;
  cinfo.err = jpeg_std_error(&jerr.head);
  jpeg_create_compress(&cinfo);

  // SPECIFY data destination file.
  jpeg_stdio_dest(&cinfo, file);

  // SET parameters for compression.
  cinfo.image_width = image->w;
  cinfo.image_height = image->h;

  if (image->imgtype == IMAGE_GRAYSCALE) {
    cinfo.input_components = 1;
    cinfo.in_color_space = JCS_GRAYSCALE;
  }
  else {
    cinfo.input_components = 3;
    cinfo.in_color_space = JCS_RGB;
  }

  jpeg_set_defaults(&cinfo);
  jpeg_set_quality(&cinfo, (int)MID(0, 100.0f * jpeg_options->quality, 100), true);
  cinfo.dct_method = JDCT_ISLOW;
  cinfo.smoothing_factor = 0;

  // START compressor.
  jpeg_start_compress(&cinfo, true);

  // CREATE the buffer.
  buffer_height = 1;
  buffer = (JSAMPARRAY)base_malloc(sizeof(JSAMPROW) * buffer_height);
  if (!buffer) {
    fop_error(fop, "Not enough memory for the buffer.\n");
    jpeg_destroy_compress(&cinfo);
    fclose(file);
    return false;
  }

  for (c=0; c<(int)buffer_height; c++) {
    buffer[c] = (JSAMPROW)base_malloc(sizeof(JSAMPLE) *
				      cinfo.image_width * cinfo.num_components);
    if (!buffer[c]) {
      fop_error(fop, "Not enough memory for buffer scanlines.\n");
      for (c--; c>=0; c--)
        base_free(buffer[c]);
      base_free(buffer);
      jpeg_destroy_compress(&cinfo);
      fclose(file);
      return false;
    }
  }

  // Write each scan line.
  while (cinfo.next_scanline < cinfo.image_height) {
    // RGB
    if (image->imgtype == IMAGE_RGB) {
      uint32_t* src_address;
      uint8_t* dst_address;
      int x, y;
      for (y=0; y<(int)buffer_height; y++) {
        src_address = ((uint32_t**)image->line)[cinfo.next_scanline+y];
        dst_address = ((uint8_t**)buffer)[y];
        for (x=0; x<image->w; x++) {
          c = *(src_address++);
          *(dst_address++) = _rgba_getr(c);
          *(dst_address++) = _rgba_getg(c);
          *(dst_address++) = _rgba_getb(c);
        }
      }
    }
    // Grayscale.
    else {
      uint16_t* src_address;
      uint8_t* dst_address;
      int x, y;
      for (y=0; y<(int)buffer_height; y++) {
        src_address = ((uint16_t**)image->line)[cinfo.next_scanline+y];
        dst_address = ((uint8_t**)buffer)[y];
        for (x=0; x<image->w; x++)
          *(dst_address++) = _graya_getv(*(src_address++));
      }
    }
    jpeg_write_scanlines(&cinfo, buffer, buffer_height);
    
    fop_progress(fop, (float)(cinfo.next_scanline+1) / (float)(cinfo.image_height));
  }

  // Destroy all data.
  for (c=0; c<(int)buffer_height; c++)
    base_free(buffer[c]);
  base_free(buffer);

  // Finish compression.
  jpeg_finish_compress(&cinfo);

  // Release JPEG compression object.
  jpeg_destroy_compress(&cinfo);

  // We can close the output file.
  fclose(file);

  // All fine.
  return true;
}
示例#13
0
static void thumbnail_render(BITMAP* bmp, const Image* image, bool has_alpha, const Palette* palette)
{
  register int c, x, y;
  int w, h, x1, y1;
  double sx, sy, scale;

  ASSERT(image != NULL);

  sx = (double)image->w / (double)bmp->w;
  sy = (double)image->h / (double)bmp->h;
  scale = MAX(sx, sy);

  w = image->w / scale;
  h = image->h / scale;
  w = MIN(bmp->w, w);
  h = MIN(bmp->h, h);

  x1 = bmp->w/2 - w/2;
  y1 = bmp->h/2 - h/2;
  x1 = MAX(0, x1);
  y1 = MAX(0, y1);

  /* with alpha blending */
  if (has_alpha) {
    register int c2;

    rectgrid(bmp, 0, 0, bmp->w-1, bmp->h-1,
             bmp->w/4, bmp->h/4);

    switch (image->getPixelFormat()) {
      case IMAGE_RGB:
        for (y=0; y<h; y++)
          for (x=0; x<w; x++) {
            c = image_getpixel(image, x*scale, y*scale);
            c2 = getpixel(bmp, x1+x, y1+y);
            c = _rgba_blend_normal(_rgba(getr(c2), getg(c2), getb(c2), 255), c, 255);

            putpixel(bmp, x1+x, y1+y, makecol(_rgba_getr(c),
                                              _rgba_getg(c),
                                              _rgba_getb(c)));
          }
        break;
      case IMAGE_GRAYSCALE:
        for (y=0; y<h; y++)
          for (x=0; x<w; x++) {
            c = image_getpixel(image, x*scale, y*scale);
            c2 = getpixel(bmp, x1+x, y1+y);
            c = _graya_blend_normal(_graya(getr(c2), 255), c, 255);

            putpixel(bmp, x1+x, y1+y, makecol(_graya_getv(c),
                                              _graya_getv(c),
                                              _graya_getv(c)));
          }
        break;
      case IMAGE_INDEXED: {
        for (y=0; y<h; y++)
          for (x=0; x<w; x++) {
            c = image_getpixel(image, x*scale, y*scale);
            if (c != 0) {
              ASSERT(c >= 0 && c < palette->size());

              c = palette->getEntry(MID(0, c, palette->size()-1));
              putpixel(bmp, x1+x, y1+y, makecol(_rgba_getr(c),
                                                _rgba_getg(c),
                                                _rgba_getb(c)));
            }
          }
        break;
      }
    }
  }
  /* without alpha blending */
  else {
    clear_to_color(bmp, makecol(128, 128, 128));

    switch (image->getPixelFormat()) {
      case IMAGE_RGB:
        for (y=0; y<h; y++)
          for (x=0; x<w; x++) {
            c = image_getpixel(image, x*scale, y*scale);
            putpixel(bmp, x1+x, y1+y, makecol(_rgba_getr(c),
                                              _rgba_getg(c),
                                              _rgba_getb(c)));
          }
        break;
      case IMAGE_GRAYSCALE:
        for (y=0; y<h; y++)
          for (x=0; x<w; x++) {
            c = image_getpixel(image, x*scale, y*scale);
            putpixel(bmp, x1+x, y1+y, makecol(_graya_getv(c),
                                              _graya_getv(c),
                                              _graya_getv(c)));
          }
        break;
      case IMAGE_INDEXED: {
        for (y=0; y<h; y++)
          for (x=0; x<w; x++) {
            c = image_getpixel(image, x*scale, y*scale);

            ASSERT(c >= 0 && c < palette->size());

            c = palette->getEntry(MID(0, c, palette->size()-1));
            putpixel(bmp, x1+x, y1+y, makecol(_rgba_getr(c),
                                              _rgba_getg(c),
                                              _rgba_getb(c)));
          }
        break;
      }
    }
  }
}