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:; }
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; } }
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 }