Fixed critical bugs in rendering code with zoom.

This commit is contained in:
David Capello 2009-08-02 22:23:37 +00:00
parent a67c563d6f
commit a872edd377
5 changed files with 777 additions and 966 deletions

View File

@ -1,3 +1,9 @@
2009-08-02 David A. Capello <davidcapello@gmail.com>
* src/util/render.cpp (merge_zoomed_image): unified all
merge_zoomed_image8/16/32 in one generic method (and fixed
critical bugs).
2009-06-14 David A. Capello <davidcapello@gmail.com>
* src/commands/cmd_rotate_canvas.cpp: Added.

View File

@ -181,6 +181,7 @@ COMMON_SOURCES = \
src/raster/dirty.cpp \
src/raster/gfxobj.cpp \
src/raster/image.cpp \
src/raster/image_impl.cpp \
src/raster/layer.cpp \
src/raster/mask.cpp \
src/raster/palette.cpp \

539
src/raster/image_impl.cpp Normal file
View File

@ -0,0 +1,539 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2009 David Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "raster/image_impl.h"
template<>
void ImageImpl<RgbTraits>::to_allegro(BITMAP *bmp, int _x, int _y) const
{
const_address_t addr = raw_pixels();
unsigned long bmp_address;
int depth = bitmap_color_depth(bmp);
int x, y;
bmp_select(bmp);
switch (depth) {
case 8:
#if defined GFX_MODEX && !defined ALLEGRO_UNIX
if (is_planar_bitmap(bmp)) {
for (y=0; y<h; y++) {
bmp_address = (unsigned long)bmp->line[_y];
for (x=0; x<image->w; x++) {
outportw(0x3C4, (0x100<<((_x+x)&3))|2);
bmp_write8(bmp_address+((_x+x)>>2),
makecol8((*addr) & 0xff,
((*addr)>>8) & 0xff,
((*addr)>>16) & 0xff));
addr++;
}
_y++;
}
}
else {
#endif
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write8(bmp_address,
makecol8((*addr) & 0xff,
((*addr)>>8) & 0xff,
((*addr)>>16) & 0xff));
addr++;
bmp_address++;
}
_y++;
}
#if defined GFX_MODEX && !defined ALLEGRO_UNIX
}
#endif
break;
case 15:
_x <<= 1;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write15(bmp_address,
makecol15((*addr) & 0xff,
((*addr)>>8) & 0xff,
((*addr)>>16) & 0xff));
addr++;
bmp_address += 2;
}
_y++;
}
break;
case 16:
_x <<= 1;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line (bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write16(bmp_address,
makecol16((*addr) & 0xff,
((*addr)>>8) & 0xff,
((*addr)>>16) & 0xff));
addr++;
bmp_address += 2;
}
_y++;
}
break;
case 24:
_x *= 3;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write24(bmp_address,
makecol24((*addr) & 0xff,
((*addr)>>8) & 0xff,
((*addr)>>16) & 0xff));
addr++;
bmp_address += 3;
}
_y++;
}
break;
case 32:
_x <<= 2;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write32(bmp_address,
makeacol32((*addr) & 0xff,
((*addr)>>8) & 0xff,
((*addr)>>16) & 0xff,
((*addr)>>24) & 0xff));
addr++;
bmp_address += 4;
}
_y++;
}
break;
}
bmp_unwrite_line(bmp);
}
template<>
void ImageImpl<GrayscaleTraits>::to_allegro(BITMAP *bmp, int _x, int _y) const
{
const_address_t addr = raw_pixels();
unsigned long bmp_address;
int depth = bitmap_color_depth(bmp);
int x, y;
bmp_select(bmp);
switch (depth) {
case 8:
#if defined GFX_MODEX && !defined ALLEGRO_UNIX
if (is_planar_bitmap(bmp)) {
for (y=0; y<h; y++) {
bmp_address = (unsigned long)bmp->line[_y];
for (x=0; x<w; x++) {
outportw(0x3C4, (0x100<<((_x+x)&3))|2);
bmp_write8(bmp_address+((_x+x)>>2),
_index_cmap[(*addr) & 0xff]);
addr++;
}
_y++;
}
}
else {
#endif
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write8(bmp_address, _index_cmap[(*addr) & 0xff]);
addr++;
bmp_address++;
}
_y++;
}
#if defined GFX_MODEX && !defined ALLEGRO_UNIX
}
#endif
break;
case 15:
_x <<= 1;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write15(bmp_address,
makecol15((*addr) & 0xff,
(*addr) & 0xff,
(*addr) & 0xff));
addr++;
bmp_address += 2;
}
_y++;
}
break;
case 16:
_x <<= 1;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write16(bmp_address,
makecol16((*addr) & 0xff,
(*addr) & 0xff,
(*addr) & 0xff));
addr++;
bmp_address += 2;
}
_y++;
}
break;
case 24:
_x *= 3;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write24(bmp_address,
makecol24((*addr) & 0xff,
(*addr) & 0xff,
(*addr) & 0xff));
addr++;
bmp_address += 3;
}
_y++;
}
break;
case 32:
_x <<= 2;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write32(bmp_address,
makeacol32((*addr) & 0xff,
(*addr) & 0xff,
(*addr) & 0xff, 255));
addr++;
bmp_address += 4;
}
_y++;
}
break;
}
bmp_unwrite_line(bmp);
}
template<>
void ImageImpl<IndexedTraits>::to_allegro(BITMAP *bmp, int _x, int _y) const
{
#define RGB_TRIPLET \
_rgb_scale_6[_current_palette[_index_cmap[(*addr)]].r], \
_rgb_scale_6[_current_palette[_index_cmap[(*addr)]].g], \
_rgb_scale_6[_current_palette[_index_cmap[(*addr)]].b]
const_address_t addr = raw_pixels();
unsigned long bmp_address;
int depth = bitmap_color_depth(bmp);
int x, y;
bmp_select(bmp);
switch (depth) {
case 8:
#if defined GFX_MODEX && !defined ALLEGRO_UNIX
if (is_planar_bitmap (bmp)) {
for (y=0; y<h; y++) {
bmp_address = (unsigned long)bmp->line[_y];
for (x=0; x<w; x++) {
outportw(0x3C4, (0x100<<((_x+x)&3))|2);
bmp_write8(bmp_address+((_x+x)>>2), _index_cmap[(*addr)]);
address++;
}
_y++;
}
}
else {
#endif
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write8(bmp_address, _index_cmap[(*addr)]);
addr++;
bmp_address++;
}
_y++;
}
#if defined GFX_MODEX && !defined ALLEGRO_UNIX
}
#endif
break;
case 15:
_x <<= 1;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write15(bmp_address, makecol15(RGB_TRIPLET));
addr++;
bmp_address += 2;
}
_y++;
}
break;
case 16:
_x <<= 1;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write16(bmp_address, makecol16(RGB_TRIPLET));
addr++;
bmp_address += 2;
}
_y++;
}
break;
case 24:
_x *= 3;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write24(bmp_address, makecol24(RGB_TRIPLET));
addr++;
bmp_address += 3;
}
_y++;
}
break;
case 32:
_x <<= 2;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write32(bmp_address, makeacol32(RGB_TRIPLET, 255));
addr++;
bmp_address += 4;
}
_y++;
}
break;
}
bmp_unwrite_line(bmp);
}
template<>
void ImageImpl<BitmapTraits>::to_allegro(BITMAP *bmp, int _x, int _y) const
{
const_address_t addr;
unsigned long bmp_address;
int depth = bitmap_color_depth(bmp);
div_t d, beg_d = div(0, 8);
int color[2];
int x, y;
bmp_select(bmp);
switch (depth) {
case 8:
color[0] = makecol8(0, 0, 0);
color[1] = makecol8(255, 255, 255);
#if defined GFX_MODEX && !defined ALLEGRO_UNIX
if (is_planar_bitmap(bmp)) {
for (y=0; y<h; y++) {
addr = line_address(y);
bmp_address = (unsigned long)bmp->line[_y];
d = beg_d;
for (x=0; x<w; x++) {
outportw (0x3C4, (0x100<<((_x+x)&3))|2);
bmp_write8(bmp_addr+((_x+x)>>2),
color[((*addr) & (1<<d.rem))? 1: 0]);
_image_bitmap_next_bit(d, addr);
}
_y++;
}
}
else {
#endif
for (y=0; y<h; y++) {
addr = line_address(y);
bmp_address = bmp_write_line(bmp, _y)+_x;
d = beg_d;
for (x=0; x<w; x++) {
bmp_write8 (bmp_address++, color[((*addr) & (1<<d.rem))? 1: 0]);
_image_bitmap_next_bit(d, addr);
}
_y++;
}
#if defined GFX_MODEX && !defined ALLEGRO_UNIX
}
#endif
break;
case 15:
color[0] = makecol15(0, 0, 0);
color[1] = makecol15(255, 255, 255);
_x <<= 1;
for (y=0; y<h; y++) {
addr = line_address(y);
bmp_address = bmp_write_line(bmp, _y)+_x;
d = beg_d;
for (x=0; x<w; x++) {
bmp_write15(bmp_address, color[((*addr) & (1<<d.rem))? 1: 0]);
bmp_address += 2;
_image_bitmap_next_bit(d, addr);
}
_y++;
}
break;
case 16:
color[0] = makecol16(0, 0, 0);
color[1] = makecol16(255, 255, 255);
_x <<= 1;
for (y=0; y<h; y++) {
addr = line_address(y);
bmp_address = bmp_write_line(bmp, _y)+_x;
d = beg_d;
for (x=0; x<w; x++) {
bmp_write16(bmp_address, color[((*addr) & (1<<d.rem))? 1: 0]);
bmp_address += 2;
_image_bitmap_next_bit(d, addr);
}
_y++;
}
break;
case 24:
color[0] = makecol24 (0, 0, 0);
color[1] = makecol24 (255, 255, 255);
_x *= 3;
for (y=0; y<h; y++) {
addr = line_address(y);
bmp_address = bmp_write_line(bmp, _y)+_x;
d = beg_d;
for (x=0; x<w; x++) {
bmp_write24(bmp_address, color[((*addr) & (1<<d.rem))? 1: 0]);
bmp_address += 3;
_image_bitmap_next_bit (d, addr);
}
_y++;
}
break;
case 32:
color[0] = makeacol32 (0, 0, 0, 255);
color[1] = makeacol32 (255, 255, 255, 255);
_x <<= 2;
for (y=0; y<h; y++) {
addr = line_address(y);
bmp_address = bmp_write_line(bmp, _y)+_x;
d = beg_d;
for (x=0; x<w; x++) {
bmp_write32(bmp_address, color[((*addr) & (1<<d.rem))? 1: 0]);
bmp_address += 4;
_image_bitmap_next_bit(d, addr);
}
_y++;
}
break;
}
bmp_unwrite_line(bmp);
}

View File

@ -20,6 +20,9 @@
#define RASTER_IMAGE_IMPL_H
#include <cassert>
#include <allegro.h>
#include "raster/image.h"
template<class Traits>
class ImageImpl : public Image
@ -27,6 +30,8 @@ class ImageImpl : public Image
typedef typename Traits::address_t address_t;
typedef typename Traits::const_address_t const_address_t;
public: // raw access to pixel-data
inline address_t raw_pixels() {
return (address_t)dat;
}
@ -44,7 +49,7 @@ class ImageImpl : public Image
assert(y >= 0 && y < h);
return ((const_address_t*)line)[y];
}
public:
ImageImpl(int w, int h)
@ -485,522 +490,4 @@ void ImageImpl<BitmapTraits>::merge(const Image* src, int x, int y, int opacity,
}
}
template<>
void ImageImpl<RgbTraits>::to_allegro(BITMAP *bmp, int _x, int _y) const
{
const_address_t addr = raw_pixels();
unsigned long bmp_address;
int depth = bitmap_color_depth(bmp);
int x, y;
bmp_select(bmp);
switch (depth) {
case 8:
#if defined GFX_MODEX && !defined ALLEGRO_UNIX
if (is_planar_bitmap(bmp)) {
for (y=0; y<h; y++) {
bmp_address = (unsigned long)bmp->line[_y];
for (x=0; x<image->w; x++) {
outportw(0x3C4, (0x100<<((_x+x)&3))|2);
bmp_write8(bmp_address+((_x+x)>>2),
makecol8((*addr) & 0xff,
((*addr)>>8) & 0xff,
((*addr)>>16) & 0xff));
addr++;
}
_y++;
}
}
else {
#endif
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write8(bmp_address,
makecol8((*addr) & 0xff,
((*addr)>>8) & 0xff,
((*addr)>>16) & 0xff));
addr++;
bmp_address++;
}
_y++;
}
#if defined GFX_MODEX && !defined ALLEGRO_UNIX
}
#endif
break;
case 15:
_x <<= 1;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write15(bmp_address,
makecol15((*addr) & 0xff,
((*addr)>>8) & 0xff,
((*addr)>>16) & 0xff));
addr++;
bmp_address += 2;
}
_y++;
}
break;
case 16:
_x <<= 1;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line (bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write16(bmp_address,
makecol16((*addr) & 0xff,
((*addr)>>8) & 0xff,
((*addr)>>16) & 0xff));
addr++;
bmp_address += 2;
}
_y++;
}
break;
case 24:
_x *= 3;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write24(bmp_address,
makecol24((*addr) & 0xff,
((*addr)>>8) & 0xff,
((*addr)>>16) & 0xff));
addr++;
bmp_address += 3;
}
_y++;
}
break;
case 32:
_x <<= 2;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write32(bmp_address,
makeacol32((*addr) & 0xff,
((*addr)>>8) & 0xff,
((*addr)>>16) & 0xff,
((*addr)>>24) & 0xff));
addr++;
bmp_address += 4;
}
_y++;
}
break;
}
bmp_unwrite_line(bmp);
}
template<>
void ImageImpl<GrayscaleTraits>::to_allegro(BITMAP *bmp, int _x, int _y) const
{
const_address_t addr = raw_pixels();
unsigned long bmp_address;
int depth = bitmap_color_depth(bmp);
int x, y;
bmp_select(bmp);
switch (depth) {
case 8:
#if defined GFX_MODEX && !defined ALLEGRO_UNIX
if (is_planar_bitmap(bmp)) {
for (y=0; y<h; y++) {
bmp_address = (unsigned long)bmp->line[_y];
for (x=0; x<w; x++) {
outportw(0x3C4, (0x100<<((_x+x)&3))|2);
bmp_write8(bmp_address+((_x+x)>>2),
_index_cmap[(*addr) & 0xff]);
addr++;
}
_y++;
}
}
else {
#endif
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write8(bmp_address, _index_cmap[(*addr) & 0xff]);
addr++;
bmp_address++;
}
_y++;
}
#if defined GFX_MODEX && !defined ALLEGRO_UNIX
}
#endif
break;
case 15:
_x <<= 1;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write15(bmp_address,
makecol15((*addr) & 0xff,
(*addr) & 0xff,
(*addr) & 0xff));
addr++;
bmp_address += 2;
}
_y++;
}
break;
case 16:
_x <<= 1;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write16(bmp_address,
makecol16((*addr) & 0xff,
(*addr) & 0xff,
(*addr) & 0xff));
addr++;
bmp_address += 2;
}
_y++;
}
break;
case 24:
_x *= 3;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write24(bmp_address,
makecol24((*addr) & 0xff,
(*addr) & 0xff,
(*addr) & 0xff));
addr++;
bmp_address += 3;
}
_y++;
}
break;
case 32:
_x <<= 2;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write32(bmp_address,
makeacol32((*addr) & 0xff,
(*addr) & 0xff,
(*addr) & 0xff, 255));
addr++;
bmp_address += 4;
}
_y++;
}
break;
}
bmp_unwrite_line(bmp);
}
template<>
void ImageImpl<IndexedTraits>::to_allegro(BITMAP *bmp, int _x, int _y) const
{
#define RGB_TRIPLET \
_rgb_scale_6[_current_palette[_index_cmap[(*addr)]].r], \
_rgb_scale_6[_current_palette[_index_cmap[(*addr)]].g], \
_rgb_scale_6[_current_palette[_index_cmap[(*addr)]].b]
const_address_t addr = raw_pixels();
unsigned long bmp_address;
int depth = bitmap_color_depth(bmp);
int x, y;
bmp_select(bmp);
switch (depth) {
case 8:
#if defined GFX_MODEX && !defined ALLEGRO_UNIX
if (is_planar_bitmap (bmp)) {
for (y=0; y<h; y++) {
bmp_address = (unsigned long)bmp->line[_y];
for (x=0; x<w; x++) {
outportw(0x3C4, (0x100<<((_x+x)&3))|2);
bmp_write8(bmp_address+((_x+x)>>2), _index_cmap[(*addr)]);
address++;
}
_y++;
}
}
else {
#endif
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write8(bmp_address, _index_cmap[(*addr)]);
addr++;
bmp_address++;
}
_y++;
}
#if defined GFX_MODEX && !defined ALLEGRO_UNIX
}
#endif
break;
case 15:
_x <<= 1;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write15(bmp_address, makecol15(RGB_TRIPLET));
addr++;
bmp_address += 2;
}
_y++;
}
break;
case 16:
_x <<= 1;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write16(bmp_address, makecol16(RGB_TRIPLET));
addr++;
bmp_address += 2;
}
_y++;
}
break;
case 24:
_x *= 3;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write24(bmp_address, makecol24(RGB_TRIPLET));
addr++;
bmp_address += 3;
}
_y++;
}
break;
case 32:
_x <<= 2;
for (y=0; y<h; y++) {
bmp_address = bmp_write_line(bmp, _y)+_x;
for (x=0; x<w; x++) {
bmp_write32(bmp_address, makeacol32(RGB_TRIPLET, 255));
addr++;
bmp_address += 4;
}
_y++;
}
break;
}
bmp_unwrite_line(bmp);
}
template<>
void ImageImpl<BitmapTraits>::to_allegro(BITMAP *bmp, int _x, int _y) const
{
const_address_t addr;
unsigned long bmp_address;
int depth = bitmap_color_depth(bmp);
div_t d, beg_d = div(0, 8);
int color[2];
int x, y;
bmp_select(bmp);
switch (depth) {
case 8:
color[0] = makecol8(0, 0, 0);
color[1] = makecol8(255, 255, 255);
#if defined GFX_MODEX && !defined ALLEGRO_UNIX
if (is_planar_bitmap(bmp)) {
for (y=0; y<h; y++) {
addr = line_address(y);
bmp_address = (unsigned long)bmp->line[_y];
d = beg_d;
for (x=0; x<w; x++) {
outportw (0x3C4, (0x100<<((_x+x)&3))|2);
bmp_write8(bmp_addr+((_x+x)>>2),
color[((*addr) & (1<<d.rem))? 1: 0]);
_image_bitmap_next_bit(d, addr);
}
_y++;
}
}
else {
#endif
for (y=0; y<h; y++) {
addr = line_address(y);
bmp_address = bmp_write_line(bmp, _y)+_x;
d = beg_d;
for (x=0; x<w; x++) {
bmp_write8 (bmp_address++, color[((*addr) & (1<<d.rem))? 1: 0]);
_image_bitmap_next_bit(d, addr);
}
_y++;
}
#if defined GFX_MODEX && !defined ALLEGRO_UNIX
}
#endif
break;
case 15:
color[0] = makecol15(0, 0, 0);
color[1] = makecol15(255, 255, 255);
_x <<= 1;
for (y=0; y<h; y++) {
addr = line_address(y);
bmp_address = bmp_write_line(bmp, _y)+_x;
d = beg_d;
for (x=0; x<w; x++) {
bmp_write15(bmp_address, color[((*addr) & (1<<d.rem))? 1: 0]);
bmp_address += 2;
_image_bitmap_next_bit(d, addr);
}
_y++;
}
break;
case 16:
color[0] = makecol16(0, 0, 0);
color[1] = makecol16(255, 255, 255);
_x <<= 1;
for (y=0; y<h; y++) {
addr = line_address(y);
bmp_address = bmp_write_line(bmp, _y)+_x;
d = beg_d;
for (x=0; x<w; x++) {
bmp_write16(bmp_address, color[((*addr) & (1<<d.rem))? 1: 0]);
bmp_address += 2;
_image_bitmap_next_bit(d, addr);
}
_y++;
}
break;
case 24:
color[0] = makecol24 (0, 0, 0);
color[1] = makecol24 (255, 255, 255);
_x *= 3;
for (y=0; y<h; y++) {
addr = line_address(y);
bmp_address = bmp_write_line(bmp, _y)+_x;
d = beg_d;
for (x=0; x<w; x++) {
bmp_write24(bmp_address, color[((*addr) & (1<<d.rem))? 1: 0]);
bmp_address += 3;
_image_bitmap_next_bit (d, addr);
}
_y++;
}
break;
case 32:
color[0] = makeacol32 (0, 0, 0, 255);
color[1] = makeacol32 (255, 255, 255, 255);
_x <<= 2;
for (y=0; y<h; y++) {
addr = line_address(y);
bmp_address = bmp_write_line(bmp, _y)+_x;
d = beg_d;
for (x=0; x<w; x++) {
bmp_write32(bmp_address, color[((*addr) & (1<<d.rem))? 1: 0]);
bmp_address += 4;
_image_bitmap_next_bit(d, addr);
}
_y++;
}
break;
}
bmp_unwrite_line(bmp);
}
#endif // RASTER_IMAGE_IMPL_H

View File

@ -27,27 +27,241 @@
#include "modules/palettes.h"
#include "modules/tools.h"
#include "raster/image.h"
#include "raster/image_impl.h"
#include "raster/raster.h"
/************************************************************************/
/* Render engine */
//////////////////////////////////////////////////////////////////////
// zoomed merge
template<class Traits>
class BlenderHelper
{
BLEND_COLOR m_blend_color;
public:
BlenderHelper(int blend_mode)
{
m_blend_color = Traits::get_blender(blend_mode);
}
inline void operator()(typename Traits::address_t& scanline_address,
typename Traits::address_t& dst_address,
typename Traits::address_t& src_address,
int& opacity)
{
*scanline_address = (*m_blend_color)(*dst_address, *src_address, opacity);
}
};
template<>
class BlenderHelper<IndexedTraits>
{
int m_blend_mode;
public:
BlenderHelper(int blend_mode)
{
m_blend_mode = blend_mode;
}
inline void operator()(IndexedTraits::address_t& scanline_address,
IndexedTraits::address_t& dst_address,
IndexedTraits::address_t& src_address,
int& opacity)
{
if (m_blend_mode == BLEND_MODE_COPY) {
*scanline_address = *src_address;
}
else {
if (*src_address) {
if (color_map)
*scanline_address = color_map->data[*src_address][*dst_address];
else
*scanline_address = *src_address;
}
else
*scanline_address = *dst_address;
}
}
};
template<class Traits>
static void merge_zoomed_image(Image *dst, Image *src,
int x, int y, int opacity,
int blend_mode, int zoom)
{
BlenderHelper<Traits> blender(blend_mode);
Traits::address_t src_address;
Traits::address_t dst_address, dst_address_end;
Traits::address_t scanline, scanline_address;
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 offsetx, offsety;
int line_h, bottom;
box_w = 1<<zoom;
box_h = 1<<zoom;
src_x = 0;
src_y = 0;
src_w = src->w;
src_h = src->h;
dst_x = x;
dst_y = y;
dst_w = src->w<<zoom;
dst_h = src->h<<zoom;
// clipping...
if (dst_x < 0) {
src_x += (-dst_x)>>zoom;
src_w -= (-dst_x)>>zoom;
dst_w -= (-dst_x);
offsetx = box_w - ((-dst_x) % box_w);
dst_x = 0;
}
else
offsetx = 0;
if (dst_y < 0) {
src_y += (-dst_y)>>zoom;
src_h -= (-dst_y)>>zoom;
dst_h -= (-dst_y);
offsety = box_h - ((-dst_y) % box_h);
dst_y = 0;
}
else
offsety = 0;
if (dst_x+dst_w > dst->w) {
src_w -= (dst_x+dst_w-dst->w) >> zoom;
dst_w = dst->w - dst_x;
}
if (dst_y+dst_h > dst->h) {
src_h -= (dst_y+dst_h-dst->h) >> zoom;
dst_h = dst->h - 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
scanline = new Traits::pixel_t[src_w];
// for each line to draw of the source image...
for (y=0; y<src_h; y++) {
assert(src_x >= 0 && src_x < src->w);
assert(dst_x >= 0 && dst_x < dst->w);
// get addresses to each line (beginning of 'src', 'dst', etc.)
src_address = ((ImageImpl<Traits>*)src)->line_address(src_y) + src_x;
dst_address = ((ImageImpl<Traits>*)dst)->line_address(dst_y) + dst_x;
dst_address_end = dst_address + dst_w;
scanline_address = scanline;
// read 'src' and 'dst' and blend them, put the result in `scanline'
for (x=0; x<src_w; x++) {
assert(scanline_address >= scanline);
assert(scanline_address < scanline + src_w);
assert(src_address >= ((ImageImpl<Traits>*)src)->line_address(src_y) + src_x);
assert(src_address < ((ImageImpl<Traits>*)src)->line_address(src_y) + src_x + src_w);
assert(dst_address >= ((ImageImpl<Traits>*)dst)->line_address(dst_y) + dst_x);
assert(dst_address < ((ImageImpl<Traits>*)dst)->line_address(dst_y) + dst_x + dst_w);
assert(dst_address < dst_address_end);
blender(scanline_address, dst_address, src_address, opacity);
src_address++;
if (x == 0 && offsetx > 0)
dst_address += offsetx;
else
dst_address += box_w;
scanline_address++;
if (dst_address >= dst_address_end)
break;
}
// get the 'height' of the line to be painted in 'dst'
if ((offsety > 0) && (y == 0))
line_h = offsety;
else
line_h = box_h;
// draw the line in `dst'
for (box_y=0; box_y<line_h; box_y++) {
dst_address = ((ImageImpl<Traits>*)dst)->line_address(dst_y) + dst_x;
dst_address_end = dst_address + dst_w;
scanline_address = scanline;
x = 0;
// first pixel
if (offsetx > 0) {
for (box_x=0; box_x<offsetx; box_x++) {
assert(scanline_address >= scanline);
assert(scanline_address < scanline + src_w);
assert(dst_address >= ((ImageImpl<Traits>*)dst)->line_address(dst_y) + dst_x);
assert(dst_address < ((ImageImpl<Traits>*)dst)->line_address(dst_y) + dst_x + dst_w);
assert(dst_address < dst_address_end);
(*dst_address++) = (*scanline_address);
if (dst_address >= dst_address_end)
goto done_with_line;
}
scanline_address++;
x++;
}
// the rest of the line
for (; x<src_w; x++) {
for (box_x=0; box_x<box_w; box_x++) {
assert(dst_address >= ((ImageImpl<Traits>*)dst)->line_address(dst_y) + dst_x);
assert(dst_address < ((ImageImpl<Traits>*)dst)->line_address(dst_y) + dst_x + dst_w);
(*dst_address++) = (*scanline_address);
if (dst_address >= dst_address_end)
goto done_with_line;
}
scanline_address++;
}
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:;
delete[] scanline;
}
//////////////////////////////////////////////////////////////////////
// Render engine
static int global_opacity = 255;
static Layer *selected_layer = NULL;
static Image *rastering_image = NULL;
static void render_layer(Sprite *sprite, Layer *layer, Image *image,
static void render_layer(Sprite* sprite, Layer* layer, Image* image,
int source_x, int source_y,
int frame, int zoom,
void (*zoomed_func)(Image *, Image *, int, int, int, int, int),
void (*zoomed_func)(Image*, Image*, int, int, int, int, int),
bool render_background,
bool render_transparent);
static void merge_zoomed_image8(Image *dst, Image *src, int x, int y, int opacity, int blend_mode, int zoom);
static void merge_zoomed_image16(Image *dst, Image *src, int x, int y, int opacity, int blend_mode, int zoom);
static void merge_zoomed_image32(Image *dst, Image *src, int x, int y, int opacity, int blend_mode, int zoom);
void set_preview_image(Layer *layer, Image *image)
{
selected_layer = layer;
@ -76,17 +290,17 @@ Image *render_sprite(Sprite *sprite,
case IMAGE_RGB:
depth = 32;
zoomed_func = merge_zoomed_image32;
zoomed_func = merge_zoomed_image<RgbTraits>;
break;
case IMAGE_GRAYSCALE:
depth = 8;
zoomed_func = merge_zoomed_image16;
zoomed_func = merge_zoomed_image<GrayscaleTraits>;
break;
case IMAGE_INDEXED:
depth = 8;
zoomed_func = merge_zoomed_image8;
zoomed_func = merge_zoomed_image<IndexedTraits>;
break;
default:
@ -259,439 +473,3 @@ static void render_layer(Sprite *sprite, Layer *layer, Image *image,
}
}
static void merge_zoomed_image8(Image *dst, Image *src,
int x, int y, int opacity,
int blend_mode, int zoom)
{
ase_uint8 *src_address;
ase_uint8 *dst_address;
ase_uint8 *scanline, *scanline_address;
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 sizeof_box, offsetx, offsety;
int line_x, line_h, right, bottom;
box_w = 1<<zoom;
box_h = 1<<zoom;
src_x = 0;
src_y = 0;
src_w = src->w;
src_h = src->h;
dst_x = x;
dst_y = y;
dst_w = src->w<<zoom;
dst_h = src->h<<zoom;
if (dst_x < 0) {
src_x += (-dst_x)>>zoom;
src_w -= (-dst_x)>>zoom;
dst_w -= (-dst_x);
offsetx = box_w - ((-dst_x) % box_w);
dst_x = 0;
}
else
offsetx = 0;
if (dst_y < 0) {
src_y += (-dst_y)>>zoom;
src_h -= (-dst_y)>>zoom;
dst_h -= (-dst_y);
offsety = box_h - ((-dst_y) % box_h);
dst_y = 0;
}
else
offsety = 0;
if (dst_x+dst_w > dst->w) {
src_w -= (dst_x+dst_w-dst->w) >> zoom;
dst_w = dst->w - dst_x;
}
if (dst_y+dst_h > dst->h) {
src_h -= (dst_y+dst_h-dst->h) >> zoom;
dst_h = dst->h - dst_y;
}
if ((src_w <= 0) || (src_h <= 0) || (dst_w <= 0) || (dst_h <= 0))
return;
sizeof_box = sizeof(ase_uint8) * box_w;
right = dst_x+dst_w-1;
bottom = dst_y+dst_h-1;
scanline = (ase_uint8*)jmalloc(sizeof(ase_uint8) * src_w);
/* merge process */
for (y=0; y<src_h; y++) {
/* process a new line */
src_address = ((ase_uint8 **)src->line)[src_y] + src_x;
dst_address = ((ase_uint8 **)dst->line)[dst_y] + dst_x;
scanline_address = scanline;
/* read `src' and `dst' and blend them, put the result in `scanline' */
for (x=0; x<src_w; x++) {
if (blend_mode == BLEND_MODE_COPY) {
*scanline_address = *src_address;
}
else {
if (*src_address) {
if (color_map)
*scanline_address = color_map->data[*src_address][*dst_address];
else
*scanline_address = *src_address;
}
else
*scanline_address = *dst_address;
}
src_address++;
dst_address += box_w;
scanline_address++;
}
/* get the `height' of the line */
if ((offsety > 0) && (y == 0))
line_h = offsety;
else
line_h = box_h;
/* put the line in `dst' */
for (box_y=0; box_y<line_h; box_y++) {
dst_address = ((ase_uint8 **)dst->line)[dst_y] + dst_x;
scanline_address = scanline;
line_x = dst_x;
x = 0;
/* first pixel */
if (offsetx > 0) {
for (box_x=0; box_x<offsetx; box_x++) {
(*dst_address++) = (*scanline_address);
line_x++;
if (line_x > right)
goto done_with_line;
}
scanline_address++;
x++;
}
/* the rest of the line */
for (; x<src_w; x++) {
for (box_x=0; box_x<box_w; box_x++) {
(*dst_address++) = (*scanline_address);
line_x++;
if (line_x > right)
goto done_with_line;
}
scanline_address++;
}
done_with_line:;
dst_y++;
if (dst_y > bottom)
goto done_with_blit;
}
/* go to the next line */
src_y++;
}
done_with_blit:;
jfree(scanline);
}
static void merge_zoomed_image16(Image *dst, Image *src,
int x, int y, int opacity,
int blend_mode, int zoom)
{
BLEND_COLOR blender;
ase_uint16 *src_address;
ase_uint16 *dst_address;
ase_uint16 *scanline, *scanline_address;
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 sizeof_box, offsetx, offsety;
int line_x, line_h, right, bottom;
blender = GrayscaleTraits::get_blender(blend_mode);
box_w = 1<<zoom;
box_h = 1<<zoom;
src_x = 0;
src_y = 0;
src_w = src->w;
src_h = src->h;
dst_x = x;
dst_y = y;
dst_w = src->w<<zoom;
dst_h = src->h<<zoom;
if (dst_x < 0) {
src_x += (-dst_x)>>zoom;
src_w -= (-dst_x)>>zoom;
dst_w -= (-dst_x);
offsetx = box_w - ((-dst_x) % box_w);
dst_x = 0;
}
else
offsetx = 0;
if (dst_y < 0) {
src_y += (-dst_y)>>zoom;
src_h -= (-dst_y)>>zoom;
dst_h -= (-dst_y);
offsety = box_h - ((-dst_y) % box_h);
dst_y = 0;
}
else
offsety = 0;
if (dst_x+dst_w > dst->w) {
src_w -= (dst_x+dst_w-dst->w) >> zoom;
dst_w = dst->w - dst_x;
}
if (dst_y+dst_h > dst->h) {
src_h -= (dst_y+dst_h-dst->h) >> zoom;
dst_h = dst->h - dst_y;
}
if ((src_w <= 0) || (src_h <= 0) || (dst_w <= 0) || (dst_h <= 0))
return;
sizeof_box = sizeof(ase_uint16) * box_w;
right = dst_x+dst_w-1;
bottom = dst_y+dst_h-1;
scanline = (ase_uint16*)jmalloc(sizeof(ase_uint16) * src_w);
/* merge process */
/* opacity = (opacity)? opacity+1: 0; */
for (y=0; y<src_h; y++) {
/* process a new line */
src_address = ((ase_uint16 **)src->line)[src_y] + src_x;
dst_address = ((ase_uint16 **)dst->line)[dst_y] + dst_x;
scanline_address = scanline;
/* read `src' and `dst' and blend them, put the result in `scanline' */
for (x=0; x<src_w; x++) {
*scanline_address = (*blender)(*dst_address, *src_address, opacity);
src_address++;
dst_address += box_w;
scanline_address++;
}
/* get the `height' of the line */
if ((offsety > 0) && (y == 0))
line_h = offsety;
else
line_h = box_h;
/* put the line in `dst' */
for (box_y=0; box_y<line_h; box_y++) {
dst_address = ((ase_uint16 **)dst->line)[dst_y] + dst_x;
scanline_address = scanline;
line_x = dst_x;
x = 0;
/* first pixel */
if (offsetx > 0) {
for (box_x=0; box_x<offsetx; box_x++) {
(*dst_address++) = (*scanline_address);
line_x++;
if (line_x > right)
goto done_with_line;
}
scanline_address++;
x++;
}
/* the rest of the line */
for (; x<src_w; x++) {
for (box_x=0; box_x<box_w; box_x++) {
(*dst_address++) = (*scanline_address);
line_x++;
if (line_x > right)
goto done_with_line;
}
scanline_address++;
}
done_with_line:;
dst_y++;
if (dst_y > bottom)
goto done_with_blit;
}
/* go to the next line */
src_y++;
}
done_with_blit:;
jfree(scanline);
}
static void merge_zoomed_image32(Image *dst, Image *src,
int x, int y, int opacity,
int blend_mode, int zoom)
{
BLEND_COLOR blender;
ase_uint32 *src_address;
ase_uint32 *dst_address;
ase_uint32 *scanline, *scanline_address;
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 sizeof_box, offsetx, offsety;
int line_x, line_h, right, bottom;
blender = RgbTraits::get_blender(blend_mode);
box_w = 1<<zoom;
box_h = 1<<zoom;
src_x = 0;
src_y = 0;
src_w = src->w;
src_h = src->h;
dst_x = x;
dst_y = y;
dst_w = src->w<<zoom;
dst_h = src->h<<zoom;
if (dst_x < 0) {
src_x += (-dst_x)>>zoom;
src_w -= (-dst_x)>>zoom;
dst_w -= (-dst_x);
offsetx = box_w - ((-dst_x) % box_w);
dst_x = 0;
}
else
offsetx = 0;
if (dst_y < 0) {
src_y += (-dst_y)>>zoom;
src_h -= (-dst_y)>>zoom;
dst_h -= (-dst_y);
offsety = box_h - ((-dst_y) % box_h);
dst_y = 0;
}
else
offsety = 0;
if (dst_x+dst_w > dst->w) {
src_w -= (dst_x+dst_w-dst->w) >> zoom;
dst_w = dst->w - dst_x;
}
if (dst_y+dst_h > dst->h) {
src_h -= (dst_y+dst_h-dst->h) >> zoom;
dst_h = dst->h - dst_y;
}
if ((src_w <= 0) || (src_h <= 0) || (dst_w <= 0) || (dst_h <= 0))
return;
sizeof_box = sizeof(ase_uint32) * box_w;
right = dst_x+dst_w-1;
bottom = dst_y+dst_h-1;
scanline = (ase_uint32*)jmalloc(sizeof(ase_uint32) * src_w);
/* merge process */
/* opacity = (opacity)? opacity+1: 0; */
for (y=0; y<src_h; y++) {
/* process a new line */
src_address = ((ase_uint32 **)src->line)[src_y] + src_x;
dst_address = ((ase_uint32 **)dst->line)[dst_y] + dst_x;
scanline_address = scanline;
/* read `src' and `dst' and blend them, put the result in `scanline' */
for (x=0; x<src_w; x++) {
*scanline_address = (*blender)(*dst_address, *src_address, opacity);
src_address++;
dst_address += box_w;
scanline_address++;
}
/* get the `height' of the line */
if ((offsety > 0) && (y == 0))
line_h = offsety;
else
line_h = box_h;
/* put the line in `dst' */
for (box_y=0; box_y<line_h; box_y++) {
dst_address = ((ase_uint32 **)dst->line)[dst_y] + dst_x;
scanline_address = scanline;
line_x = dst_x;
x = 0;
/* first pixel */
if (offsetx > 0) {
for (box_x=0; box_x<offsetx; box_x++) {
(*dst_address++) = (*scanline_address);
line_x++;
if (line_x > right)
goto done_with_line;
}
scanline_address++;
x++;
}
/* the rest of the line */
for (; x<src_w; x++) {
for (box_x=0; box_x<box_w; box_x++) {
(*dst_address++) = (*scanline_address);
line_x++;
if (line_x > right)
goto done_with_line;
}
scanline_address++;
}
done_with_line:;
dst_y++;
if (dst_y > bottom)
goto done_with_blit;
}
/* go to the next line */
src_y++;
}
done_with_blit:;
jfree(scanline);
}