示例#1
0
int Color::getBlue() const
{
  switch (getType()) {

    case Color::MaskType:
      return 0;

    case Color::RgbType:
      return m_value.rgb.b;

    case Color::HsvType:
      return Rgb(Hsv(m_value.hsv.h,
                     double(m_value.hsv.s) / 100.0,
                     double(m_value.hsv.v) / 100.0)).blue();

    case Color::GrayType:
      return m_value.gray;

    case Color::IndexType: {
      int i = m_value.index;
      ASSERT(i >= 0 && i < get_current_palette()->size());

      return _rgba_getb(get_current_palette()->getEntry(i));
    }

  }

  ASSERT(false);
  return -1;
}
示例#2
0
int Color::getGray() const
{
  switch (getType()) {

    case Color::MaskType:
      return 0;

    case Color::RgbType:
      return 255 * Hsv(Rgb(m_value.rgb.r,
                           m_value.rgb.g,
                           m_value.rgb.b)).valueInt() / 100;

    case Color::HsvType:
      return 255 * m_value.hsv.v / 100;

    case Color::GrayType:
      return m_value.gray;

    case Color::IndexType: {
      int i = m_value.index;
      ASSERT(i >= 0 && i < get_current_palette()->size());

      uint32_t c = get_current_palette()->getEntry(i);

      return 255 * Hsv(Rgb(_rgba_getr(c),
                           _rgba_getg(c),
                           _rgba_getb(c))).valueInt() / 100;
    }

  }

  ASSERT(false);
  return -1;
}
示例#3
0
void InvertColorFilter::applyToRgba(FilterManager* filterMgr)
{
    const uint32_t* src_address = (uint32_t*)filterMgr->getSourceAddress();
    uint32_t* dst_address = (uint32_t*)filterMgr->getDestinationAddress();
    int w = filterMgr->getWidth();
    Target target = filterMgr->getTarget();
    int x, c, r, g, b, a;

    for (x=0; x<w; x++) {
        if (filterMgr->skipPixel()) {
            ++src_address;
            ++dst_address;
            continue;
        }

        c = *(src_address++);

        r = _rgba_getr(c);
        g = _rgba_getg(c);
        b = _rgba_getb(c);
        a = _rgba_geta(c);

        if (target & TARGET_RED_CHANNEL) r ^= 0xff;
        if (target & TARGET_GREEN_CHANNEL) g ^= 0xff;
        if (target & TARGET_BLUE_CHANNEL) b ^= 0xff;
        if (target & TARGET_ALPHA_CHANNEL) a ^= 0xff;

        *(dst_address++) = _rgba(r, g, b, a);
    }
}
示例#4
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;
}
示例#5
0
void MedianFilter::applyToIndexed(FilterManager* filterMgr)
{
  const Image* src = filterMgr->getSourceImage();
  uint8_t* dst_address = (uint8_t*)filterMgr->getDestinationAddress();
  const Palette* pal = filterMgr->getIndexedData()->getPalette();
  const RgbMap* rgbmap = filterMgr->getIndexedData()->getRgbMap();
  Target target = filterMgr->getTarget();
  int color, r, g, b;
  GetPixelsDelegateIndexed delegate(pal, m_channel, target);
  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<IndexedTraits>(src, x, y, m_width, m_height, m_width/2, m_height/2,
                                          m_tiledMode, delegate);

    if (target & TARGET_INDEX_CHANNEL) {
      std::sort(m_channel[0].begin(), m_channel[0].end());
      *(dst_address++) = m_channel[0][m_ncolors/2];
    }
    else {
      color = image_getpixel_fast<IndexedTraits>(src, x, y);

      if (target & TARGET_RED_CHANNEL) {
        std::sort(m_channel[0].begin(), m_channel[0].end());
        r = m_channel[0][m_ncolors/2];
      }
      else
        r = _rgba_getr(pal->getEntry(color));

      if (target & TARGET_GREEN_CHANNEL) {
        std::sort(m_channel[1].begin(), m_channel[1].end());
        g = m_channel[1][m_ncolors/2];
      }
      else
        g = _rgba_getg(pal->getEntry(color));

      if (target & TARGET_BLUE_CHANNEL) {
        std::sort(m_channel[2].begin(), m_channel[2].end());
        b = m_channel[2][m_ncolors/2];
      }
      else
        b = _rgba_getb(pal->getEntry(color));

      *(dst_address++) = rgbmap->mapColor(r, g, b);
    }
  }
}
示例#6
0
void MedianFilter::applyToRgba(FilterManager* filterMgr)
{
  const Image* src = filterMgr->getSourceImage();
  uint32_t* dst_address = (uint32_t*)filterMgr->getDestinationAddress();
  Target target = filterMgr->getTarget();
  int color;
  int r, g, b, a;
  GetPixelsDelegateRgba 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<RgbTraits>(src, x, y, m_width, m_height, m_width/2, m_height/2,
                                      m_tiledMode, delegate);

    color = image_getpixel_fast<RgbTraits>(src, x, y);

    if (target & TARGET_RED_CHANNEL) {
      std::sort(m_channel[0].begin(), m_channel[0].end());
      r = m_channel[0][m_ncolors/2];
    }
    else
      r = _rgba_getr(color);

    if (target & TARGET_GREEN_CHANNEL) {
      std::sort(m_channel[1].begin(), m_channel[1].end());
      g = m_channel[1][m_ncolors/2];
    }
    else
      g = _rgba_getg(color);

    if (target & TARGET_BLUE_CHANNEL) {
      std::sort(m_channel[2].begin(), m_channel[2].end());
      b = m_channel[2][m_ncolors/2];
    }
    else
      b = _rgba_getb(color);

    if (target & TARGET_ALPHA_CHANNEL) {
      std::sort(m_channel[3].begin(), m_channel[3].end());
      a = m_channel[3][m_ncolors/2];
    }
    else
      a = _rgba_geta(color);

    *(dst_address++) = _rgba(r, g, b, a);
  }
}
示例#7
0
 void write_scanline(RgbTraits::address_t address, int w, uint8_t* buffer)
 {
   for (int x=0; x<w; ++x) {
     *(buffer++) = _rgba_getr(*address);
     *(buffer++) = _rgba_getg(*address);
     *(buffer++) = _rgba_getb(*address);
     *(buffer++) = _rgba_geta(*address);
     ++address;
   }
 }
示例#8
0
static inline bool color_equal_32(uint32_t c1, uint32_t c2, int tolerance)
{
  if (tolerance == 0)
    return (c1 == c2) || (_rgba_geta(c1) == 0 && _rgba_geta(c2) == 0);
  else {
    int r1 = _rgba_getr(c1);
    int g1 = _rgba_getg(c1);
    int b1 = _rgba_getb(c1);
    int a1 = _rgba_geta(c1);
    int r2 = _rgba_getr(c2);
    int g2 = _rgba_getg(c2);
    int b2 = _rgba_getb(c2);
    int a2 = _rgba_geta(c2);

    if (a1 == 0 && a2 == 0)
      return true;

    return ((ABS(r1-r2) <= tolerance) &&
            (ABS(g1-g2) <= tolerance) &&
            (ABS(b1-b2) <= tolerance) &&
            (ABS(a1-a2) <= tolerance));
  }
}
示例#9
0
void ReplaceColorFilter::applyToRgba(FilterManager* filterMgr)
{
  const uint32_t* src_address = (uint32_t*)filterMgr->getSourceAddress();
  uint32_t* dst_address = (uint32_t*)filterMgr->getDestinationAddress();
  int w = filterMgr->getWidth();
  int src_r, src_g, src_b, src_a;
  int dst_r, dst_g, dst_b, dst_a;
  int x, c;

  dst_r = _rgba_getr(m_from);
  dst_g = _rgba_getg(m_from);
  dst_b = _rgba_getb(m_from);
  dst_a = _rgba_geta(m_from);

  for (x=0; x<w; x++) {
    if (filterMgr->skipPixel()) {
      ++src_address;
      ++dst_address;
      continue;
    }

    c = *(src_address++);

    src_r = _rgba_getr(c);
    src_g = _rgba_getg(c);
    src_b = _rgba_getb(c);
    src_a = _rgba_geta(c);

    if ((ABS(src_r-dst_r) <= m_tolerance) &&
        (ABS(src_g-dst_g) <= m_tolerance) &&
        (ABS(src_b-dst_b) <= m_tolerance) &&
        (ABS(src_a-dst_a) <= m_tolerance))
      *(dst_address++) = m_to;
    else
      *(dst_address++) = c;
  }
}
示例#10
0
/* writes the original color chunk in FLI files for the entire palette "pal" */
static void ase_file_write_color2_chunk(FILE *f, Palette *pal)
{
  int c, color;

  ase_file_write_start_chunk(f, ASE_FILE_CHUNK_FLI_COLOR2);

  fputw(1, f);                  // number of packets

  // First packet
  fputc(0, f);                                   // skip 0 colors
  fputc(pal->size() == 256 ? 0: pal->size(), f); // number of colors
  for (c=0; c<pal->size(); c++) {
    color = pal->getEntry(c);

    fputc(_rgba_getr(color), f);
    fputc(_rgba_getg(color), f);
    fputc(_rgba_getb(color), f);
  }

  ase_file_write_close_chunk(f);
}
示例#11
0
void InvertColorFilter::applyToIndexed(FilterManager* filterMgr)
{
    const uint8_t* src_address = (uint8_t*)filterMgr->getSourceAddress();
    uint8_t* dst_address = (uint8_t*)filterMgr->getDestinationAddress();
    const Palette* pal = filterMgr->getIndexedData()->getPalette();
    const RgbMap* rgbmap = filterMgr->getIndexedData()->getRgbMap();
    int w = filterMgr->getWidth();
    Target target = filterMgr->getTarget();
    int x, c, r, g, b;

    for (x=0; x<w; x++) {
        if (filterMgr->skipPixel()) {
            ++src_address;
            ++dst_address;
            continue;
        }

        c = *(src_address++);

        if (target & TARGET_INDEX_CHANNEL)
            c ^= 0xff;
        else {
            r = _rgba_getr(pal->getEntry(c));
            g = _rgba_getg(pal->getEntry(c));
            b = _rgba_getb(pal->getEntry(c));

            if (target & TARGET_RED_CHANNEL  ) r ^= 0xff;
            if (target & TARGET_GREEN_CHANNEL) g ^= 0xff;
            if (target & TARGET_BLUE_CHANNEL ) b ^= 0xff;

            c = rgbmap->mapColor(r, g, b);
        }

        *(dst_address++) = c;
    }
}
示例#12
0
/* saves an Animator Pro COL file */
bool save_col_file(const Palette *pal, const char *filename)
{
  FILE *f = fopen(filename, "wb");
  if (!f)
    return false;

  fputl(8+768, f);                 /* file size */
  fputw(PROCOL_MAGIC_NUMBER, f);   /* file format identifier */
  fputw(0, f);                     /* version file */

  uint32_t c;
  for (int i=0; i<256; i++) {
    c = pal->getEntry(i);

    fputc(_rgba_getr(c), f);
    fputc(_rgba_getg(c), f);
    fputc(_rgba_getb(c), f);
    if (ferror(f))
      break;
  }

  fclose(f);
  return true;
}
示例#13
0
bool FliFormat::onSave(FileOp* fop)
{
  Sprite* sprite = fop->document->getSprite();
  unsigned char cmap[768];
  unsigned char omap[768];
  s_fli_header fli_header;
  int c, times;
  Image *bmp, *old;
  Palette *pal;

  /* prepare fli header */
  fli_header.filesize = 0;
  fli_header.frames = 0;
  fli_header.width = sprite->getWidth();
  fli_header.height = sprite->getHeight();

  if ((fli_header.width == 320) && (fli_header.height == 200))
    fli_header.magic = HEADER_FLI;
  else
    fli_header.magic = HEADER_FLC;

  fli_header.depth = 8;
  fli_header.flags = 3;
  fli_header.speed = get_time_precision(sprite);
  fli_header.created = 0;
  fli_header.updated = 0;
  fli_header.aspect_x = 1;
  fli_header.aspect_y = 1;
  fli_header.oframe1 = fli_header.oframe2 = 0;

  /* open the file to write in binary mode */
  FileHandle f(fop->filename.c_str(), "wb");

  fseek(f, 128, SEEK_SET);

  /* create the bitmaps */
  bmp = Image::create(IMAGE_INDEXED, sprite->getWidth(), sprite->getHeight());
  old = Image::create(IMAGE_INDEXED, sprite->getWidth(), sprite->getHeight());
  if ((!bmp) || (!old)) {
    fop_error(fop, "Not enough memory for temporary bitmaps.\n");
    if (bmp) image_free(bmp);
    if (old) image_free(old);
    return false;
  }

  /* write frame by frame */
  for (FrameNumber frpos(0);
       frpos < sprite->getTotalFrames();
       ++frpos) {
    /* get color map */
    pal = sprite->getPalette(frpos);
    for (c=0; c<256; c++) {
      cmap[3*c  ] = _rgba_getr(pal->getEntry(c));
      cmap[3*c+1] = _rgba_getg(pal->getEntry(c));
      cmap[3*c+2] = _rgba_getb(pal->getEntry(c));
    }

    /* render the frame in the bitmap */
    image_clear(bmp, 0);
    layer_render(sprite->getFolder(), bmp, 0, 0, frpos);

    /* how many times this frame should be written to get the same
       time that it has in the sprite */
    times = sprite->getFrameDuration(frpos) / fli_header.speed;

    for (c=0; c<times; c++) {
      /* write this frame */
      if (frpos == 0 && c == 0)
        fli_write_frame(f, &fli_header, NULL, NULL,
                        (unsigned char *)bmp->dat, cmap, W_ALL);
      else
        fli_write_frame(f, &fli_header,
                        (unsigned char *)old->dat, omap,
                        (unsigned char *)bmp->dat, cmap, W_ALL);

      /* update the old image and color-map to the new ones to compare later */
      image_copy(old, bmp, 0, 0);
      memcpy(omap, cmap, 768);
    }

    /* update progress */
    fop_progress(fop, (float)(frpos.next()) / (float)(sprite->getTotalFrames()));
  }

  /* write the header and close the file */
  fli_write_header(f, &fli_header);

  /* destroy the bitmaps */
  image_free(bmp);
  image_free(old);

  return true;
}
示例#14
0
bool PaletteView::onProcessMessage(Message* msg)
{
  switch (msg->type) {

    case JM_REQSIZE:
      request_size(&msg->reqsize.w, &msg->reqsize.h);
      return true;

    case JM_DRAW: {
      div_t d = div(Palette::MaxColors, m_columns);
      int cols = m_columns;
      int rows = d.quot + ((d.rem)? 1: 0);
      int x, y, u, v;
      int c, color;
      BITMAP *bmp;
      Palette* palette = get_current_palette();
      int bordercolor = makecol(255, 255, 255);

      bmp = create_bitmap(jrect_w(this->rc), jrect_h(this->rc));
      clear_to_color(bmp, makecol(0 , 0, 0));

      y = this->border_width.t;
      c = 0;

      for (v=0; v<rows; v++) {
        x = this->border_width.l;

        for (u=0; u<cols; u++) {
          if (c >= palette->size())
            break;

          if (bitmap_color_depth(ji_screen) == 8)
            color = c;
          else
            color = makecol_depth
              (bitmap_color_depth(ji_screen),
               _rgba_getr(palette->getEntry(c)),
               _rgba_getg(palette->getEntry(c)),
               _rgba_getb(palette->getEntry(c)));

          rectfill(bmp, x, y, x+m_boxsize-1, y+m_boxsize-1, color);

          if (m_selectedEntries[c]) {
            const int max = Palette::MaxColors;
            bool top    = (c >= m_columns            && c-m_columns >= 0  ? m_selectedEntries[c-m_columns]: false);
            bool bottom = (c < max-m_columns         && c+m_columns < max ? m_selectedEntries[c+m_columns]: false);
            bool left   = ((c%m_columns)>0           && c-1         >= 0  ? m_selectedEntries[c-1]: false);
            bool right  = ((c%m_columns)<m_columns-1 && c+1         < max ? m_selectedEntries[c+1]: false);

            if (!top) hline(bmp, x-1, y-1, x+m_boxsize, bordercolor);
            if (!bottom) hline(bmp, x-1, y+m_boxsize, x+m_boxsize, bordercolor);
            if (!left) vline(bmp, x-1, y-1, y+m_boxsize, bordercolor);
            if (!right) vline(bmp, x+m_boxsize, y-1, y+m_boxsize, bordercolor);
          }

          x += m_boxsize+this->child_spacing;
          c++;
        }

        y += m_boxsize+this->child_spacing;
      }

      blit(bmp, ji_screen,
           0, 0, this->rc->x1, this->rc->y1, bmp->w, bmp->h);
      destroy_bitmap(bmp);
      return true;
    }

    case JM_BUTTONPRESSED:
      captureMouse();
      /* continue... */

    case JM_MOTION: {
      JRect cpos = jwidget_get_child_rect(this);

      int req_w, req_h;
      request_size(&req_w, &req_h);

      int mouse_x = MID(cpos->x1, msg->mouse.x, cpos->x1+req_w-this->border_width.r-1);
      int mouse_y = MID(cpos->y1, msg->mouse.y, cpos->y1+req_h-this->border_width.b-1);

      jrect_free(cpos);

      Color color = getColorByPosition(mouse_x, mouse_y);
      if (color.getType() == Color::IndexType) {
        int idx = color.getIndex();

        app_get_statusbar()->showColor(0, "", color, 255);

        if (hasCapture() && idx != m_currentEntry) {
          if (!(msg->any.shifts & KB_CTRL_FLAG))
            clearSelection();

          if (msg->any.shifts & KB_SHIFT_FLAG)
            selectRange(m_rangeAnchor, idx);
          else
            selectColor(idx);

          // Emit signals
          jwidget_emit_signal(this, SIGNAL_PALETTE_EDITOR_CHANGE);
          IndexChange(idx);
        }
      }

      if (hasCapture())
        return true;

      break;
    }

    case JM_BUTTONRELEASED:
      releaseMouse();
      return true;

    case JM_WHEEL: {
      View* view = View::getView(this);
      if (view) {
        gfx::Point scroll = view->getViewScroll();
        scroll.y += (jmouse_z(1)-jmouse_z(0)) * 3 * m_boxsize;
        view->setViewScroll(scroll);
      }
      break;
    }

    case JM_MOUSELEAVE:
      app_get_statusbar()->clearText();
      break;

  }

  return Widget::onProcessMessage(msg);
}
void ConvolutionMatrixFilter::applyToRgba(FilterManager* filterMgr)
{
  if (!m_matrix)
    return;

  const Image* src = filterMgr->getSourceImage();
  uint32_t* dst_address = (uint32_t*)filterMgr->getDestinationAddress();
  Target target = filterMgr->getTarget();
  uint32_t color;
  GetPixelsDelegateRgba 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<RgbTraits>(src, x, y,
                                      m_matrix->getWidth(),
                                      m_matrix->getHeight(),
                                      m_matrix->getCenterX(),
                                      m_matrix->getCenterY(),
                                      m_tiledMode, delegate);

    color = image_getpixel_fast<RgbTraits>(src, x, y);
    if (delegate.div == 0) {
      *(dst_address++) = color;
      continue;
    }

    if (target & TARGET_RED_CHANNEL) {
      delegate.r = delegate.r / delegate.div + m_matrix->getBias();
      delegate.r = MID(0, delegate.r, 255);
    }
    else
      delegate.r = _rgba_getr(color);

    if (target & TARGET_GREEN_CHANNEL) {
      delegate.g = delegate.g / delegate.div + m_matrix->getBias();
      delegate.g = MID(0, delegate.g, 255);
    }
    else
      delegate.g = _rgba_getg(color);

    if (target & TARGET_BLUE_CHANNEL) {
      delegate.b = delegate.b / delegate.div + m_matrix->getBias();
      delegate.b = MID(0, delegate.b, 255);
    }
    else
      delegate.b = _rgba_getb(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 = _rgba_geta(color);

    *(dst_address++) = _rgba(delegate.r, delegate.g, delegate.b, delegate.a);
  }
}
示例#16
0
std::string Color::toHumanReadableString(PixelFormat pixelFormat, HumanReadableString humanReadable) const
{
  std::stringstream result;

  if (humanReadable == LongHumanReadableString) {
    switch (getType()) {

      case Color::MaskType:
        result << "Mask";
        break;

      case Color::RgbType:
        if (pixelFormat == IMAGE_GRAYSCALE) {
          result << "Gray " << getGray();
        }
        else {
          result << "RGB "
                 << m_value.rgb.r << " "
                 << m_value.rgb.g << " "
                 << m_value.rgb.b;

          if (pixelFormat == IMAGE_INDEXED)
            result << " Index "
                   << color_utils::color_for_image(*this, pixelFormat);
        }
        break;

      case Color::HsvType:
        if (pixelFormat == IMAGE_GRAYSCALE) {
          result << "Gray " << getGray();
        }
        else {
          result << "HSB "
                 << m_value.hsv.h << "\xB0 "
                 << m_value.hsv.s << " "
                 << m_value.hsv.v;

          if (pixelFormat == IMAGE_INDEXED)
            result << " Index " << color_utils::color_for_image(*this, pixelFormat);
        }
        break;

      case Color::GrayType:
        result << "Gray " << m_value.gray;
        break;

      case Color::IndexType: {
        int i = m_value.index;
        if (i >= 0 && i < (int)get_current_palette()->size()) {
          uint32_t _c = get_current_palette()->getEntry(i);
          result << "Index " << i
                 << " (RGB "
                 << (int)_rgba_getr(_c) << " "
                 << (int)_rgba_getg(_c) << " "
                 << (int)_rgba_getb(_c) << ")";
        }
        else {
          result << "Index "
                 << i
                 << " (out of range)";
        }
        break;
      }

      default:
        ASSERT(false);
        break;
    }
  }
  else if (humanReadable == ShortHumanReadableString) {
    switch (getType()) {

      case Color::MaskType:
        result << "Mask";
        break;

      case Color::RgbType:
        if (pixelFormat == IMAGE_GRAYSCALE) {
          result << "Gry-" << getGray();
        }
        else {
          result << "#" << std::hex << std::setfill('0')
                 << std::setw(2) << m_value.rgb.r
                 << std::setw(2) << m_value.rgb.g
                 << std::setw(2) << m_value.rgb.b;
        }
        break;

      case Color::HsvType:
        if (pixelFormat == IMAGE_GRAYSCALE) {
          result << "Gry-" << getGray();
        }
        else {
          result << m_value.hsv.h << "\xB0"
                 << m_value.hsv.s << ","
                 << m_value.hsv.v;
        }
        break;

      case Color::GrayType:
        result << "Gry-" << m_value.gray;
        break;

      case Color::IndexType:
        result << "Idx-" << m_value.index;
        break;

      default:
        ASSERT(false);
        break;
    }
  }

  return result.str();
}
void ConvolutionMatrixFilter::applyToIndexed(FilterManager* filterMgr)
{
  if (!m_matrix)
    return;

  const Image* src = filterMgr->getSourceImage();
  uint8_t* dst_address = (uint8_t*)filterMgr->getDestinationAddress();
  const Palette* pal = filterMgr->getIndexedData()->getPalette();
  const RgbMap* rgbmap = filterMgr->getIndexedData()->getRgbMap();
  Target target = filterMgr->getTarget();
  uint8_t color;
  GetPixelsDelegateIndexed delegate(pal);
  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<IndexedTraits>(src, x, y,
                                          m_matrix->getWidth(),
                                          m_matrix->getHeight(),
                                          m_matrix->getCenterX(),
                                          m_matrix->getCenterY(),
                                          m_tiledMode, delegate);

    color = image_getpixel_fast<IndexedTraits>(src, x, y);
    if (delegate.div == 0) {
      *(dst_address++) = color;
      continue;
    }

    if (target & TARGET_INDEX_CHANNEL) {
      delegate.index = delegate.index / m_matrix->getDiv() + m_matrix->getBias();
      delegate.index = MID(0, delegate.index, 255);

      *(dst_address++) = delegate.index;
    }
    else {
      if (target & TARGET_RED_CHANNEL) {
        delegate.r = delegate.r / delegate.div + m_matrix->getBias();
        delegate.r = MID(0, delegate.r, 255);
      }
      else
        delegate.r = _rgba_getr(pal->getEntry(color));

      if (target & TARGET_GREEN_CHANNEL) {
        delegate.g =  delegate.g / delegate.div + m_matrix->getBias();
        delegate.g = MID(0, delegate.g, 255);
      }
      else
        delegate.g = _rgba_getg(pal->getEntry(color));

      if (target & TARGET_BLUE_CHANNEL) {
        delegate.b = delegate.b / delegate.div + m_matrix->getBias();
        delegate.b = MID(0, delegate.b, 255);
      }
      else
        delegate.b = _rgba_getb(pal->getEntry(color));

      *(dst_address++) = rgbmap->mapColor(delegate.r, delegate.g, delegate.b);
    }
  }
}
示例#18
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;
    }

  }
}
示例#19
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;
    }

  }
}
示例#20
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;
      }
    }
  }
}
示例#21
0
 void write_pixel(FILE* f, RgbTraits::pixel_t c) {
   fputc(_rgba_getr(c), f);
   fputc(_rgba_getg(c), f);
   fputc(_rgba_getb(c), f);
   fputc(_rgba_geta(c), f);
 }
示例#22
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;
}