示例#1
0
文件: dirty.cpp 项目: Skiles/aseprite
Dirty::Dirty(Image* image, Image* image_diff)
  : m_imgtype(image->imgtype)
  , m_x1(0), m_y1(0)
  , m_x2(image->w-1), m_y2(image->h-1)
{
  int x, y, x1, x2;

  for (y=0; y<image->h; y++) {
    x1 = -1;
    for (x=0; x<image->w; x++) {
      if (image_getpixel(image, x, y) != image_getpixel(image_diff, x, y)) {
	x1 = x;
	break;
      }
    }
    if (x1 < 0)
      continue;

    for (x2=image->w-1; x2>x1; x2--) {
      if (image_getpixel(image, x2, y) != image_getpixel(image_diff, x2, y))
	break;
    }

    Col* col = new Col(x1, x2-x1+1);
    col->data.resize(getLineSize(col->w));

    Row* row = new Row(y);
    row->cols.push_back(col);

    m_rows.push_back(row);
  }
}
示例#2
0
// static
Color Color::fromImageGetPixel(Image *image, int x, int y)
{
  if ((x >= 0) && (y >= 0) && (x < image->w) && (y < image->h))
    return Color::fromImage(image->getPixelFormat(), image_getpixel(image, x, y));
  else
    return Color::fromMask();
}
示例#3
0
static void ase_file_write_mask_chunk(FILE *f, Mask *mask)
{
  int c, u, v, byte;
  const gfx::Rect& bounds(mask->getBounds());

  ase_file_write_start_chunk(f, ASE_FILE_CHUNK_MASK);

  fputw(bounds.x, f);
  fputw(bounds.y, f);
  fputw(bounds.w, f);
  fputw(bounds.h, f);
  ase_file_write_padding(f, 8);

  // Name
  ase_file_write_string(f, mask->getName().c_str());

  // Bitmap
  for (v=0; v<bounds.h; v++)
    for (u=0; u<(bounds.w+7)/8; u++) {
      byte = 0;
      for (c=0; c<8; c++)
        if (image_getpixel(mask->getBitmap(), u*8+c, v))
          byte |= (1<<(7-c));
      fputc(byte, f);
    }

  ase_file_write_close_chunk(f);
}
示例#4
0
int Sprite::getPixel(int x, int y, FrameNumber frame) const
{
  int color = 0;

  if ((x >= 0) && (y >= 0) && (x < m_width) && (y < m_height)) {
    Image* image = Image::create(m_format, 1, 1);
    image_clear(image, (m_format == IMAGE_INDEXED ? getTransparentColor(): 0));
    render(image, -x, -y, frame);
    color = image_getpixel(image, 0, 0);
    image_free(image);
  }

  return color;
}
示例#5
0
void image_putpen(Image* image, Pen* pen, int x, int y, int fg_color, int bg_color)
{
  Image* pen_image = pen->get_image();
  int u, v, size = pen->get_size();

  x -= size/2;
  y -= size/2;

  if (fg_color == bg_color) {
    image_rectfill(image, x, y, x+pen_image->w-1, y+pen_image->h-1, bg_color);
  }
  else {
    for (v=0; v<pen_image->h; v++) {
      for (u=0; u<pen_image->w; u++) {
        if (image_getpixel(pen_image, u, v))
          image_putpixel(image, x+u, y+v, fg_color);
        else
          image_putpixel(image, x+u, y+v, bg_color);
      }
    }
  }
}
示例#6
0
void UndoTransaction::autocropSprite(int bgcolor)
{
  int old_frame = m_sprite->getCurrentFrame();
  int x1, y1, x2, y2;
  int u1, v1, u2, v2;

  x1 = y1 = INT_MAX;
  x2 = y2 = INT_MIN;

  Image* image = Image::create(m_sprite->getPixelFormat(),
                               m_sprite->getWidth(),
                               m_sprite->getHeight());

  for (int frame=0; frame<m_sprite->getTotalFrames(); ++frame) {
    m_sprite->setCurrentFrame(frame);
    m_sprite->render(image, 0, 0);

    // TODO configurable (what color pixel to use as "refpixel",
    // here we are using the top-left pixel by default)
    if (image_shrink_rect(image, &u1, &v1, &u2, &v2,
                          image_getpixel(image, 0, 0))) {
      x1 = MIN(x1, u1);
      y1 = MIN(y1, v1);
      x2 = MAX(x2, u2);
      y2 = MAX(y2, v2);
    }
  }
  m_sprite->setCurrentFrame(old_frame);

  image_free(image);

  // do nothing
  if (x1 > x2 || y1 > y2)
    return;

  cropSprite(gfx::Rect(x1, y1, x2-x1+1, y2-y1+1), bgcolor);
}
示例#7
0
void DocumentApi::trimSprite(Sprite* sprite, int bgcolor)
{
  gfx::Rect bounds;

  UniquePtr<Image> image_wrap(Image::create(sprite->getPixelFormat(),
                                            sprite->getWidth(),
                                            sprite->getHeight()));
  Image* image = image_wrap.get();

  for (FrameNumber frame(0); frame<sprite->getTotalFrames(); ++frame) {
    image->clear(0);

    sprite->render(image, 0, 0, frame);

    // TODO configurable (what color pixel to use as "refpixel",
    // here we are using the top-left pixel by default)
    gfx::Rect frameBounds;
    if (image_shrink_rect(image, frameBounds, image_getpixel(image, 0, 0)))
      bounds = bounds.createUnion(frameBounds);
  }

  if (!bounds.isEmpty())
    cropSprite(sprite, bounds, bgcolor);
}
示例#8
0
/* flooder:
 *  Fills a horizontal line around the specified position, and adds it
 *  to the list of drawn segments. Returns the first x coordinate after
 *  the part of the line which it has dealt with.
 */
static int flooder (Image *image, int x, int y,
                    int src_color, int tolerance, void *data, AlgoHLine proc)
{
  FLOODED_LINE *p;
  int left = 0, right = 0;
  int c;

  switch (image->getPixelFormat()) {

    case IMAGE_RGB:
      {
        uint32_t* address = ((uint32_t**)image->line)[y];

        /* check start pixel */
        if (!color_equal_32((int)*(address+x), src_color, tolerance))
          return x+1;

        /* work left from starting point */
        for (left=x-1; left>=0; left--) {
          if (!color_equal_32((int)*(address+left), src_color, tolerance))
            break;
        }

        /* work right from starting point */
        for (right=x+1; right<image->w; right++) {
          if (!color_equal_32((int)*(address+right), src_color, tolerance))
            break;
        }
      }
      break;

    case IMAGE_GRAYSCALE:
      {
        uint16_t* address = ((uint16_t**)image->line)[y];

        /* check start pixel */
        if (!color_equal_16((int)*(address+x), src_color, tolerance))
          return x+1;

        /* work left from starting point */
        for (left=x-1; left>=0; left--) {
          if (!color_equal_16((int)*(address+left), src_color, tolerance))
            break;
        }

        /* work right from starting point */
        for (right=x+1; right<image->w; right++) {
          if (!color_equal_16((int)*(address+right), src_color, tolerance))
            break;
        }
      }
      break;

    case IMAGE_INDEXED:
      {
        uint8_t* address = ((uint8_t**)image->line)[y];

        /* check start pixel */
        if (!color_equal_8((int)*(address+x), src_color, tolerance))
          return x+1;

        /* work left from starting point */
        for (left=x-1; left>=0; left--) {
          if (!color_equal_8((int)*(address+left), src_color, tolerance))
            break;
        }

        /* work right from starting point */
        for (right=x+1; right<image->w; right++) {
          if (!color_equal_8((int)*(address+right), src_color, tolerance))
            break;
        }
      }
      break;

    default:
      /* check start pixel */
      if (image_getpixel(image, x, y) != src_color)
        return x+1;

      /* work left from starting point */
      for (left=x-1; left>=0; left--) {
        if (image_getpixel(image, left, y) != src_color)
          break;
      }

      /* work right from starting point */
      for (right=x+1; right<image->w; right++) {
        if (image_getpixel(image, right, y) != src_color)
          break;
      }
      break;
  }

  left++;
  right--;

  /* draw the line */
  (*proc)(left, y, right, data);

  /* store it in the list of flooded segments */
  c = y;
  p = FLOOD_LINE(c);

  if (p->flags) {
    while (p->next) {
      c = p->next;
      p = FLOOD_LINE(c);
    }

    p->next = c = flood_count++;
    _grow_scratch_mem(sizeof(FLOODED_LINE) * flood_count);
    p = FLOOD_LINE(c);
  }

  p->flags = FLOOD_IN_USE;
  p->lpos = left;
  p->rpos = right;
  p->y = y;
  p->next = 0;

  if (y > 0)
    p->flags |= FLOOD_TODO_ABOVE;

  if (y+1 < image->h)
    p->flags |= FLOOD_TODO_BELOW;

  return right+2;
}
示例#9
0
/* floodfill:
 *  Fills an enclosed area (starting at point x, y) with the specified color.
 */
void algo_floodfill(Image* image, int x, int y, int tolerance, void *data, AlgoHLine proc)
{
  int src_color;
  int c, done;
  FLOODED_LINE *p;

  /* make sure we have a valid starting point */
  if ((x < 0) || (x >= image->w) ||
      (y < 0) || (y >= image->h))
    return;

  /* what color to replace? */
  src_color = image_getpixel (image, x, y);

  /* set up the list of flooded segments */
  _grow_scratch_mem(sizeof(FLOODED_LINE) * image->h);
  flood_count = image->h;
  p = (FLOODED_LINE*)_scratch_mem;
  for (c=0; c<flood_count; c++) {
    p[c].flags = 0;
    p[c].lpos = SHRT_MAX;
    p[c].rpos = SHRT_MIN;
    p[c].y = y;
    p[c].next = 0;
  }

  /* start up the flood algorithm */
  flooder(image, x, y, src_color, tolerance, data, proc);

  /* continue as long as there are some segments still to test */
  do {
    done = true;

    /* for each line on the screen */
    for (c=0; c<flood_count; c++) {

      p = FLOOD_LINE(c);

      /* check below the segment? */
      if (p->flags & FLOOD_TODO_BELOW) {
        p->flags &= ~FLOOD_TODO_BELOW;
        if (check_flood_line(image, p->y+1, p->lpos, p->rpos,
                             src_color, tolerance, data, proc)) {
          done = false;
          p = FLOOD_LINE(c);
        }
      }

      /* check above the segment? */
      if (p->flags & FLOOD_TODO_ABOVE) {
        p->flags &= ~FLOOD_TODO_ABOVE;
        if (check_flood_line(image, p->y-1, p->lpos, p->rpos,
                             src_color, tolerance, data, proc)) {
          done = false;
          /* special case shortcut for going backwards */
          if ((c < image->h) && (c > 0))
            c -= 2;
        }
      }
    }
  } while (!done);
}
示例#10
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;
      }
    }
  }
}