示例#1
0
文件: render.cpp 项目: vmrob/aseprite
static void merge_zoomed_image_scale_up(Image* dst, const Image* src, const Palette* pal,
  int x, int y, int opacity, int blend_mode, Zoom zoom)
{
  BlenderHelper<DstTraits, SrcTraits> blender(src, pal, blend_mode);
  int src_x, src_y, src_w, src_h;
  int dst_x, dst_y, dst_w, dst_h;
  int box_x, box_y, box_w, box_h;
  int first_box_w, first_box_h;
  int line_h, bottom;

  box_w = zoom.apply(1);
  box_h = zoom.apply(1);

  src_x = 0;
  src_y = 0;
  src_w = src->width();
  src_h = src->height();

  dst_x = x;
  dst_y = y;
  dst_w = zoom.apply(src->width());
  dst_h = zoom.apply(src->height());

  // clipping...
  if (dst_x < 0) {
    src_x += zoom.remove(-dst_x);
    src_w -= zoom.remove(-dst_x);
    dst_w -= (-dst_x);
    first_box_w = box_w - ((-dst_x) % box_w);
    dst_x = 0;
  }
  else
    first_box_w = 0;

  if (dst_y < 0) {
    src_y += zoom.remove(-dst_y);
    src_h -= zoom.remove(-dst_y);
    dst_h -= (-dst_y);
    first_box_h = box_h - ((-dst_y) % box_h);
    dst_y = 0;
  }
  else
    first_box_h = 0;

  if (dst_x+dst_w > dst->width()) {
    src_w -= zoom.remove(dst_x+dst_w-dst->width());
    dst_w = dst->width() - dst_x;
  }

  if (dst_y+dst_h > dst->height()) {
    src_h -= zoom.remove(dst_y+dst_h-dst->height());
    dst_h = dst->height() - dst_y;
  }

  if ((src_w <= 0) || (src_h <= 0) ||
      (dst_w <= 0) || (dst_h <= 0))
    return;

  bottom = dst_y+dst_h-1;

  // the scanline variable is used to blend src/dst pixels one time for each pixel
  typedef std::vector<typename DstTraits::pixel_t> Scanline;
  Scanline scanline(src_w);
  typename Scanline::iterator scanline_it;
#ifdef _DEBUG
  typename Scanline::iterator scanline_end = scanline.end();
#endif

  // Lock all necessary bits
  const LockImageBits<SrcTraits> srcBits(src, gfx::Rect(src_x, src_y, src_w, src_h));
  LockImageBits<DstTraits> dstBits(dst, gfx::Rect(dst_x, dst_y, dst_w, dst_h));
  typename LockImageBits<SrcTraits>::const_iterator src_it = srcBits.begin();
#ifdef _DEBUG
  typename LockImageBits<SrcTraits>::const_iterator src_end = srcBits.end();
#endif
  typename LockImageBits<DstTraits>::iterator dst_it, dst_end;

  // For each line to draw of the source image...
  for (y=0; y<src_h; ++y) {
    dst_it = dstBits.begin_area(gfx::Rect(dst_x, dst_y, dst_w, 1));
    dst_end = dstBits.end_area(gfx::Rect(dst_x, dst_y, dst_w, 1));

    // Read 'src' and 'dst' and blend them, put the result in `scanline'
    scanline_it = scanline.begin();
    for (x=0; x<src_w; ++x) {
      ASSERT(src_it >= srcBits.begin() && src_it < src_end);
      ASSERT(dst_it >= dstBits.begin() && dst_it < dst_end);
      ASSERT(scanline_it >= scanline.begin() && scanline_it < scanline_end);

      blender(*scanline_it, *dst_it, *src_it, opacity);

      ++src_it;

      int delta;
      if ((x == 0) && (first_box_w > 0))
        delta = first_box_w;
      else
        delta = box_w;

      while (dst_it != dst_end && delta-- > 0)
        ++dst_it;

      ++scanline_it;
    }

    // Get the 'height' of the line to be painted in 'dst'
    if ((y == 0) && (first_box_h > 0))
      line_h = first_box_h;
    else
      line_h = box_h;

    // Draw the line in 'dst'
    for (box_y=0; box_y<line_h; ++box_y) {
      dst_it = dstBits.begin_area(gfx::Rect(dst_x, dst_y, dst_w, 1));
      dst_end = dstBits.end_area(gfx::Rect(dst_x, dst_y, dst_w, 1));
      scanline_it = scanline.begin();

      x = 0;

      // first pixel
      if (first_box_w > 0) {
        for (box_x=0; box_x<first_box_w; ++box_x) {
          ASSERT(scanline_it != scanline_end);
          ASSERT(dst_it != dst_end);

          *dst_it = *scanline_it;

          ++dst_it;
          if (dst_it == dst_end)
            goto done_with_line;
        }

        ++scanline_it;
        ++x;
      }

      // the rest of the line
      for (; x<src_w; ++x) {
        for (box_x=0; box_x<box_w; ++box_x) {
          ASSERT(dst_it !=  dst_end);

          *dst_it = *scanline_it;

          ++dst_it;
          if (dst_it == dst_end)
            goto done_with_line;
        }

        ++scanline_it;
      }

done_with_line:;
      if (++dst_y > bottom)
        goto done_with_blit;
    }

    // go to the next line in the source image
    ++src_y;
  }

done_with_blit:;
}
示例#2
0
文件: render.cpp 项目: vmrob/aseprite
static void merge_zoomed_image_scale_down(Image* dst, const Image* src, const Palette* pal,
  int x, int y, int opacity, int blend_mode, Zoom zoom)
{
  BlenderHelper<DstTraits, SrcTraits> blender(src, pal, blend_mode);
  int src_x, src_y, src_w, src_h;
  int dst_x, dst_y, dst_w, dst_h;
  int unbox_w, unbox_h;
  int bottom;

  unbox_w = zoom.remove(1);
  unbox_h = zoom.remove(1);

  src_x = 0;
  src_y = 0;
  src_w = src->width();
  src_h = src->height();

  dst_x = x;
  dst_y = y;
  dst_w = zoom.apply(src->width());
  dst_h = zoom.apply(src->height());

  // clipping...
  if (dst_x < 0) {
    src_x += zoom.remove(-dst_x);
    src_w -= zoom.remove(-dst_x);
    dst_w -= (-dst_x);
    dst_x = 0;
  }

  if (dst_y < 0) {
    src_y += zoom.remove(-dst_y);
    src_h -= zoom.remove(-dst_y);
    dst_h -= (-dst_y);
    dst_y = 0;
  }

  if (dst_x+dst_w > dst->width()) {
    src_w -= zoom.remove(dst_x+dst_w-dst->width());
    dst_w = dst->width() - dst_x;
  }

  if (dst_y+dst_h > dst->height()) {
    src_h -= zoom.remove(dst_y+dst_h-dst->height());
    dst_h = dst->height() - dst_y;
  }

  src_w = zoom.remove(zoom.apply(src_w));
  src_h = zoom.remove(zoom.apply(src_h));

  if ((src_w <= 0) || (src_h <= 0) ||
      (dst_w <= 0) || (dst_h <= 0))
    return;

  bottom = dst_y+dst_h-1;

  // Lock all necessary bits
  const LockImageBits<SrcTraits> srcBits(src, gfx::Rect(src_x, src_y, src_w, src_h));
  LockImageBits<DstTraits> dstBits(dst, gfx::Rect(dst_x, dst_y, dst_w, dst_h));
  typename LockImageBits<SrcTraits>::const_iterator src_it = srcBits.begin();
  typename LockImageBits<SrcTraits>::const_iterator src_end = srcBits.end();
  typename LockImageBits<DstTraits>::iterator dst_it, dst_end;

  // For each line to draw of the source image...
  for (y=0; y<src_h; y+=unbox_h) {
    dst_it = dstBits.begin_area(gfx::Rect(dst_x, dst_y, dst_w, 1));
    dst_end = dstBits.end_area(gfx::Rect(dst_x, dst_y, dst_w, 1));

    for (x=0; x<src_w; x+=unbox_w) {
      ASSERT(src_it >= srcBits.begin() && src_it < src_end);
      ASSERT(dst_it >= dstBits.begin() && dst_it < dst_end);

      blender(*dst_it, *dst_it, *src_it, opacity);

      // Skip source pixels
      for (int delta=0; delta < unbox_w && src_it != src_end; ++delta)
        ++src_it;

      ++dst_it;
    }

    if (++dst_y > bottom)
      break;

    // Skip lines
    for (int delta=0; delta < src_w * (unbox_h-1) && src_it != src_end; ++delta)
      ++src_it;
  }
}
示例#3
0
static void image_scale2x_tpl(Image* dst, const Image* src, int src_w, int src_h)
{
#if 0      // TODO complete this implementation that should be faster
           // than using a lot of get/put_pixel_fast calls.
  int dst_w = src_w*2;
  int dst_h = src_h*2;

  LockImageBits<ImageTraits> dstBits(dst, Image::WriteLock, gfx::Rect(0, 0, dst_w, dst_h));
  const LockImageBits<ImageTraits> srcBits(src);

  LockImageBits<ImageTraits>::iterator dstRow0_it = dstBits.begin();
  LockImageBits<ImageTraits>::iterator dstRow1_it = dstBits.begin();
  LockImageBits<ImageTraits>::iterator dstRow0_end = dstBits.end();
  LockImageBits<ImageTraits>::iterator dstRow1_end = dstBits.end();

  // Iterators:
  //   A
  // C P B
  //   D
  //
  // These iterators are displaced through src image and are modified in this way:
  //
  // P: is the simplest one, we just start from (0, 0) to srcEnd.
  // A: starts from row 0 (so A = P in the first row), then we start
  //    again from the row 0.
  // B: It starts from (1, row) and in the last pixel we don't moved it.
  // C: It starts from (0, 0) and then it is moved with a delay.
  // D: It starts from row 1 and continues until we reach the last
  //    row, in that case we start D iterator again.
  //
  LockImageBits<ImageTraits>::const_iterator itP, itA, itB, itC, itD, savedD;
  LockImageBits<ImageTraits>::const_iterator srcEnd = srcBits.end();
  color_t P, A, B, C, D;

  // Adjust iterators
  itP = itA = itB = itC = itD = savedD = srcBits.begin();
  dstRow1_it += dst_w;
  itD += src->width();

  for (int y=0; y<src_h; ++y) {
    if (y == 1) itA = srcBits.begin();
    if (y == src_h-2) savedD = itD;
    if (y == src_h-1) itD = savedD;
    ++itB;

    for (int x=0; x<src_w; ++x) {
      ASSERT(itP != srcEnd);
      ASSERT(itA != srcEnd);
      ASSERT(itB != srcEnd);
      ASSERT(itC != srcEnd);
      ASSERT(itD != srcEnd);
      ASSERT(dstRow0_it != dstRow0_end);
      ASSERT(dstRow1_it != dstRow1_end);

      P = *itP;
      A = *itA;                 // y-1
      B = *itB;                 // x+1
      C = *itC;                 // x-1
      D = *itD;                 // y+1

      *dstRow0_it = (C == A && C != D && A != B ? A: P);
      ++dstRow0_it;
      *dstRow0_it = (A == B && A != C && B != D ? B: P);
      ++dstRow0_it;

      *dstRow1_it = (D == C && D != B && C != A ? C: P);
      ++dstRow1_it;
      *dstRow1_it = (B == D && B != A && D != C ? D: P);
      ++dstRow1_it;

      ++itP;
      ++itA;
      if (x < src_w-2) ++itB;
      if (x > 0) ++itC;
      ++itD;
    }

    // Adjust iterators for the next two rows.
    ++itB;
    ++itC;
    dstRow0_it += dst_w;
    if (y < src_h-1)
      dstRow1_it += dst_w;
  }

  // ASSERT(itP == srcEnd);
  // ASSERT(itA == srcEnd);
  // ASSERT(itB == srcEnd);
  // ASSERT(itC == srcEnd);
  // ASSERT(itD == srcEnd);
  ASSERT(dstRow0_it == dstRow0_end);
  ASSERT(dstRow1_it == dstRow1_end);
#else

#define A c[0]
#define B c[1]
#define C c[2]
#define D c[3]
#define P c[4]

  color_t c[5];
  for (int y=0; y<src_h; ++y) {
    for (int x=0; x<src_w; ++x) {
      P = get_pixel_fast<ImageTraits>(src, x, y);
      A = (y > 0 ? get_pixel_fast<ImageTraits>(src, x, y-1): P);
      B = (x < src_w-1 ? get_pixel_fast<ImageTraits>(src, x+1, y): P);
      C = (x > 0 ? get_pixel_fast<ImageTraits>(src, x-1, y): P);
      D = (y < src_h-1 ? get_pixel_fast<ImageTraits>(src, x, y+1): P);

      put_pixel_fast<ImageTraits>(dst, 2*x,   2*y,   (C == A && C != D && A != B ? A: P));
      put_pixel_fast<ImageTraits>(dst, 2*x+1, 2*y,   (A == B && A != C && B != D ? B: P));
      put_pixel_fast<ImageTraits>(dst, 2*x,   2*y+1, (D == C && D != B && C != A ? C: P));
      put_pixel_fast<ImageTraits>(dst, 2*x+1, 2*y+1, (B == D && B != A && D != C ? D: P));
    }
  }

#endif
}