mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-18 07:21:09 +00:00
Encapsulate Image implementation (private members, accessors, iterators, etc.)
- Rename _rgba/_graya to raster::rgba()/graya() - Add raster::color_t type (alias for uint32_t) - Rename raster::GfxObj to Object. And GfxObj::getType() to Object::type() - Move conversion from raster::Image/Palette to Allegro BITMAP/RGB to raster/conversion_alleg.h file - Add raster/color_scales.h - Rename image_* functions to raster/primitives.h - Reimplement ink processing with templates instead of macros
This commit is contained in:
parent
7657461162
commit
e5ba8e0922
2
TODO.md
2
TODO.md
@ -1,5 +1,7 @@
|
||||
# Very high priority (next release?)
|
||||
|
||||
* Remove Image::getPixelAddress() shouldn't be public, and almost
|
||||
everywhere we should use iterators for images.
|
||||
* Warning icon when selecting RGB/HSB color in indexed image.
|
||||
* Warning message when we open a file that is already opened file
|
||||
(show an option to create a second view, or maybe this should
|
||||
|
@ -145,9 +145,8 @@ else()
|
||||
endif()
|
||||
|
||||
######################################################################
|
||||
# ASEPRITE libraries
|
||||
# Aseprite Libraries (in preferred order to be built)
|
||||
|
||||
add_subdirectory(app)
|
||||
add_subdirectory(base)
|
||||
add_subdirectory(filters)
|
||||
add_subdirectory(gfx)
|
||||
@ -157,6 +156,8 @@ add_subdirectory(she)
|
||||
add_subdirectory(ui)
|
||||
add_subdirectory(undo)
|
||||
|
||||
add_subdirectory(app)
|
||||
|
||||
if(V8_FOUND)
|
||||
list(APPEND libs3rdparty ${V8_LIBRARIES})
|
||||
endif()
|
||||
@ -242,6 +243,7 @@ endfunction()
|
||||
|
||||
find_unittests(base base-lib ${sys_libs})
|
||||
find_unittests(gfx gfx-lib base-lib ${sys_libs})
|
||||
find_unittests(raster raster-lib gfx-lib base-lib ${libs3rdparty} ${sys_libs})
|
||||
find_unittests(ui ui-lib she gfx-lib base-lib ${libs3rdparty} ${sys_libs})
|
||||
find_unittests(file ${all_libs})
|
||||
find_unittests(app ${all_libs})
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "gfx/rgb.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/primitives.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iomanip>
|
||||
@ -83,23 +84,23 @@ Color Color::fromIndex(int index)
|
||||
}
|
||||
|
||||
// static
|
||||
Color Color::fromImage(PixelFormat pixelFormat, int c)
|
||||
Color Color::fromImage(PixelFormat pixelFormat, color_t 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));
|
||||
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));
|
||||
if (graya_geta(c) > 0) {
|
||||
color = Color::fromGray(graya_getv(c));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -114,8 +115,8 @@ Color Color::fromImage(PixelFormat pixelFormat, int c)
|
||||
// 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));
|
||||
if ((x >= 0) && (y >= 0) && (x < image->getWidth()) && (y < image->getHeight()))
|
||||
return Color::fromImage(image->getPixelFormat(), raster::get_pixel(image, x, y));
|
||||
else
|
||||
return Color::fromMask();
|
||||
}
|
||||
@ -245,9 +246,9 @@ std::string Color::toHumanReadableString(PixelFormat pixelFormat, HumanReadableS
|
||||
uint32_t _c = get_current_palette()->getEntry(i);
|
||||
result << "Index " << i
|
||||
<< " (RGB "
|
||||
<< (int)_rgba_getr(_c) << " "
|
||||
<< (int)_rgba_getg(_c) << " "
|
||||
<< (int)_rgba_getb(_c) << ")";
|
||||
<< (int)rgba_getr(_c) << " "
|
||||
<< (int)rgba_getg(_c) << " "
|
||||
<< (int)rgba_getb(_c) << ")";
|
||||
}
|
||||
else {
|
||||
result << "Index "
|
||||
@ -381,7 +382,7 @@ int Color::getRed() const
|
||||
int i = m_value.index;
|
||||
ASSERT(i >= 0 && i < get_current_palette()->size());
|
||||
|
||||
return _rgba_getr(get_current_palette()->getEntry(i));
|
||||
return rgba_getr(get_current_palette()->getEntry(i));
|
||||
}
|
||||
|
||||
}
|
||||
@ -412,7 +413,7 @@ int Color::getGreen() const
|
||||
int i = m_value.index;
|
||||
ASSERT(i >= 0 && i < get_current_palette()->size());
|
||||
|
||||
return _rgba_getg(get_current_palette()->getEntry(i));
|
||||
return rgba_getg(get_current_palette()->getEntry(i));
|
||||
}
|
||||
|
||||
}
|
||||
@ -443,7 +444,7 @@ int Color::getBlue() const
|
||||
int i = m_value.index;
|
||||
ASSERT(i >= 0 && i < get_current_palette()->size());
|
||||
|
||||
return _rgba_getb(get_current_palette()->getEntry(i));
|
||||
return rgba_getb(get_current_palette()->getEntry(i));
|
||||
}
|
||||
|
||||
}
|
||||
@ -476,9 +477,9 @@ int Color::getHue() const
|
||||
|
||||
uint32_t c = get_current_palette()->getEntry(i);
|
||||
|
||||
return Hsv(Rgb(_rgba_getr(c),
|
||||
_rgba_getg(c),
|
||||
_rgba_getb(c))).hueInt();
|
||||
return Hsv(Rgb(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c))).hueInt();
|
||||
}
|
||||
|
||||
}
|
||||
@ -511,9 +512,9 @@ int Color::getSaturation() const
|
||||
|
||||
uint32_t c = get_current_palette()->getEntry(i);
|
||||
|
||||
return Hsv(Rgb(_rgba_getr(c),
|
||||
_rgba_getg(c),
|
||||
_rgba_getb(c))).saturationInt();
|
||||
return Hsv(Rgb(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c))).saturationInt();
|
||||
}
|
||||
|
||||
}
|
||||
@ -546,9 +547,9 @@ int Color::getValue() const
|
||||
|
||||
uint32_t c = get_current_palette()->getEntry(i);
|
||||
|
||||
return Hsv(Rgb(_rgba_getr(c),
|
||||
_rgba_getg(c),
|
||||
_rgba_getb(c))).valueInt();
|
||||
return Hsv(Rgb(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c))).valueInt();
|
||||
}
|
||||
|
||||
}
|
||||
@ -581,9 +582,9 @@ int Color::getGray() const
|
||||
|
||||
uint32_t c = get_current_palette()->getEntry(i);
|
||||
|
||||
return 255 * Hsv(Rgb(_rgba_getr(c),
|
||||
_rgba_getg(c),
|
||||
_rgba_getb(c))).valueInt() / 100;
|
||||
return 255 * Hsv(Rgb(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c))).valueInt() / 100;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#ifndef APP_COLOR_H_INCLUDED
|
||||
#define APP_COLOR_H_INCLUDED
|
||||
|
||||
#include "raster/color.h"
|
||||
#include "raster/pixel_format.h"
|
||||
|
||||
#include <string>
|
||||
@ -56,7 +57,7 @@ namespace app {
|
||||
static Color fromGray(int g);
|
||||
static Color fromIndex(int index);
|
||||
|
||||
static Color fromImage(PixelFormat pixelFormat, int pixel);
|
||||
static Color fromImage(PixelFormat pixelFormat, color_t c);
|
||||
static Color fromImageGetPixel(Image* image, int x, int y);
|
||||
static Color fromString(const std::string& str);
|
||||
|
||||
|
@ -100,9 +100,9 @@ ui::Color color_utils::color_for_ui(const app::Color& color)
|
||||
ASSERT(i >= 0 && i < (int)get_current_palette()->size());
|
||||
|
||||
uint32_t _c = get_current_palette()->getEntry(i);
|
||||
c = ui::rgba(_rgba_getr(_c),
|
||||
_rgba_getg(_c),
|
||||
_rgba_getb(_c), 255);
|
||||
c = ui::rgba(rgba_getr(_c),
|
||||
rgba_getg(_c),
|
||||
rgba_getb(_c), 255);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -142,9 +142,9 @@ int color_utils::color_for_allegro(const app::Color& color, int depth)
|
||||
|
||||
uint32_t _c = get_current_palette()->getEntry(c);
|
||||
c = makeacol_depth(depth,
|
||||
_rgba_getr(_c),
|
||||
_rgba_getg(_c),
|
||||
_rgba_getb(_c), 255);
|
||||
rgba_getr(_c),
|
||||
rgba_getg(_c),
|
||||
rgba_getb(_c), 255);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -153,19 +153,19 @@ int color_utils::color_for_allegro(const app::Color& color, int depth)
|
||||
return c;
|
||||
}
|
||||
|
||||
int color_utils::color_for_image(const app::Color& color, PixelFormat format)
|
||||
raster::color_t color_utils::color_for_image(const app::Color& color, PixelFormat format)
|
||||
{
|
||||
if (color.getType() == app::Color::MaskType)
|
||||
return 0;
|
||||
|
||||
int c = -1;
|
||||
raster::color_t c = -1;
|
||||
|
||||
switch (format) {
|
||||
case IMAGE_RGB:
|
||||
c = _rgba(color.getRed(), color.getGreen(), color.getBlue(), 255);
|
||||
c = rgba(color.getRed(), color.getGreen(), color.getBlue(), 255);
|
||||
break;
|
||||
case IMAGE_GRAYSCALE:
|
||||
c = _graya(color.getGray(), 255);
|
||||
c = graya(color.getGray(), 255);
|
||||
break;
|
||||
case IMAGE_INDEXED:
|
||||
if (color.getType() == app::Color::IndexType)
|
||||
@ -178,9 +178,9 @@ int color_utils::color_for_image(const app::Color& color, PixelFormat format)
|
||||
return c;
|
||||
}
|
||||
|
||||
int color_utils::color_for_layer(const app::Color& color, Layer* layer)
|
||||
raster::color_t color_utils::color_for_layer(const app::Color& color, Layer* layer)
|
||||
{
|
||||
int pixel_color;
|
||||
raster::color_t pixel_color;
|
||||
|
||||
if (color.getType() == app::Color::MaskType) {
|
||||
pixel_color = layer->getSprite()->getTransparentColor();
|
||||
@ -193,7 +193,7 @@ int color_utils::color_for_layer(const app::Color& color, Layer* layer)
|
||||
return fixup_color_for_layer(layer, pixel_color);
|
||||
}
|
||||
|
||||
int color_utils::fixup_color_for_layer(Layer *layer, int color)
|
||||
raster::color_t color_utils::fixup_color_for_layer(Layer *layer, raster::color_t color)
|
||||
{
|
||||
if (layer->isBackground())
|
||||
return fixup_color_for_background(layer->getSprite()->getPixelFormat(), color);
|
||||
@ -201,19 +201,19 @@ int color_utils::fixup_color_for_layer(Layer *layer, int color)
|
||||
return color;
|
||||
}
|
||||
|
||||
int color_utils::fixup_color_for_background(PixelFormat format, int color)
|
||||
raster::color_t color_utils::fixup_color_for_background(PixelFormat format, raster::color_t color)
|
||||
{
|
||||
switch (format) {
|
||||
case IMAGE_RGB:
|
||||
if (_rgba_geta(color) < 255) {
|
||||
return _rgba(_rgba_getr(color),
|
||||
_rgba_getg(color),
|
||||
_rgba_getb(color), 255);
|
||||
if (rgba_geta(color) < 255) {
|
||||
return rgba(rgba_getr(color),
|
||||
rgba_getg(color),
|
||||
rgba_getb(color), 255);
|
||||
}
|
||||
break;
|
||||
case IMAGE_GRAYSCALE:
|
||||
if (_graya_geta(color) < 255) {
|
||||
return _graya(_graya_getv(color), 255);
|
||||
if (graya_geta(color) < 255) {
|
||||
return graya(graya_getv(color), 255);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define APP_COLOR_UTILS_H_INCLUDED
|
||||
|
||||
#include "app/color.h"
|
||||
#include "raster/color.h"
|
||||
#include "raster/pixel_format.h"
|
||||
#include "ui/color.h"
|
||||
|
||||
@ -35,11 +36,11 @@ namespace app {
|
||||
|
||||
ui::Color color_for_ui(const app::Color& color);
|
||||
int color_for_allegro(const app::Color& color, int depth);
|
||||
int color_for_image(const app::Color& color, raster::PixelFormat format);
|
||||
int color_for_layer(const app::Color& color, raster::Layer* layer);
|
||||
raster::color_t color_for_image(const app::Color& color, raster::PixelFormat format);
|
||||
raster::color_t color_for_layer(const app::Color& color, raster::Layer* layer);
|
||||
|
||||
int fixup_color_for_layer(raster::Layer* layer, int color);
|
||||
int fixup_color_for_background(raster::PixelFormat format, int color);
|
||||
raster::color_t fixup_color_for_layer(raster::Layer* layer, raster::color_t color);
|
||||
raster::color_t fixup_color_for_background(raster::PixelFormat format, raster::color_t color);
|
||||
|
||||
} // namespace color_utils
|
||||
} // namespace app
|
||||
|
@ -99,14 +99,12 @@ void CelPropertiesCommand::onExecute(Context* context)
|
||||
label_pos->setTextf("%d, %d", cel->getX(), cel->getY());
|
||||
|
||||
// Dimension (and memory size)
|
||||
int memsize =
|
||||
image_line_size(sprite->getStock()->getImage(cel->getImage()),
|
||||
sprite->getStock()->getImage(cel->getImage())->w)*
|
||||
sprite->getStock()->getImage(cel->getImage())->h;
|
||||
Image* image = sprite->getStock()->getImage(cel->getImage());
|
||||
int memsize = image->getRowStrideSize() * image->getHeight();
|
||||
|
||||
label_size->setTextf("%dx%d (%s)",
|
||||
sprite->getStock()->getImage(cel->getImage())->w,
|
||||
sprite->getStock()->getImage(cel->getImage())->h,
|
||||
sprite->getStock()->getImage(cel->getImage())->getWidth(),
|
||||
sprite->getStock()->getImage(cel->getImage())->getHeight(),
|
||||
base::get_pretty_memory_size(memsize).c_str());
|
||||
|
||||
// Opacity
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "raster/image.h"
|
||||
#include "raster/layer.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/primitives.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "raster/stock.h"
|
||||
#include "ui/ui.h"
|
||||
@ -146,7 +147,7 @@ protected:
|
||||
int sheet_h = sprite->getHeight()*((nframes/columns)+((nframes%columns)>0?1:0));
|
||||
base::UniquePtr<Image> resultImage(Image::create(sprite->getPixelFormat(), sheet_w, sheet_h));
|
||||
base::UniquePtr<Image> tempImage(Image::create(sprite->getPixelFormat(), sprite->getWidth(), sprite->getHeight()));
|
||||
image_clear(resultImage, 0);
|
||||
raster::clear_image(resultImage, 0);
|
||||
|
||||
int column = 0, row = 0;
|
||||
for (FrameNumber frame(0); frame<nframes; ++frame) {
|
||||
|
@ -89,8 +89,7 @@ void FlipCommand::onExecute(Context* context)
|
||||
bool alreadyFlipped = false;
|
||||
|
||||
// This variable will be the area to be flipped inside the image.
|
||||
gfx::Rect bounds(gfx::Point(0, 0),
|
||||
gfx::Size(image->w, image->h));
|
||||
gfx::Rect bounds(image->getBounds());
|
||||
|
||||
// If there is some portion of sprite selected, we flip the
|
||||
// selected region only. If the mask isn't visible, we flip the
|
||||
@ -122,8 +121,7 @@ void FlipCommand::onExecute(Context* context)
|
||||
base::UniquePtr<Mask> newMask(new Mask(*mask));
|
||||
newMask->freeze();
|
||||
raster::algorithm::flip_image(newMask->getBitmap(),
|
||||
gfx::Rect(gfx::Point(0, 0),
|
||||
gfx::Size(maskBitmap->w, maskBitmap->h)),
|
||||
maskBitmap->getBounds(),
|
||||
m_flipType);
|
||||
newMask->unfreeze();
|
||||
|
||||
@ -153,13 +151,13 @@ void FlipCommand::onExecute(Context* context)
|
||||
api.setCelPosition
|
||||
(sprite, cel,
|
||||
(m_flipType == raster::algorithm::FlipHorizontal ?
|
||||
sprite->getWidth() - image->w - cel->getX():
|
||||
sprite->getWidth() - image->getWidth() - cel->getX():
|
||||
cel->getX()),
|
||||
(m_flipType == raster::algorithm::FlipVertical ?
|
||||
sprite->getHeight() - image->h - cel->getY():
|
||||
sprite->getHeight() - image->getHeight() - cel->getY():
|
||||
cel->getY()));
|
||||
|
||||
api.flipImage(image, gfx::Rect(0, 0, image->w, image->h), m_flipType);
|
||||
api.flipImage(image, image->getBounds(), m_flipType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "raster/image.h"
|
||||
#include "raster/layer.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/primitives.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "raster/stock.h"
|
||||
#include "ui/ui.h"
|
||||
@ -168,7 +169,7 @@ protected:
|
||||
base::UniquePtr<Image> resultImage(Image::create(sprite->getPixelFormat(), m_rect.w, m_rect.h));
|
||||
|
||||
// Clear the image with mask color.
|
||||
image_clear(resultImage, 0);
|
||||
raster::clear_image(resultImage, 0);
|
||||
|
||||
// Render the portion of sheet.
|
||||
sprite->render(resultImage, -x, -y, currentFrame);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "base/unique_ptr.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/primitives.h"
|
||||
#include "raster/sprite.h"
|
||||
|
||||
namespace app {
|
||||
@ -89,19 +90,19 @@ void InvertMaskCommand::onExecute(Context* context)
|
||||
|
||||
/* remove in the new mask the current sprite marked region */
|
||||
const gfx::Rect& maskBounds = document->getMask()->getBounds();
|
||||
image_rectfill(mask->getBitmap(),
|
||||
maskBounds.x, maskBounds.y,
|
||||
maskBounds.x + maskBounds.w-1,
|
||||
maskBounds.y + maskBounds.h-1, 0);
|
||||
raster::fill_rect(mask->getBitmap(),
|
||||
maskBounds.x, maskBounds.y,
|
||||
maskBounds.x + maskBounds.w-1,
|
||||
maskBounds.y + maskBounds.h-1, 0);
|
||||
|
||||
// Invert the current mask in the sprite
|
||||
document->getMask()->invert();
|
||||
if (document->getMask()->getBitmap()) {
|
||||
// Copy the inverted region in the new mask
|
||||
image_copy(mask->getBitmap(),
|
||||
document->getMask()->getBitmap(),
|
||||
document->getMask()->getBounds().x,
|
||||
document->getMask()->getBounds().y);
|
||||
raster::copy_image(mask->getBitmap(),
|
||||
document->getMask()->getBitmap(),
|
||||
document->getMask()->getBounds().x,
|
||||
document->getMask()->getBounds().y);
|
||||
}
|
||||
|
||||
// We need only need the area inside the sprite
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "raster/cel.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/layer.h"
|
||||
#include "raster/primitives.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "raster/stock.h"
|
||||
#include "ui/ui.h"
|
||||
@ -146,22 +147,22 @@ void MergeDownLayerCommand::onExecute(Context* context)
|
||||
else {
|
||||
x1 = MIN(src_cel->getX(), dst_cel->getX());
|
||||
y1 = MIN(src_cel->getY(), dst_cel->getY());
|
||||
x2 = MAX(src_cel->getX()+src_image->w-1, dst_cel->getX()+dst_image->w-1);
|
||||
y2 = MAX(src_cel->getY()+src_image->h-1, dst_cel->getY()+dst_image->h-1);
|
||||
x2 = MAX(src_cel->getX()+src_image->getWidth()-1, dst_cel->getX()+dst_image->getWidth()-1);
|
||||
y2 = MAX(src_cel->getY()+src_image->getHeight()-1, dst_cel->getY()+dst_image->getHeight()-1);
|
||||
bgcolor = 0;
|
||||
}
|
||||
|
||||
new_image = image_crop(dst_image,
|
||||
x1-dst_cel->getX(),
|
||||
y1-dst_cel->getY(),
|
||||
x2-x1+1, y2-y1+1, bgcolor);
|
||||
new_image = raster::crop_image(dst_image,
|
||||
x1-dst_cel->getX(),
|
||||
y1-dst_cel->getY(),
|
||||
x2-x1+1, y2-y1+1, bgcolor);
|
||||
|
||||
// Merge src_image in new_image
|
||||
image_merge(new_image, src_image,
|
||||
src_cel->getX()-x1,
|
||||
src_cel->getY()-y1,
|
||||
src_cel->getOpacity(),
|
||||
static_cast<LayerImage*>(src_layer)->getBlendMode());
|
||||
raster::composite_image(new_image, src_image,
|
||||
src_cel->getX()-x1,
|
||||
src_cel->getY()-y1,
|
||||
src_cel->getOpacity(),
|
||||
static_cast<LayerImage*>(src_layer)->getBlendMode());
|
||||
|
||||
if (undo.isEnabled())
|
||||
undo.pushUndoer(new undoers::SetCelPosition(undo.getObjects(), dst_cel));
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "raster/image.h"
|
||||
#include "raster/layer.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/primitives.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "raster/stock.h"
|
||||
#include "ui/ui.h"
|
||||
@ -189,7 +190,7 @@ void NewFileCommand::onExecute(Context* context)
|
||||
layerImage->configureAsBackground();
|
||||
|
||||
Image* image = sprite->getStock()->getImage(layerImage->getCel(FrameNumber(0))->getImage());
|
||||
image_clear(image, color_utils::color_for_image(color, format));
|
||||
raster::clear_image(image, color_utils::color_for_image(color, format));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -666,9 +666,9 @@ void PaletteEntryEditor::setPaletteEntry(const app::Color& color)
|
||||
PaletteView::SelectedEntries entries;
|
||||
palView->getSelectedEntries(entries);
|
||||
|
||||
uint32_t new_pal_color = _rgba(color.getRed(),
|
||||
color.getGreen(),
|
||||
color.getBlue(), 255);
|
||||
color_t new_pal_color = raster::rgba(color.getRed(),
|
||||
color.getGreen(),
|
||||
color.getBlue(), 255);
|
||||
|
||||
Palette* palette = get_current_palette();
|
||||
for (int c=0; c<palette->size(); c++) {
|
||||
@ -695,9 +695,9 @@ void PaletteEntryEditor::setPaletteEntryChannel(const app::Color& color, ColorSl
|
||||
if (entries[c]) {
|
||||
// Get the current RGB values of the palette entry
|
||||
src_color = palette->getEntry(c);
|
||||
r = _rgba_getr(src_color);
|
||||
g = _rgba_getg(src_color);
|
||||
b = _rgba_getb(src_color);
|
||||
r = rgba_getr(src_color);
|
||||
g = rgba_getg(src_color);
|
||||
b = rgba_getb(src_color);
|
||||
|
||||
switch (color.getType()) {
|
||||
|
||||
@ -762,7 +762,7 @@ void PaletteEntryEditor::setPaletteEntryChannel(const app::Color& color, ColorSl
|
||||
break;
|
||||
}
|
||||
|
||||
palette->setEntry(c, _rgba(r, g, b, 255));
|
||||
palette->setEntry(c, raster::rgba(r, g, b, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "app/settings/document_settings.h"
|
||||
#include "app/settings/settings.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "raster/conversion_alleg.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/sprite.h"
|
||||
@ -81,7 +82,6 @@ void PlayAnimationCommand::onExecute(Context* context)
|
||||
IDocumentSettings* docSettings = context->getSettings()->getDocumentSettings(document);
|
||||
bool onionskin_state = docSettings->getUseOnionskin();
|
||||
Palette *oldpal, *newpal;
|
||||
PALETTE rgbpal;
|
||||
|
||||
if (sprite->getTotalFrames() < 2)
|
||||
return;
|
||||
@ -113,7 +113,8 @@ void PlayAnimationCommand::onExecute(Context* context)
|
||||
|
||||
newpal = sprite->getPalette(current_editor->getFrame());
|
||||
if (oldpal != newpal) {
|
||||
newpal->toAllegro(rgbpal);
|
||||
PALETTE rgbpal;
|
||||
raster::convert_palette_to_allegro(newpal, rgbpal);
|
||||
set_palette(rgbpal);
|
||||
oldpal = newpal;
|
||||
}
|
||||
|
@ -37,8 +37,10 @@
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/ui/status_bar.h"
|
||||
#include "app/util/render.h"
|
||||
#include "raster/conversion_alleg.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/primitives.h"
|
||||
#include "raster/sprite.h"
|
||||
|
||||
#define PREVIEW_TILED 1
|
||||
@ -158,7 +160,7 @@ void PreviewCommand::onExecute(Context* context)
|
||||
if (index_bg_color == -1)
|
||||
RenderEngine::renderCheckedBackground(doublebuf, -pos_x, -pos_y, zoom);
|
||||
else
|
||||
image_clear(doublebuf, pal->getEntry(index_bg_color));
|
||||
raster::clear_image(doublebuf, pal->getEntry(index_bg_color));
|
||||
|
||||
switch (tiled) {
|
||||
case TILED_NONE:
|
||||
@ -179,7 +181,7 @@ void PreviewCommand::onExecute(Context* context)
|
||||
break;
|
||||
}
|
||||
|
||||
image_to_allegro(doublebuf, ji_screen, 0, 0, pal);
|
||||
raster::convert_image_to_allegro(doublebuf, ji_screen, 0, 0, pal);
|
||||
}
|
||||
|
||||
// It is necessary in case ji_screen is double-bufferred
|
||||
|
@ -94,14 +94,18 @@ protected:
|
||||
switch (m_angle) {
|
||||
case 180:
|
||||
api.setCelPosition(m_sprite, cel,
|
||||
m_sprite->getWidth() - cel->getX() - image->w,
|
||||
m_sprite->getHeight() - cel->getY() - image->h);
|
||||
m_sprite->getWidth() - cel->getX() - image->getWidth(),
|
||||
m_sprite->getHeight() - cel->getY() - image->getHeight());
|
||||
break;
|
||||
case 90:
|
||||
api.setCelPosition(m_sprite, cel, m_sprite->getHeight() - cel->getY() - image->h, cel->getX());
|
||||
api.setCelPosition(m_sprite, cel,
|
||||
m_sprite->getHeight() - cel->getY() - image->getHeight(),
|
||||
cel->getX());
|
||||
break;
|
||||
case -90:
|
||||
api.setCelPosition(m_sprite, cel, cel->getY(), m_sprite->getWidth() - cel->getX() - image->w);
|
||||
api.setCelPosition(m_sprite, cel,
|
||||
cel->getY(),
|
||||
m_sprite->getWidth() - cel->getX() - image->getWidth());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -114,9 +118,9 @@ protected:
|
||||
|
||||
// rotate the image
|
||||
Image* new_image = Image::create(image->getPixelFormat(),
|
||||
m_angle == 180 ? image->w: image->h,
|
||||
m_angle == 180 ? image->h: image->w);
|
||||
image_rotate(image, new_image, m_angle);
|
||||
m_angle == 180 ? image->getWidth(): image->getHeight(),
|
||||
m_angle == 180 ? image->getHeight(): image->getWidth());
|
||||
raster::rotate_image(image, new_image, m_angle);
|
||||
|
||||
api.replaceStockImage(m_sprite, i, new_image);
|
||||
|
||||
@ -153,7 +157,7 @@ protected:
|
||||
new_mask->replace(x, y,
|
||||
m_angle == 180 ? origBounds.w: origBounds.h,
|
||||
m_angle == 180 ? origBounds.h: origBounds.w);
|
||||
image_rotate(origMask->getBitmap(), new_mask->getBitmap(), m_angle);
|
||||
raster::rotate_image(origMask->getBitmap(), new_mask->getBitmap(), m_angle);
|
||||
|
||||
// Copy new mask
|
||||
api.copyToCurrentMask(new_mask);
|
||||
|
@ -33,9 +33,11 @@
|
||||
#include "app/undo_transaction.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/unique_ptr.h"
|
||||
#include "raster/algorithm/resize_image.h"
|
||||
#include "raster/cel.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/primitives.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "raster/stock.h"
|
||||
#include "ui/ui.h"
|
||||
@ -47,6 +49,7 @@
|
||||
namespace app {
|
||||
|
||||
using namespace ui;
|
||||
using raster::algorithm::ResizeMethod;
|
||||
|
||||
class SpriteSizeJob : public Job {
|
||||
ContextWriter m_writer;
|
||||
@ -100,15 +103,15 @@ protected:
|
||||
continue;
|
||||
|
||||
// Resize the image
|
||||
int w = scale_x(image->w);
|
||||
int h = scale_y(image->h);
|
||||
int w = scale_x(image->getWidth());
|
||||
int h = scale_y(image->getHeight());
|
||||
Image* new_image = Image::create(image->getPixelFormat(), MAX(1, w), MAX(1, h));
|
||||
|
||||
image_fixup_transparent_colors(image);
|
||||
image_resize(image, new_image,
|
||||
m_resize_method,
|
||||
m_sprite->getPalette(cel->getFrame()),
|
||||
m_sprite->getRgbMap(cel->getFrame()));
|
||||
raster::algorithm::fixup_image_transparent_colors(image);
|
||||
raster::algorithm::resize_image(image, new_image,
|
||||
m_resize_method,
|
||||
m_sprite->getPalette(cel->getFrame()),
|
||||
m_sprite->getRgbMap(cel->getFrame()));
|
||||
|
||||
api.replaceStockImage(m_sprite, cel->getImage(), new_image);
|
||||
|
||||
@ -122,23 +125,22 @@ protected:
|
||||
// Resize mask
|
||||
if (m_document->isMaskVisible()) {
|
||||
base::UniquePtr<Image> old_bitmap
|
||||
(image_crop(m_document->getMask()->getBitmap(), -1, -1,
|
||||
m_document->getMask()->getBitmap()->w+2,
|
||||
m_document->getMask()->getBitmap()->h+2, 0));
|
||||
(crop_image(m_document->getMask()->getBitmap(), -1, -1,
|
||||
m_document->getMask()->getBitmap()->getWidth()+2,
|
||||
m_document->getMask()->getBitmap()->getHeight()+2, 0));
|
||||
|
||||
int w = scale_x(old_bitmap->w);
|
||||
int h = scale_y(old_bitmap->h);
|
||||
int w = scale_x(old_bitmap->getWidth());
|
||||
int h = scale_y(old_bitmap->getHeight());
|
||||
base::UniquePtr<Mask> new_mask(new Mask);
|
||||
new_mask->replace(scale_x(m_document->getMask()->getBounds().x-1),
|
||||
scale_y(m_document->getMask()->getBounds().y-1), MAX(1, w), MAX(1, h));
|
||||
image_resize(old_bitmap, new_mask->getBitmap(),
|
||||
m_resize_method,
|
||||
m_sprite->getPalette(FrameNumber(0)), // Ignored
|
||||
m_sprite->getRgbMap(FrameNumber(0))); // Ignored
|
||||
algorithm::resize_image(old_bitmap, new_mask->getBitmap(),
|
||||
m_resize_method,
|
||||
m_sprite->getPalette(FrameNumber(0)), // Ignored
|
||||
m_sprite->getRgbMap(FrameNumber(0))); // Ignored
|
||||
|
||||
// Reshrink
|
||||
new_mask->intersect(new_mask->getBounds().x, new_mask->getBounds().y,
|
||||
new_mask->getBounds().w, new_mask->getBounds().h);
|
||||
new_mask->intersect(new_mask->getBounds());
|
||||
|
||||
// Copy new mask
|
||||
api.copyToCurrentMask(new_mask);
|
||||
@ -219,7 +221,8 @@ void SpriteSizeCommand::onExecute(Context* context)
|
||||
|
||||
method->addItem("Nearest-neighbor");
|
||||
method->addItem("Bilinear");
|
||||
method->setSelectedItemIndex(get_config_int("SpriteSize", "Method", RESIZE_METHOD_NEAREST_NEIGHBOR));
|
||||
method->setSelectedItemIndex(get_config_int("SpriteSize", "Method",
|
||||
raster::algorithm::RESIZE_METHOD_NEAREST_NEIGHBOR));
|
||||
|
||||
window->remapWindow();
|
||||
window->centerWindow();
|
||||
|
@ -64,7 +64,6 @@ FilterManagerImpl::FilterManagerImpl(Context* context, Filter* filter)
|
||||
m_offset_x = 0;
|
||||
m_offset_y = 0;
|
||||
m_mask = NULL;
|
||||
m_mask_address = NULL;
|
||||
m_targetOrig = TARGET_ALL_CHANNELS;
|
||||
m_target = TARGET_ALL_CHANNELS;
|
||||
|
||||
@ -119,7 +118,8 @@ void FilterManagerImpl::beginForPreview()
|
||||
else {
|
||||
m_preview_mask.reset(new Mask());
|
||||
m_preview_mask->replace(m_offset_x, m_offset_y,
|
||||
m_src->w, m_src->h);
|
||||
m_src->getWidth(),
|
||||
m_src->getHeight());
|
||||
}
|
||||
|
||||
m_row = 0;
|
||||
@ -161,15 +161,24 @@ void FilterManagerImpl::beginForPreview()
|
||||
}
|
||||
}
|
||||
|
||||
void FilterManagerImpl::end()
|
||||
{
|
||||
m_maskBits.unlock();
|
||||
}
|
||||
|
||||
bool FilterManagerImpl::applyStep()
|
||||
{
|
||||
if ((m_row >= 0) && (m_row < m_h)) {
|
||||
if ((m_mask) && (m_mask->getBitmap())) {
|
||||
m_d = div(m_x-m_mask->getBounds().x+m_offset_x, 8);
|
||||
m_mask_address = ((uint8_t**)m_mask->getBitmap()->line)[m_row+m_y-m_mask->getBounds().y+m_offset_y]+m_d.quot;
|
||||
int x = m_x - m_mask->getBounds().x + m_offset_x;
|
||||
int y = m_row + m_y - m_mask->getBounds().y + m_offset_y;
|
||||
|
||||
m_maskBits = m_mask->getBitmap()
|
||||
->lockBits<BitmapTraits>(Image::ReadLock,
|
||||
gfx::Rect(x, y, m_w - x, m_h - y));
|
||||
|
||||
m_maskIterator = m_maskBits.begin();
|
||||
}
|
||||
else
|
||||
m_mask_address = NULL;
|
||||
|
||||
switch (m_location.sprite()->getPixelFormat()) {
|
||||
case IMAGE_RGB: m_filter->applyToRgba(this); break;
|
||||
@ -208,7 +217,7 @@ void FilterManagerImpl::apply()
|
||||
undo.pushUndoer(new undoers::ImageArea(undo.getObjects(), m_src, m_x, m_y, m_w, m_h));
|
||||
|
||||
// Copy "dst" to "src"
|
||||
image_copy(m_src, m_dst, 0, 0);
|
||||
copy_image(m_src, m_dst, 0, 0);
|
||||
|
||||
undo.commit();
|
||||
}
|
||||
@ -275,34 +284,23 @@ void FilterManagerImpl::flush()
|
||||
|
||||
const void* FilterManagerImpl::getSourceAddress()
|
||||
{
|
||||
switch (m_location.sprite()->getPixelFormat()) {
|
||||
case IMAGE_RGB: return ((uint32_t**)m_src->line)[m_row+m_y]+m_x;
|
||||
case IMAGE_GRAYSCALE: return ((uint16_t**)m_src->line)[m_row+m_y]+m_x;
|
||||
case IMAGE_INDEXED: return ((uint8_t**)m_src->line)[m_row+m_y]+m_x;
|
||||
}
|
||||
return NULL;
|
||||
return m_src->getPixelAddress(m_x, m_row+m_y);
|
||||
}
|
||||
|
||||
void* FilterManagerImpl::getDestinationAddress()
|
||||
{
|
||||
switch (m_location.sprite()->getPixelFormat()) {
|
||||
case IMAGE_RGB: return ((uint32_t**)m_dst->line)[m_row+m_y]+m_x;
|
||||
case IMAGE_GRAYSCALE: return ((uint16_t**)m_dst->line)[m_row+m_y]+m_x;
|
||||
case IMAGE_INDEXED: return ((uint8_t**)m_dst->line)[m_row+m_y]+m_x;
|
||||
}
|
||||
return NULL;
|
||||
return m_dst->getPixelAddress(m_x, m_row+m_y);
|
||||
}
|
||||
|
||||
bool FilterManagerImpl::skipPixel()
|
||||
{
|
||||
bool skip = false;
|
||||
|
||||
if (m_mask_address) {
|
||||
if (!((*m_mask_address) & (1<<m_d.rem)))
|
||||
if ((m_mask) && (m_mask->getBitmap())) {
|
||||
if (!*m_maskIterator)
|
||||
skip = true;
|
||||
|
||||
// Move to the next pixel in the mask.
|
||||
_image_bitmap_next_bit(m_d, m_mask_address);
|
||||
++m_maskIterator;
|
||||
}
|
||||
|
||||
return skip;
|
||||
@ -327,11 +325,10 @@ void FilterManagerImpl::init(const Layer* layer, Image* image, int offset_x, int
|
||||
throw InvalidAreaException();
|
||||
|
||||
m_src = image;
|
||||
m_dst.reset(image_crop(image, 0, 0, image->w, image->h, 0));
|
||||
m_dst.reset(crop_image(image, 0, 0, image->getWidth(), image->getHeight(), 0));
|
||||
m_row = -1;
|
||||
m_mask = NULL;
|
||||
m_preview_mask.reset(NULL);
|
||||
m_mask_address = NULL;
|
||||
|
||||
m_target = m_targetOrig;
|
||||
|
||||
@ -366,17 +363,17 @@ bool FilterManagerImpl::updateMask(Mask* mask, const Image* image)
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if (x+w-1 >= image->w-1)
|
||||
w = image->w-x;
|
||||
if (x+w-1 >= image->getWidth()-1)
|
||||
w = image->getWidth()-x;
|
||||
|
||||
if (y+h-1 >= image->h-1)
|
||||
h = image->h-y;
|
||||
if (y+h-1 >= image->getHeight()-1)
|
||||
h = image->getHeight()-y;
|
||||
}
|
||||
else {
|
||||
x = 0;
|
||||
y = 0;
|
||||
w = image->w;
|
||||
h = image->h;
|
||||
w = image->getWidth();
|
||||
h = image->getHeight();
|
||||
}
|
||||
|
||||
if ((w < 1) || (h < 1)) {
|
||||
|
@ -24,9 +24,10 @@
|
||||
#include "base/unique_ptr.h"
|
||||
#include "filters/filter_indexed_data.h"
|
||||
#include "filters/filter_manager.h"
|
||||
#include "raster/image_bits.h"
|
||||
#include "raster/image_traits.h"
|
||||
#include "raster/pixel_format.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
namespace raster {
|
||||
@ -86,6 +87,7 @@ namespace app {
|
||||
|
||||
void begin();
|
||||
void beginForPreview();
|
||||
void end();
|
||||
bool applyStep();
|
||||
void applyToTarget();
|
||||
|
||||
@ -128,8 +130,8 @@ namespace app {
|
||||
int m_offset_x, m_offset_y;
|
||||
Mask* m_mask;
|
||||
base::UniquePtr<Mask> m_preview_mask;
|
||||
unsigned char* m_mask_address;
|
||||
div_t m_d;
|
||||
raster::ImageBits<raster::BitmapTraits> m_maskBits;
|
||||
raster::ImageBits<raster::BitmapTraits>::iterator m_maskIterator;
|
||||
Target m_targetOrig; // Original targets
|
||||
Target m_target; // Filtered targets
|
||||
|
||||
|
@ -49,6 +49,12 @@ FilterPreview::~FilterPreview()
|
||||
|
||||
void FilterPreview::stop()
|
||||
{
|
||||
if (m_timer.isRunning()) {
|
||||
ASSERT(m_filterMgr != NULL);
|
||||
|
||||
m_filterMgr->end();
|
||||
}
|
||||
|
||||
m_filterMgr = NULL;
|
||||
m_timer.stop();
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ Document* Document::createBasicDocument(PixelFormat format, int width, int heigh
|
||||
base::UniquePtr<Image> image(Image::create(format, width, height));
|
||||
|
||||
// Clear the image with mask color.
|
||||
image_clear(image, 0);
|
||||
clear_image(image, 0);
|
||||
|
||||
// Add image in the sprite's stock.
|
||||
indexInStock = sprite->getStock()->addImage(image);
|
||||
@ -286,12 +286,12 @@ void Document::prepareExtraCel(int x, int y, int w, int h, int opacity)
|
||||
|
||||
if (!m_extraImage ||
|
||||
m_extraImage->getPixelFormat() != getSprite()->getPixelFormat() ||
|
||||
m_extraImage->w != w ||
|
||||
m_extraImage->h != h) {
|
||||
m_extraImage->getWidth() != w ||
|
||||
m_extraImage->getHeight() != h) {
|
||||
delete m_extraImage; // image
|
||||
m_extraImage = Image::create(getSprite()->getPixelFormat(), w, h);
|
||||
image_clear(m_extraImage,
|
||||
m_extraImage->mask_color = 0);
|
||||
m_extraImage->setMaskColor(0);
|
||||
clear_image(m_extraImage, m_extraImage->getMaskColor());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,10 +57,12 @@
|
||||
#include "app/undoers/set_total_frames.h"
|
||||
#include "base/unique_ptr.h"
|
||||
#include "raster/algorithm/flip_image.h"
|
||||
#include "raster/algorithm/shrink_bounds.h"
|
||||
#include "raster/blend.h"
|
||||
#include "raster/cel.h"
|
||||
#include "raster/dirty.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/image_bits.h"
|
||||
#include "raster/layer.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/palette.h"
|
||||
@ -68,6 +70,7 @@
|
||||
#include "raster/sprite.h"
|
||||
#include "raster/stock.h"
|
||||
|
||||
|
||||
namespace app {
|
||||
|
||||
DocumentApi::DocumentApi(Document* document, undo::UndoersCollector* undoers)
|
||||
@ -116,8 +119,8 @@ void DocumentApi::trimSprite(Sprite* sprite, int bgcolor)
|
||||
gfx::Rect bounds;
|
||||
|
||||
base::UniquePtr<Image> image_wrap(Image::create(sprite->getPixelFormat(),
|
||||
sprite->getWidth(),
|
||||
sprite->getHeight()));
|
||||
sprite->getWidth(),
|
||||
sprite->getHeight()));
|
||||
Image* image = image_wrap.get();
|
||||
|
||||
for (FrameNumber frame(0); frame<sprite->getTotalFrames(); ++frame) {
|
||||
@ -128,7 +131,7 @@ void DocumentApi::trimSprite(Sprite* sprite, int bgcolor)
|
||||
// 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)))
|
||||
if (raster::algorithm::shrink_bounds(image, frameBounds, get_pixel(image, 0, 0)))
|
||||
bounds = bounds.createUnion(frameBounds);
|
||||
}
|
||||
|
||||
@ -232,9 +235,9 @@ void DocumentApi::addFrameForLayer(Layer* layer, FrameNumber frame)
|
||||
|
||||
Sprite* sprite = layer->getSprite();
|
||||
|
||||
switch (layer->getType()) {
|
||||
switch (layer->type()) {
|
||||
|
||||
case GFXOBJ_LAYER_IMAGE:
|
||||
case OBJECT_LAYER_IMAGE:
|
||||
// Displace all cels in '>=frame' to the next frame.
|
||||
for (FrameNumber c=sprite->getLastFrame(); c>=frame; --c) {
|
||||
Cel* cel = static_cast<LayerImage*>(layer)->getCel(c);
|
||||
@ -245,7 +248,7 @@ void DocumentApi::addFrameForLayer(Layer* layer, FrameNumber frame)
|
||||
copyPreviousFrame(layer, frame);
|
||||
break;
|
||||
|
||||
case GFXOBJ_LAYER_FOLDER: {
|
||||
case OBJECT_LAYER_FOLDER: {
|
||||
LayerIterator it = static_cast<LayerFolder*>(layer)->getLayerBegin();
|
||||
LayerIterator end = static_cast<LayerFolder*>(layer)->getLayerEnd();
|
||||
|
||||
@ -322,9 +325,9 @@ void DocumentApi::removeFrameOfLayer(Layer* layer, FrameNumber frame)
|
||||
|
||||
Sprite* sprite = layer->getSprite();
|
||||
|
||||
switch (layer->getType()) {
|
||||
switch (layer->type()) {
|
||||
|
||||
case GFXOBJ_LAYER_IMAGE:
|
||||
case OBJECT_LAYER_IMAGE:
|
||||
if (Cel* cel = static_cast<LayerImage*>(layer)->getCel(frame))
|
||||
removeCel(static_cast<LayerImage*>(layer), cel);
|
||||
|
||||
@ -333,7 +336,7 @@ void DocumentApi::removeFrameOfLayer(Layer* layer, FrameNumber frame)
|
||||
setCelFramePosition(sprite, cel, cel->getFrame().previous());
|
||||
break;
|
||||
|
||||
case GFXOBJ_LAYER_FOLDER: {
|
||||
case OBJECT_LAYER_FOLDER: {
|
||||
LayerIterator it = static_cast<LayerFolder*>(layer)->getLayerBegin();
|
||||
LayerIterator end = static_cast<LayerFolder*>(layer)->getLayerEnd();
|
||||
|
||||
@ -430,9 +433,9 @@ void DocumentApi::moveFrameBeforeLayer(Layer* layer, FrameNumber frame, FrameNum
|
||||
{
|
||||
ASSERT(layer);
|
||||
|
||||
switch (layer->getType()) {
|
||||
switch (layer->type()) {
|
||||
|
||||
case GFXOBJ_LAYER_IMAGE: {
|
||||
case OBJECT_LAYER_IMAGE: {
|
||||
CelIterator it = ((LayerImage*)layer)->getCelBegin();
|
||||
CelIterator end = ((LayerImage*)layer)->getCelEnd();
|
||||
|
||||
@ -467,7 +470,7 @@ void DocumentApi::moveFrameBeforeLayer(Layer* layer, FrameNumber frame, FrameNum
|
||||
break;
|
||||
}
|
||||
|
||||
case GFXOBJ_LAYER_FOLDER: {
|
||||
case OBJECT_LAYER_FOLDER: {
|
||||
LayerIterator it = static_cast<LayerFolder*>(layer)->getLayerBegin();
|
||||
LayerIterator end = static_cast<LayerFolder*>(layer)->getLayerEnd();
|
||||
|
||||
@ -578,7 +581,7 @@ void DocumentApi::cropCel(Sprite* sprite, Cel* cel, int x, int y, int w, int h,
|
||||
ASSERT(cel_image);
|
||||
|
||||
// create the new image through a crop
|
||||
Image* new_image = image_crop(cel_image, x-cel->getX(), y-cel->getY(), w, h, bgcolor);
|
||||
Image* new_image = crop_image(cel_image, x-cel->getX(), y-cel->getY(), w, h, bgcolor);
|
||||
|
||||
// replace the image in the stock that is pointed by the cel
|
||||
replaceStockImage(sprite, cel->getImage(), new_image);
|
||||
@ -693,9 +696,9 @@ void DocumentApi::cropLayer(Layer* layer, int x, int y, int w, int h, int bgcolo
|
||||
// Moves every frame in @a layer with the offset (@a dx, @a dy).
|
||||
void DocumentApi::displaceLayers(Layer* layer, int dx, int dy)
|
||||
{
|
||||
switch (layer->getType()) {
|
||||
switch (layer->type()) {
|
||||
|
||||
case GFXOBJ_LAYER_IMAGE: {
|
||||
case OBJECT_LAYER_IMAGE: {
|
||||
CelIterator it = ((LayerImage*)layer)->getCelBegin();
|
||||
CelIterator end = ((LayerImage*)layer)->getCelEnd();
|
||||
for (; it != end; ++it) {
|
||||
@ -705,7 +708,7 @@ void DocumentApi::displaceLayers(Layer* layer, int dx, int dy)
|
||||
break;
|
||||
}
|
||||
|
||||
case GFXOBJ_LAYER_FOLDER: {
|
||||
case OBJECT_LAYER_FOLDER: {
|
||||
LayerIterator it = ((LayerFolder*)layer)->getLayerBegin();
|
||||
LayerIterator end = ((LayerFolder*)layer)->getLayerEnd();
|
||||
for (; it != end; ++it)
|
||||
@ -747,24 +750,24 @@ void DocumentApi::backgroundFromLayer(LayerImage* layer, int bgcolor)
|
||||
Image* cel_image = sprite->getStock()->getImage(cel->getImage());
|
||||
ASSERT(cel_image);
|
||||
|
||||
image_clear(bg_image, bgcolor);
|
||||
image_merge(bg_image, cel_image,
|
||||
cel->getX(),
|
||||
cel->getY(),
|
||||
MID(0, cel->getOpacity(), 255),
|
||||
layer->getBlendMode());
|
||||
clear_image(bg_image, bgcolor);
|
||||
composite_image(bg_image, cel_image,
|
||||
cel->getX(),
|
||||
cel->getY(),
|
||||
MID(0, cel->getOpacity(), 255),
|
||||
layer->getBlendMode());
|
||||
|
||||
// now we have to copy the new image (bg_image) to the cel...
|
||||
setCelPosition(sprite, cel, 0, 0);
|
||||
|
||||
// same size of cel-image and bg-image
|
||||
if (bg_image->w == cel_image->w &&
|
||||
bg_image->h == cel_image->h) {
|
||||
if (bg_image->getWidth() == cel_image->getWidth() &&
|
||||
bg_image->getHeight() == cel_image->getHeight()) {
|
||||
if (undo->isEnabled())
|
||||
m_undoers->pushUndoer(new undoers::ImageArea(getObjects(),
|
||||
cel_image, 0, 0, cel_image->w, cel_image->h));
|
||||
cel_image, 0, 0, cel_image->getWidth(), cel_image->getHeight()));
|
||||
|
||||
image_copy(cel_image, bg_image, 0, 0);
|
||||
copy_image(cel_image, bg_image, 0, 0);
|
||||
}
|
||||
else {
|
||||
replaceStockImage(sprite, cel->getImage(), Image::createCopy(bg_image));
|
||||
@ -776,7 +779,7 @@ void DocumentApi::backgroundFromLayer(LayerImage* layer, int bgcolor)
|
||||
Cel* cel = layer->getCel(frame);
|
||||
if (!cel) {
|
||||
Image* cel_image = Image::create(sprite->getPixelFormat(), sprite->getWidth(), sprite->getHeight());
|
||||
image_clear(cel_image, bgcolor);
|
||||
clear_image(cel_image, bgcolor);
|
||||
|
||||
// Add the new image in the stock
|
||||
int image_index = addImageInStock(sprite, cel_image);
|
||||
@ -837,7 +840,7 @@ void DocumentApi::flattenLayers(Sprite* sprite, int bgcolor)
|
||||
// Copy all frames to the background.
|
||||
for (FrameNumber frame(0); frame<sprite->getTotalFrames(); ++frame) {
|
||||
// Clear the image and render this frame.
|
||||
image_clear(image, bgcolor);
|
||||
clear_image(image, bgcolor);
|
||||
layer_render(sprite->getFolder(), image, 0, 0, frame);
|
||||
|
||||
cel = background->getCel(frame);
|
||||
@ -868,7 +871,7 @@ void DocumentApi::flattenLayers(Sprite* sprite, int bgcolor)
|
||||
background->addCel(cel);
|
||||
}
|
||||
|
||||
image_copy(cel_image, image, 0, 0);
|
||||
copy_image(cel_image, image, 0, 0);
|
||||
}
|
||||
|
||||
// Delete old layers.
|
||||
@ -956,10 +959,10 @@ void DocumentApi::clearMask(Layer* layer, Cel* cel, int bgcolor)
|
||||
if (layer->isBackground()) {
|
||||
if (undo->isEnabled())
|
||||
m_undoers->pushUndoer(new undoers::ImageArea(getObjects(),
|
||||
image, 0, 0, image->w, image->h));
|
||||
image, 0, 0, image->getWidth(), image->getHeight()));
|
||||
|
||||
// clear all
|
||||
image_clear(image, bgcolor);
|
||||
clear_image(image, bgcolor);
|
||||
}
|
||||
// If the layer is transparent we can remove the cel (and its
|
||||
// associated image).
|
||||
@ -974,8 +977,8 @@ void DocumentApi::clearMask(Layer* layer, Cel* cel, int bgcolor)
|
||||
int u, v, putx, puty;
|
||||
int x1 = MAX(0, offset_x);
|
||||
int y1 = MAX(0, offset_y);
|
||||
int x2 = MIN(image->w-1, offset_x+mask->getBounds().w-1);
|
||||
int y2 = MIN(image->h-1, offset_y+mask->getBounds().h-1);
|
||||
int x2 = MIN(image->getWidth()-1, offset_x+mask->getBounds().w-1);
|
||||
int y2 = MIN(image->getHeight()-1, offset_y+mask->getBounds().h-1);
|
||||
|
||||
// Do nothing
|
||||
if (x1 > x2 || y1 > y2)
|
||||
@ -985,21 +988,22 @@ void DocumentApi::clearMask(Layer* layer, Cel* cel, int bgcolor)
|
||||
m_undoers->pushUndoer(new undoers::ImageArea(getObjects(),
|
||||
image, x1, y1, x2-x1+1, y2-y1+1));
|
||||
|
||||
// Clear the masked zones
|
||||
for (v=0; v<mask->getBounds().h; v++) {
|
||||
div_t d = div(0, 8);
|
||||
uint8_t* address = ((uint8_t**)mask->getBitmap()->line)[v]+d.quot;
|
||||
const LockImageBits<BitmapTraits> maskBits(mask->getBitmap());
|
||||
LockImageBits<BitmapTraits>::const_iterator it = maskBits.begin();
|
||||
|
||||
for (u=0; u<mask->getBounds().w; u++) {
|
||||
if ((*address & (1<<d.rem))) {
|
||||
// Clear the masked zones
|
||||
for (v=0; v<mask->getBounds().h; ++v) {
|
||||
for (u=0; u<mask->getBounds().w; ++u, ++it) {
|
||||
ASSERT(it != maskBits.end());
|
||||
if (*it) {
|
||||
putx = u + offset_x;
|
||||
puty = v + offset_y;
|
||||
image_putpixel(image, putx, puty, bgcolor);
|
||||
put_pixel(image, putx, puty, bgcolor);
|
||||
}
|
||||
|
||||
_image_bitmap_next_bit(d, address);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(it == maskBits.end());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1036,7 +1040,7 @@ void DocumentApi::flipImageWithMask(Image* image, const Mask* mask, raster::algo
|
||||
}
|
||||
|
||||
// Copy the flipped image into the image specified as argument.
|
||||
image_copy(image, flippedImage, 0, 0);
|
||||
copy_image(image, flippedImage, 0, 0);
|
||||
}
|
||||
|
||||
void DocumentApi::pasteImage(Sprite* sprite, Cel* cel, const Image* src_image, int x, int y, int opacity)
|
||||
@ -1045,7 +1049,7 @@ void DocumentApi::pasteImage(Sprite* sprite, Cel* cel, const Image* src_image, i
|
||||
|
||||
Image* cel_image = sprite->getStock()->getImage(cel->getImage());
|
||||
Image* cel_image2 = Image::createCopy(cel_image);
|
||||
image_merge(cel_image2, src_image, x-cel->getX(), y-cel->getY(), opacity, BLEND_MODE_NORMAL);
|
||||
composite_image(cel_image2, src_image, x-cel->getX(), y-cel->getY(), opacity, BLEND_MODE_NORMAL);
|
||||
|
||||
replaceStockImage(sprite, cel->getImage(), cel_image2); // TODO fix this, improve, avoid replacing the whole image
|
||||
}
|
||||
|
@ -35,18 +35,18 @@
|
||||
|
||||
#ifdef ALLEGRO_WINDOWS
|
||||
#include <winalleg.h>
|
||||
|
||||
#ifdef STRICT
|
||||
typedef WNDPROC wndproc_t;
|
||||
#else
|
||||
typedef FARPROC wndproc_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace app {
|
||||
|
||||
#ifdef ALLEGRO_WINDOWS
|
||||
|
||||
#ifdef STRICT
|
||||
typedef WNDPROC wndproc_t;
|
||||
#else
|
||||
typedef FARPROC wndproc_t;
|
||||
#endif
|
||||
|
||||
static wndproc_t base_wnd_proc = NULL;
|
||||
static std::vector<base::string>* dropped_files;
|
||||
static base::mutex* dropped_files_mutex = NULL;
|
||||
|
@ -574,9 +574,9 @@ static Palette *ase_file_read_color_chunk(FILE *f, Sprite *sprite, FrameNumber f
|
||||
r = fgetc(f);
|
||||
g = fgetc(f);
|
||||
b = fgetc(f);
|
||||
pal->setEntry(c, _rgba(_rgb_scale_6[r],
|
||||
_rgb_scale_6[g],
|
||||
_rgb_scale_6[b], 255));
|
||||
pal->setEntry(c, rgba(scale_6bits_to_8bits(r),
|
||||
scale_6bits_to_8bits(g),
|
||||
scale_6bits_to_8bits(b), 255));
|
||||
}
|
||||
}
|
||||
|
||||
@ -602,7 +602,7 @@ static Palette *ase_file_read_color2_chunk(FILE *f, Sprite *sprite, FrameNumber
|
||||
r = fgetc(f);
|
||||
g = fgetc(f);
|
||||
b = fgetc(f);
|
||||
pal->setEntry(c, _rgba(r, g, b, 255));
|
||||
pal->setEntry(c, rgba(r, g, b, 255));
|
||||
}
|
||||
}
|
||||
|
||||
@ -624,9 +624,9 @@ static void ase_file_write_color2_chunk(FILE *f, Palette *pal)
|
||||
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);
|
||||
fputc(rgba_getr(color), f);
|
||||
fputc(rgba_getg(color), f);
|
||||
fputc(rgba_getb(color), f);
|
||||
}
|
||||
|
||||
ase_file_write_close_chunk(f);
|
||||
@ -722,8 +722,7 @@ static void ase_file_write_layer_chunk(FILE *f, Layer *layer)
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename ImageTraits>
|
||||
class PixelIO
|
||||
{
|
||||
class PixelIO {
|
||||
public:
|
||||
typename ImageTraits::pixel_t read_pixel(FILE* f);
|
||||
void write_pixel(FILE* f, typename ImageTraits::pixel_t c);
|
||||
@ -732,8 +731,7 @@ public:
|
||||
};
|
||||
|
||||
template<>
|
||||
class PixelIO<RgbTraits>
|
||||
{
|
||||
class PixelIO<RgbTraits> {
|
||||
int r, g, b, a;
|
||||
public:
|
||||
RgbTraits::pixel_t read_pixel(FILE* f) {
|
||||
@ -741,13 +739,13 @@ public:
|
||||
g = fgetc(f);
|
||||
b = fgetc(f);
|
||||
a = fgetc(f);
|
||||
return _rgba(r, g, b, a);
|
||||
return rgba(r, g, b, a);
|
||||
}
|
||||
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);
|
||||
fputc(rgba_getr(c), f);
|
||||
fputc(rgba_getg(c), f);
|
||||
fputc(rgba_getb(c), f);
|
||||
fputc(rgba_geta(c), f);
|
||||
}
|
||||
void read_scanline(RgbTraits::address_t address, int w, uint8_t* buffer)
|
||||
{
|
||||
@ -756,56 +754,54 @@ public:
|
||||
g = *(buffer++);
|
||||
b = *(buffer++);
|
||||
a = *(buffer++);
|
||||
*(address++) = _rgba(r, g, b, a);
|
||||
*(address++) = rgba(r, g, b, a);
|
||||
}
|
||||
}
|
||||
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);
|
||||
*(buffer++) = rgba_getr(*address);
|
||||
*(buffer++) = rgba_getg(*address);
|
||||
*(buffer++) = rgba_getb(*address);
|
||||
*(buffer++) = rgba_geta(*address);
|
||||
++address;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class PixelIO<GrayscaleTraits>
|
||||
{
|
||||
class PixelIO<GrayscaleTraits> {
|
||||
int k, a;
|
||||
public:
|
||||
GrayscaleTraits::pixel_t read_pixel(FILE* f) {
|
||||
k = fgetc(f);
|
||||
a = fgetc(f);
|
||||
return _graya(k, a);
|
||||
return graya(k, a);
|
||||
}
|
||||
void write_pixel(FILE* f, GrayscaleTraits::pixel_t c) {
|
||||
fputc(_graya_getv(c), f);
|
||||
fputc(_graya_geta(c), f);
|
||||
fputc(graya_getv(c), f);
|
||||
fputc(graya_geta(c), f);
|
||||
}
|
||||
void read_scanline(GrayscaleTraits::address_t address, int w, uint8_t* buffer)
|
||||
{
|
||||
for (int x=0; x<w; ++x) {
|
||||
k = *(buffer++);
|
||||
a = *(buffer++);
|
||||
*(address++) = _graya(k, a);
|
||||
*(address++) = graya(k, a);
|
||||
}
|
||||
}
|
||||
void write_scanline(GrayscaleTraits::address_t address, int w, uint8_t* buffer)
|
||||
{
|
||||
for (int x=0; x<w; ++x) {
|
||||
*(buffer++) = _graya_getv(*address);
|
||||
*(buffer++) = _graya_geta(*address);
|
||||
*(buffer++) = graya_getv(*address);
|
||||
*(buffer++) = graya_geta(*address);
|
||||
++address;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class PixelIO<IndexedTraits>
|
||||
{
|
||||
class PixelIO<IndexedTraits> {
|
||||
public:
|
||||
IndexedTraits::pixel_t read_pixel(FILE* f) {
|
||||
return fgetc(f);
|
||||
@ -833,9 +829,9 @@ static void read_raw_image(FILE* f, Image* image, FileOp* fop, ASE_Header* heade
|
||||
PixelIO<ImageTraits> pixel_io;
|
||||
int x, y;
|
||||
|
||||
for (y=0; y<image->h; y++) {
|
||||
for (x=0; x<image->w; x++)
|
||||
image_putpixel_fast<ImageTraits>(image, x, y, pixel_io.read_pixel(f));
|
||||
for (y=0; y<image->getHeight(); y++) {
|
||||
for (x=0; x<image->getWidth(); x++)
|
||||
put_pixel_fast<ImageTraits>(image, x, y, pixel_io.read_pixel(f));
|
||||
|
||||
fop_progress(fop, (float)ftell(f) / (float)header->size);
|
||||
}
|
||||
@ -847,9 +843,9 @@ static void write_raw_image(FILE* f, Image* image)
|
||||
PixelIO<ImageTraits> pixel_io;
|
||||
int x, y;
|
||||
|
||||
for (y=0; y<image->h; y++)
|
||||
for (x=0; x<image->w; x++)
|
||||
pixel_io.write_pixel(f, image_getpixel_fast<ImageTraits>(image, x, y));
|
||||
for (y=0; y<image->getHeight(); y++)
|
||||
for (x=0; x<image->getWidth(); x++)
|
||||
pixel_io.write_pixel(f, get_pixel_fast<ImageTraits>(image, x, y));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@ -871,8 +867,8 @@ static void read_compressed_image(FILE* f, Image* image, size_t chunk_end, FileO
|
||||
if (err != Z_OK)
|
||||
throw base::Exception("ZLib error %d in inflateInit().", err);
|
||||
|
||||
std::vector<uint8_t> scanline(ImageTraits::scanline_size(image->w));
|
||||
std::vector<uint8_t> uncompressed(image->h * ImageTraits::scanline_size(image->w));
|
||||
std::vector<uint8_t> scanline(ImageTraits::getRowStrideBytes(image->getWidth()));
|
||||
std::vector<uint8_t> uncompressed(image->getHeight() * ImageTraits::getRowStrideBytes(image->getWidth()));
|
||||
std::vector<uint8_t> compressed(4096);
|
||||
int uncompressed_offset = 0;
|
||||
|
||||
@ -917,11 +913,13 @@ static void read_compressed_image(FILE* f, Image* image, size_t chunk_end, FileO
|
||||
}
|
||||
|
||||
uncompressed_offset = 0;
|
||||
for (y=0; y<image->h; y++) {
|
||||
typename ImageTraits::address_t address = image_address_fast<ImageTraits>(image, 0, y);
|
||||
pixel_io.read_scanline(address, image->w, &uncompressed[uncompressed_offset]);
|
||||
for (y=0; y<image->getHeight(); y++) {
|
||||
typename ImageTraits::address_t address =
|
||||
(typename ImageTraits::address_t)image->getPixelAddress(0, y);
|
||||
|
||||
uncompressed_offset += ImageTraits::scanline_size(image->w);
|
||||
pixel_io.read_scanline(address, image->getWidth(), &uncompressed[uncompressed_offset]);
|
||||
|
||||
uncompressed_offset += ImageTraits::getRowStrideBytes(image->getWidth());
|
||||
}
|
||||
|
||||
err = inflateEnd(&zstream);
|
||||
@ -943,16 +941,18 @@ static void write_compressed_image(FILE* f, Image* image)
|
||||
if (err != Z_OK)
|
||||
throw base::Exception("ZLib error %d in deflateInit().", err);
|
||||
|
||||
std::vector<uint8_t> scanline(ImageTraits::scanline_size(image->w));
|
||||
std::vector<uint8_t> scanline(ImageTraits::getRowStrideBytes(image->getWidth()));
|
||||
std::vector<uint8_t> compressed(4096);
|
||||
|
||||
for (y=0; y<image->h; y++) {
|
||||
typename ImageTraits::address_t address = image_address_fast<ImageTraits>(image, 0, y);
|
||||
pixel_io.write_scanline(address, image->w, &scanline[0]);
|
||||
for (y=0; y<image->getHeight(); y++) {
|
||||
typename ImageTraits::address_t address =
|
||||
(typename ImageTraits::address_t)image->getPixelAddress(0, y);
|
||||
|
||||
pixel_io.write_scanline(address, image->getWidth(), &scanline[0]);
|
||||
|
||||
zstream.next_in = (Bytef*)&scanline[0];
|
||||
zstream.avail_in = scanline.size();
|
||||
int flush = (y == image->h-1 ? Z_FINISH: Z_NO_FLUSH);
|
||||
int flush = (y == image->getHeight()-1 ? Z_FINISH: Z_NO_FLUSH);
|
||||
|
||||
do {
|
||||
zstream.next_out = (Bytef*)&compressed[0];
|
||||
@ -1124,8 +1124,8 @@ static void ase_file_write_cel_chunk(FILE *f, Cel *cel, LayerImage *layer, Sprit
|
||||
|
||||
if (image) {
|
||||
// Width and height
|
||||
fputw(image->w, f);
|
||||
fputw(image->h, f);
|
||||
fputw(image->getWidth(), f);
|
||||
fputw(image->getHeight(), f);
|
||||
|
||||
// Pixel data
|
||||
switch (image->getPixelFormat()) {
|
||||
@ -1162,8 +1162,8 @@ static void ase_file_write_cel_chunk(FILE *f, Cel *cel, LayerImage *layer, Sprit
|
||||
|
||||
if (image) {
|
||||
// Width and height
|
||||
fputw(image->w, f);
|
||||
fputw(image->h, f);
|
||||
fputw(image->getWidth(), f);
|
||||
fputw(image->getHeight(), f);
|
||||
|
||||
// Pixel data
|
||||
switch (image->getPixelFormat()) {
|
||||
@ -1215,7 +1215,7 @@ static Mask *ase_file_read_mask_chunk(FILE *f)
|
||||
for (u=0; u<(w+7)/8; u++) {
|
||||
byte = fgetc(f);
|
||||
for (c=0; c<8; c++)
|
||||
image_putpixel(mask->getBitmap(), u*8+c, v, byte & (1<<(7-c)));
|
||||
put_pixel(mask->getBitmap(), u*8+c, v, byte & (1<<(7-c)));
|
||||
}
|
||||
|
||||
return mask;
|
||||
@ -1242,7 +1242,7 @@ static void ase_file_write_mask_chunk(FILE *f, Mask *mask)
|
||||
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))
|
||||
if (get_pixel(mask->getBitmap(), u*8+c, v))
|
||||
byte |= (1<<(7-c));
|
||||
fputc(byte, f);
|
||||
}
|
||||
|
@ -242,7 +242,7 @@ static void read_1bit_line(int length, FILE *f, Image *image, int line)
|
||||
}
|
||||
}
|
||||
pix = b[j];
|
||||
image_putpixel(image, i, line, pix);
|
||||
put_pixel(image, i, line, pix);
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,7 +270,7 @@ static void read_4bit_line(int length, FILE *f, Image *image, int line)
|
||||
}
|
||||
}
|
||||
pix = b[j];
|
||||
image_putpixel(image, i, line, pix);
|
||||
put_pixel(image, i, line, pix);
|
||||
}
|
||||
}
|
||||
|
||||
@ -294,7 +294,7 @@ static void read_8bit_line(int length, FILE *f, Image *image, int line)
|
||||
}
|
||||
}
|
||||
pix = b[j];
|
||||
image_putpixel(image, i, line, pix);
|
||||
put_pixel(image, i, line, pix);
|
||||
}
|
||||
}
|
||||
|
||||
@ -309,10 +309,10 @@ static void read_16bit_line(int length, FILE *f, Image *image, int line)
|
||||
g = (word >> 5) & 0x1f;
|
||||
b = (word) & 0x1f;
|
||||
|
||||
image_putpixel(image, i, line,
|
||||
_rgba(_rgb_scale_5[r],
|
||||
_rgb_scale_5[g],
|
||||
_rgb_scale_5[b], 255));
|
||||
put_pixel(image, i, line,
|
||||
rgba(scale_5bits_to_8bits(r),
|
||||
scale_5bits_to_8bits(g),
|
||||
scale_5bits_to_8bits(b), 255));
|
||||
}
|
||||
|
||||
i = (2*i) % 4;
|
||||
@ -329,7 +329,7 @@ static void read_24bit_line(int length, FILE *f, Image *image, int line)
|
||||
b = fgetc(f);
|
||||
g = fgetc(f);
|
||||
r = fgetc(f);
|
||||
image_putpixel(image, i, line, _rgba(r, g, b, 255));
|
||||
put_pixel(image, i, line, rgba(r, g, b, 255));
|
||||
}
|
||||
|
||||
i = (3*i) % 4;
|
||||
@ -347,7 +347,7 @@ static void read_32bit_line(int length, FILE *f, Image *image, int line)
|
||||
g = fgetc(f);
|
||||
r = fgetc(f);
|
||||
fgetc(f);
|
||||
image_putpixel(image, i, line, _rgba(r, g, b, 255));
|
||||
put_pixel(image, i, line, rgba(r, g, b, 255));
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,7 +408,7 @@ static void read_rle8_compressed_image(FILE *f, Image *image, AL_CONST BITMAPINF
|
||||
|
||||
if (count > 0) { /* repeat pixel count times */
|
||||
for (j=0;j<count;j++) {
|
||||
image_putpixel(image, pos, line, val);
|
||||
put_pixel(image, pos, line, val);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
@ -433,7 +433,7 @@ static void read_rle8_compressed_image(FILE *f, Image *image, AL_CONST BITMAPINF
|
||||
default: /* read in absolute mode */
|
||||
for (j=0; j<val; j++) {
|
||||
val0 = fgetc(f);
|
||||
image_putpixel(image, pos, line, val0);
|
||||
put_pixel(image, pos, line, val0);
|
||||
pos++;
|
||||
}
|
||||
|
||||
@ -487,7 +487,7 @@ static void read_rle4_compressed_image(FILE *f, Image *image, AL_CONST BITMAPINF
|
||||
b[1] = val & 15;
|
||||
b[0] = (val >> 4) & 15;
|
||||
for (j=0; j<count; j++) {
|
||||
image_putpixel(image, pos, line, b[j%2]);
|
||||
put_pixel(image, pos, line, b[j%2]);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
@ -520,7 +520,7 @@ static void read_rle4_compressed_image(FILE *f, Image *image, AL_CONST BITMAPINF
|
||||
val0 = val0 >> 4;
|
||||
}
|
||||
}
|
||||
image_putpixel(image, pos, line, b[j%4]);
|
||||
put_pixel(image, pos, line, b[j%4]);
|
||||
pos++;
|
||||
}
|
||||
break;
|
||||
@ -548,15 +548,17 @@ static int read_bitfields_image(FILE *f, Image *image, BITMAPINFOHEADER *infohea
|
||||
mask >>= 1; \
|
||||
} \
|
||||
if ((c##mask >> c##shift) == 0x1f) \
|
||||
c##scale = _rgb_scale_5; \
|
||||
c##scale = scale_5bits_to_8bits; \
|
||||
else if ((c##mask >> c##shift) == 0x3f) \
|
||||
c##scale = _rgb_scale_6; \
|
||||
c##scale = scale_6bits_to_8bits; \
|
||||
else \
|
||||
c##scale = NULL;
|
||||
|
||||
unsigned long buffer, mask, rshift, gshift, bshift;
|
||||
int i, j, k, line, height, dir, r, g, b;
|
||||
int *rscale, *gscale, *bscale;
|
||||
int (*rscale)(int);
|
||||
int (*gscale)(int);
|
||||
int (*bscale)(int);
|
||||
int bits_per_pixel;
|
||||
int bytes_per_pixel;
|
||||
|
||||
@ -586,11 +588,11 @@ static int read_bitfields_image(FILE *f, Image *image, BITMAPINFOHEADER *infohea
|
||||
g = (buffer & gmask) >> gshift;
|
||||
b = (buffer & bmask) >> bshift;
|
||||
|
||||
r = rscale ? rscale[r]: r;
|
||||
g = gscale ? gscale[g]: g;
|
||||
b = bscale ? bscale[b]: b;
|
||||
r = rscale ? rscale(r): r;
|
||||
g = gscale ? gscale(g): g;
|
||||
b = bscale ? bscale(b): b;
|
||||
|
||||
image_putpixel_fast<RgbTraits>(image, j, line, _rgba(r, g, b, 255));
|
||||
put_pixel_fast<RgbTraits>(image, j, line, rgba(r, g, b, 255));
|
||||
}
|
||||
|
||||
j = (bytes_per_pixel*j) % 4;
|
||||
@ -665,9 +667,9 @@ bool BmpFormat::onLoad(FileOp *fop)
|
||||
}
|
||||
|
||||
if (pixelFormat == IMAGE_RGB)
|
||||
image_clear(image, _rgba(0, 0, 0, 255));
|
||||
clear_image(image, rgba(0, 0, 0, 255));
|
||||
else
|
||||
image_clear(image, 0);
|
||||
clear_image(image, 0);
|
||||
|
||||
switch (infoheader.biCompression) {
|
||||
|
||||
@ -723,17 +725,17 @@ bool BmpFormat::onSave(FileOp *fop)
|
||||
int bfSize;
|
||||
int biSizeImage;
|
||||
int bpp = (image->getPixelFormat() == IMAGE_RGB) ? 24 : 8;
|
||||
int filler = 3 - ((image->w*(bpp/8)-1) & 3);
|
||||
int filler = 3 - ((image->getWidth()*(bpp/8)-1) & 3);
|
||||
int c, i, j, r, g, b;
|
||||
|
||||
if (bpp == 8) {
|
||||
biSizeImage = (image->w + filler) * image->h;
|
||||
biSizeImage = (image->getWidth() + filler) * image->getHeight();
|
||||
bfSize = (54 /* header */
|
||||
+ 256*4 /* palette */
|
||||
+ biSizeImage); /* image data */
|
||||
}
|
||||
else {
|
||||
biSizeImage = (image->w*3 + filler) * image->h;
|
||||
biSizeImage = (image->getWidth()*3 + filler) * image->getHeight();
|
||||
bfSize = 54 + biSizeImage; /* header + image data */
|
||||
}
|
||||
|
||||
@ -752,8 +754,8 @@ bool BmpFormat::onSave(FileOp *fop)
|
||||
|
||||
/* info_header */
|
||||
fputl(40, f); /* biSize */
|
||||
fputl(image->w, f); /* biWidth */
|
||||
fputl(image->h, f); /* biHeight */
|
||||
fputl(image->getWidth(), f); /* biWidth */
|
||||
fputl(image->getHeight(), f); /* biHeight */
|
||||
fputw(1, f); /* biPlanes */
|
||||
fputw(bpp, f); /* biBitCount */
|
||||
fputl(0, f); /* biCompression */
|
||||
@ -780,26 +782,26 @@ bool BmpFormat::onSave(FileOp *fop)
|
||||
}
|
||||
|
||||
/* image data */
|
||||
for (i=image->h-1; i>=0; i--) {
|
||||
for (j=0; j<image->w; j++) {
|
||||
for (i=image->getHeight()-1; i>=0; i--) {
|
||||
for (j=0; j<image->getWidth(); j++) {
|
||||
if (bpp == 8) {
|
||||
if (image->getPixelFormat() == IMAGE_INDEXED)
|
||||
fputc(image_getpixel_fast<IndexedTraits>(image, j, i), f);
|
||||
fputc(get_pixel_fast<IndexedTraits>(image, j, i), f);
|
||||
else if (image->getPixelFormat() == IMAGE_GRAYSCALE)
|
||||
fputc(_graya_getv(image_getpixel_fast<GrayscaleTraits>(image, j, i)), f);
|
||||
fputc(graya_getv(get_pixel_fast<GrayscaleTraits>(image, j, i)), f);
|
||||
}
|
||||
else {
|
||||
c = image_getpixel_fast<RgbTraits>(image, j, i);
|
||||
fputc(_rgba_getb(c), f);
|
||||
fputc(_rgba_getg(c), f);
|
||||
fputc(_rgba_getr(c), f);
|
||||
c = get_pixel_fast<RgbTraits>(image, j, i);
|
||||
fputc(rgba_getb(c), f);
|
||||
fputc(rgba_getg(c), f);
|
||||
fputc(rgba_getr(c), f);
|
||||
}
|
||||
}
|
||||
|
||||
for (j=0; j<filler; j++)
|
||||
fputc(0, f);
|
||||
|
||||
fop_progress(fop, (float)(image->h-i) / (float)image->h);
|
||||
fop_progress(fop, (float)(image->getHeight()-i) / (float)image->getHeight());
|
||||
}
|
||||
|
||||
if (ferror(f)) {
|
||||
|
@ -495,7 +495,7 @@ void fop_operate(FileOp *fop, IFileOpProgress* progress)
|
||||
|
||||
// Compare the old frame with the new one
|
||||
#if USE_LINK // TODO this should be configurable through a check-box
|
||||
if (image_count_diff(old_image, fop->seq.image)) {
|
||||
if (count_diff_between_images(old_image, fop->seq.image)) {
|
||||
SEQUENCE_IMAGE();
|
||||
}
|
||||
// We don't need this image
|
||||
@ -675,16 +675,16 @@ void fop_sequence_set_format_options(FileOp* fop, const SharedPtr<FormatOptions>
|
||||
|
||||
void fop_sequence_set_color(FileOp *fop, int index, int r, int g, int b)
|
||||
{
|
||||
fop->seq.palette->setEntry(index, _rgba(r, g, b, 255));
|
||||
fop->seq.palette->setEntry(index, rgba(r, g, b, 255));
|
||||
}
|
||||
|
||||
void fop_sequence_get_color(FileOp *fop, int index, int *r, int *g, int *b)
|
||||
{
|
||||
uint32_t c = fop->seq.palette->getEntry(index);
|
||||
|
||||
*r = _rgba_getr(c);
|
||||
*g = _rgba_getg(c);
|
||||
*b = _rgba_getb(c);
|
||||
*r = rgba_getr(c);
|
||||
*g = rgba_getg(c);
|
||||
*b = rgba_getb(c);
|
||||
}
|
||||
|
||||
Image* fop_sequence_image(FileOp* fop, PixelFormat pixelFormat, int w, int h)
|
||||
|
@ -55,7 +55,7 @@ TEST(File, SeveralSizes)
|
||||
int c = std::rand()%256;
|
||||
for (int y=0; y<h; y++) {
|
||||
for (int x=0; x<w; x++) {
|
||||
image_putpixel_fast<IndexedTraits>(image, x, y, c);
|
||||
put_pixel_fast<IndexedTraits>(image, x, y, c);
|
||||
if ((std::rand()&4) == 0)
|
||||
c = std::rand()%256;
|
||||
}
|
||||
@ -77,7 +77,7 @@ TEST(File, SeveralSizes)
|
||||
int c = std::rand()%256;
|
||||
for (int y=0; y<h; y++) {
|
||||
for (int x=0; x<w; x++) {
|
||||
ASSERT_EQ(c, image_getpixel_fast<IndexedTraits>(image, x, y));
|
||||
ASSERT_EQ(c, get_pixel_fast<IndexedTraits>(image, x, y));
|
||||
if ((std::rand()&4) == 0)
|
||||
c = std::rand()%256;
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ bool FliFormat::onLoad(FileOp* fop)
|
||||
#define SETPAL() \
|
||||
do { \
|
||||
for (c=0; c<256; c++) { \
|
||||
pal->setEntry(c, _rgba(cmap[c*3], \
|
||||
pal->setEntry(c, rgba(cmap[c*3], \
|
||||
cmap[c*3+1], \
|
||||
cmap[c*3+2], 255)); \
|
||||
} \
|
||||
@ -96,9 +96,9 @@ bool FliFormat::onLoad(FileOp* fop)
|
||||
h = fli_header.height;
|
||||
|
||||
// Create the bitmaps
|
||||
UniquePtr<Image> bmp(Image::create(IMAGE_INDEXED, w, h));
|
||||
UniquePtr<Image> old(Image::create(IMAGE_INDEXED, w, h));
|
||||
UniquePtr<Palette> pal(new Palette(FrameNumber(0), 256));
|
||||
base::UniquePtr<Image> bmp(Image::create(IMAGE_INDEXED, w, h));
|
||||
base::UniquePtr<Image> old(Image::create(IMAGE_INDEXED, w, h));
|
||||
base::UniquePtr<Palette> pal(new Palette(FrameNumber(0), 256));
|
||||
|
||||
// Create the image
|
||||
Sprite* sprite = new Sprite(IMAGE_INDEXED, w, h, 256);
|
||||
@ -116,12 +116,12 @@ bool FliFormat::onLoad(FileOp* fop)
|
||||
++frpos_in) {
|
||||
/* read the frame */
|
||||
fli_read_frame(f, &fli_header,
|
||||
(unsigned char *)old->dat, omap,
|
||||
(unsigned char *)bmp->dat, cmap);
|
||||
(unsigned char *)old->getPixelAddress(0, 0), omap,
|
||||
(unsigned char *)bmp->getPixelAddress(0, 0), cmap);
|
||||
|
||||
/* first frame, or the frames changes, or the palette changes */
|
||||
if ((frpos_in == 0) ||
|
||||
(image_count_diff(old, bmp))
|
||||
(count_diff_between_images(old, bmp))
|
||||
#ifndef USE_LINK /* TODO this should be configurable through a check-box */
|
||||
|| (memcmp(omap, cmap, 768) != 0)
|
||||
#endif
|
||||
@ -159,7 +159,7 @@ bool FliFormat::onLoad(FileOp* fop)
|
||||
}
|
||||
|
||||
/* update the old image and color-map to the new ones to compare later */
|
||||
image_copy(old, bmp, 0, 0);
|
||||
copy_image(old, bmp, 0, 0);
|
||||
memcpy(omap, cmap, 768);
|
||||
|
||||
/* update progress */
|
||||
@ -214,8 +214,8 @@ bool FliFormat::onSave(FileOp* fop)
|
||||
fseek(f, 128, SEEK_SET);
|
||||
|
||||
// Create the bitmaps
|
||||
UniquePtr<Image> bmp(Image::create(IMAGE_INDEXED, sprite->getWidth(), sprite->getHeight()));
|
||||
UniquePtr<Image> old(Image::create(IMAGE_INDEXED, sprite->getWidth(), sprite->getHeight()));
|
||||
base::UniquePtr<Image> bmp(Image::create(IMAGE_INDEXED, sprite->getWidth(), sprite->getHeight()));
|
||||
base::UniquePtr<Image> old(Image::create(IMAGE_INDEXED, sprite->getWidth(), sprite->getHeight()));
|
||||
|
||||
// Write frame by frame
|
||||
for (FrameNumber frpos(0);
|
||||
@ -224,13 +224,13 @@ bool FliFormat::onSave(FileOp* fop)
|
||||
/* 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));
|
||||
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);
|
||||
clear_image(bmp, 0);
|
||||
layer_render(sprite->getFolder(), bmp, 0, 0, frpos);
|
||||
|
||||
/* how many times this frame should be written to get the same
|
||||
@ -241,14 +241,14 @@ bool FliFormat::onSave(FileOp* fop)
|
||||
/* write this frame */
|
||||
if (frpos == 0 && c == 0)
|
||||
fli_write_frame(f, &fli_header, NULL, NULL,
|
||||
(unsigned char *)bmp->dat, cmap, W_ALL);
|
||||
(unsigned char *)bmp->getPixelAddress(0, 0), cmap, W_ALL);
|
||||
else
|
||||
fli_write_frame(f, &fli_header,
|
||||
(unsigned char *)old->dat, omap,
|
||||
(unsigned char *)bmp->dat, cmap, W_ALL);
|
||||
(unsigned char *)old->getPixelAddress(0, 0), omap,
|
||||
(unsigned char *)bmp->getPixelAddress(0, 0), cmap, W_ALL);
|
||||
|
||||
/* update the old image and color-map to the new ones to compare later */
|
||||
image_copy(old, bmp, 0, 0);
|
||||
copy_image(old, bmp, 0, 0);
|
||||
memcpy(omap, cmap, 768);
|
||||
}
|
||||
|
||||
|
@ -124,7 +124,7 @@ bool GifFormat::onLoad(FileOp* fop)
|
||||
// Setup the first palette using the global color map.
|
||||
ColorMapObject* colormap = gif_file->SColorMap;
|
||||
for (int i=0; i<colormap->ColorCount; ++i) {
|
||||
current_palette->setEntry(i, _rgba(colormap->Colors[i].Red,
|
||||
current_palette->setEntry(i, rgba(colormap->Colors[i].Red,
|
||||
colormap->Colors[i].Green,
|
||||
colormap->Colors[i].Blue, 255));
|
||||
}
|
||||
@ -175,7 +175,7 @@ bool GifFormat::onLoad(FileOp* fop)
|
||||
if (gif_file->Image.ColorMap) {
|
||||
ColorMapObject* colormap = gif_file->Image.ColorMap;
|
||||
for (int i=0; i<colormap->ColorCount; ++i) {
|
||||
current_palette->setEntry(i, _rgba(colormap->Colors[i].Red,
|
||||
current_palette->setEntry(i, rgba(colormap->Colors[i].Red,
|
||||
colormap->Colors[i].Green,
|
||||
colormap->Colors[i].Blue, 255));
|
||||
}
|
||||
@ -198,14 +198,14 @@ bool GifFormat::onLoad(FileOp* fop)
|
||||
// Need to perform 4 passes on the images.
|
||||
for (int i=0; i<4; ++i)
|
||||
for (int y = interlaced_offset[i]; y < frame_h; y += interlaced_jumps[i]) {
|
||||
addr = image_address_fast<IndexedTraits>(frame_image, 0, y);
|
||||
addr = frame_image->getPixelAddress(0, y);
|
||||
if (DGifGetLine(gif_file, addr, frame_w) == GIF_ERROR)
|
||||
throw base::Exception("Invalid interlaced image data.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int y = 0; y < frame_h; ++y) {
|
||||
addr = image_address_fast<IndexedTraits>(frame_image, 0, y);
|
||||
addr = frame_image->getPixelAddress(0, y);
|
||||
if (DGifGetLine(gif_file, addr, frame_w) == GIF_ERROR)
|
||||
throw base::Exception("Invalid image data (%d).\n", GifLastError());
|
||||
}
|
||||
@ -287,9 +287,9 @@ bool GifFormat::onPostLoad(FileOp* fop)
|
||||
frame_end=data->frames.end(); frame_it != frame_end; ++frame_it) {
|
||||
|
||||
// Convert the indexed image to RGB
|
||||
for (int y=0; y<frame_it->image->h; ++y) {
|
||||
for (int x=0; x<frame_it->image->w; ++x) {
|
||||
int pixel_index = image_getpixel_fast<IndexedTraits>(frame_it->image, x, y);
|
||||
for (int y=0; y<frame_it->image->getHeight(); ++y) {
|
||||
for (int x=0; x<frame_it->image->getWidth(); ++x) {
|
||||
int pixel_index = get_pixel_fast<IndexedTraits>(frame_it->image, x, y);
|
||||
|
||||
if (pixel_index >= 0 && pixel_index < 256) {
|
||||
// This pixel matches the frame's transparent color
|
||||
@ -354,10 +354,10 @@ bool GifFormat::onPostLoad(FileOp* fop)
|
||||
base::UniquePtr<Image> previous_image(Image::create(pixelFormat, data->sprite_w, data->sprite_h));
|
||||
|
||||
// Clear both images with the transparent color (alpha = 0).
|
||||
uint32_t bgcolor = (pixelFormat == IMAGE_RGB ? _rgba(0, 0, 0, 0):
|
||||
uint32_t bgcolor = (pixelFormat == IMAGE_RGB ? rgba(0, 0, 0, 0):
|
||||
(data->bgcolor_index >= 0 ? data->bgcolor_index: 0));
|
||||
image_clear(current_image, bgcolor);
|
||||
image_clear(previous_image, bgcolor);
|
||||
clear_image(current_image, bgcolor);
|
||||
clear_image(previous_image, bgcolor);
|
||||
|
||||
// Add all frames in the sprite.
|
||||
sprite->setTotalFrames(FrameNumber(data->frames.size()));
|
||||
@ -380,27 +380,27 @@ bool GifFormat::onPostLoad(FileOp* fop)
|
||||
switch (pixelFormat) {
|
||||
|
||||
case IMAGE_INDEXED:
|
||||
for (int y = 0; y < frame_it->image->h; ++y)
|
||||
for (int x = 0; x < frame_it->image->w; ++x) {
|
||||
int pixel_index = image_getpixel_fast<IndexedTraits>(frame_it->image, x, y);
|
||||
for (int y = 0; y < frame_it->image->getHeight(); ++y)
|
||||
for (int x = 0; x < frame_it->image->getWidth(); ++x) {
|
||||
int pixel_index = get_pixel_fast<IndexedTraits>(frame_it->image, x, y);
|
||||
if (pixel_index != frame_it->mask_index)
|
||||
image_putpixel_fast<IndexedTraits>(current_image,
|
||||
frame_it->x + x,
|
||||
frame_it->y + y,
|
||||
pixel_index);
|
||||
put_pixel_fast<IndexedTraits>(current_image,
|
||||
frame_it->x + x,
|
||||
frame_it->y + y,
|
||||
pixel_index);
|
||||
}
|
||||
break;
|
||||
|
||||
case IMAGE_RGB:
|
||||
// Convert the indexed image to RGB
|
||||
for (int y = 0; y < frame_it->image->h; ++y)
|
||||
for (int x = 0; x < frame_it->image->w; ++x) {
|
||||
int pixel_index = image_getpixel_fast<IndexedTraits>(frame_it->image, x, y);
|
||||
for (int y = 0; y < frame_it->image->getHeight(); ++y)
|
||||
for (int x = 0; x < frame_it->image->getWidth(); ++x) {
|
||||
int pixel_index = get_pixel_fast<IndexedTraits>(frame_it->image, x, y);
|
||||
if (pixel_index != frame_it->mask_index)
|
||||
image_putpixel_fast<RgbTraits>(current_image,
|
||||
frame_it->x + x,
|
||||
frame_it->y + y,
|
||||
current_palette->getEntry(pixel_index));
|
||||
put_pixel_fast<RgbTraits>(current_image,
|
||||
frame_it->x + x,
|
||||
frame_it->y + y,
|
||||
current_palette->getEntry(pixel_index));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -439,16 +439,16 @@ bool GifFormat::onPostLoad(FileOp* fop)
|
||||
break;
|
||||
|
||||
case DISPOSAL_METHOD_RESTORE_BGCOLOR:
|
||||
image_rectfill(current_image,
|
||||
frame_it->x,
|
||||
frame_it->y,
|
||||
frame_it->x+frame_it->image->w-1,
|
||||
frame_it->y+frame_it->image->h-1,
|
||||
bgcolor);
|
||||
fill_rect(current_image,
|
||||
frame_it->x,
|
||||
frame_it->y,
|
||||
frame_it->x+frame_it->image->getWidth()-1,
|
||||
frame_it->y+frame_it->image->getHeight()-1,
|
||||
bgcolor);
|
||||
break;
|
||||
|
||||
case DISPOSAL_METHOD_RESTORE_PREVIOUS:
|
||||
image_copy(current_image, previous_image, 0, 0);
|
||||
copy_image(current_image, previous_image, 0, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -457,7 +457,7 @@ bool GifFormat::onPostLoad(FileOp* fop)
|
||||
// that we have already updated current_image from
|
||||
// previous_image).
|
||||
if (frame_it->disposal_method != DISPOSAL_METHOD_RESTORE_PREVIOUS)
|
||||
image_copy(previous_image, current_image, 0, 0);
|
||||
copy_image(previous_image, current_image, 0, 0);
|
||||
}
|
||||
|
||||
fop->document->addSprite(sprite);
|
||||
@ -502,9 +502,9 @@ bool GifFormat::onSave(FileOp* fop)
|
||||
Palette* previous_palette = current_palette;
|
||||
ColorMapObject* color_map = MakeMapObject(current_palette->size(), NULL);
|
||||
for (int i = 0; i < current_palette->size(); ++i) {
|
||||
color_map->Colors[i].Red = _rgba_getr(current_palette->getEntry(i));
|
||||
color_map->Colors[i].Green = _rgba_getg(current_palette->getEntry(i));
|
||||
color_map->Colors[i].Blue = _rgba_getb(current_palette->getEntry(i));
|
||||
color_map->Colors[i].Red = rgba_getr(current_palette->getEntry(i));
|
||||
color_map->Colors[i].Green = rgba_getg(current_palette->getEntry(i));
|
||||
color_map->Colors[i].Blue = rgba_getb(current_palette->getEntry(i));
|
||||
}
|
||||
|
||||
if (EGifPutScreenDesc(gif_file, sprite_w, sprite_h,
|
||||
@ -524,15 +524,15 @@ bool GifFormat::onSave(FileOp* fop)
|
||||
if (sprite_format != IMAGE_INDEXED)
|
||||
buffer_image.reset(Image::create(sprite_format, sprite_w, sprite_h));
|
||||
|
||||
image_clear(current_image, background_color);
|
||||
image_clear(previous_image, background_color);
|
||||
clear_image(current_image, background_color);
|
||||
clear_image(previous_image, background_color);
|
||||
|
||||
for (FrameNumber frame_num(0); frame_num<sprite->getTotalFrames(); ++frame_num) {
|
||||
current_palette = sprite->getPalette(frame_num);
|
||||
|
||||
// If the sprite is RGB or Grayscale, we must to convert it to Indexed on the fly.
|
||||
if (sprite_format != IMAGE_INDEXED) {
|
||||
image_clear(buffer_image, 0);
|
||||
clear_image(buffer_image, 0);
|
||||
layer_render(sprite->getFolder(), buffer_image, 0, 0, frame_num);
|
||||
|
||||
switch (sprite_format) {
|
||||
@ -541,13 +541,13 @@ bool GifFormat::onSave(FileOp* fop)
|
||||
case IMAGE_RGB:
|
||||
for (int y = 0; y < sprite_h; ++y)
|
||||
for (int x = 0; x < sprite_w; ++x) {
|
||||
uint32_t pixel_value = image_getpixel_fast<RgbTraits>(buffer_image, x, y);
|
||||
image_putpixel_fast<IndexedTraits>(current_image, x, y,
|
||||
(_rgba_geta(pixel_value) >= 128) ?
|
||||
current_palette->findBestfit(_rgba_getr(pixel_value),
|
||||
_rgba_getg(pixel_value),
|
||||
_rgba_getb(pixel_value)):
|
||||
transparent_index);
|
||||
uint32_t pixel_value = get_pixel_fast<RgbTraits>(buffer_image, x, y);
|
||||
put_pixel_fast<IndexedTraits>(current_image, x, y,
|
||||
(rgba_geta(pixel_value) >= 128) ?
|
||||
current_palette->findBestfit(rgba_getr(pixel_value),
|
||||
rgba_getg(pixel_value),
|
||||
rgba_getb(pixel_value)):
|
||||
transparent_index);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -555,20 +555,20 @@ bool GifFormat::onSave(FileOp* fop)
|
||||
case IMAGE_GRAYSCALE:
|
||||
for (int y = 0; y < sprite_h; ++y)
|
||||
for (int x = 0; x < sprite_w; ++x) {
|
||||
uint16_t pixel_value = image_getpixel_fast<GrayscaleTraits>(buffer_image, x, y);
|
||||
image_putpixel_fast<IndexedTraits>(current_image, x, y,
|
||||
(_graya_geta(pixel_value) >= 128) ?
|
||||
current_palette->findBestfit(_graya_getv(pixel_value),
|
||||
_graya_getv(pixel_value),
|
||||
_graya_getv(pixel_value)):
|
||||
transparent_index);
|
||||
uint16_t pixel_value = get_pixel_fast<GrayscaleTraits>(buffer_image, x, y);
|
||||
put_pixel_fast<IndexedTraits>(current_image, x, y,
|
||||
(graya_geta(pixel_value) >= 128) ?
|
||||
current_palette->findBestfit(graya_getv(pixel_value),
|
||||
graya_getv(pixel_value),
|
||||
graya_getv(pixel_value)):
|
||||
transparent_index);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If the sprite is Indexed, we can render directly into "current_image".
|
||||
else {
|
||||
image_clear(current_image, background_color);
|
||||
clear_image(current_image, background_color);
|
||||
layer_render(sprite->getFolder(), current_image, 0, 0, frame_num);
|
||||
}
|
||||
|
||||
@ -632,9 +632,9 @@ bool GifFormat::onSave(FileOp* fop)
|
||||
if (current_palette != previous_palette) {
|
||||
image_color_map = MakeMapObject(current_palette->size(), NULL);
|
||||
for (int i = 0; i < current_palette->size(); ++i) {
|
||||
image_color_map->Colors[i].Red = _rgba_getr(current_palette->getEntry(i));
|
||||
image_color_map->Colors[i].Green = _rgba_getg(current_palette->getEntry(i));
|
||||
image_color_map->Colors[i].Blue = _rgba_getb(current_palette->getEntry(i));
|
||||
image_color_map->Colors[i].Red = rgba_getr(current_palette->getEntry(i));
|
||||
image_color_map->Colors[i].Green = rgba_getg(current_palette->getEntry(i));
|
||||
image_color_map->Colors[i].Blue = rgba_getb(current_palette->getEntry(i));
|
||||
}
|
||||
previous_palette = current_palette;
|
||||
}
|
||||
@ -651,7 +651,9 @@ bool GifFormat::onSave(FileOp* fop)
|
||||
// Need to perform 4 passes on the images.
|
||||
for (int i=0; i<4; ++i)
|
||||
for (int y = interlaced_offset[i]; y < frame_h; y += interlaced_jumps[i]) {
|
||||
IndexedTraits::address_t addr = image_address_fast<IndexedTraits>(current_image, frame_x, frame_y + y);
|
||||
IndexedTraits::address_t addr =
|
||||
(IndexedTraits::address_t)current_image->getPixelAddress(frame_x, frame_y + y);
|
||||
|
||||
if (EGifPutLine(gif_file, addr, frame_w) == GIF_ERROR)
|
||||
throw base::Exception("Error writing GIF image scanlines for frame %d.\n", (int)frame_num);
|
||||
}
|
||||
@ -659,13 +661,15 @@ bool GifFormat::onSave(FileOp* fop)
|
||||
else {
|
||||
// Write all image scanlines (not interlaced in this case).
|
||||
for (int y = 0; y < frame_h; ++y) {
|
||||
IndexedTraits::address_t addr = image_address_fast<IndexedTraits>(current_image, frame_x, frame_y + y);
|
||||
IndexedTraits::address_t addr =
|
||||
(IndexedTraits::address_t)current_image->getPixelAddress(frame_x, frame_y + y);
|
||||
|
||||
if (EGifPutLine(gif_file, addr, frame_w) == GIF_ERROR)
|
||||
throw base::Exception("Error writing GIF image scanlines for frame %d.\n", (int)frame_num);
|
||||
}
|
||||
}
|
||||
|
||||
image_copy(previous_image, current_image, 0, 0);
|
||||
copy_image(previous_image, current_image, 0, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -143,7 +143,7 @@ bool IcoFormat::onLoad(FileOp* fop)
|
||||
int image_index = sprite->getStock()->addImage(image);
|
||||
Cel* cel = new Cel(FrameNumber(0), image_index);
|
||||
layer->addCel(cel);
|
||||
image_clear(image, 0);
|
||||
clear_image(image, 0);
|
||||
|
||||
// Go to the entry start in the file
|
||||
fseek(f, entry.image_offset, SEEK_SET);
|
||||
@ -172,7 +172,7 @@ bool IcoFormat::onLoad(FileOp* fop)
|
||||
int r = fgetc(f);
|
||||
fgetc(f);
|
||||
|
||||
pal->setEntry(i, _rgba(r, g, b, 255));
|
||||
pal->setEntry(i, rgba(r, g, b, 255));
|
||||
}
|
||||
|
||||
sprite->setPalette(pal, true);
|
||||
@ -181,24 +181,24 @@ bool IcoFormat::onLoad(FileOp* fop)
|
||||
|
||||
// Read XOR MASK
|
||||
int x, y, c, r, g, b;
|
||||
for (y=image->h-1; y>=0; --y) {
|
||||
for (x=0; x<image->w; ++x) {
|
||||
for (y=image->getHeight()-1; y>=0; --y) {
|
||||
for (x=0; x<image->getWidth(); ++x) {
|
||||
switch (entry.bpp) {
|
||||
|
||||
case 8:
|
||||
c = fgetc(f);
|
||||
ASSERT(c >= 0 && c < numcolors);
|
||||
if (c >= 0 && c < numcolors)
|
||||
image_putpixel(image, x, y, c);
|
||||
put_pixel(image, x, y, c);
|
||||
else
|
||||
image_putpixel(image, x, y, 0);
|
||||
put_pixel(image, x, y, 0);
|
||||
break;
|
||||
|
||||
case 24:
|
||||
b = fgetc(f);
|
||||
g = fgetc(f);
|
||||
r = fgetc(f);
|
||||
image_putpixel(image, x, y, _rgba(r, g, b, 255));
|
||||
put_pixel(image, x, y, rgba(r, g, b, 255));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -212,13 +212,13 @@ bool IcoFormat::onLoad(FileOp* fop)
|
||||
|
||||
// AND mask
|
||||
int m, v;
|
||||
for (y=image->h-1; y>=0; --y) {
|
||||
for (x=0; x<(image->w+7)/8; ++x) {
|
||||
for (y=image->getHeight()-1; y>=0; --y) {
|
||||
for (x=0; x<(image->getWidth()+7)/8; ++x) {
|
||||
m = fgetc(f);
|
||||
v = 128;
|
||||
for (b=0; b<8; b++) {
|
||||
if ((m & v) == v)
|
||||
image_putpixel(image, x*8+b, y, 0); // TODO mask color
|
||||
put_pixel(image, x*8+b, y, 0); // TODO mask color
|
||||
v >>= 1;
|
||||
}
|
||||
}
|
||||
@ -279,21 +279,21 @@ bool IcoFormat::onSave(FileOp* fop)
|
||||
sprite->getHeight()));
|
||||
|
||||
for (n=FrameNumber(0); n<num; ++n) {
|
||||
image_clear(image, 0);
|
||||
clear_image(image, 0);
|
||||
layer_render(sprite->getFolder(), image, 0, 0, n);
|
||||
|
||||
bpp = (sprite->getPixelFormat() == IMAGE_INDEXED) ? 8 : 24;
|
||||
bw = (((image->w * bpp / 8) + 3) / 4) * 4;
|
||||
bitsw = ((((image->w + 7) / 8) + 3) / 4) * 4;
|
||||
size = image->h * (bw + bitsw) + 40;
|
||||
bw = (((image->getWidth() * bpp / 8) + 3) / 4) * 4;
|
||||
bitsw = ((((image->getWidth() + 7) / 8) + 3) / 4) * 4;
|
||||
size = image->getHeight() * (bw + bitsw) + 40;
|
||||
|
||||
if (bpp == 8)
|
||||
size += 256 * 4;
|
||||
|
||||
// BITMAPINFOHEADER
|
||||
fputl(40, f); // size
|
||||
fputl(image->w, f); // width
|
||||
fputl(image->h * 2, f); // XOR height + AND height
|
||||
fputl(image->getWidth(), f); // width
|
||||
fputl(image->getHeight() * 2, f); // XOR height + AND height
|
||||
fputw(1, f); // planes
|
||||
fputw(bpp, f); // bitcount
|
||||
fputl(0, f); // unused for ico
|
||||
@ -310,34 +310,34 @@ bool IcoFormat::onSave(FileOp* fop)
|
||||
fputl(0, f); // color 0 is black, so the XOR mask works
|
||||
|
||||
for (i=1; i<256; i++) {
|
||||
fputc(_rgba_getb(pal->getEntry(i)), f);
|
||||
fputc(_rgba_getg(pal->getEntry(i)), f);
|
||||
fputc(_rgba_getr(pal->getEntry(i)), f);
|
||||
fputc(rgba_getb(pal->getEntry(i)), f);
|
||||
fputc(rgba_getg(pal->getEntry(i)), f);
|
||||
fputc(rgba_getr(pal->getEntry(i)), f);
|
||||
fputc(0, f);
|
||||
}
|
||||
}
|
||||
|
||||
// XOR MASK
|
||||
for (y=image->h-1; y>=0; --y) {
|
||||
for (x=0; x<image->w; ++x) {
|
||||
for (y=image->getHeight()-1; y>=0; --y) {
|
||||
for (x=0; x<image->getWidth(); ++x) {
|
||||
switch (image->getPixelFormat()) {
|
||||
|
||||
case IMAGE_RGB:
|
||||
c = image_getpixel(image, x, y);
|
||||
fputc(_rgba_getb(c), f);
|
||||
fputc(_rgba_getg(c), f);
|
||||
fputc(_rgba_getr(c), f);
|
||||
c = get_pixel(image, x, y);
|
||||
fputc(rgba_getb(c), f);
|
||||
fputc(rgba_getg(c), f);
|
||||
fputc(rgba_getr(c), f);
|
||||
break;
|
||||
|
||||
case IMAGE_GRAYSCALE:
|
||||
c = image_getpixel(image, x, y);
|
||||
fputc(_graya_getv(c), f);
|
||||
fputc(_graya_getv(c), f);
|
||||
fputc(_graya_getv(c), f);
|
||||
c = get_pixel(image, x, y);
|
||||
fputc(graya_getv(c), f);
|
||||
fputc(graya_getv(c), f);
|
||||
fputc(graya_getv(c), f);
|
||||
break;
|
||||
|
||||
case IMAGE_INDEXED:
|
||||
c = image_getpixel(image, x, y);
|
||||
c = get_pixel(image, x, y);
|
||||
fputc(c, f);
|
||||
break;
|
||||
}
|
||||
@ -351,23 +351,23 @@ bool IcoFormat::onSave(FileOp* fop)
|
||||
}
|
||||
|
||||
// AND MASK
|
||||
for (y=image->h-1; y>=0; --y) {
|
||||
for (x=0; x<(image->w+7)/8; ++x) {
|
||||
for (y=image->getHeight()-1; y>=0; --y) {
|
||||
for (x=0; x<(image->getWidth()+7)/8; ++x) {
|
||||
m = 0;
|
||||
v = 128;
|
||||
|
||||
for (b=0; b<8; b++) {
|
||||
c = image_getpixel(image, x*8+b, y);
|
||||
c = get_pixel(image, x*8+b, y);
|
||||
|
||||
switch (image->getPixelFormat()) {
|
||||
|
||||
case IMAGE_RGB:
|
||||
if (_rgba_geta(c) == 0)
|
||||
if (rgba_geta(c) == 0)
|
||||
m |= v;
|
||||
break;
|
||||
|
||||
case IMAGE_GRAYSCALE:
|
||||
if (_graya_geta(c) == 0)
|
||||
if (graya_geta(c) == 0)
|
||||
m |= v;
|
||||
break;
|
||||
|
||||
|
@ -187,7 +187,7 @@ bool JpegFormat::onLoad(FileOp* fop)
|
||||
|
||||
num_scanlines = jpeg_read_scanlines(&cinfo, buffer, buffer_height);
|
||||
|
||||
/* RGB */
|
||||
// RGB
|
||||
if (image->getPixelFormat() == IMAGE_RGB) {
|
||||
uint8_t* src_address;
|
||||
uint32_t* dst_address;
|
||||
@ -195,17 +195,17 @@ bool JpegFormat::onLoad(FileOp* fop)
|
||||
|
||||
for (y=0; y<(int)num_scanlines; y++) {
|
||||
src_address = ((uint8_t**)buffer)[y];
|
||||
dst_address = ((uint32_t**)image->line)[cinfo.output_scanline-1+y];
|
||||
dst_address = (uint32_t*)image->getPixelAddress(0, cinfo.output_scanline-1+y);
|
||||
|
||||
for (x=0; x<image->w; x++) {
|
||||
for (x=0; x<image->getWidth(); x++) {
|
||||
r = *(src_address++);
|
||||
g = *(src_address++);
|
||||
b = *(src_address++);
|
||||
*(dst_address++) = _rgba(r, g, b, 255);
|
||||
*(dst_address++) = rgba(r, g, b, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Grayscale */
|
||||
// Grayscale
|
||||
else {
|
||||
uint8_t* src_address;
|
||||
uint16_t* dst_address;
|
||||
@ -213,10 +213,10 @@ bool JpegFormat::onLoad(FileOp* fop)
|
||||
|
||||
for (y=0; y<(int)num_scanlines; y++) {
|
||||
src_address = ((uint8_t**)buffer)[y];
|
||||
dst_address = ((uint16_t**)image->line)[cinfo.output_scanline-1+y];
|
||||
dst_address = (uint16_t*)image->getPixelAddress(0, cinfo.output_scanline-1+y);
|
||||
|
||||
for (x=0; x<image->w; x++)
|
||||
*(dst_address++) = _graya(*(src_address++), 255);
|
||||
for (x=0; x<image->getWidth(); x++)
|
||||
*(dst_address++) = graya(*(src_address++), 255);
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,8 +258,8 @@ bool JpegFormat::onSave(FileOp* fop)
|
||||
jpeg_stdio_dest(&cinfo, file);
|
||||
|
||||
// SET parameters for compression.
|
||||
cinfo.image_width = image->w;
|
||||
cinfo.image_height = image->h;
|
||||
cinfo.image_width = image->getWidth();
|
||||
cinfo.image_height = image->getHeight();
|
||||
|
||||
if (image->getPixelFormat() == IMAGE_GRAYSCALE) {
|
||||
cinfo.input_components = 1;
|
||||
@ -308,13 +308,14 @@ bool JpegFormat::onSave(FileOp* fop)
|
||||
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];
|
||||
src_address = (uint32_t*)image->getPixelAddress(0, cinfo.next_scanline+y);
|
||||
dst_address = ((uint8_t**)buffer)[y];
|
||||
for (x=0; x<image->w; x++) {
|
||||
|
||||
for (x=0; x<image->getWidth(); ++x) {
|
||||
c = *(src_address++);
|
||||
*(dst_address++) = _rgba_getr(c);
|
||||
*(dst_address++) = _rgba_getg(c);
|
||||
*(dst_address++) = _rgba_getb(c);
|
||||
*(dst_address++) = rgba_getr(c);
|
||||
*(dst_address++) = rgba_getg(c);
|
||||
*(dst_address++) = rgba_getb(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -324,10 +325,10 @@ bool JpegFormat::onSave(FileOp* fop)
|
||||
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];
|
||||
src_address = (uint16_t*)image->getPixelAddress(0, cinfo.next_scanline+y);
|
||||
dst_address = ((uint8_t**)buffer)[y];
|
||||
for (x=0; x<image->w; x++)
|
||||
*(dst_address++) = _graya_getv(*(src_address++));
|
||||
for (x=0; x<image->getWidth(); ++x)
|
||||
*(dst_address++) = graya_getv(*(src_address++));
|
||||
}
|
||||
}
|
||||
jpeg_write_scanlines(&cinfo, buffer, buffer_height);
|
||||
|
@ -112,11 +112,11 @@ bool PcxFormat::onLoad(FileOp* fop)
|
||||
}
|
||||
|
||||
if (bpp == 24)
|
||||
image_clear(image, _rgba(0, 0, 0, 255));
|
||||
clear_image(image, rgba(0, 0, 0, 255));
|
||||
|
||||
for (y=0; y<height; y++) { /* read RLE encoded PCX data */
|
||||
x = xx = 0;
|
||||
po = _rgba_r_shift;
|
||||
po = rgba_r_shift;
|
||||
|
||||
while (x < bytes_per_line*bpp/8) {
|
||||
ch = fgetc(f);
|
||||
@ -129,23 +129,26 @@ bool PcxFormat::onLoad(FileOp* fop)
|
||||
|
||||
if (bpp == 8) {
|
||||
while (c--) {
|
||||
if (x < image->w)
|
||||
*(((uint8_t**)image->line)[y]+x) = ch;
|
||||
if (x < image->getWidth())
|
||||
put_pixel_fast<IndexedTraits>(image, x, y, ch);
|
||||
|
||||
x++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
while (c--) {
|
||||
if (xx < image->w)
|
||||
*(((uint32_t**)image->line)[y]+xx) |= (ch & 0xff) << po;
|
||||
if (xx < image->getWidth())
|
||||
put_pixel_fast<RgbTraits>(image, xx, y,
|
||||
get_pixel_fast<RgbTraits>(image, xx, y) | ((ch & 0xff) << po));
|
||||
|
||||
x++;
|
||||
if (x == bytes_per_line) {
|
||||
xx = 0;
|
||||
po = _rgba_g_shift;
|
||||
po = rgba_g_shift;
|
||||
}
|
||||
else if (x == bytes_per_line*2) {
|
||||
xx = 0;
|
||||
po = _rgba_b_shift;
|
||||
po = rgba_b_shift;
|
||||
}
|
||||
else
|
||||
xx++;
|
||||
@ -210,8 +213,8 @@ bool PcxFormat::onSave(FileOp* fop)
|
||||
fputc(8, f); /* 8 bits per pixel */
|
||||
fputw(0, f); /* xmin */
|
||||
fputw(0, f); /* ymin */
|
||||
fputw(image->w-1, f); /* xmax */
|
||||
fputw(image->h-1, f); /* ymax */
|
||||
fputw(image->getWidth()-1, f); /* xmax */
|
||||
fputw(image->getHeight()-1, f); /* ymax */
|
||||
fputw(320, f); /* HDpi */
|
||||
fputw(200, f); /* VDpi */
|
||||
|
||||
@ -224,37 +227,37 @@ bool PcxFormat::onSave(FileOp* fop)
|
||||
|
||||
fputc(0, f); /* reserved */
|
||||
fputc(planes, f); /* one or three color planes */
|
||||
fputw(image->w, f); /* number of bytes per scanline */
|
||||
fputw(image->getWidth(), f); /* number of bytes per scanline */
|
||||
fputw(1, f); /* color palette */
|
||||
fputw(image->w, f); /* hscreen size */
|
||||
fputw(image->h, f); /* vscreen size */
|
||||
fputw(image->getWidth(), f); /* hscreen size */
|
||||
fputw(image->getHeight(), f); /* vscreen size */
|
||||
for (c=0; c<54; c++) /* filler */
|
||||
fputc(0, f);
|
||||
|
||||
for (y=0; y<image->h; y++) { /* for each scanline... */
|
||||
for (y=0; y<image->getHeight(); y++) { /* for each scanline... */
|
||||
runcount = 0;
|
||||
runchar = 0;
|
||||
for (x=0; x<image->w*planes; x++) { /* for each pixel... */
|
||||
for (x=0; x<image->getWidth()*planes; x++) { /* for each pixel... */
|
||||
if (depth == 8) {
|
||||
if (image->getPixelFormat() == IMAGE_INDEXED)
|
||||
ch = image_getpixel_fast<IndexedTraits>(image, x, y);
|
||||
ch = get_pixel_fast<IndexedTraits>(image, x, y);
|
||||
else if (image->getPixelFormat() == IMAGE_GRAYSCALE) {
|
||||
c = image_getpixel_fast<GrayscaleTraits>(image, x, y);
|
||||
ch = _graya_getv(c);
|
||||
c = get_pixel_fast<GrayscaleTraits>(image, x, y);
|
||||
ch = graya_getv(c);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (x < image->w) {
|
||||
c = image_getpixel_fast<RgbTraits>(image, x, y);
|
||||
ch = _rgba_getr(c);
|
||||
if (x < image->getWidth()) {
|
||||
c = get_pixel_fast<RgbTraits>(image, x, y);
|
||||
ch = rgba_getr(c);
|
||||
}
|
||||
else if (x<image->w*2) {
|
||||
c = image_getpixel_fast<RgbTraits>(image, x-image->w, y);
|
||||
ch = _rgba_getg(c);
|
||||
else if (x<image->getWidth()*2) {
|
||||
c = get_pixel_fast<RgbTraits>(image, x-image->getWidth(), y);
|
||||
ch = rgba_getg(c);
|
||||
}
|
||||
else {
|
||||
c = image_getpixel_fast<RgbTraits>(image, x-image->w*2, y);
|
||||
ch = _rgba_getb(c);
|
||||
c = get_pixel_fast<RgbTraits>(image, x-image->getWidth()*2, y);
|
||||
ch = rgba_getb(c);
|
||||
}
|
||||
}
|
||||
if (runcount == 0) {
|
||||
@ -279,7 +282,7 @@ bool PcxFormat::onSave(FileOp* fop)
|
||||
|
||||
fputc(runchar, f);
|
||||
|
||||
fop_progress(fop, (float)(y+1) / (float)(image->h));
|
||||
fop_progress(fop, (float)(y+1) / (float)(image->getHeight()));
|
||||
}
|
||||
|
||||
if (depth == 8) { /* 256 color palette */
|
||||
|
@ -247,7 +247,7 @@ bool PngFormat::onLoad(FileOp* fop)
|
||||
/* RGB_ALPHA */
|
||||
if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGB_ALPHA) {
|
||||
register uint8_t* src_address = row_pointer;
|
||||
register uint32_t* dst_address = ((uint32_t**)image->line)[y];
|
||||
register uint32_t* dst_address = (uint32_t*)image->getPixelAddress(0, y);
|
||||
register unsigned int x, r, g, b, a;
|
||||
|
||||
for (x=0; x<width; x++) {
|
||||
@ -255,49 +255,49 @@ bool PngFormat::onLoad(FileOp* fop)
|
||||
g = *(src_address++);
|
||||
b = *(src_address++);
|
||||
a = *(src_address++);
|
||||
*(dst_address++) = _rgba(r, g, b, a);
|
||||
*(dst_address++) = rgba(r, g, b, a);
|
||||
}
|
||||
}
|
||||
/* RGB */
|
||||
else if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGB) {
|
||||
register uint8_t* src_address = row_pointer;
|
||||
register uint32_t* dst_address = ((uint32_t**)image->line)[y];
|
||||
register uint32_t* dst_address = (uint32_t*)image->getPixelAddress(0, y);
|
||||
register unsigned int x, r, g, b;
|
||||
|
||||
for (x=0; x<width; x++) {
|
||||
r = *(src_address++);
|
||||
g = *(src_address++);
|
||||
b = *(src_address++);
|
||||
*(dst_address++) = _rgba(r, g, b, 255);
|
||||
*(dst_address++) = rgba(r, g, b, 255);
|
||||
}
|
||||
}
|
||||
/* GRAY_ALPHA */
|
||||
else if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_GRAY_ALPHA) {
|
||||
register uint8_t* src_address = row_pointer;
|
||||
register uint16_t* dst_address = ((uint16_t**)image->line)[y];
|
||||
register uint16_t* dst_address = (uint16_t*)image->getPixelAddress(0, y);
|
||||
register unsigned int x, k, a;
|
||||
|
||||
for (x=0; x<width; x++) {
|
||||
k = *(src_address++);
|
||||
a = *(src_address++);
|
||||
*(dst_address++) = _graya(k, a);
|
||||
*(dst_address++) = graya(k, a);
|
||||
}
|
||||
}
|
||||
/* GRAY */
|
||||
else if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_GRAY) {
|
||||
register uint8_t* src_address = row_pointer;
|
||||
register uint16_t* dst_address = ((uint16_t**)image->line)[y];
|
||||
register uint16_t* dst_address = (uint16_t*)image->getPixelAddress(0, y);
|
||||
register unsigned int x, k;
|
||||
|
||||
for (x=0; x<width; x++) {
|
||||
k = *(src_address++);
|
||||
*(dst_address++) = _graya(k, 255);
|
||||
*(dst_address++) = graya(k, 255);
|
||||
}
|
||||
}
|
||||
/* PALETTE */
|
||||
else if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) {
|
||||
register uint8_t* src_address = row_pointer;
|
||||
register uint8_t* dst_address = ((uint8_t**)image->line)[y];
|
||||
register uint8_t* dst_address = (uint8_t*)image->getPixelAddress(0, y);
|
||||
register unsigned int x, c;
|
||||
|
||||
for (x=0; x<width; x++) {
|
||||
@ -380,8 +380,8 @@ bool PngFormat::onSave(FileOp* fop)
|
||||
* PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
|
||||
* currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
|
||||
*/
|
||||
width = image->w;
|
||||
height = image->h;
|
||||
width = image->getWidth();
|
||||
height = image->getHeight();
|
||||
|
||||
switch (image->getPixelFormat()) {
|
||||
case IMAGE_RGB:
|
||||
@ -455,57 +455,57 @@ bool PngFormat::onSave(FileOp* fop)
|
||||
for (y = 0; y < height; y++) {
|
||||
/* RGB_ALPHA */
|
||||
if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGB_ALPHA) {
|
||||
register uint32_t* src_address = ((uint32_t**)image->line)[y];
|
||||
register uint32_t* src_address = (uint32_t*)image->getPixelAddress(0, y);
|
||||
register uint8_t* dst_address = row_pointer;
|
||||
register unsigned int x, c;
|
||||
|
||||
for (x=0; x<width; x++) {
|
||||
c = *(src_address++);
|
||||
*(dst_address++) = _rgba_getr(c);
|
||||
*(dst_address++) = _rgba_getg(c);
|
||||
*(dst_address++) = _rgba_getb(c);
|
||||
*(dst_address++) = _rgba_geta(c);
|
||||
*(dst_address++) = rgba_getr(c);
|
||||
*(dst_address++) = rgba_getg(c);
|
||||
*(dst_address++) = rgba_getb(c);
|
||||
*(dst_address++) = rgba_geta(c);
|
||||
}
|
||||
}
|
||||
/* RGB */
|
||||
else if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGB) {
|
||||
register uint32_t* src_address = ((uint32_t**)image->line)[y];
|
||||
register uint32_t* src_address = (uint32_t*)image->getPixelAddress(0, y);
|
||||
register uint8_t* dst_address = row_pointer;
|
||||
register unsigned int x, c;
|
||||
|
||||
for (x=0; x<width; x++) {
|
||||
c = *(src_address++);
|
||||
*(dst_address++) = _rgba_getr(c);
|
||||
*(dst_address++) = _rgba_getg(c);
|
||||
*(dst_address++) = _rgba_getb(c);
|
||||
*(dst_address++) = rgba_getr(c);
|
||||
*(dst_address++) = rgba_getg(c);
|
||||
*(dst_address++) = rgba_getb(c);
|
||||
}
|
||||
}
|
||||
/* GRAY_ALPHA */
|
||||
else if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_GRAY_ALPHA) {
|
||||
register uint16_t* src_address = ((uint16_t**)image->line)[y];
|
||||
register uint16_t* src_address = (uint16_t*)image->getPixelAddress(0, y);
|
||||
register uint8_t* dst_address = row_pointer;
|
||||
register unsigned int x, c;
|
||||
|
||||
for (x=0; x<width; x++) {
|
||||
c = *(src_address++);
|
||||
*(dst_address++) = _graya_getv(c);
|
||||
*(dst_address++) = _graya_geta(c);
|
||||
*(dst_address++) = graya_getv(c);
|
||||
*(dst_address++) = graya_geta(c);
|
||||
}
|
||||
}
|
||||
/* GRAY */
|
||||
else if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_GRAY) {
|
||||
register uint16_t* src_address = ((uint16_t**)image->line)[y];
|
||||
register uint16_t* src_address = (uint16_t*)image->getPixelAddress(0, y);
|
||||
register uint8_t* dst_address = row_pointer;
|
||||
register unsigned int x, c;
|
||||
|
||||
for (x=0; x<width; x++) {
|
||||
c = *(src_address++);
|
||||
*(dst_address++) = _graya_getv(c);
|
||||
*(dst_address++) = graya_getv(c);
|
||||
}
|
||||
}
|
||||
/* PALETTE */
|
||||
else if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE) {
|
||||
register uint8_t* src_address = ((uint8_t**)image->line)[y];
|
||||
register uint8_t* src_address = (uint8_t*)image->getPixelAddress(0, y);
|
||||
register uint8_t* dst_address = row_pointer;
|
||||
register unsigned int x;
|
||||
|
||||
|
@ -116,14 +116,14 @@ static void rle_tga_read32(uint32_t* address, int w, FILE *f)
|
||||
c += count;
|
||||
fread(value, 1, 4, f);
|
||||
while (count--)
|
||||
*(address++) = _rgba(value[2], value[1], value[0], value[3]);
|
||||
*(address++) = rgba(value[2], value[1], value[0], value[3]);
|
||||
}
|
||||
else {
|
||||
count++;
|
||||
c += count;
|
||||
while (count--) {
|
||||
fread(value, 1, 4, f);
|
||||
*(address++) = _rgba(value[2], value[1], value[0], value[3]);
|
||||
*(address++) = rgba(value[2], value[1], value[0], value[3]);
|
||||
}
|
||||
}
|
||||
} while (c < w);
|
||||
@ -145,14 +145,14 @@ static void rle_tga_read24(uint32_t* address, int w, FILE *f)
|
||||
c += count;
|
||||
fread(value, 1, 3, f);
|
||||
while (count--)
|
||||
*(address++) = _rgba(value[2], value[1], value[0], 255);
|
||||
*(address++) = rgba(value[2], value[1], value[0], 255);
|
||||
}
|
||||
else {
|
||||
count++;
|
||||
c += count;
|
||||
while (count--) {
|
||||
fread(value, 1, 3, f);
|
||||
*(address++) = _rgba(value[2], value[1], value[0], 255);
|
||||
*(address++) = rgba(value[2], value[1], value[0], 255);
|
||||
}
|
||||
}
|
||||
} while (c < w);
|
||||
@ -174,9 +174,9 @@ static void rle_tga_read16(uint32_t* address, int w, FILE *f)
|
||||
count = (count & 0x7F) + 1;
|
||||
c += count;
|
||||
value = fgetw(f);
|
||||
color = _rgba(_rgb_scale_5[((value >> 10) & 0x1F)],
|
||||
_rgb_scale_5[((value >> 5) & 0x1F)],
|
||||
_rgb_scale_5[(value & 0x1F)], 255);
|
||||
color = rgba(scale_5bits_to_8bits(((value >> 10) & 0x1F)),
|
||||
scale_5bits_to_8bits(((value >> 5) & 0x1F)),
|
||||
scale_5bits_to_8bits((value & 0x1F)), 255);
|
||||
|
||||
while (count--)
|
||||
*(address++) = color;
|
||||
@ -186,9 +186,9 @@ static void rle_tga_read16(uint32_t* address, int w, FILE *f)
|
||||
c += count;
|
||||
while (count--) {
|
||||
value = fgetw(f);
|
||||
color = _rgba(_rgb_scale_5[((value >> 10) & 0x1F)],
|
||||
_rgb_scale_5[((value >> 5) & 0x1F)],
|
||||
_rgb_scale_5[(value & 0x1F)], 255);
|
||||
color = rgba(scale_5bits_to_8bits(((value >> 10) & 0x1F)),
|
||||
scale_5bits_to_8bits(((value >> 5) & 0x1F)),
|
||||
scale_5bits_to_8bits((value & 0x1F)), 255);
|
||||
*(address++) = color;
|
||||
}
|
||||
}
|
||||
@ -325,52 +325,48 @@ bool TgaFormat::onLoad(FileOp* fop)
|
||||
case 1:
|
||||
case 3:
|
||||
if (compressed)
|
||||
rle_tga_read(image->line[yc], image_width, image_type, f);
|
||||
rle_tga_read(image->getPixelAddress(0, yc), image_width, image_type, f);
|
||||
else if (image_type == 1)
|
||||
fread(image->line[yc], 1, image_width, f);
|
||||
fread(image->getPixelAddress(0, yc), 1, image_width, f);
|
||||
else {
|
||||
for (x=0; x<image_width; x++)
|
||||
*(((uint16_t**)image->line)[yc]+x) =
|
||||
_graya(fgetc(f), 255);
|
||||
put_pixel_fast<GrayscaleTraits>(image, x, yc, graya(fgetc(f), 255));
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (bpp == 32) {
|
||||
if (compressed) {
|
||||
rle_tga_read32((uint32_t*)image->line[yc], image_width, f);
|
||||
rle_tga_read32((uint32_t*)image->getPixelAddress(0, yc), image_width, f);
|
||||
}
|
||||
else {
|
||||
for (x=0; x<image_width; x++) {
|
||||
fread(rgb, 1, 4, f);
|
||||
*(((uint32_t**)image->line)[yc]+x) =
|
||||
_rgba(rgb[2], rgb[1], rgb[0], rgb[3]);
|
||||
put_pixel_fast<RgbTraits>(image, x, yc, rgba(rgb[2], rgb[1], rgb[0], rgb[3]));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bpp == 24) {
|
||||
if (compressed) {
|
||||
rle_tga_read24((uint32_t*)image->line[yc], image_width, f);
|
||||
rle_tga_read24((uint32_t*)image->getPixelAddress(0, yc), image_width, f);
|
||||
}
|
||||
else {
|
||||
for (x=0; x<image_width; x++) {
|
||||
fread(rgb, 1, 3, f);
|
||||
*(((uint32_t**)image->line)[yc]+x) =
|
||||
_rgba(rgb[2], rgb[1], rgb[0], 255);
|
||||
put_pixel_fast<RgbTraits>(image, x, yc, rgba(rgb[2], rgb[1], rgb[0], 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (compressed) {
|
||||
rle_tga_read16((uint32_t*)image->line[yc], image_width, f);
|
||||
rle_tga_read16((uint32_t*)image->getPixelAddress(0, yc), image_width, f);
|
||||
}
|
||||
else {
|
||||
for (x=0; x<image_width; x++) {
|
||||
c = fgetw(f);
|
||||
*(((uint32_t**)image->line)[yc]+x) =
|
||||
_rgba(((c >> 10) & 0x1F),
|
||||
((c >> 5) & 0x1F),
|
||||
(c & 0x1F), 255);
|
||||
put_pixel_fast<RgbTraits>(image, x, yc, rgba(((c >> 10) & 0x1F),
|
||||
((c >> 5) & 0x1F),
|
||||
(c & 0x1F), 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -418,8 +414,8 @@ bool TgaFormat::onSave(FileOp* fop)
|
||||
fputc((need_pal) ? 24 : 0, f); /* palette entry size */
|
||||
fputw(0, f); /* left */
|
||||
fputw(0, f); /* top */
|
||||
fputw(image->w, f); /* width */
|
||||
fputw(image->h, f); /* height */
|
||||
fputw(image->getWidth(), f); /* width */
|
||||
fputw(image->getHeight(), f); /* height */
|
||||
fputc(depth, f); /* bits per pixel */
|
||||
|
||||
/* descriptor (bottom to top, 8-bit alpha) */
|
||||
@ -438,34 +434,34 @@ bool TgaFormat::onSave(FileOp* fop)
|
||||
switch (image->getPixelFormat()) {
|
||||
|
||||
case IMAGE_RGB:
|
||||
for (y=image->h-1; y>=0; y--) {
|
||||
for (x=0; x<image->w; x++) {
|
||||
c = image_getpixel(image, x, y);
|
||||
fputc(_rgba_getb(c), f);
|
||||
fputc(_rgba_getg(c), f);
|
||||
fputc(_rgba_getr(c), f);
|
||||
fputc(_rgba_geta(c), f);
|
||||
for (y=image->getHeight()-1; y>=0; y--) {
|
||||
for (x=0; x<image->getWidth(); x++) {
|
||||
c = get_pixel(image, x, y);
|
||||
fputc(rgba_getb(c), f);
|
||||
fputc(rgba_getg(c), f);
|
||||
fputc(rgba_getr(c), f);
|
||||
fputc(rgba_geta(c), f);
|
||||
}
|
||||
|
||||
fop_progress(fop, (float)(image->h-y) / (float)(image->h));
|
||||
fop_progress(fop, (float)(image->getHeight()-y) / (float)(image->getHeight()));
|
||||
}
|
||||
break;
|
||||
|
||||
case IMAGE_GRAYSCALE:
|
||||
for (y=image->h-1; y>=0; y--) {
|
||||
for (x=0; x<image->w; x++)
|
||||
fputc(_graya_getv(image_getpixel(image, x, y)), f);
|
||||
for (y=image->getHeight()-1; y>=0; y--) {
|
||||
for (x=0; x<image->getWidth(); x++)
|
||||
fputc(graya_getv(get_pixel(image, x, y)), f);
|
||||
|
||||
fop_progress(fop, (float)(image->h-y) / (float)(image->h));
|
||||
fop_progress(fop, (float)(image->getHeight()-y) / (float)(image->getHeight()));
|
||||
}
|
||||
break;
|
||||
|
||||
case IMAGE_INDEXED:
|
||||
for (y=image->h-1; y>=0; y--) {
|
||||
for (x=0; x<image->w; x++)
|
||||
fputc(image_getpixel(image, x, y), f);
|
||||
for (y=image->getHeight()-1; y>=0; y--) {
|
||||
for (x=0; x<image->getWidth(); x++)
|
||||
fputc(get_pixel(image, x, y), f);
|
||||
|
||||
fop_progress(fop, (float)(image->h-y) / (float)(image->h));
|
||||
fop_progress(fop, (float)(image->getHeight()-y) / (float)(image->getHeight()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -75,12 +75,12 @@ static bool has_cels(const Layer* layer, FrameNumber frame)
|
||||
if (!layer->isReadable())
|
||||
return false;
|
||||
|
||||
switch (layer->getType()) {
|
||||
switch (layer->type()) {
|
||||
|
||||
case GFXOBJ_LAYER_IMAGE:
|
||||
case OBJECT_LAYER_IMAGE:
|
||||
return static_cast<const LayerImage*>(layer)->getCel(frame) ? true: false;
|
||||
|
||||
case GFXOBJ_LAYER_FOLDER: {
|
||||
case OBJECT_LAYER_FOLDER: {
|
||||
LayerConstIterator it = static_cast<const LayerFolder*>(layer)->getLayerBegin();
|
||||
LayerConstIterator end = static_cast<const LayerFolder*>(layer)->getLayerEnd();
|
||||
|
||||
|
@ -354,9 +354,9 @@ void draw_color(BITMAP* bmp, const Rect& rc, PixelFormat pixelFormat, const app:
|
||||
|
||||
{
|
||||
int rgb_bitmap_color = color_utils::color_for_image(color, pixelFormat);
|
||||
app::Color color2 = app::Color::fromRgb(_rgba_getr(rgb_bitmap_color),
|
||||
_rgba_getg(rgb_bitmap_color),
|
||||
_rgba_getb(rgb_bitmap_color));
|
||||
app::Color color2 = app::Color::fromRgb(rgba_getr(rgb_bitmap_color),
|
||||
rgba_getg(rgb_bitmap_color),
|
||||
rgba_getb(rgb_bitmap_color));
|
||||
rectfill(graph, 0, 0, rc.w-1, rc.h-1,
|
||||
color_utils::color_for_allegro(color2, 32));
|
||||
}
|
||||
@ -373,7 +373,7 @@ void draw_color(BITMAP* bmp, const Rect& rc, PixelFormat pixelFormat, const app:
|
||||
|
||||
{
|
||||
int gray_bitmap_color = color_utils::color_for_image(color, pixelFormat);
|
||||
app::Color color2 = app::Color::fromGray(_graya_getv(gray_bitmap_color));
|
||||
app::Color color2 = app::Color::fromGray(graya_getv(gray_bitmap_color));
|
||||
rectfill(graph, 0, 0, rc.w-1, rc.h-1,
|
||||
color_utils::color_for_allegro(color2, 32));
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "app/app.h"
|
||||
#include "app/modules/palettes.h"
|
||||
#include "raster/blend.h"
|
||||
#include "raster/conversion_alleg.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/sprite.h"
|
||||
@ -46,10 +47,10 @@ static Palette* ase_current_palette = NULL;
|
||||
int init_module_palette()
|
||||
{
|
||||
ase_default_palette = new Palette(FrameNumber(0), 256);
|
||||
ase_default_palette->fromAllegro(default_palette);
|
||||
convert_palette_from_allegro(default_palette, ase_default_palette);
|
||||
|
||||
ase_current_palette = new Palette(FrameNumber(0), 256);
|
||||
ase_current_palette->fromAllegro(black_palette);
|
||||
convert_palette_from_allegro(black_palette, ase_current_palette);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -94,7 +95,7 @@ bool set_current_palette(const Palette *_palette, bool forced)
|
||||
|
||||
// Change system color palette
|
||||
PALETTE allegPal;
|
||||
palette->toAllegro(allegPal);
|
||||
convert_palette_to_allegro(palette, allegPal);
|
||||
set_palette(allegPal);
|
||||
|
||||
// Call slots in signals
|
||||
@ -125,12 +126,12 @@ void set_current_color(int index, int r, int g, int b)
|
||||
|
||||
c = ase_current_palette->getEntry(index);
|
||||
|
||||
if (_rgba_getr(c) != r ||
|
||||
_rgba_getg(c) != g ||
|
||||
_rgba_getb(c) != b) {
|
||||
if (rgba_getr(c) != r ||
|
||||
rgba_getg(c) != g ||
|
||||
rgba_getb(c) != b) {
|
||||
RGB rgb;
|
||||
|
||||
ase_current_palette->setEntry(index, _rgba(r, g, b, 255));
|
||||
ase_current_palette->setEntry(index, rgba(r, g, b, 255));
|
||||
|
||||
rgb.r = r>>2;
|
||||
rgb.g = g>>2;
|
||||
|
@ -29,8 +29,10 @@
|
||||
#include "base/bind.h"
|
||||
#include "base/scoped_lock.h"
|
||||
#include "base/thread.h"
|
||||
#include "raster/conversion_alleg.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/primitives.h"
|
||||
#include "raster/rotate.h"
|
||||
#include "raster/sprite.h"
|
||||
|
||||
@ -47,7 +49,6 @@ public:
|
||||
, m_fileitem(fileitem)
|
||||
, m_thumbnail(NULL)
|
||||
, m_palette(NULL)
|
||||
, m_thumbnailBitmap(NULL)
|
||||
, m_thread(Bind<void>(&Worker::loadBgThread, this)) {
|
||||
}
|
||||
|
||||
@ -84,18 +85,18 @@ private:
|
||||
sprite->render(image, 0, 0, FrameNumber(0));
|
||||
|
||||
// Calculate the thumbnail size
|
||||
int thumb_w = MAX_THUMBNAIL_SIZE * image->w / MAX(image->w, image->h);
|
||||
int thumb_h = MAX_THUMBNAIL_SIZE * image->h / MAX(image->w, image->h);
|
||||
if (MAX(thumb_w, thumb_h) > MAX(image->w, image->h)) {
|
||||
thumb_w = image->w;
|
||||
thumb_h = image->h;
|
||||
int thumb_w = MAX_THUMBNAIL_SIZE * image->getWidth() / MAX(image->getWidth(), image->getHeight());
|
||||
int thumb_h = MAX_THUMBNAIL_SIZE * image->getHeight() / MAX(image->getWidth(), image->getHeight());
|
||||
if (MAX(thumb_w, thumb_h) > MAX(image->getWidth(), image->getHeight())) {
|
||||
thumb_w = image->getWidth();
|
||||
thumb_h = image->getHeight();
|
||||
}
|
||||
thumb_w = MID(1, thumb_w, MAX_THUMBNAIL_SIZE);
|
||||
thumb_h = MID(1, thumb_h, MAX_THUMBNAIL_SIZE);
|
||||
|
||||
// Stretch the 'image'
|
||||
m_thumbnail.reset(Image::create(image->getPixelFormat(), thumb_w, thumb_h));
|
||||
image_clear(m_thumbnail, 0);
|
||||
clear_image(m_thumbnail, 0);
|
||||
image_scale(m_thumbnail, image, 0, 0, thumb_w, thumb_h);
|
||||
}
|
||||
|
||||
@ -103,8 +104,8 @@ private:
|
||||
|
||||
// Set the thumbnail of the file-item.
|
||||
if (m_thumbnail) {
|
||||
BITMAP* bmp = create_bitmap_ex(16, m_thumbnail->w, m_thumbnail->h);
|
||||
image_to_allegro(m_thumbnail, bmp, 0, 0, m_palette);
|
||||
BITMAP* bmp = create_bitmap_ex(16, m_thumbnail->getWidth(), m_thumbnail->getHeight());
|
||||
convert_image_to_allegro(m_thumbnail, bmp, 0, 0, m_palette);
|
||||
m_fileitem->setThumbnail(bmp);
|
||||
}
|
||||
}
|
||||
@ -117,7 +118,6 @@ private:
|
||||
FileOp* m_fop;
|
||||
IFileItem* m_fileitem;
|
||||
base::UniquePtr<Image> m_thumbnail;
|
||||
BITMAP* m_thumbnailBitmap;
|
||||
base::UniquePtr<Palette> m_palette;
|
||||
base::thread m_thread;
|
||||
};
|
||||
|
@ -31,223 +31,358 @@ namespace tools {
|
||||
using namespace gfx;
|
||||
using namespace filters;
|
||||
|
||||
namespace {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Ink Processing
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define DEFINE_INK_PROCESSING(addresses_define, \
|
||||
addresses_initialize, \
|
||||
addresses_increment, \
|
||||
processing) \
|
||||
addresses_define \
|
||||
register int x; \
|
||||
\
|
||||
/* Use mask */ \
|
||||
if (loop->useMask()) { \
|
||||
Point maskOrigin(loop->getMaskOrigin()); \
|
||||
const Rect& maskBounds(loop->getMask()->getBounds()); \
|
||||
\
|
||||
if ((y < maskOrigin.y) || (y >= maskOrigin.y+maskBounds.h)) \
|
||||
return; \
|
||||
\
|
||||
if (x1 < maskOrigin.x) \
|
||||
x1 = maskOrigin.x; \
|
||||
\
|
||||
if (x2 > maskOrigin.x+maskBounds.w-1) \
|
||||
x2 = maskOrigin.x+maskBounds.w-1; \
|
||||
\
|
||||
if (Image* bitmap = loop->getMask()->getBitmap()) { \
|
||||
addresses_initialize; \
|
||||
for (x=x1; x<=x2; ++x) { \
|
||||
if (bitmap->getpixel(x-maskOrigin.x, y-maskOrigin.y)) \
|
||||
processing; \
|
||||
\
|
||||
addresses_increment; \
|
||||
} \
|
||||
return; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
addresses_initialize; \
|
||||
for (x=x1; x<=x2; ++x) { \
|
||||
processing; \
|
||||
addresses_increment; \
|
||||
template<typename Derived>
|
||||
class InkProcessing {
|
||||
public:
|
||||
void operator()(int x1, int y, int x2, ToolLoop* loop) {
|
||||
int x;
|
||||
|
||||
// Use mask
|
||||
if (loop->useMask()) {
|
||||
Point maskOrigin(loop->getMaskOrigin());
|
||||
const Rect& maskBounds(loop->getMask()->getBounds());
|
||||
|
||||
if ((y < maskOrigin.y) || (y >= maskOrigin.y+maskBounds.h))
|
||||
return;
|
||||
|
||||
if (x1 < maskOrigin.x)
|
||||
x1 = maskOrigin.x;
|
||||
|
||||
if (x2 > maskOrigin.x+maskBounds.w-1)
|
||||
x2 = maskOrigin.x+maskBounds.w-1;
|
||||
|
||||
if (Image* bitmap = loop->getMask()->getBitmap()) {
|
||||
static_cast<Derived*>(this)->initIterators(loop, x1, y);
|
||||
|
||||
for (x=x1; x<=x2; ++x) {
|
||||
if (bitmap->getPixel(x-maskOrigin.x, y-maskOrigin.y))
|
||||
static_cast<Derived*>(this)->processPixel(x, y);
|
||||
|
||||
static_cast<Derived*>(this)->moveIterators();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static_cast<Derived*>(this)->initIterators(loop, x1, y);
|
||||
for (x=x1; x<=x2; ++x) {
|
||||
static_cast<Derived*>(this)->processPixel(x, y);
|
||||
static_cast<Derived*>(this)->moveIterators();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived, typename ImageTraits>
|
||||
class SimpleInkProcessing : public InkProcessing<Derived> {
|
||||
public:
|
||||
void initIterators(ToolLoop* loop, int x1, int y) {
|
||||
m_dstAddress = (typename ImageTraits::address_t)loop->getDstImage()->getPixelAddress(x1, y);
|
||||
}
|
||||
|
||||
#define DEFINE_INK_PROCESSING_DST(Traits, processing) \
|
||||
DEFINE_INK_PROCESSING(register Traits::address_t dst_address; , \
|
||||
dst_address = ((Traits::address_t*)loop->getDstImage()->line)[y]+x1; , \
|
||||
++dst_address , \
|
||||
processing)
|
||||
void moveIterators() {
|
||||
++m_dstAddress;
|
||||
}
|
||||
|
||||
#define DEFINE_INK_PROCESSING_SRCDST(Traits, processing) \
|
||||
DEFINE_INK_PROCESSING(register Traits::address_t src_address; \
|
||||
register Traits::address_t dst_address; , \
|
||||
src_address = ((Traits::address_t*)loop->getSrcImage()->line)[y]+x1; \
|
||||
dst_address = ((Traits::address_t*)loop->getDstImage()->line)[y]+x1; , \
|
||||
++src_address; \
|
||||
++dst_address; , \
|
||||
processing)
|
||||
protected:
|
||||
typename ImageTraits::address_t m_dstAddress;
|
||||
};
|
||||
|
||||
template<typename Derived, typename ImageTraits>
|
||||
class DoubleInkProcessing : public InkProcessing<Derived> {
|
||||
public:
|
||||
void initIterators(ToolLoop* loop, int x1, int y) {
|
||||
m_srcAddress = (typename ImageTraits::address_t)loop->getSrcImage()->getPixelAddress(x1, y);
|
||||
m_dstAddress = (typename ImageTraits::address_t)loop->getDstImage()->getPixelAddress(x1, y);
|
||||
}
|
||||
|
||||
void moveIterators() {
|
||||
++m_srcAddress;
|
||||
++m_dstAddress;
|
||||
}
|
||||
|
||||
protected:
|
||||
typename ImageTraits::address_t m_srcAddress;
|
||||
typename ImageTraits::address_t m_dstAddress;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Opaque Ink
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void ink_hline32_opaque(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
int c = loop->getPrimaryColor();
|
||||
template<typename ImageTraits>
|
||||
class OpaqueInkProcessing : public SimpleInkProcessing<OpaqueInkProcessing<ImageTraits>, ImageTraits> {
|
||||
public:
|
||||
OpaqueInkProcessing(ToolLoop* loop) {
|
||||
m_color = loop->getPrimaryColor();
|
||||
}
|
||||
|
||||
DEFINE_INK_PROCESSING_DST
|
||||
(RgbTraits,
|
||||
*dst_address = c );
|
||||
}
|
||||
void processPixel(int x, int y) {
|
||||
*SimpleInkProcessing<OpaqueInkProcessing<ImageTraits>, ImageTraits>::m_dstAddress = m_color;
|
||||
}
|
||||
|
||||
static void ink_hline16_opaque(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
int c = loop->getPrimaryColor();
|
||||
|
||||
DEFINE_INK_PROCESSING_DST
|
||||
(GrayscaleTraits,
|
||||
*dst_address = c );
|
||||
}
|
||||
|
||||
static void ink_hline8_opaque(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
int c = loop->getPrimaryColor();
|
||||
|
||||
DEFINE_INK_PROCESSING_DST
|
||||
(IndexedTraits,
|
||||
*dst_address = c );
|
||||
|
||||
/* memset(((uint8_t**)data->dst_image->line)[y]+x1, data->color, x2-x1+1); */
|
||||
}
|
||||
private:
|
||||
color_t m_color;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Putalpha Ink
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void ink_hline32_putalpha(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
int c = loop->getPrimaryColor();
|
||||
int opacity = loop->getOpacity();
|
||||
template<typename ImageTraits>
|
||||
class PutAlphaInkProcessing : public SimpleInkProcessing<OpaqueInkProcessing<ImageTraits>, ImageTraits> {
|
||||
public:
|
||||
PutAlphaInkProcessing(ToolLoop* loop) {
|
||||
m_color = loop->getPrimaryColor();
|
||||
m_opacity = loop->getOpacity();
|
||||
}
|
||||
|
||||
DEFINE_INK_PROCESSING_DST
|
||||
(RgbTraits,
|
||||
*dst_address = _rgba(_rgba_getr(c),
|
||||
_rgba_getg(c),
|
||||
_rgba_getb(c),
|
||||
opacity)
|
||||
);
|
||||
void processPixel(int x, int y) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
private:
|
||||
color_t m_color;
|
||||
int m_opacity;
|
||||
};
|
||||
|
||||
template<>
|
||||
void PutAlphaInkProcessing<RgbTraits>::processPixel(int x, int y) {
|
||||
*m_dstAddress = rgba(rgba_getr(m_color),
|
||||
rgba_getg(m_color),
|
||||
rgba_getb(m_color),
|
||||
m_opacity);
|
||||
}
|
||||
|
||||
static void ink_hline16_putalpha(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
int c = loop->getPrimaryColor();
|
||||
int opacity = loop->getOpacity();
|
||||
|
||||
DEFINE_INK_PROCESSING_DST
|
||||
(GrayscaleTraits,
|
||||
*dst_address = _graya(_graya_getv(c),
|
||||
opacity)
|
||||
);
|
||||
template<>
|
||||
void PutAlphaInkProcessing<GrayscaleTraits>::processPixel(int x, int y) {
|
||||
*m_dstAddress = graya(graya_getv(m_color), m_opacity);
|
||||
}
|
||||
|
||||
static void ink_hline8_putalpha(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
int c = loop->getPrimaryColor();
|
||||
|
||||
DEFINE_INK_PROCESSING_DST
|
||||
(IndexedTraits,
|
||||
*dst_address = c );
|
||||
template<>
|
||||
void PutAlphaInkProcessing<IndexedTraits>::processPixel(int x, int y) {
|
||||
// Do nothing, as indexed images doesn't have alpha channel.
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Transparent Ink
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void ink_hline32_transparent(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
int color = loop->getPrimaryColor();
|
||||
int opacity = loop->getOpacity();
|
||||
template<typename ImageTraits>
|
||||
class TransparentInkProcessing : public DoubleInkProcessing<TransparentInkProcessing<ImageTraits>, ImageTraits> {
|
||||
public:
|
||||
TransparentInkProcessing(ToolLoop* loop) {
|
||||
m_color = loop->getPrimaryColor();
|
||||
m_opacity = loop->getOpacity();
|
||||
}
|
||||
|
||||
DEFINE_INK_PROCESSING_SRCDST
|
||||
(RgbTraits,
|
||||
*dst_address = _rgba_blend_normal(*src_address, color, opacity));
|
||||
void processPixel(int x, int y) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
private:
|
||||
color_t m_color;
|
||||
int m_opacity;
|
||||
};
|
||||
|
||||
template<>
|
||||
void TransparentInkProcessing<RgbTraits>::processPixel(int x, int y) {
|
||||
*m_dstAddress = rgba_blend_normal(*m_srcAddress, m_color, m_opacity);
|
||||
}
|
||||
|
||||
static void ink_hline16_transparent(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
int color = loop->getPrimaryColor();
|
||||
int opacity = loop->getOpacity();
|
||||
|
||||
DEFINE_INK_PROCESSING_SRCDST
|
||||
(GrayscaleTraits,
|
||||
*dst_address = _graya_blend_normal(*src_address, color, opacity));
|
||||
template<>
|
||||
void TransparentInkProcessing<GrayscaleTraits>::processPixel(int x, int y) {
|
||||
*m_dstAddress = graya_blend_normal(*m_srcAddress, m_color, m_opacity);
|
||||
}
|
||||
|
||||
static void ink_hline8_transparent(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
Palette* pal = get_current_palette();
|
||||
RgbMap* rgbmap = loop->getRgbMap();
|
||||
uint32_t c;
|
||||
uint32_t tc = pal->getEntry(loop->getPrimaryColor());
|
||||
int opacity = loop->getOpacity();
|
||||
template<>
|
||||
class TransparentInkProcessing<IndexedTraits> : public DoubleInkProcessing<TransparentInkProcessing<IndexedTraits>, IndexedTraits> {
|
||||
public:
|
||||
TransparentInkProcessing(ToolLoop* loop) :
|
||||
m_palette(get_current_palette()),
|
||||
m_rgbmap(loop->getRgbMap()),
|
||||
m_opacity(loop->getOpacity()),
|
||||
m_color(m_palette->getEntry(loop->getPrimaryColor())) {
|
||||
}
|
||||
|
||||
DEFINE_INK_PROCESSING_SRCDST
|
||||
(IndexedTraits,
|
||||
{
|
||||
c = _rgba_blend_normal(pal->getEntry(*src_address), tc, opacity);
|
||||
*dst_address = rgbmap->mapColor(_rgba_getr(c),
|
||||
_rgba_getg(c),
|
||||
_rgba_getb(c));
|
||||
});
|
||||
}
|
||||
void processPixel(int x, int y) {
|
||||
color_t c = rgba_blend_normal(m_palette->getEntry(*m_srcAddress), m_color, m_opacity);
|
||||
*m_dstAddress = m_rgbmap->mapColor(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c));
|
||||
}
|
||||
|
||||
private:
|
||||
const Palette* m_palette;
|
||||
const RgbMap* m_rgbmap;
|
||||
int m_opacity;
|
||||
color_t m_color;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Blur Ink
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace {
|
||||
struct BlurGetPixelsDelegateRgba
|
||||
{
|
||||
template<typename ImageTraits>
|
||||
class BlurInkProcessing : public DoubleInkProcessing<BlurInkProcessing<ImageTraits>, ImageTraits> {
|
||||
public:
|
||||
BlurInkProcessing(ToolLoop* loop) {
|
||||
}
|
||||
void processPixel(int x, int y) {
|
||||
// Do nothing (it's specialized for each case)
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class BlurInkProcessing<RgbTraits> : public DoubleInkProcessing<BlurInkProcessing<RgbTraits>, RgbTraits> {
|
||||
public:
|
||||
BlurInkProcessing(ToolLoop* loop) :
|
||||
m_opacity(loop->getOpacity()),
|
||||
m_tiledMode(loop->getDocumentSettings()->getTiledMode()),
|
||||
m_srcImage(loop->getSrcImage()) {
|
||||
}
|
||||
|
||||
void processPixel(int x, int y) {
|
||||
m_area.reset();
|
||||
get_neighboring_pixels<RgbTraits>(m_srcImage, x, y, 3, 3, 1, 1, m_tiledMode, m_area);
|
||||
|
||||
if (m_area.count > 0) {
|
||||
m_area.r /= m_area.count;
|
||||
m_area.g /= m_area.count;
|
||||
m_area.b /= m_area.count;
|
||||
m_area.a /= 9;
|
||||
|
||||
RgbTraits::pixel_t c = *m_srcAddress;
|
||||
m_area.r = rgba_getr(c) + (m_area.r-rgba_getr(c)) * m_opacity / 255;
|
||||
m_area.g = rgba_getg(c) + (m_area.g-rgba_getg(c)) * m_opacity / 255;
|
||||
m_area.b = rgba_getb(c) + (m_area.b-rgba_getb(c)) * m_opacity / 255;
|
||||
m_area.a = rgba_geta(c) + (m_area.a-rgba_geta(c)) * m_opacity / 255;
|
||||
|
||||
*m_dstAddress = rgba(m_area.r, m_area.g, m_area.b, m_area.a);
|
||||
}
|
||||
else {
|
||||
*m_dstAddress = *m_srcAddress;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct GetPixelsDelegate {
|
||||
int count, r, g, b, a;
|
||||
|
||||
void reset() { count = r = g = b = a = 0; }
|
||||
|
||||
void operator()(RgbTraits::pixel_t color)
|
||||
{
|
||||
if (_rgba_geta(color) != 0) {
|
||||
r += _rgba_getr(color);
|
||||
g += _rgba_getg(color);
|
||||
b += _rgba_getb(color);
|
||||
a += _rgba_geta(color);
|
||||
if (rgba_geta(color) != 0) {
|
||||
r += rgba_getr(color);
|
||||
g += rgba_getg(color);
|
||||
b += rgba_getb(color);
|
||||
a += rgba_geta(color);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct BlurGetPixelsDelegateGrayscale
|
||||
{
|
||||
int m_opacity;
|
||||
TiledMode m_tiledMode;
|
||||
const Image* m_srcImage;
|
||||
GetPixelsDelegate m_area;
|
||||
};
|
||||
|
||||
template<>
|
||||
class BlurInkProcessing<GrayscaleTraits> : public DoubleInkProcessing<BlurInkProcessing<GrayscaleTraits>, GrayscaleTraits> {
|
||||
public:
|
||||
BlurInkProcessing(ToolLoop* loop) :
|
||||
m_opacity(loop->getOpacity()),
|
||||
m_tiledMode(loop->getDocumentSettings()->getTiledMode()),
|
||||
m_srcImage(loop->getSrcImage()) {
|
||||
}
|
||||
|
||||
void processPixel(int x, int y) {
|
||||
m_area.reset();
|
||||
get_neighboring_pixels<GrayscaleTraits>(m_srcImage, x, y, 3, 3, 1, 1, m_tiledMode, m_area);
|
||||
|
||||
if (m_area.count > 0) {
|
||||
m_area.v /= m_area.count;
|
||||
m_area.a /= 9;
|
||||
|
||||
GrayscaleTraits::pixel_t c = *m_srcAddress;
|
||||
m_area.v = graya_getv(c) + (m_area.v-graya_getv(c)) * m_opacity / 255;
|
||||
m_area.a = graya_geta(c) + (m_area.a-graya_geta(c)) * m_opacity / 255;
|
||||
|
||||
*m_dstAddress = graya(m_area.v, m_area.a);
|
||||
}
|
||||
else {
|
||||
*m_dstAddress = *m_srcAddress;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct GetPixelsDelegate {
|
||||
int count, v, a;
|
||||
|
||||
void reset() { count = v = a = 0; }
|
||||
|
||||
void operator()(GrayscaleTraits::pixel_t color)
|
||||
{
|
||||
if (_graya_geta(color) > 0) {
|
||||
v += _graya_getv(color);
|
||||
a += _graya_geta(color);
|
||||
if (graya_geta(color) > 0) {
|
||||
v += graya_getv(color);
|
||||
a += graya_geta(color);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct BlurGetPixelsDelegateIndexed
|
||||
{
|
||||
int m_opacity;
|
||||
TiledMode m_tiledMode;
|
||||
const Image* m_srcImage;
|
||||
GetPixelsDelegate m_area;
|
||||
};
|
||||
|
||||
template<>
|
||||
class BlurInkProcessing<IndexedTraits> : public DoubleInkProcessing<BlurInkProcessing<IndexedTraits>, IndexedTraits> {
|
||||
public:
|
||||
BlurInkProcessing(ToolLoop* loop) :
|
||||
m_palette(get_current_palette()),
|
||||
m_rgbmap(loop->getRgbMap()),
|
||||
m_area(get_current_palette()),
|
||||
m_opacity(loop->getOpacity()),
|
||||
m_tiledMode(loop->getDocumentSettings()->getTiledMode()),
|
||||
m_srcImage(loop->getSrcImage()) {
|
||||
}
|
||||
|
||||
void processPixel(int x, int y) {
|
||||
m_area.reset();
|
||||
get_neighboring_pixels<IndexedTraits>(m_srcImage, x, y, 3, 3, 1, 1, m_tiledMode, m_area);
|
||||
|
||||
if (m_area.count > 0 && m_area.a/9 >= 128) {
|
||||
m_area.r /= m_area.count;
|
||||
m_area.g /= m_area.count;
|
||||
m_area.b /= m_area.count;
|
||||
|
||||
uint32_t color32 = m_palette->getEntry(*m_srcAddress);
|
||||
m_area.r = rgba_getr(color32) + (m_area.r-rgba_getr(color32)) * m_opacity / 255;
|
||||
m_area.g = rgba_getg(color32) + (m_area.g-rgba_getg(color32)) * m_opacity / 255;
|
||||
m_area.b = rgba_getb(color32) + (m_area.b-rgba_getb(color32)) * m_opacity / 255;
|
||||
|
||||
*m_dstAddress = m_rgbmap->mapColor(m_area.r, m_area.g, m_area.b);
|
||||
}
|
||||
else {
|
||||
*m_dstAddress = *m_srcAddress;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct GetPixelsDelegate {
|
||||
const Palette* pal;
|
||||
int count, r, g, b, a;
|
||||
|
||||
BlurGetPixelsDelegateIndexed(const Palette* pal) : pal(pal) { }
|
||||
GetPixelsDelegate(const Palette* pal) : pal(pal) { }
|
||||
|
||||
void reset() { count = r = g = b = a = 0; }
|
||||
|
||||
@ -256,274 +391,211 @@ namespace {
|
||||
a += (color == 0 ? 0: 255);
|
||||
|
||||
uint32_t color32 = pal->getEntry(color);
|
||||
r += _rgba_getr(color32);
|
||||
g += _rgba_getg(color32);
|
||||
b += _rgba_getb(color32);
|
||||
r += rgba_getr(color32);
|
||||
g += rgba_getg(color32);
|
||||
b += rgba_getb(color32);
|
||||
count++;
|
||||
}
|
||||
};
|
||||
|
||||
const Palette* m_palette;
|
||||
const RgbMap* m_rgbmap;
|
||||
int m_opacity;
|
||||
TiledMode m_tiledMode;
|
||||
const Image* m_srcImage;
|
||||
GetPixelsDelegate m_area;
|
||||
};
|
||||
|
||||
static void ink_hline32_blur(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
int opacity = loop->getOpacity();
|
||||
TiledMode tiledMode = loop->getDocumentSettings()->getTiledMode();
|
||||
const Image* src = loop->getSrcImage();
|
||||
BlurGetPixelsDelegateRgba delegate;
|
||||
|
||||
DEFINE_INK_PROCESSING_SRCDST
|
||||
(RgbTraits,
|
||||
{
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<RgbTraits>(src, x, y, 3, 3, 1, 1, tiledMode, delegate);
|
||||
|
||||
if (delegate.count > 0) {
|
||||
delegate.r /= delegate.count;
|
||||
delegate.g /= delegate.count;
|
||||
delegate.b /= delegate.count;
|
||||
delegate.a /= 9;
|
||||
|
||||
RgbTraits::pixel_t c = *src_address;
|
||||
delegate.r = _rgba_getr(c) + (delegate.r-_rgba_getr(c)) * opacity / 255;
|
||||
delegate.g = _rgba_getg(c) + (delegate.g-_rgba_getg(c)) * opacity / 255;
|
||||
delegate.b = _rgba_getb(c) + (delegate.b-_rgba_getb(c)) * opacity / 255;
|
||||
delegate.a = _rgba_geta(c) + (delegate.a-_rgba_geta(c)) * opacity / 255;
|
||||
|
||||
*dst_address = _rgba(delegate.r, delegate.g, delegate.b, delegate.a);
|
||||
}
|
||||
else {
|
||||
*dst_address = *src_address;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void ink_hline16_blur(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
int opacity = loop->getOpacity();
|
||||
TiledMode tiledMode = loop->getDocumentSettings()->getTiledMode();
|
||||
const Image* src = loop->getSrcImage();
|
||||
BlurGetPixelsDelegateGrayscale delegate;
|
||||
|
||||
DEFINE_INK_PROCESSING_SRCDST
|
||||
(GrayscaleTraits,
|
||||
{
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<GrayscaleTraits>(src, x, y, 3, 3, 1, 1, tiledMode, delegate);
|
||||
|
||||
if (delegate.count > 0) {
|
||||
delegate.v /= delegate.count;
|
||||
delegate.a /= 9;
|
||||
|
||||
GrayscaleTraits::pixel_t c = *src_address;
|
||||
delegate.v = _graya_getv(c) + (delegate.v-_graya_getv(c)) * opacity / 255;
|
||||
delegate.a = _graya_geta(c) + (delegate.a-_graya_geta(c)) * opacity / 255;
|
||||
|
||||
*dst_address = _graya(delegate.v, delegate.a);
|
||||
}
|
||||
else {
|
||||
*dst_address = *src_address;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void ink_hline8_blur(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
const Palette *pal = get_current_palette();
|
||||
RgbMap* rgbmap = loop->getRgbMap();
|
||||
int opacity = loop->getOpacity();
|
||||
TiledMode tiledMode = loop->getDocumentSettings()->getTiledMode();
|
||||
const Image* src = loop->getSrcImage();
|
||||
BlurGetPixelsDelegateIndexed delegate(pal);
|
||||
|
||||
DEFINE_INK_PROCESSING_SRCDST
|
||||
(IndexedTraits,
|
||||
{
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<IndexedTraits>(src, x, y, 3, 3, 1, 1, tiledMode, delegate);
|
||||
|
||||
if (delegate.count > 0 && delegate.a/9 >= 128) {
|
||||
delegate.r /= delegate.count;
|
||||
delegate.g /= delegate.count;
|
||||
delegate.b /= delegate.count;
|
||||
|
||||
uint32_t color32 = pal->getEntry(*src_address);
|
||||
delegate.r = _rgba_getr(color32) + (delegate.r-_rgba_getr(color32)) * opacity / 255;
|
||||
delegate.g = _rgba_getg(color32) + (delegate.g-_rgba_getg(color32)) * opacity / 255;
|
||||
delegate.b = _rgba_getb(color32) + (delegate.b-_rgba_getb(color32)) * opacity / 255;
|
||||
|
||||
*dst_address = rgbmap->mapColor(delegate.r, delegate.g, delegate.b);
|
||||
}
|
||||
else {
|
||||
*dst_address = *src_address;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Replace Ink
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void ink_hline32_replace(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
uint32_t color1 = loop->getPrimaryColor();
|
||||
uint32_t color2 = loop->getSecondaryColor();
|
||||
int opacity = loop->getOpacity();
|
||||
template<typename ImageTraits>
|
||||
class ReplaceInkProcessing : public DoubleInkProcessing<ReplaceInkProcessing<ImageTraits>, ImageTraits> {
|
||||
public:
|
||||
ReplaceInkProcessing(ToolLoop* loop) {
|
||||
m_color1 = loop->getPrimaryColor();
|
||||
m_color2 = loop->getSecondaryColor();
|
||||
m_opacity = loop->getOpacity();
|
||||
}
|
||||
|
||||
DEFINE_INK_PROCESSING_SRCDST
|
||||
(RgbTraits,
|
||||
if (*src_address == color1) {
|
||||
*dst_address = _rgba_blend_normal(*src_address, color2, opacity);
|
||||
});
|
||||
void processPixel(int x, int y) {
|
||||
// Do nothing (it's specialized for each case)
|
||||
}
|
||||
|
||||
private:
|
||||
color_t m_color1;
|
||||
color_t m_color2;
|
||||
int m_opacity;
|
||||
};
|
||||
|
||||
template<>
|
||||
void ReplaceInkProcessing<RgbTraits>::processPixel(int x, int y) {
|
||||
if (*m_srcAddress == m_color1)
|
||||
*m_dstAddress = rgba_blend_normal(*m_srcAddress, m_color2, m_opacity);
|
||||
}
|
||||
|
||||
static void ink_hline16_replace(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
int color1 = loop->getPrimaryColor();
|
||||
int color2 = loop->getSecondaryColor();
|
||||
int opacity = loop->getOpacity();
|
||||
|
||||
DEFINE_INK_PROCESSING_SRCDST
|
||||
(GrayscaleTraits,
|
||||
if (*src_address == color1) {
|
||||
*dst_address = _graya_blend_normal(*src_address, color2, opacity);
|
||||
});
|
||||
template<>
|
||||
void ReplaceInkProcessing<GrayscaleTraits>::processPixel(int x, int y) {
|
||||
if (*m_srcAddress == m_color1)
|
||||
*m_dstAddress = graya_blend_normal(*m_srcAddress, m_color2, m_opacity);
|
||||
}
|
||||
|
||||
static void ink_hline8_replace(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
int color1 = loop->getPrimaryColor();
|
||||
const Palette *pal = get_current_palette();
|
||||
RgbMap* rgbmap = loop->getRgbMap();
|
||||
uint32_t c;
|
||||
uint32_t tc = pal->getEntry(loop->getSecondaryColor());
|
||||
int opacity = loop->getOpacity();
|
||||
template<>
|
||||
class ReplaceInkProcessing<IndexedTraits> : public DoubleInkProcessing<ReplaceInkProcessing<IndexedTraits>, IndexedTraits> {
|
||||
public:
|
||||
ReplaceInkProcessing(ToolLoop* loop) {
|
||||
m_palette = get_current_palette();
|
||||
m_rgbmap = loop->getRgbMap();
|
||||
m_color1 = loop->getPrimaryColor();
|
||||
m_color2 = m_palette->getEntry(loop->getSecondaryColor());
|
||||
m_opacity = loop->getOpacity();
|
||||
}
|
||||
|
||||
DEFINE_INK_PROCESSING_SRCDST
|
||||
(IndexedTraits,
|
||||
if (*src_address == color1) {
|
||||
c = _rgba_blend_normal(pal->getEntry(*src_address), tc, opacity);
|
||||
*dst_address = rgbmap->mapColor(_rgba_getr(c),
|
||||
_rgba_getg(c),
|
||||
_rgba_getb(c));
|
||||
});
|
||||
}
|
||||
void processPixel(int x, int y) {
|
||||
if (*m_srcAddress == m_color1) {
|
||||
color_t c = rgba_blend_normal(m_palette->getEntry(*m_srcAddress), m_color2, m_opacity);
|
||||
*m_dstAddress = m_rgbmap->mapColor(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const Palette* m_palette;
|
||||
const RgbMap* m_rgbmap;
|
||||
color_t m_color1;
|
||||
color_t m_color2;
|
||||
int m_opacity;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Jumble Ink
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define JUMBLE_XY_IN_UV() \
|
||||
u = x + (rand() % 3)-1 - speed.x; \
|
||||
v = y + (rand() % 3)-1 - speed.y; \
|
||||
\
|
||||
if (tiled & TILED_X_AXIS) { \
|
||||
if (u < 0) \
|
||||
u = loop->getSrcImage()->w - (-(u+1) % loop->getSrcImage()->w) - 1; \
|
||||
else if (u >= loop->getSrcImage()->w) \
|
||||
u %= loop->getSrcImage()->w; \
|
||||
} \
|
||||
else { \
|
||||
u = MID(0, u, loop->getSrcImage()->w-1); \
|
||||
} \
|
||||
\
|
||||
if (tiled & TILED_Y_AXIS) { \
|
||||
if (v < 0) \
|
||||
v = loop->getSrcImage()->h - (-(v+1) % loop->getSrcImage()->h) - 1; \
|
||||
else if (v >= loop->getSrcImage()->h) \
|
||||
v %= loop->getSrcImage()->h; \
|
||||
} \
|
||||
else { \
|
||||
v = MID(0, v, loop->getSrcImage()->h-1); \
|
||||
} \
|
||||
color = image_getpixel(loop->getSrcImage(), u, v);
|
||||
template<typename ImageTraits>
|
||||
class JumbleInkProcessing : public DoubleInkProcessing<JumbleInkProcessing<ImageTraits>, ImageTraits> {
|
||||
public:
|
||||
JumbleInkProcessing(ToolLoop* loop) :
|
||||
m_palette(get_current_palette()),
|
||||
m_rgbmap(loop->getRgbMap()),
|
||||
m_speed(loop->getSpeed() / 4),
|
||||
m_opacity(loop->getOpacity()),
|
||||
m_tiledMode(loop->getDocumentSettings()->getTiledMode()),
|
||||
m_srcImage(loop->getSrcImage()),
|
||||
m_srcImageWidth(m_srcImage->getWidth()),
|
||||
m_srcImageHeight(m_srcImage->getHeight()) {
|
||||
}
|
||||
|
||||
static void ink_hline32_jumble(int x1, int y, int x2, ToolLoop* loop)
|
||||
void processPixel(int x, int y) {
|
||||
// Do nothing (it's specialized for each case)
|
||||
}
|
||||
|
||||
private:
|
||||
void pickColorFromArea(int x, int y) {
|
||||
int u = x + (rand() % 3)-1 - m_speed.x;
|
||||
int v = y + (rand() % 3)-1 - m_speed.y;
|
||||
|
||||
if (m_tiledMode & TILED_X_AXIS) {
|
||||
if (u < 0)
|
||||
u = m_srcImageWidth - (-(u+1) % m_srcImageWidth) - 1;
|
||||
else if (u >= m_srcImageWidth)
|
||||
u %= m_srcImageWidth;
|
||||
}
|
||||
else {
|
||||
u = MID(0, u, m_srcImageWidth-1);
|
||||
}
|
||||
|
||||
if (m_tiledMode & TILED_Y_AXIS) {
|
||||
if (v < 0)
|
||||
v = m_srcImageHeight - (-(v+1) % m_srcImageHeight) - 1;
|
||||
else if (v >= m_srcImageHeight)
|
||||
v %= m_srcImageHeight;
|
||||
}
|
||||
else {
|
||||
v = MID(0, v, m_srcImageHeight-1);
|
||||
}
|
||||
m_color = get_pixel(m_srcImage, u, v);
|
||||
}
|
||||
|
||||
const Palette* m_palette;
|
||||
const RgbMap* m_rgbmap;
|
||||
Point m_speed;
|
||||
int m_opacity;
|
||||
TiledMode m_tiledMode;
|
||||
Image* m_srcImage;
|
||||
int m_srcImageWidth;
|
||||
int m_srcImageHeight;
|
||||
color_t m_color;
|
||||
};
|
||||
|
||||
template<>
|
||||
void JumbleInkProcessing<RgbTraits>::processPixel(int x, int y)
|
||||
{
|
||||
int opacity = loop->getOpacity();
|
||||
Point speed(loop->getSpeed() / 4);
|
||||
TiledMode tiled = loop->getDocumentSettings()->getTiledMode();
|
||||
int u, v, color;
|
||||
|
||||
DEFINE_INK_PROCESSING_SRCDST
|
||||
(RgbTraits,
|
||||
{
|
||||
JUMBLE_XY_IN_UV();
|
||||
*dst_address = _rgba_blend_merge(*src_address, color, opacity);
|
||||
}
|
||||
);
|
||||
pickColorFromArea(x, y);
|
||||
*m_dstAddress = rgba_blend_merge(*m_srcAddress, m_color, m_opacity);
|
||||
}
|
||||
|
||||
static void ink_hline16_jumble(int x1, int y, int x2, ToolLoop* loop)
|
||||
template<>
|
||||
void JumbleInkProcessing<GrayscaleTraits>::processPixel(int x, int y)
|
||||
{
|
||||
int opacity = loop->getOpacity();
|
||||
Point speed(loop->getSpeed() / 4);
|
||||
TiledMode tiled = loop->getDocumentSettings()->getTiledMode();
|
||||
int u, v, color;
|
||||
|
||||
DEFINE_INK_PROCESSING_SRCDST
|
||||
(GrayscaleTraits,
|
||||
{
|
||||
JUMBLE_XY_IN_UV();
|
||||
*dst_address = _graya_blend_merge(*src_address, color, opacity);
|
||||
}
|
||||
);
|
||||
pickColorFromArea(x, y);
|
||||
*m_dstAddress = graya_blend_merge(*m_srcAddress, m_color, m_opacity);
|
||||
}
|
||||
|
||||
static void ink_hline8_jumble(int x1, int y, int x2, ToolLoop* loop)
|
||||
template<>
|
||||
void JumbleInkProcessing<IndexedTraits>::processPixel(int x, int y)
|
||||
{
|
||||
const Palette *pal = get_current_palette();
|
||||
const RgbMap* rgbmap = loop->getRgbMap();
|
||||
uint32_t c, tc;
|
||||
int opacity = loop->getOpacity();
|
||||
Point speed(loop->getSpeed() / 4);
|
||||
TiledMode tiled = loop->getDocumentSettings()->getTiledMode();
|
||||
int u, v, color;
|
||||
pickColorFromArea(x, y);
|
||||
|
||||
DEFINE_INK_PROCESSING_SRCDST
|
||||
(IndexedTraits,
|
||||
{
|
||||
JUMBLE_XY_IN_UV();
|
||||
color_t tc = (m_color != 0 ? m_palette->getEntry(m_color): 0);
|
||||
color_t c = rgba_blend_merge(*m_srcAddress != 0 ?
|
||||
m_palette->getEntry(*m_srcAddress): 0,
|
||||
tc, m_opacity);
|
||||
|
||||
tc = color != 0 ? pal->getEntry(color): 0;
|
||||
c = _rgba_blend_merge(*src_address != 0 ? pal->getEntry(*src_address): 0,
|
||||
tc, opacity);
|
||||
|
||||
if (_rgba_geta(c) >= 128)
|
||||
*dst_address = rgbmap->mapColor(_rgba_getr(c),
|
||||
_rgba_getg(c),
|
||||
_rgba_getb(c));
|
||||
else
|
||||
*dst_address = 0;
|
||||
}
|
||||
);
|
||||
if (rgba_geta(c) >= 128)
|
||||
*m_dstAddress = m_rgbmap->mapColor(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c));
|
||||
else
|
||||
*m_dstAddress = 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Shading Ink
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void ink_hline32_shading(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
}
|
||||
template<typename ImageTraits>
|
||||
class ShadingInkProcessing : public DoubleInkProcessing<ShadingInkProcessing<ImageTraits>, ImageTraits> {
|
||||
public:
|
||||
ShadingInkProcessing(ToolLoop* loop) {
|
||||
}
|
||||
void processPixel(int x, int y) {
|
||||
// Do nothing (it's specialized for each case)
|
||||
}
|
||||
};
|
||||
|
||||
static void ink_hline16_shading(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
}
|
||||
template<>
|
||||
class ShadingInkProcessing<IndexedTraits> : public DoubleInkProcessing<ShadingInkProcessing<IndexedTraits>, IndexedTraits> {
|
||||
public:
|
||||
ShadingInkProcessing(ToolLoop* loop) :
|
||||
m_palette(get_current_palette()),
|
||||
m_shadeTable(loop->getShadingOptions()->getShadeTable()),
|
||||
m_left(loop->getMouseButton() == ToolLoop::Left) {
|
||||
}
|
||||
|
||||
static void ink_hline8_shading(int x1, int y, int x2, ToolLoop* loop)
|
||||
{
|
||||
const Palette* pal = get_current_palette();
|
||||
tools::ShadeTable8* shadeTable = loop->getShadingOptions()->getShadeTable();
|
||||
bool left = (loop->getMouseButton() == ToolLoop::Left);
|
||||
void processPixel(int x, int y) {
|
||||
if (m_left)
|
||||
*m_dstAddress = m_shadeTable->left(*m_srcAddress);
|
||||
else
|
||||
*m_dstAddress = m_shadeTable->right(*m_srcAddress);
|
||||
}
|
||||
|
||||
DEFINE_INK_PROCESSING_SRCDST
|
||||
(IndexedTraits,
|
||||
if (left)
|
||||
*dst_address = shadeTable->left(*src_address);
|
||||
else
|
||||
*dst_address = shadeTable->right(*src_address);
|
||||
);
|
||||
}
|
||||
private:
|
||||
const Palette* m_palette;
|
||||
tools::ShadeTable8* m_shadeTable;
|
||||
bool m_left;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -538,21 +610,30 @@ enum {
|
||||
MAX_INKS
|
||||
};
|
||||
|
||||
static AlgoHLine ink_processing[][3] =
|
||||
template<typename InkProcessing>
|
||||
void ink_processing_algo(int x1, int y, int x2, void* data)
|
||||
{
|
||||
#define DEF_INK(name) \
|
||||
{ (AlgoHLine)ink_hline32_##name, \
|
||||
(AlgoHLine)ink_hline16_##name, \
|
||||
(AlgoHLine)ink_hline8_##name }
|
||||
ToolLoop* loop = reinterpret_cast<ToolLoop*>(data);
|
||||
InkProcessing ink(loop);
|
||||
ink(x1, y, x2, loop);
|
||||
}
|
||||
|
||||
DEF_INK(opaque),
|
||||
DEF_INK(putalpha),
|
||||
DEF_INK(transparent),
|
||||
DEF_INK(blur),
|
||||
DEF_INK(replace),
|
||||
DEF_INK(jumble),
|
||||
DEF_INK(shading)
|
||||
AlgoHLine ink_processing[][3] =
|
||||
{
|
||||
#define DEFINE_INK(name) \
|
||||
{ ink_processing_algo<name<RgbTraits> >, \
|
||||
ink_processing_algo<name<GrayscaleTraits> >, \
|
||||
ink_processing_algo<name<IndexedTraits> > }
|
||||
|
||||
DEFINE_INK(OpaqueInkProcessing),
|
||||
DEFINE_INK(PutAlphaInkProcessing),
|
||||
DEFINE_INK(TransparentInkProcessing),
|
||||
DEFINE_INK(BlurInkProcessing),
|
||||
DEFINE_INK(ReplaceInkProcessing),
|
||||
DEFINE_INK(JumbleInkProcessing),
|
||||
DEFINE_INK(ShadingInkProcessing)
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
} // namespace tools
|
||||
} // namespace app
|
||||
|
@ -281,7 +281,7 @@ public:
|
||||
loop->getMask()->subtract(x1-offset.x, y-offset.y, x2-x1+1, 1);
|
||||
}
|
||||
else
|
||||
image_hline(loop->getDstImage(), x1, y, x2, loop->getPrimaryColor());
|
||||
draw_hline(loop->getDstImage(), x1, y, x2, loop->getPrimaryColor());
|
||||
}
|
||||
|
||||
void setFinalStep(ToolLoop* loop, bool state)
|
||||
|
@ -41,13 +41,13 @@ void PointShape::doInkHline(int x1, int y, int x2, ToolLoop* loop)
|
||||
|
||||
// Tiled in Y axis
|
||||
if (tiledMode & TILED_Y_AXIS) {
|
||||
size = loop->getDstImage()->h; // size = image height
|
||||
size = loop->getDstImage()->getHeight(); // size = image height
|
||||
if (y < 0)
|
||||
y = size - (-(y+1) % size) - 1;
|
||||
else
|
||||
y = y % size;
|
||||
}
|
||||
else if (y < 0 || y >= loop->getDstImage()->h)
|
||||
else if (y < 0 || y >= loop->getDstImage()->getHeight())
|
||||
return;
|
||||
|
||||
// Tiled in X axis
|
||||
@ -55,7 +55,7 @@ void PointShape::doInkHline(int x1, int y, int x2, ToolLoop* loop)
|
||||
if (x1 > x2)
|
||||
return;
|
||||
|
||||
size = loop->getDstImage()->w; // size = image width
|
||||
size = loop->getDstImage()->getWidth(); // size = image width
|
||||
w = x2-x1+1;
|
||||
if (w >= size)
|
||||
loop->getInk()->inkHline(0, y, size-1, loop);
|
||||
@ -79,8 +79,8 @@ void PointShape::doInkHline(int x1, int y, int x2, ToolLoop* loop)
|
||||
if (x1 < 0)
|
||||
x1 = 0;
|
||||
|
||||
if (x2 >= loop->getDstImage()->w)
|
||||
x2 = loop->getDstImage()->w-1;
|
||||
if (x2 >= loop->getDstImage()->getWidth())
|
||||
x2 = loop->getDstImage()->getWidth()-1;
|
||||
|
||||
if (x2-x1+1 < 1)
|
||||
return;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "app/util/render.h"
|
||||
#include "gfx/region.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/primitives.h"
|
||||
#include "raster/sprite.h"
|
||||
|
||||
namespace app {
|
||||
@ -61,7 +62,7 @@ void ToolLoopManager::prepareLoop(const Pointer& pointer)
|
||||
m_points.clear();
|
||||
|
||||
// Prepare the image where we will draw on
|
||||
image_copy(m_toolLoop->getDstImage(),
|
||||
copy_image(m_toolLoop->getDstImage(),
|
||||
m_toolLoop->getSrcImage(), 0, 0);
|
||||
|
||||
// Prepare the ink
|
||||
@ -168,14 +169,14 @@ void ToolLoopManager::doLoopStep(bool last_step)
|
||||
case TracePolicyLast:
|
||||
// Copy source to destination (reset the previous trace). Useful
|
||||
// for tools like Line and Ellipse tools (we kept the last trace only).
|
||||
image_clear(m_toolLoop->getDstImage(), 0);
|
||||
image_copy(m_toolLoop->getDstImage(), m_toolLoop->getSrcImage(), 0, 0);
|
||||
clear_image(m_toolLoop->getDstImage(), 0);
|
||||
copy_image(m_toolLoop->getDstImage(), m_toolLoop->getSrcImage(), 0, 0);
|
||||
break;
|
||||
|
||||
case TracePolicyOverlap:
|
||||
// Copy destination to source (yes, destination to source). In
|
||||
// this way each new trace overlaps the previous one.
|
||||
image_copy(m_toolLoop->getSrcImage(), m_toolLoop->getDstImage(), 0, 0);
|
||||
copy_image(m_toolLoop->getSrcImage(), m_toolLoop->getDstImage(), 0, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/ui/context_bar.h"
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/settings/ink_type.h"
|
||||
@ -28,11 +30,12 @@
|
||||
#include "app/tools/point_shape.h"
|
||||
#include "app/tools/tool.h"
|
||||
#include "app/ui/button_set.h"
|
||||
#include "app/ui/context_bar.h"
|
||||
#include "app/ui/skin/skin_theme.h"
|
||||
#include "app/ui_context.h"
|
||||
#include "base/unique_ptr.h"
|
||||
#include "raster/conversion_alleg.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/pen.h"
|
||||
#include "ui/button.h"
|
||||
#include "ui/combobox.h"
|
||||
@ -74,16 +77,20 @@ public:
|
||||
}
|
||||
|
||||
void setPenSettings(IPenSettings* penSettings) {
|
||||
base::UniquePtr<Palette> palette(new Palette(FrameNumber(0), 2));
|
||||
palette->setEntry(0, raster::rgba(0, 0, 0, 0));
|
||||
palette->setEntry(1, raster::rgba(0, 0, 0, 255));
|
||||
|
||||
base::UniquePtr<Pen> pen(new Pen(m_penType = penSettings->getType(),
|
||||
std::min(10, penSettings->getSize()),
|
||||
penSettings->getAngle()));
|
||||
std::min(10, penSettings->getSize()),
|
||||
penSettings->getAngle()));
|
||||
Image* image = pen->get_image();
|
||||
|
||||
if (m_bitmap)
|
||||
destroy_bitmap(m_bitmap);
|
||||
m_bitmap = create_bitmap_ex(32, image->w, image->h);
|
||||
m_bitmap = create_bitmap_ex(32, image->getWidth(), image->getHeight());
|
||||
clear(m_bitmap);
|
||||
image_to_allegro(image, m_bitmap, 0, 0, NULL);
|
||||
convert_image_to_allegro(image, m_bitmap, 0, 0, palette);
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "raster/image.h"
|
||||
#include "raster/layer.h"
|
||||
#include "raster/pen.h"
|
||||
#include "raster/primitives.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "ui/base.h"
|
||||
#include "ui/rect.h"
|
||||
@ -102,7 +103,7 @@ static void savepixel(BITMAP *bmp, int x, int y, int color);
|
||||
static void drawpixel(BITMAP *bmp, int x, int y, int color);
|
||||
static void cleanpixel(BITMAP *bmp, int x, int y, int color);
|
||||
|
||||
static int get_pen_color(Sprite* sprite, Layer* layer);
|
||||
static color_t get_pen_color(Sprite* sprite, Layer* layer);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CURSOR COLOR
|
||||
@ -288,7 +289,7 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
|
||||
->getSettings()
|
||||
->getToolSettings(current_tool);
|
||||
|
||||
int pen_color = get_pen_color(m_sprite, m_layer);
|
||||
color_t pen_color = get_pen_color(m_sprite, m_layer);
|
||||
uint32_t new_mask_color;
|
||||
Pen* pen = editor_get_current_pen();
|
||||
gfx::Rect penBounds = pen->getBounds();
|
||||
@ -308,10 +309,12 @@ void Editor::editor_draw_cursor(int x, int y, bool refresh)
|
||||
}
|
||||
|
||||
Image* extraImage = m_document->getExtraCelImage();
|
||||
if (extraImage->mask_color != new_mask_color)
|
||||
image_clear(extraImage, extraImage->mask_color = new_mask_color);
|
||||
image_putpen(extraImage, pen, -penBounds.x, -penBounds.y,
|
||||
pen_color, extraImage->mask_color);
|
||||
if (extraImage->getMaskColor() != new_mask_color) {
|
||||
extraImage->setMaskColor(new_mask_color);
|
||||
clear_image(extraImage, new_mask_color);
|
||||
}
|
||||
put_pen(extraImage, pen, -penBounds.x, -penBounds.y,
|
||||
pen_color, extraImage->getMaskColor());
|
||||
|
||||
if (refresh) {
|
||||
m_document->notifySpritePixelsModified
|
||||
@ -665,7 +668,7 @@ static void cleanpixel(BITMAP *bmp, int x, int y, int color)
|
||||
}
|
||||
}
|
||||
|
||||
static int get_pen_color(Sprite* sprite, Layer* layer)
|
||||
static color_t get_pen_color(Sprite* sprite, Layer* layer)
|
||||
{
|
||||
app::Color c = UIContext::instance()->getSettings()->getFgColor();
|
||||
ASSERT(sprite != NULL);
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "app/util/render.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/unique_ptr.h"
|
||||
#include "raster/conversion_alleg.h"
|
||||
#include "raster/raster.h"
|
||||
#include "ui/ui.h"
|
||||
|
||||
@ -88,11 +89,11 @@ public:
|
||||
|
||||
void fillRect(const gfx::Rect& rect, uint32_t rgbaColor, int opacity) OVERRIDE
|
||||
{
|
||||
image_rectblend(m_image,
|
||||
m_offset.x + (rect.x << m_zoom),
|
||||
m_offset.y + (rect.y << m_zoom),
|
||||
m_offset.x + ((rect.x+rect.w) << m_zoom) - 1,
|
||||
m_offset.y + ((rect.y+rect.h) << m_zoom) - 1, rgbaColor, opacity);
|
||||
blend_rect(m_image,
|
||||
m_offset.x + (rect.x << m_zoom),
|
||||
m_offset.y + (rect.y << m_zoom),
|
||||
m_offset.x + ((rect.x+rect.w) << m_zoom) - 1,
|
||||
m_offset.y + ((rect.y+rect.h) << m_zoom) - 1, rgbaColor, opacity);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -429,8 +430,8 @@ void Editor::drawSpriteUnclippedRect(const gfx::Rect& rc)
|
||||
destroy_bitmap(bmp);
|
||||
#else
|
||||
acquire_bitmap(ji_screen);
|
||||
image_to_allegro(rendered, ji_screen, dest_x, dest_y,
|
||||
m_sprite->getPalette(m_frame));
|
||||
convert_image_to_allegro(rendered, ji_screen, dest_x, dest_y,
|
||||
m_sprite->getPalette(m_frame));
|
||||
release_bitmap(ji_screen);
|
||||
#endif
|
||||
}
|
||||
@ -640,16 +641,16 @@ void Editor::flashCurrentLayer()
|
||||
Image* flash_image = m_document->getExtraCelImage();
|
||||
int u, v;
|
||||
|
||||
image_clear(flash_image, flash_image->mask_color);
|
||||
for (v=0; v<flash_image->h; ++v) {
|
||||
for (u=0; u<flash_image->w; ++u) {
|
||||
if (u-x >= 0 && u-x < src_image->w &&
|
||||
v-y >= 0 && v-y < src_image->h) {
|
||||
uint32_t color = image_getpixel(src_image, u-x, v-y);
|
||||
clear_image(flash_image, flash_image->mask_color);
|
||||
for (v=0; v<flash_image->getHeight(); ++v) {
|
||||
for (u=0; u<flash_image->getWidth(); ++u) {
|
||||
if (u-x >= 0 && u-x < src_image->getWidth() &&
|
||||
v-y >= 0 && v-y < src_image->getHeight()) {
|
||||
uint32_t color = get_pixel(src_image, u-x, v-y);
|
||||
if (color != src_image->mask_color) {
|
||||
Color ccc = Color::fromRgb(255, 255, 255);
|
||||
image_putpixel(flash_image, u, v,
|
||||
color_utils::color_for_image(ccc, flash_image->imgtype));
|
||||
put_pixel(flash_image, u, v,
|
||||
color_utils::color_for_image(ccc, flash_image->imgtype));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -658,7 +659,7 @@ void Editor::flashCurrentLayer()
|
||||
drawSpriteSafe(0, 0, m_sprite->getWidth()-1, m_sprite->getHeight()-1);
|
||||
gui_flip_screen();
|
||||
|
||||
image_clear(flash_image, flash_image->mask_color);
|
||||
clear_image(flash_image, flash_image->mask_color);
|
||||
drawSpriteSafe(0, 0, m_sprite->getWidth()-1, m_sprite->getHeight()-1);
|
||||
}
|
||||
#endif
|
||||
@ -1164,24 +1165,24 @@ void Editor::pasteImage(const Image* image, int x, int y)
|
||||
// Check bounds where the image will be pasted.
|
||||
{
|
||||
// First we limit the image inside the sprite's bounds.
|
||||
x = MID(0, x, sprite->getWidth() - image->w);
|
||||
y = MID(0, y, sprite->getHeight() - image->h);
|
||||
x = MID(0, x, sprite->getWidth() - image->getWidth());
|
||||
y = MID(0, y, sprite->getHeight() - image->getHeight());
|
||||
|
||||
// Then we check if the image will be visible by the user.
|
||||
Rect visibleBounds = getVisibleSpriteBounds();
|
||||
x = MID(visibleBounds.x-image->w, x, visibleBounds.x+visibleBounds.w-1);
|
||||
y = MID(visibleBounds.y-image->h, y, visibleBounds.y+visibleBounds.h-1);
|
||||
x = MID(visibleBounds.x-image->getWidth(), x, visibleBounds.x+visibleBounds.w-1);
|
||||
y = MID(visibleBounds.y-image->getHeight(), y, visibleBounds.y+visibleBounds.h-1);
|
||||
|
||||
// If the visible part of the pasted image will not fit in the
|
||||
// visible bounds of the editor, we put the image in the center of
|
||||
// the visible bounds.
|
||||
Rect visiblePasted = visibleBounds.createIntersect(gfx::Rect(x, y, image->w, image->h));
|
||||
if (((visibleBounds.w >= image->w && visiblePasted.w < image->w/2) ||
|
||||
(visibleBounds.w < image->w && visiblePasted.w < visibleBounds.w/2)) ||
|
||||
((visibleBounds.h >= image->h && visiblePasted.h < image->w/2) ||
|
||||
(visibleBounds.h < image->h && visiblePasted.h < visibleBounds.h/2))) {
|
||||
x = visibleBounds.x + visibleBounds.w/2 - image->w/2;
|
||||
y = visibleBounds.y + visibleBounds.h/2 - image->h/2;
|
||||
Rect visiblePasted = visibleBounds.createIntersect(gfx::Rect(x, y, image->getWidth(), image->getHeight()));
|
||||
if (((visibleBounds.w >= image->getWidth() && visiblePasted.w < image->getWidth()/2) ||
|
||||
(visibleBounds.w < image->getWidth() && visiblePasted.w < visibleBounds.w/2)) ||
|
||||
((visibleBounds.h >= image->getHeight() && visiblePasted.h < image->getWidth()/2) ||
|
||||
(visibleBounds.h < image->getHeight() && visiblePasted.h < visibleBounds.h/2))) {
|
||||
x = visibleBounds.x + visibleBounds.w/2 - image->getWidth()/2;
|
||||
y = visibleBounds.y + visibleBounds.h/2 - image->getHeight()/2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,15 +61,15 @@ PixelsMovement::PixelsMovement(Context* context,
|
||||
, m_handle(NoHandle)
|
||||
, m_originalImage(Image::createCopy(moveThis))
|
||||
{
|
||||
m_initialData = gfx::Transformation(gfx::Rect(initialX, initialY, moveThis->w, moveThis->h));
|
||||
m_initialData = gfx::Transformation(gfx::Rect(initialX, initialY, moveThis->getWidth(), moveThis->getHeight()));
|
||||
m_currentData = m_initialData;
|
||||
|
||||
ContextWriter writer(m_reader);
|
||||
m_document->prepareExtraCel(0, 0, m_sprite->getWidth(), m_sprite->getHeight(), opacity);
|
||||
|
||||
Image* extraImage = m_document->getExtraCelImage();
|
||||
image_clear(extraImage, extraImage->mask_color);
|
||||
image_copy(extraImage, moveThis, initialX, initialY);
|
||||
clear_image(extraImage, extraImage->getMaskColor());
|
||||
copy_image(extraImage, moveThis, initialX, initialY);
|
||||
|
||||
m_initialMask = new Mask(*m_document->getMask());
|
||||
m_currentMask = new Mask(*m_document->getMask());
|
||||
@ -87,8 +87,8 @@ void PixelsMovement::flipImage(raster::algorithm::FlipType flipType)
|
||||
// Flip the image.
|
||||
raster::algorithm::flip_image(m_originalImage,
|
||||
gfx::Rect(gfx::Point(0, 0),
|
||||
gfx::Size(m_originalImage->w,
|
||||
m_originalImage->h)),
|
||||
gfx::Size(m_originalImage->getWidth(),
|
||||
m_originalImage->getHeight())),
|
||||
flipType);
|
||||
|
||||
// Flip the mask.
|
||||
@ -439,7 +439,7 @@ Image* PixelsMovement::getDraggedImageCopy(gfx::Point& origin)
|
||||
int width = rightBottom.x - leftTop.x;
|
||||
int height = rightBottom.y - leftTop.y;
|
||||
base::UniquePtr<Image> image(Image::create(m_sprite->getPixelFormat(), width, height));
|
||||
image_clear(image, image->mask_color);
|
||||
clear_image(image, image->getMaskColor());
|
||||
image_parallelogram(image, m_originalImage,
|
||||
corners.leftTop().x-leftTop.x, corners.leftTop().y-leftTop.y,
|
||||
corners.rightTop().x-leftTop.x, corners.rightTop().y-leftTop.y,
|
||||
@ -466,10 +466,10 @@ void PixelsMovement::stampImage()
|
||||
ExpandCelCanvas expandCelCanvas(writer.context(), TILED_NONE,
|
||||
m_undoTransaction);
|
||||
|
||||
image_merge(expandCelCanvas.getDestCanvas(), image,
|
||||
-expandCelCanvas.getCel()->getX(),
|
||||
-expandCelCanvas.getCel()->getY(),
|
||||
cel->getOpacity(), BLEND_MODE_NORMAL);
|
||||
composite_image(expandCelCanvas.getDestCanvas(), image,
|
||||
-expandCelCanvas.getCel()->getX(),
|
||||
-expandCelCanvas.getCel()->getY(),
|
||||
cel->getOpacity(), BLEND_MODE_NORMAL);
|
||||
|
||||
expandCelCanvas.commit();
|
||||
}
|
||||
@ -562,7 +562,7 @@ gfx::Rect PixelsMovement::getImageBounds()
|
||||
ASSERT(cel != NULL);
|
||||
ASSERT(image != NULL);
|
||||
|
||||
return gfx::Rect(cel->getX(), cel->getY(), image->w, image->h);
|
||||
return gfx::Rect(cel->getX(), cel->getY(), image->getWidth(), image->getHeight());
|
||||
}
|
||||
|
||||
gfx::Size PixelsMovement::getInitialImageSize() const
|
||||
@ -578,7 +578,7 @@ void PixelsMovement::setMaskColor(uint32_t mask_color)
|
||||
|
||||
ASSERT(extraImage != NULL);
|
||||
|
||||
extraImage->mask_color = mask_color;
|
||||
extraImage->setMaskColor(mask_color);
|
||||
redrawExtraImage();
|
||||
update_screen_for_document(m_document);
|
||||
}
|
||||
@ -592,7 +592,7 @@ void PixelsMovement::redrawExtraImage()
|
||||
|
||||
// Transform the extra-cel which is the chunk of pixels that the user is moving.
|
||||
Image* extraImage = m_document->getExtraCelImage();
|
||||
image_clear(extraImage, extraImage->mask_color);
|
||||
clear_image(extraImage, extraImage->getMaskColor());
|
||||
image_parallelogram(extraImage, m_originalImage,
|
||||
corners.leftTop().x, corners.leftTop().y,
|
||||
corners.rightTop().x, corners.rightTop().y,
|
||||
@ -609,7 +609,7 @@ void PixelsMovement::redrawCurrentMask()
|
||||
|
||||
m_currentMask->replace(0, 0, m_sprite->getWidth(), m_sprite->getHeight());
|
||||
m_currentMask->freeze();
|
||||
image_clear(m_currentMask->getBitmap(), 0);
|
||||
clear_image(m_currentMask->getBitmap(), 0);
|
||||
image_parallelogram(m_currentMask->getBitmap(),
|
||||
m_initialMask->getBitmap(),
|
||||
corners.leftTop().x, corners.leftTop().y,
|
||||
|
@ -165,19 +165,19 @@ void SelectBoxState::preRenderDecorator(EditorPreRender* render)
|
||||
|
||||
// Top band
|
||||
if (rc.y > 0)
|
||||
render->fillRect(gfx::Rect(0, 0, sprite_w, rc.y), _rgba(0, 0, 0, 255), 128);
|
||||
render->fillRect(gfx::Rect(0, 0, sprite_w, rc.y), raster::rgba(0, 0, 0, 255), 128);
|
||||
|
||||
// Bottom band
|
||||
if (rc.y+rc.h < sprite_h)
|
||||
render->fillRect(gfx::Rect(0, rc.y+rc.h, sprite_w, sprite_h-(rc.y+rc.h)), _rgba(0, 0, 0, 255), 128);
|
||||
render->fillRect(gfx::Rect(0, rc.y+rc.h, sprite_w, sprite_h-(rc.y+rc.h)), raster::rgba(0, 0, 0, 255), 128);
|
||||
|
||||
// Left band
|
||||
if (rc.x > 0)
|
||||
render->fillRect(gfx::Rect(0, rc.y, rc.x, rc.h), _rgba(0, 0, 0, 255), 128);
|
||||
render->fillRect(gfx::Rect(0, rc.y, rc.x, rc.h), raster::rgba(0, 0, 0, 255), 128);
|
||||
|
||||
// Right band
|
||||
if (rc.x+rc.w < sprite_w)
|
||||
render->fillRect(gfx::Rect(rc.x+rc.w, rc.y, sprite_w-(rc.x+rc.w), rc.h), _rgba(0, 0, 0, 255), 128);
|
||||
render->fillRect(gfx::Rect(rc.x+rc.w, rc.y, sprite_w-(rc.x+rc.w), rc.h), raster::rgba(0, 0, 0, 255), 128);
|
||||
}
|
||||
|
||||
void SelectBoxState::postRenderDecorator(EditorPostRender* render)
|
||||
|
@ -156,7 +156,7 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg)
|
||||
// Move cel X,Y coordinates
|
||||
if (clickedInk->isCelMovement()) {
|
||||
if ((layer) &&
|
||||
(layer->getType() == GFXOBJ_LAYER_IMAGE)) {
|
||||
(layer->type() == OBJECT_LAYER_IMAGE)) {
|
||||
// TODO you can move the `Background' with tiled mode
|
||||
if (layer->isBackground()) {
|
||||
Alert::show(PACKAGE
|
||||
@ -458,8 +458,8 @@ bool StandbyState::onUpdateStatusBar(Editor* editor)
|
||||
|
||||
int alpha = 255;
|
||||
switch (format) {
|
||||
case IMAGE_RGB: alpha = _rgba_geta(pixel); break;
|
||||
case IMAGE_GRAYSCALE: alpha = _graya_geta(pixel); break;
|
||||
case IMAGE_RGB: alpha = rgba_geta(pixel); break;
|
||||
case IMAGE_GRAYSCALE: alpha = graya_geta(pixel); break;
|
||||
}
|
||||
|
||||
char buf[256];
|
||||
|
@ -233,9 +233,9 @@ bool PaletteView::onProcessMessage(Message* msg)
|
||||
else
|
||||
color = makecol_depth
|
||||
(bitmap_color_depth(ji_screen),
|
||||
_rgba_getr(palette->getEntry(c)),
|
||||
_rgba_getg(palette->getEntry(c)),
|
||||
_rgba_getb(palette->getEntry(c)));
|
||||
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);
|
||||
|
||||
|
@ -48,7 +48,7 @@ FlipImage::FlipImage(ObjectsContainer* objects, Image* image,
|
||||
, m_flipType(flipType)
|
||||
{
|
||||
ASSERT(m_w >= 1 && m_h >= 1);
|
||||
ASSERT(m_x >= 0 && m_y >= 0 && m_x+m_w <= image->w && m_y+m_h <= image->h);
|
||||
ASSERT(m_x >= 0 && m_y >= 0 && m_x+m_w <= image->getWidth() && m_y+m_h <= image->getHeight());
|
||||
}
|
||||
|
||||
void FlipImage::dispose()
|
||||
|
@ -36,14 +36,14 @@ ImageArea::ImageArea(ObjectsContainer* objects, Image* image, int x, int y, int
|
||||
: m_imageId(objects->addObject(image))
|
||||
, m_format(image->getPixelFormat())
|
||||
, m_x(x), m_y(y), m_w(w), m_h(h)
|
||||
, m_lineSize(image_line_size(image, w))
|
||||
, m_lineSize(image->getRowStrideSize(w))
|
||||
, m_data(m_lineSize * h)
|
||||
{
|
||||
ASSERT(w >= 1 && h >= 1);
|
||||
ASSERT(x >= 0 && y >= 0 && x+w <= image->w && y+h <= image->h);
|
||||
ASSERT(x >= 0 && y >= 0 && x+w <= image->getWidth() && y+h <= image->getHeight());
|
||||
|
||||
for (int v=0; v<h; ++v)
|
||||
memcpy(&m_data[m_lineSize*v], image_address(image, x, y+v), m_lineSize);
|
||||
memcpy(&m_data[m_lineSize*v], image->getPixelAddress(x, y+v), m_lineSize);
|
||||
}
|
||||
|
||||
void ImageArea::dispose()
|
||||
@ -63,7 +63,7 @@ void ImageArea::revert(ObjectsContainer* objects, UndoersCollector* redoers)
|
||||
|
||||
// Restore the old image portion
|
||||
for (int v=0; v<m_h; ++v)
|
||||
memcpy(image_address(image, m_x, m_y+v), &m_data[m_lineSize*v], m_lineSize);
|
||||
memcpy(image->getPixelAddress(m_x, m_y+v), &m_data[m_lineSize*v], m_lineSize);
|
||||
}
|
||||
|
||||
} // namespace undoers
|
||||
|
@ -37,7 +37,7 @@ bool get_shrink_rect(int *x1, int *y1, int *x2, int *y2,
|
||||
do { \
|
||||
for (u = u_begin; u u_op u_final; u u_add) { \
|
||||
for (v = v_begin; v v_op v_final; v v_add) { \
|
||||
if (image->getpixel(U, V) != refpixel) \
|
||||
if (image->getPixel(U, V) != refpixel) \
|
||||
break; \
|
||||
} \
|
||||
if (v == v_final) \
|
||||
@ -51,20 +51,20 @@ bool get_shrink_rect(int *x1, int *y1, int *x2, int *y2,
|
||||
|
||||
*x1 = 0;
|
||||
*y1 = 0;
|
||||
*x2 = image->w-1;
|
||||
*y2 = image->h-1;
|
||||
*x2 = image->getWidth()-1;
|
||||
*y2 = image->getHeight()-1;
|
||||
|
||||
SHRINK_SIDE(0, <, image->w, ++,
|
||||
0, <, image->h, ++, u, v, (*x1)++);
|
||||
SHRINK_SIDE(0, <, image->getWidth(), ++,
|
||||
0, <, image->getHeight(), ++, u, v, (*x1)++);
|
||||
|
||||
SHRINK_SIDE(0, <, image->h, ++,
|
||||
0, <, image->w, ++, v, u, (*y1)++);
|
||||
SHRINK_SIDE(0, <, image->getHeight(), ++,
|
||||
0, <, image->getWidth(), ++, v, u, (*y1)++);
|
||||
|
||||
SHRINK_SIDE(image->w-1, >, 0, --,
|
||||
0, <, image->h, ++, u, v, (*x2)--);
|
||||
SHRINK_SIDE(image->getWidth()-1, >, 0, --,
|
||||
0, <, image->getHeight(), ++, u, v, (*x2)--);
|
||||
|
||||
SHRINK_SIDE(image->h-1, >, 0, --,
|
||||
0, <, image->w, ++, v, u, (*y2)--);
|
||||
SHRINK_SIDE(image->getHeight()-1, >, 0, --,
|
||||
0, <, image->getWidth(), ++, v, u, (*y2)--);
|
||||
|
||||
if ((*x1 > *x2) || (*y1 > *y2))
|
||||
return false;
|
||||
@ -82,7 +82,7 @@ bool get_shrink_rect2(int *x1, int *y1, int *x2, int *y2,
|
||||
do { \
|
||||
for (u = u_begin; u u_op u_final; u u_add) { \
|
||||
for (v = v_begin; v v_op v_final; v v_add) { \
|
||||
if (image->getpixel(U, V) != refimage->getpixel(U, V)) \
|
||||
if (image->getPixel(U, V) != refimage->getPixel(U, V)) \
|
||||
break; \
|
||||
} \
|
||||
if (v == v_final) \
|
||||
@ -96,20 +96,20 @@ bool get_shrink_rect2(int *x1, int *y1, int *x2, int *y2,
|
||||
|
||||
*x1 = 0;
|
||||
*y1 = 0;
|
||||
*x2 = image->w-1;
|
||||
*y2 = image->h-1;
|
||||
*x2 = image->getWidth()-1;
|
||||
*y2 = image->getHeight()-1;
|
||||
|
||||
SHRINK_SIDE(0, <, image->w, ++,
|
||||
0, <, image->h, ++, u, v, (*x1)++);
|
||||
SHRINK_SIDE(0, <, image->getWidth(), ++,
|
||||
0, <, image->getHeight(), ++, u, v, (*x1)++);
|
||||
|
||||
SHRINK_SIDE(0, <, image->h, ++,
|
||||
0, <, image->w, ++, v, u, (*y1)++);
|
||||
SHRINK_SIDE(0, <, image->getHeight(), ++,
|
||||
0, <, image->getWidth(), ++, v, u, (*y1)++);
|
||||
|
||||
SHRINK_SIDE(image->w-1, >, 0, --,
|
||||
0, <, image->h, ++, u, v, (*x2)--);
|
||||
SHRINK_SIDE(image->getWidth()-1, >, 0, --,
|
||||
0, <, image->getHeight(), ++, u, v, (*x2)--);
|
||||
|
||||
SHRINK_SIDE(image->h-1, >, 0, --,
|
||||
0, <, image->w, ++, v, u, (*y2)--);
|
||||
SHRINK_SIDE(image->getHeight()-1, >, 0, --,
|
||||
0, <, image->getWidth(), ++, v, u, (*y2)--);
|
||||
|
||||
if ((*x1 > *x2) || (*y1 > *y2))
|
||||
return false;
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <limits.h>
|
||||
#include "base/memory.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/image_bits.h"
|
||||
#include "app/util/boundary.h"
|
||||
|
||||
#define g_new(struct_type, n_structs) \
|
||||
@ -45,8 +46,7 @@
|
||||
#define gboolean bool
|
||||
#define G_MAXINT INT_MAX
|
||||
#define g_message(msg) {}
|
||||
|
||||
typedef const raster::Image PixelRegion;
|
||||
#define PixelRegion const raster::Image
|
||||
|
||||
namespace app {
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@ -124,20 +124,17 @@ find_empty_segs (PixelRegion *maskPR,
|
||||
gint x2,
|
||||
gint y2)
|
||||
{
|
||||
uint8_t* data;
|
||||
int x;
|
||||
int start, end;
|
||||
int val, last;
|
||||
int endx, l_num_empty;
|
||||
div_t d;
|
||||
|
||||
data = NULL;
|
||||
start = 0;
|
||||
end = 0;
|
||||
|
||||
*num_empty = 0;
|
||||
|
||||
if (scanline < 0 || scanline >= maskPR->h)
|
||||
if (scanline < 0 || scanline >= maskPR->getHeight())
|
||||
{
|
||||
empty_segs[(*num_empty)++] = 0;
|
||||
empty_segs[(*num_empty)++] = G_MAXINT;
|
||||
@ -159,7 +156,7 @@ find_empty_segs (PixelRegion *maskPR,
|
||||
else if (type == IgnoreBounds)
|
||||
{
|
||||
start = 0;
|
||||
end = maskPR->w;
|
||||
end = maskPR->getWidth();
|
||||
if (scanline < y1 || scanline >= y2)
|
||||
x2 = -1;
|
||||
}
|
||||
@ -170,8 +167,8 @@ find_empty_segs (PixelRegion *maskPR,
|
||||
|
||||
l_num_empty = *num_empty;
|
||||
|
||||
d = div (start, 8);
|
||||
data = ((uint8_t*)maskPR->line[scanline])+d.quot;
|
||||
const LockImageBits<BitmapTraits> bits(maskPR, gfx::Rect(start, scanline, end - start, 1));
|
||||
LockImageBits<BitmapTraits>::const_iterator it = bits.begin();
|
||||
|
||||
for (x = start; x < end;)
|
||||
{
|
||||
@ -180,15 +177,18 @@ find_empty_segs (PixelRegion *maskPR,
|
||||
{
|
||||
for (; x < endx; x++)
|
||||
{
|
||||
if (*data & (1<<d.rem))
|
||||
ASSERT(it != bits.end());
|
||||
|
||||
if (*it) {
|
||||
if (x >= x1 && x < x2)
|
||||
val = -1;
|
||||
else
|
||||
val = 1;
|
||||
}
|
||||
else
|
||||
val = -1;
|
||||
|
||||
_image_bitmap_next_bit(d, data);
|
||||
++it;
|
||||
|
||||
if (last != val)
|
||||
empty_segs[l_num_empty++] = x;
|
||||
@ -200,12 +200,14 @@ find_empty_segs (PixelRegion *maskPR,
|
||||
{
|
||||
for (; x < endx; x++)
|
||||
{
|
||||
if (*data & (1<<d.rem))
|
||||
ASSERT(it != bits.end());
|
||||
|
||||
if (*it)
|
||||
val = 1;
|
||||
else
|
||||
val = -1;
|
||||
|
||||
_image_bitmap_next_bit(d, data);
|
||||
++it;
|
||||
|
||||
if (last != val)
|
||||
empty_segs[l_num_empty++] = x;
|
||||
@ -252,9 +254,9 @@ allocate_vert_segs (PixelRegion *PR)
|
||||
gint i;
|
||||
|
||||
/* allocate and initialize the vert_segs array */
|
||||
vert_segs = g_renew (gint, vert_segs, PR->w + 1);
|
||||
vert_segs = g_renew (gint, vert_segs, PR->getWidth() + 1);
|
||||
|
||||
for (i = 0; i <= PR->w; i++)
|
||||
for (i = 0; i <= PR->getWidth(); i++)
|
||||
vert_segs[i] = -1;
|
||||
}
|
||||
|
||||
@ -265,7 +267,7 @@ allocate_empty_segs (PixelRegion *PR)
|
||||
gint need_num_segs;
|
||||
|
||||
/* find the maximum possible number of empty segments given the current mask */
|
||||
need_num_segs = PR->w + 3;
|
||||
need_num_segs = PR->getWidth() + 3;
|
||||
|
||||
if (need_num_segs > max_empty_segs)
|
||||
{
|
||||
@ -369,7 +371,7 @@ generate_boundary (PixelRegion *PR,
|
||||
else if (type == IgnoreBounds)
|
||||
{
|
||||
start = 0;
|
||||
end = PR->h;
|
||||
end = PR->getHeight();
|
||||
}
|
||||
|
||||
/* Find the empty segments for the previous and current scanlines */
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "raster/cel.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/layer.h"
|
||||
#include "raster/primitives.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "raster/stock.h"
|
||||
|
||||
@ -111,7 +112,7 @@ void move_cel(ContextWriter& writer)
|
||||
if (!src_layer->isBackground() &&
|
||||
dst_layer->isBackground()) {
|
||||
Image* src_image = sprite->getStock()->getImage(src_cel->getImage());
|
||||
Image* dst_image = image_crop(src_image,
|
||||
Image* dst_image = crop_image(src_image,
|
||||
-src_cel->getX(),
|
||||
-src_cel->getY(),
|
||||
sprite->getWidth(),
|
||||
@ -124,8 +125,8 @@ void move_cel(ContextWriter& writer)
|
||||
undo.pushUndoer(new undoers::SetCelOpacity(undo.getObjects(), src_cel));
|
||||
}
|
||||
|
||||
image_clear(dst_image, app_get_color_to_clear_layer(dst_layer));
|
||||
image_merge(dst_image, src_image, src_cel->getX(), src_cel->getY(), 255, BLEND_MODE_NORMAL);
|
||||
clear_image(dst_image, app_get_color_to_clear_layer(dst_layer));
|
||||
composite_image(dst_image, src_image, src_cel->getX(), src_cel->getY(), 255, BLEND_MODE_NORMAL);
|
||||
|
||||
src_cel->setPosition(0, 0);
|
||||
src_cel->setOpacity(255);
|
||||
@ -180,14 +181,14 @@ void copy_cel(ContextWriter& writer)
|
||||
// background layer, we have to clear the background of the image.
|
||||
if (!src_layer->isBackground() &&
|
||||
dst_layer->isBackground()) {
|
||||
dst_image = image_crop(src_image,
|
||||
dst_image = crop_image(src_image,
|
||||
-src_cel->getX(),
|
||||
-src_cel->getY(),
|
||||
sprite->getWidth(),
|
||||
sprite->getHeight(), 0);
|
||||
|
||||
image_clear(dst_image, app_get_color_to_clear_layer(dst_layer));
|
||||
image_merge(dst_image, src_image, src_cel->getX(), src_cel->getY(), 255, BLEND_MODE_NORMAL);
|
||||
clear_image(dst_image, app_get_color_to_clear_layer(dst_layer));
|
||||
composite_image(dst_image, src_image, src_cel->getX(), src_cel->getY(), 255, BLEND_MODE_NORMAL);
|
||||
|
||||
dst_cel_x = 0;
|
||||
dst_cel_y = 0;
|
||||
|
@ -42,15 +42,7 @@
|
||||
#include "app/undoers/image_area.h"
|
||||
#include "app/util/clipboard.h"
|
||||
#include "app/util/misc.h"
|
||||
#include "raster/cel.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/layer.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/quantization.h"
|
||||
#include "raster/rotate.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "raster/stock.h"
|
||||
#include "raster/raster.h"
|
||||
#include "ui/ui.h"
|
||||
#include "undo/undo_history.h"
|
||||
|
||||
@ -225,8 +217,8 @@ bool clipboard::get_image_size(gfx::Size& size)
|
||||
return get_win32_clipboard_bitmap_size(size);
|
||||
#else
|
||||
if (clipboard_image != NULL) {
|
||||
size.w = clipboard_image->w;
|
||||
size.h = clipboard_image->h;
|
||||
size.w = clipboard_image->getWidth();
|
||||
size.h = clipboard_image->getHeight();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -70,17 +70,17 @@ static void set_win32_clipboard_bitmap(Image* image, Palette* palette)
|
||||
|
||||
switch (image->getPixelFormat()) {
|
||||
case IMAGE_RGB:
|
||||
scanline = sizeof(uint32_t) * image->w;
|
||||
scanline = sizeof(uint32_t) * image->getWidth();
|
||||
color_depth = 32;
|
||||
break;
|
||||
case IMAGE_GRAYSCALE:
|
||||
// this is right! Grayscaled is copied as RGBA in Win32 Clipboard
|
||||
scanline = sizeof(uint32_t) * image->w;
|
||||
scanline = sizeof(uint32_t) * image->getWidth();
|
||||
color_depth = 32;
|
||||
break;
|
||||
case IMAGE_INDEXED:
|
||||
padding = (4-(image->w&3))&3;
|
||||
scanline = sizeof(uint8_t) * image->w;
|
||||
padding = (4-(image->getWidth()&3))&3;
|
||||
scanline = sizeof(uint8_t) * image->getWidth();
|
||||
scanline += padding;
|
||||
color_depth = 8;
|
||||
palette_entries = palette->size();
|
||||
@ -92,16 +92,16 @@ static void set_win32_clipboard_bitmap(Image* image, Palette* palette)
|
||||
HGLOBAL hmem = GlobalAlloc(GHND,
|
||||
sizeof(BITMAPV5HEADER)
|
||||
+ palette_entries*sizeof(RGBQUAD)
|
||||
+ scanline*image->h);
|
||||
+ scanline*image->getHeight());
|
||||
BITMAPV5HEADER* bi = (BITMAPV5HEADER*)GlobalLock(hmem);
|
||||
|
||||
bi->bV5Size = sizeof(BITMAPV5HEADER);
|
||||
bi->bV5Width = image->w;
|
||||
bi->bV5Height = image->h;
|
||||
bi->bV5Width = image->getWidth();
|
||||
bi->bV5Height = image->getHeight();
|
||||
bi->bV5Planes = 1;
|
||||
bi->bV5BitCount = color_depth;
|
||||
bi->bV5Compression = BI_RGB;
|
||||
bi->bV5SizeImage = scanline*image->h;
|
||||
bi->bV5SizeImage = scanline*image->getHeight();
|
||||
bi->bV5RedMask = 0x00ff0000;
|
||||
bi->bV5GreenMask = 0x0000ff00;
|
||||
bi->bV5BlueMask = 0x000000ff;
|
||||
@ -115,26 +115,26 @@ static void set_win32_clipboard_bitmap(Image* image, Palette* palette)
|
||||
case IMAGE_RGB: {
|
||||
uint32_t* dst = (uint32_t*)(((uint8_t*)bi)+bi->bV5Size);
|
||||
uint32_t c;
|
||||
for (int y=image->h-1; y>=0; --y)
|
||||
for (int x=0; x<image->w; ++x) {
|
||||
c = image_getpixel_fast<RgbTraits>(image, x, y);
|
||||
*(dst++) = ((_rgba_getb(c) << 0) |
|
||||
(_rgba_getg(c) << 8) |
|
||||
(_rgba_getr(c) << 16) |
|
||||
(_rgba_geta(c) << 24));
|
||||
for (int y=image->getHeight()-1; y>=0; --y)
|
||||
for (int x=0; x<image->getWidth(); ++x) {
|
||||
c = get_pixel_fast<RgbTraits>(image, x, y);
|
||||
*(dst++) = ((rgba_getb(c) << 0) |
|
||||
(rgba_getg(c) << 8) |
|
||||
(rgba_getr(c) << 16) |
|
||||
(rgba_geta(c) << 24));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IMAGE_GRAYSCALE: {
|
||||
uint32_t* dst = (uint32_t*)(((uint8_t*)bi)+bi->bV5Size);
|
||||
uint16_t c;
|
||||
for (int y=image->h-1; y>=0; --y)
|
||||
for (int x=0; x<image->w; ++x) {
|
||||
c = image_getpixel_fast<GrayscaleTraits>(image, x, y);
|
||||
*(dst++) = ((_graya_getv(c) << 0) |
|
||||
(_graya_getv(c) << 8) |
|
||||
(_graya_getv(c) << 16) |
|
||||
(_graya_geta(c) << 24));
|
||||
for (int y=image->getHeight()-1; y>=0; --y)
|
||||
for (int x=0; x<image->getWidth(); ++x) {
|
||||
c = get_pixel_fast<GrayscaleTraits>(image, x, y);
|
||||
*(dst++) = ((graya_getv(c) << 0) |
|
||||
(graya_getv(c) << 8) |
|
||||
(graya_getv(c) << 16) |
|
||||
(graya_geta(c) << 24));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -142,17 +142,17 @@ static void set_win32_clipboard_bitmap(Image* image, Palette* palette)
|
||||
Palette* palette = app::get_current_palette();
|
||||
RGBQUAD* rgbquad = (RGBQUAD*)(((uint8_t*)bi)+bi->bV5Size);
|
||||
for (int i=0; i<palette->size(); ++i) {
|
||||
rgbquad->rgbRed = _rgba_getr(palette->getEntry(i));
|
||||
rgbquad->rgbGreen = _rgba_getg(palette->getEntry(i));
|
||||
rgbquad->rgbBlue = _rgba_getb(palette->getEntry(i));
|
||||
rgbquad->rgbRed = rgba_getr(palette->getEntry(i));
|
||||
rgbquad->rgbGreen = rgba_getg(palette->getEntry(i));
|
||||
rgbquad->rgbBlue = rgba_getb(palette->getEntry(i));
|
||||
rgbquad++;
|
||||
}
|
||||
|
||||
uint8_t* dst = (uint8_t*)(((uint8_t*)bi)+bi->bV5Size
|
||||
+ palette_entries*sizeof(RGBQUAD));
|
||||
for (int y=image->h-1; y>=0; --y) {
|
||||
for (int x=0; x<image->w; ++x) {
|
||||
*(dst++) = image_getpixel_fast<IndexedTraits>(image, x, y);
|
||||
for (int y=image->getHeight()-1; y>=0; --y) {
|
||||
for (int x=0; x<image->getWidth(); ++x) {
|
||||
*(dst++) = get_pixel_fast<IndexedTraits>(image, x, y);
|
||||
}
|
||||
dst += padding;
|
||||
}
|
||||
@ -211,12 +211,12 @@ static void get_win32_clipboard_bitmap(Image*& image, Palette*& palette)
|
||||
uint32_t g_shift = get_shift_from_mask(g_mask);
|
||||
uint32_t b_shift = get_shift_from_mask(b_mask);
|
||||
|
||||
for (int y=image->h-1; y>=0; --y) {
|
||||
uint32_t* dst = (uint32_t*)image->line[y];
|
||||
for (int y=image->getHeight()-1; y>=0; --y) {
|
||||
uint32_t* dst = (uint32_t*)image->getPixelAddress(0, y);
|
||||
|
||||
for (int x=0; x<image->w; ++x) {
|
||||
for (int x=0; x<image->getWidth(); ++x) {
|
||||
c = *(src++);
|
||||
*(dst++) = _rgba((c & r_mask) >> r_shift,
|
||||
*(dst++) = rgba((c & r_mask) >> r_shift,
|
||||
(c & g_mask) >> g_shift,
|
||||
(c & b_mask) >> b_shift, 255);
|
||||
}
|
||||
@ -226,12 +226,12 @@ static void get_win32_clipboard_bitmap(Image*& image, Palette*& palette)
|
||||
uint32_t* src = (uint32_t*)(((uint8_t*)bi)+bi->bmiHeader.biSize);
|
||||
uint32_t c;
|
||||
|
||||
for (int y=image->h-1; y>=0; --y) {
|
||||
uint32_t* dst = (uint32_t*)image->line[y];
|
||||
for (int y=image->getHeight()-1; y>=0; --y) {
|
||||
uint32_t* dst = (uint32_t*)image->getPixelAddress(0, y);
|
||||
|
||||
for (int x=0; x<image->w; ++x) {
|
||||
for (int x=0; x<image->getWidth(); ++x) {
|
||||
c = *(src++);
|
||||
*(dst++) = _rgba((c & 0x00ff0000) >> 16,
|
||||
*(dst++) = rgba((c & 0x00ff0000) >> 16,
|
||||
(c & 0x0000ff00) >> 8,
|
||||
(c & 0x000000ff) >> 0,
|
||||
(c & 0xff000000) >> 24);
|
||||
@ -245,16 +245,16 @@ static void get_win32_clipboard_bitmap(Image*& image, Palette*& palette)
|
||||
case 24: {
|
||||
uint8_t* src = (((uint8_t*)bi)+bi->bmiHeader.biSize);
|
||||
uint8_t r, g, b;
|
||||
int padding = (4-((image->w*3)&3))&3;
|
||||
int padding = (4-((image->getWidth()*3)&3))&3;
|
||||
|
||||
for (int y=image->h-1; y>=0; --y) {
|
||||
uint32_t* dst = (uint32_t*)image->line[y];
|
||||
for (int y=image->getHeight()-1; y>=0; --y) {
|
||||
uint32_t* dst = (uint32_t*)image->getPixelAddress(0, y);
|
||||
|
||||
for (int x=0; x<image->w; ++x) {
|
||||
for (int x=0; x<image->getWidth(); ++x) {
|
||||
b = *(src++);
|
||||
g = *(src++);
|
||||
r = *(src++);
|
||||
*(dst++) = _rgba(r, g, b, 255);
|
||||
*(dst++) = rgba(r, g, b, 255);
|
||||
}
|
||||
src += padding;
|
||||
}
|
||||
@ -267,16 +267,16 @@ static void get_win32_clipboard_bitmap(Image*& image, Palette*& palette)
|
||||
// TODO I am not sure if this really works
|
||||
uint8_t* src = (((uint8_t*)bi)+bi->bmiHeader.biSize);
|
||||
uint8_t b1, b2, r, g, b;
|
||||
int padding = (4-((image->w*2)&3))&3;
|
||||
int padding = (4-((image->getWidth()*2)&3))&3;
|
||||
|
||||
for (int y=image->h-1; y>=0; --y) {
|
||||
for (int x=0; x<image->w; ++x) {
|
||||
for (int y=image->getHeight()-1; y>=0; --y) {
|
||||
for (int x=0; x<image->getWidth(); ++x) {
|
||||
b1 = *(src++);
|
||||
b2 = *(src++);
|
||||
b = _rgb_scale_5[((b1 & 0xf800) >> 11)];
|
||||
g = _rgb_scale_6[((b2 & 0x07e0) >> 5)];
|
||||
r = _rgb_scale_5[(b2 & 0x001f)];
|
||||
image_putpixel_fast<RgbTraits>(image, x, y, _rgba(r, g, b, 255));
|
||||
put_pixel_fast<RgbTraits>(image, x, y, rgba(r, g, b, 255));
|
||||
}
|
||||
src += padding;
|
||||
}
|
||||
@ -289,18 +289,18 @@ static void get_win32_clipboard_bitmap(Image*& image, Palette*& palette)
|
||||
int colors = bi->bmiHeader.biClrUsed > 0 ? bi->bmiHeader.biClrUsed: 256;
|
||||
palette = new Palette(FrameNumber(0), colors);
|
||||
for (int c=0; c<colors; ++c) {
|
||||
palette->setEntry(c, _rgba(bi->bmiColors[c].rgbRed,
|
||||
palette->setEntry(c, rgba(bi->bmiColors[c].rgbRed,
|
||||
bi->bmiColors[c].rgbGreen,
|
||||
bi->bmiColors[c].rgbBlue, 255));
|
||||
}
|
||||
|
||||
uint8_t* src = (((uint8_t*)bi)+bi->bmiHeader.biSize+sizeof(RGBQUAD)*colors);
|
||||
int padding = (4-(image->w&3))&3;
|
||||
int padding = (4-(image->getWidth()&3))&3;
|
||||
|
||||
for (int y=image->h-1; y>=0; --y) {
|
||||
for (int x=0; x<image->w; ++x) {
|
||||
for (int y=image->getHeight()-1; y>=0; --y) {
|
||||
for (int x=0; x<image->getWidth(); ++x) {
|
||||
int c = *(src++);
|
||||
image_putpixel_fast<IndexedTraits>(image, x, y, MID(0, c, colors-1));
|
||||
put_pixel_fast<IndexedTraits>(image, x, y, MID(0, c, colors-1));
|
||||
}
|
||||
|
||||
src += padding;
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "raster/cel.h"
|
||||
#include "raster/dirty.h"
|
||||
#include "raster/layer.h"
|
||||
#include "raster/primitives.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "raster/stock.h"
|
||||
|
||||
@ -63,7 +64,7 @@ ExpandCelCanvas::ExpandCelCanvas(Context* context, TiledMode tiledMode, UndoTran
|
||||
if (m_cel == NULL) {
|
||||
// Create the image
|
||||
m_celImage = Image::create(m_sprite->getPixelFormat(), m_sprite->getWidth(), m_sprite->getHeight());
|
||||
image_clear(m_celImage, m_sprite->getTransparentColor());
|
||||
clear_image(m_celImage, m_sprite->getTransparentColor());
|
||||
|
||||
// Create the cel
|
||||
m_cel = new Cel(location.frame(), 0);
|
||||
@ -81,8 +82,8 @@ ExpandCelCanvas::ExpandCelCanvas(Context* context, TiledMode tiledMode, UndoTran
|
||||
if (tiledMode == TILED_NONE) { // Non-tiled
|
||||
x1 = MIN(m_cel->getX(), 0);
|
||||
y1 = MIN(m_cel->getY(), 0);
|
||||
x2 = MAX(m_cel->getX()+m_celImage->w, m_sprite->getWidth());
|
||||
y2 = MAX(m_cel->getY()+m_celImage->h, m_sprite->getHeight());
|
||||
x2 = MAX(m_cel->getX()+m_celImage->getWidth(), m_sprite->getWidth());
|
||||
y2 = MAX(m_cel->getY()+m_celImage->getHeight(), m_sprite->getHeight());
|
||||
}
|
||||
else { // Tiled
|
||||
x1 = 0;
|
||||
@ -92,7 +93,7 @@ ExpandCelCanvas::ExpandCelCanvas(Context* context, TiledMode tiledMode, UndoTran
|
||||
}
|
||||
|
||||
// create two copies of the image region which we'll modify with the tool
|
||||
m_srcImage = image_crop(m_celImage,
|
||||
m_srcImage = crop_image(m_celImage,
|
||||
x1-m_cel->getX(),
|
||||
y1-m_cel->getY(), x2-x1, y2-y1,
|
||||
m_sprite->getTransparentColor());
|
||||
@ -127,14 +128,14 @@ void ExpandCelCanvas::commit()
|
||||
// with only the differences between both images.
|
||||
if (m_cel->getX() == m_originalCelX &&
|
||||
m_cel->getY() == m_originalCelY &&
|
||||
m_celImage->w == m_dstImage->w &&
|
||||
m_celImage->h == m_dstImage->h) {
|
||||
m_celImage->getWidth() == m_dstImage->getWidth() &&
|
||||
m_celImage->getHeight() == m_dstImage->getHeight()) {
|
||||
// Was m_celImage created in the start of the tool-loop?.
|
||||
if (m_celCreated) {
|
||||
// We can keep the m_celImage
|
||||
|
||||
// We copy the destination image to the m_celImage
|
||||
image_copy(m_celImage, m_dstImage, 0, 0);
|
||||
copy_image(m_celImage, m_dstImage, 0, 0);
|
||||
|
||||
// Add the m_celImage in the images stock of the sprite.
|
||||
m_cel->setImage(m_sprite->getStock()->addImage(m_celImage));
|
||||
@ -167,7 +168,7 @@ void ExpandCelCanvas::commit()
|
||||
}
|
||||
|
||||
// Copy the destination to the cel image.
|
||||
image_copy(m_celImage, m_dstImage, 0, 0);
|
||||
copy_image(m_celImage, m_dstImage, 0, 0);
|
||||
}
|
||||
}
|
||||
// If the size of both images are different, we have to
|
||||
|
@ -46,17 +46,15 @@ Image* NewImageFromMask(const DocumentLocation& location)
|
||||
{
|
||||
const Sprite* srcSprite = location.sprite();
|
||||
const Mask* srcMask = location.document()->getMask();
|
||||
const Image* srcBitmap = srcMask->getBitmap();
|
||||
const Image* srcMaskBitmap = srcMask->getBitmap();
|
||||
const gfx::Rect& srcBounds = srcMask->getBounds();
|
||||
const uint8_t* address;
|
||||
int x, y, u, v, getx, gety;
|
||||
Image *dst;
|
||||
const Image *src = location.image(&x, &y);
|
||||
div_t d;
|
||||
|
||||
ASSERT(srcSprite);
|
||||
ASSERT(srcMask);
|
||||
ASSERT(srcBitmap);
|
||||
ASSERT(srcMaskBitmap);
|
||||
ASSERT(src);
|
||||
|
||||
dst = Image::create(srcSprite->getPixelFormat(), srcBounds.w, srcBounds.h);
|
||||
@ -64,24 +62,24 @@ Image* NewImageFromMask(const DocumentLocation& location)
|
||||
return NULL;
|
||||
|
||||
// Clear the new image
|
||||
image_clear(dst, 0);
|
||||
clear_image(dst, 0);
|
||||
|
||||
// Copy the masked zones
|
||||
for (v=0; v<srcBounds.h; v++) {
|
||||
d = div(0, 8);
|
||||
address = ((const uint8_t**)srcBitmap->line)[v]+d.quot;
|
||||
const LockImageBits<BitmapTraits> maskBits(srcMaskBitmap, gfx::Rect(0, 0, srcBounds.w, srcBounds.h));
|
||||
LockImageBits<BitmapTraits>::const_iterator mask_it = maskBits.begin();
|
||||
|
||||
for (u=0; u<srcBounds.w; u++) {
|
||||
if ((*address & (1<<d.rem))) {
|
||||
for (v=0; v<srcBounds.h; ++v) {
|
||||
for (u=0; u<srcBounds.w; ++u, ++mask_it) {
|
||||
ASSERT(mask_it != maskBits.end());
|
||||
|
||||
if (*mask_it) {
|
||||
getx = u+srcBounds.x-x;
|
||||
gety = v+srcBounds.y-y;
|
||||
|
||||
if ((getx >= 0) && (getx < src->w) &&
|
||||
(gety >= 0) && (gety < src->h))
|
||||
dst->putpixel(u, v, src->getpixel(getx, gety));
|
||||
if ((getx >= 0) && (getx < src->getWidth()) &&
|
||||
(gety >= 0) && (gety < src->getHeight()))
|
||||
dst->putPixel(u, v, src->getPixel(getx, gety));
|
||||
}
|
||||
|
||||
_image_bitmap_next_bit(d, address);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,9 +60,8 @@ Mask* load_msk_file(const char* filename)
|
||||
|
||||
// Just load an Animator Pro PIC file
|
||||
base::UniquePtr<Image> image(load_pic_file(filename, &x, &y, NULL));
|
||||
if (image != NULL && (image->getPixelFormat() == IMAGE_BITMAP)) {
|
||||
if (image != NULL && (image->getPixelFormat() == IMAGE_BITMAP))
|
||||
mask = new Mask(x, y, image.release());
|
||||
}
|
||||
}
|
||||
// Animator MSK format
|
||||
else if (orig_size == 8000) {
|
||||
@ -73,7 +72,7 @@ Mask* load_msk_file(const char* filename)
|
||||
for (i=0; i<8000; i++) {
|
||||
byte = pack_getc (f);
|
||||
for (c=0; c<8; c++) {
|
||||
mask->getBitmap()->putpixel(u, v, byte & (1<<(7-c)));
|
||||
mask->getBitmap()->putPixel(u, v, byte & (1<<(7-c)));
|
||||
u++;
|
||||
if (u == 320) {
|
||||
u = 0;
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "base/unique_ptr.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/primitives.h"
|
||||
|
||||
#include <allegro/color.h>
|
||||
#include <allegro/file.h>
|
||||
@ -86,7 +87,7 @@ Image* load_pic_file(const char* filename, int* x, int* y, RGB* palette)
|
||||
|
||||
for (v=0; v<h; v++)
|
||||
for (u=0; u<w; u++)
|
||||
image->putpixel(u, v, pack_getc(f));
|
||||
image->putPixel(u, v, pack_getc(f));
|
||||
|
||||
pack_fclose(f);
|
||||
return image.release();
|
||||
@ -157,7 +158,7 @@ Image* load_pic_file(const char* filename, int* x, int* y, RGB* palette)
|
||||
case 1:
|
||||
for (v=0; v<h; v++)
|
||||
for (u=0; u<w; u++)
|
||||
image->putpixel(u, v, pack_getc(f));
|
||||
image->putPixel(u, v, pack_getc(f));
|
||||
break;
|
||||
|
||||
/* bit-per-pixel image data */
|
||||
@ -166,7 +167,7 @@ Image* load_pic_file(const char* filename, int* x, int* y, RGB* palette)
|
||||
for (u=0; u<(w+7)/8; u++) {
|
||||
byte = pack_getc (f);
|
||||
for (c=0; c<8; c++)
|
||||
image_putpixel (image, u*8+c, v, byte & (1<<(7-c)));
|
||||
put_pixel(image, u*8+c, v, byte & (1<<(7-c)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -201,15 +202,15 @@ int save_pic_file(const char *filename, int x, int y, const RGB* palette, const
|
||||
size = 64;
|
||||
/* bit-per-pixel image data block */
|
||||
if (bpp == 1)
|
||||
size += (4+2+((image->w+7)/8)*image->h);
|
||||
size += (4+2+((image->getWidth()+7)/8)*image->getHeight());
|
||||
/* color palette info + byte-per-pixel image data block */
|
||||
else
|
||||
size += (4+2+2+256*3) + (4+2+image->w*image->h);
|
||||
size += (4+2+2+256*3) + (4+2+image->getWidth()*image->getHeight());
|
||||
|
||||
pack_iputl(size, f); /* file size */
|
||||
pack_iputw(0x9500, f); /* magic number 9500h */
|
||||
pack_iputw(image->w, f); /* width */
|
||||
pack_iputw(image->h, f); /* height */
|
||||
pack_iputw(image->getWidth(), f); /* width */
|
||||
pack_iputw(image->getHeight(), f); /* height */
|
||||
pack_iputw(x, f); /* X offset */
|
||||
pack_iputw(y, f); /* Y offset */
|
||||
pack_iputl(0, f); /* user ID, is 0 */
|
||||
@ -222,35 +223,35 @@ int save_pic_file(const char *filename, int x, int y, const RGB* palette, const
|
||||
/* 1 bpp */
|
||||
if (bpp == 1) {
|
||||
/* bit-per-data image data block */
|
||||
pack_iputl ((4+2+((image->w+7)/8)*image->h), f); /* block size */
|
||||
pack_iputw (2, f); /* block type */
|
||||
for (v=0; v<image->h; v++) /* image data */
|
||||
for (u=0; u<(image->w+7)/8; u++) {
|
||||
pack_iputl((4+2+((image->getWidth()+7)/8)*image->getHeight()), f); /* block size */
|
||||
pack_iputw(2, f); /* block type */
|
||||
for (v=0; v<image->getHeight(); v++) /* image data */
|
||||
for (u=0; u<(image->getWidth()+7)/8; u++) {
|
||||
byte = 0;
|
||||
for (c=0; c<8; c++)
|
||||
if (image_getpixel (image, u*8+c, v))
|
||||
if (get_pixel(image, u*8+c, v))
|
||||
byte |= (1<<(7-c));
|
||||
pack_putc (byte, f);
|
||||
}
|
||||
}
|
||||
/* 8 bpp */
|
||||
// 8 bpp
|
||||
else {
|
||||
/* color palette info */
|
||||
pack_iputl((4+2+2+256*3), f); /* block size */
|
||||
pack_iputw(0, f); /* block type */
|
||||
pack_iputw(0, f); /* version */
|
||||
for (c=0; c<256; c++) { /* 256 palette entries */
|
||||
// Color palette info
|
||||
pack_iputl((4+2+2+256*3), f); // Block size
|
||||
pack_iputw(0, f); // Block type
|
||||
pack_iputw(0, f); // Version
|
||||
for (c=0; c<256; c++) { // 256 palette entries
|
||||
pack_putc(_rgb_scale_6[palette[c].r], f);
|
||||
pack_putc(_rgb_scale_6[palette[c].g], f);
|
||||
pack_putc(_rgb_scale_6[palette[c].b], f);
|
||||
}
|
||||
|
||||
/* pixel-per-data image data block */
|
||||
pack_iputl ((4+2+image->w*image->h), f); /* block size */
|
||||
pack_iputw (1, f); /* block type */
|
||||
for (v=0; v<image->h; v++) /* image data */
|
||||
for (u=0; u<image->w; u++)
|
||||
pack_putc(image->getpixel(u, v), f);
|
||||
pack_iputl ((4+2+image->getWidth()*image->getHeight()), f); // Block size
|
||||
pack_iputw (1, f); // Block type
|
||||
for (v=0; v<image->getHeight(); v++) // Image data
|
||||
for (u=0; u<image->getWidth(); u++)
|
||||
pack_putc(image->getPixel(u, v), f);
|
||||
}
|
||||
|
||||
pack_fclose (f);
|
||||
|
@ -44,17 +44,17 @@ public:
|
||||
BlenderHelper(const Image* src, const Palette* pal, int blend_mode)
|
||||
{
|
||||
m_blend_color = SrcTraits::get_blender(blend_mode);
|
||||
m_mask_color = src->mask_color;
|
||||
m_mask_color = src->getMaskColor();
|
||||
}
|
||||
inline void operator()(typename DstTraits::address_t& scanline_address,
|
||||
typename DstTraits::address_t& dst_address,
|
||||
typename SrcTraits::address_t& src_address,
|
||||
inline void operator()(typename DstTraits::pixel_t& scanline,
|
||||
const typename DstTraits::pixel_t& dst,
|
||||
const typename SrcTraits::pixel_t& src,
|
||||
int opacity)
|
||||
{
|
||||
if (*src_address != m_mask_color)
|
||||
*scanline_address = (*m_blend_color)(*dst_address, *src_address, opacity);
|
||||
if (src != m_mask_color)
|
||||
scanline = (*m_blend_color)(dst, src, opacity);
|
||||
else
|
||||
*scanline_address = *dst_address;
|
||||
scanline = dst;
|
||||
}
|
||||
};
|
||||
|
||||
@ -67,19 +67,19 @@ public:
|
||||
BlenderHelper(const Image* src, const Palette* pal, int blend_mode)
|
||||
{
|
||||
m_blend_color = RgbTraits::get_blender(blend_mode);
|
||||
m_mask_color = src->mask_color;
|
||||
m_mask_color = src->getMaskColor();
|
||||
}
|
||||
inline void operator()(RgbTraits::address_t& scanline_address,
|
||||
RgbTraits::address_t& dst_address,
|
||||
GrayscaleTraits::address_t& src_address,
|
||||
inline void operator()(RgbTraits::pixel_t& scanline,
|
||||
const RgbTraits::pixel_t& dst,
|
||||
const GrayscaleTraits::pixel_t& src,
|
||||
int opacity)
|
||||
{
|
||||
if (*src_address != m_mask_color) {
|
||||
int v = _graya_getv(*src_address);
|
||||
*scanline_address = (*m_blend_color)(*dst_address, _rgba(v, v, v, _graya_geta(*src_address)), opacity);
|
||||
if (src != m_mask_color) {
|
||||
int v = graya_getv(src);
|
||||
scanline = (*m_blend_color)(dst, rgba(v, v, v, graya_geta(src)), opacity);
|
||||
}
|
||||
else
|
||||
*scanline_address = *dst_address;
|
||||
scanline = dst;
|
||||
}
|
||||
};
|
||||
|
||||
@ -93,23 +93,23 @@ public:
|
||||
BlenderHelper(const Image* src, const Palette* pal, int blend_mode)
|
||||
{
|
||||
m_blend_mode = blend_mode;
|
||||
m_mask_color = src->mask_color;
|
||||
m_mask_color = src->getMaskColor();
|
||||
m_pal = pal;
|
||||
}
|
||||
inline void operator()(RgbTraits::address_t& scanline_address,
|
||||
RgbTraits::address_t& dst_address,
|
||||
IndexedTraits::address_t& src_address,
|
||||
inline void operator()(RgbTraits::pixel_t& scanline,
|
||||
const RgbTraits::pixel_t& dst,
|
||||
const IndexedTraits::pixel_t& src,
|
||||
int opacity)
|
||||
{
|
||||
if (m_blend_mode == BLEND_MODE_COPY) {
|
||||
*scanline_address = m_pal->getEntry(*src_address);
|
||||
scanline = m_pal->getEntry(src);
|
||||
}
|
||||
else {
|
||||
if (*src_address != m_mask_color) {
|
||||
*scanline_address = _rgba_blend_normal(*dst_address, m_pal->getEntry(*src_address), opacity);
|
||||
if (src != m_mask_color) {
|
||||
scanline = rgba_blend_normal(dst, m_pal->getEntry(src), opacity);
|
||||
}
|
||||
else
|
||||
*scanline_address = *dst_address;
|
||||
scanline = dst;
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -120,9 +120,6 @@ static void merge_zoomed_image(Image* dst, const Image* src, const Palette* pal,
|
||||
int blend_mode, int zoom)
|
||||
{
|
||||
BlenderHelper<DstTraits, SrcTraits> blender(src, pal, blend_mode);
|
||||
typename SrcTraits::address_t src_address;
|
||||
typename DstTraits::address_t dst_address, dst_address_end;
|
||||
typename DstTraits::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;
|
||||
@ -134,13 +131,13 @@ static void merge_zoomed_image(Image* dst, const Image* src, const Palette* pal,
|
||||
|
||||
src_x = 0;
|
||||
src_y = 0;
|
||||
src_w = src->w;
|
||||
src_h = src->h;
|
||||
src_w = src->getWidth();
|
||||
src_h = src->getHeight();
|
||||
|
||||
dst_x = x;
|
||||
dst_y = y;
|
||||
dst_w = src->w<<zoom;
|
||||
dst_h = src->h<<zoom;
|
||||
dst_w = src->getWidth()<<zoom;
|
||||
dst_h = src->getHeight()<<zoom;
|
||||
|
||||
// clipping...
|
||||
if (dst_x < 0) {
|
||||
@ -163,120 +160,118 @@ static void merge_zoomed_image(Image* dst, const Image* src, const Palette* pal,
|
||||
else
|
||||
first_box_h = 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_x+dst_w > dst->getWidth()) {
|
||||
src_w -= (dst_x+dst_w-dst->getWidth()) >> zoom;
|
||||
dst_w = dst->getWidth() - 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 (dst_y+dst_h > dst->getHeight()) {
|
||||
src_h -= (dst_y+dst_h-dst->getHeight()) >> zoom;
|
||||
dst_h = dst->getHeight() - dst_y;
|
||||
}
|
||||
|
||||
if ((src_w <= 0) || (src_h <= 0) || (dst_w <= 0) || (dst_h <= 0))
|
||||
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
|
||||
scanline = new typename DstTraits::pixel_t[src_w];
|
||||
typedef std::vector<typename DstTraits::pixel_t> Scanline;
|
||||
Scanline scanline(src_w);
|
||||
typename Scanline::iterator scanline_it;
|
||||
typename Scanline::iterator scanline_end = scanline.end();
|
||||
|
||||
// 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);
|
||||
// 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(), src_end = srcBits.end();
|
||||
typename LockImageBits<DstTraits>::iterator dst_it, dst_end;
|
||||
|
||||
// get addresses to each line (beginning of 'src', 'dst', etc.)
|
||||
src_address = image_address_fast<SrcTraits>(src, src_x, src_y);
|
||||
dst_address = image_address_fast<DstTraits>(dst, dst_x, dst_y);
|
||||
dst_address_end = dst_address + dst_w;
|
||||
scanline_address = scanline;
|
||||
// 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'
|
||||
for (x=0; x<src_w; x++) {
|
||||
ASSERT(scanline_address >= scanline);
|
||||
ASSERT(scanline_address < scanline + src_w);
|
||||
// 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);
|
||||
|
||||
ASSERT(src_address >= image_address_fast<SrcTraits>(src, src_x, src_y));
|
||||
ASSERT(src_address <= image_address_fast<SrcTraits>(src, src_x+src_w-1, src_y));
|
||||
ASSERT(dst_address >= image_address_fast<DstTraits>(dst, dst_x, dst_y));
|
||||
ASSERT(dst_address <= image_address_fast<DstTraits>(dst, dst_x+dst_w-1, dst_y));
|
||||
ASSERT(dst_address < dst_address_end);
|
||||
blender(*scanline_it, *dst_it, *src_it, opacity);
|
||||
|
||||
blender(scanline_address, dst_address, src_address, opacity);
|
||||
++src_it;
|
||||
|
||||
src_address++;
|
||||
int delta;
|
||||
if ((x == 0) && (first_box_w > 0))
|
||||
dst_address += first_box_w;
|
||||
delta = first_box_w;
|
||||
else
|
||||
dst_address += box_w;
|
||||
scanline_address++;
|
||||
delta = box_w;
|
||||
|
||||
if (dst_address >= dst_address_end)
|
||||
break;
|
||||
while (dst_it != dst_end && delta-- > 0)
|
||||
++dst_it;
|
||||
|
||||
++scanline_it;
|
||||
}
|
||||
|
||||
// get the 'height' of the line to be painted in 'dst'
|
||||
// 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_address = image_address_fast<DstTraits>(dst, dst_x, dst_y);
|
||||
dst_address_end = dst_address + dst_w;
|
||||
scanline_address = scanline;
|
||||
// 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_address >= scanline);
|
||||
ASSERT(scanline_address < scanline + src_w);
|
||||
ASSERT(dst_address >= image_address_fast<DstTraits>(dst, dst_x, dst_y));
|
||||
ASSERT(dst_address <= image_address_fast<DstTraits>(dst, dst_x+dst_w-1, dst_y));
|
||||
ASSERT(dst_address < dst_address_end);
|
||||
for (box_x=0; box_x<first_box_w; ++box_x) {
|
||||
ASSERT(scanline_it != scanline_end);
|
||||
ASSERT(dst_it != dst_end);
|
||||
|
||||
(*dst_address++) = (*scanline_address);
|
||||
*dst_it = *scanline_it;
|
||||
|
||||
if (dst_address >= dst_address_end)
|
||||
++dst_it;
|
||||
if (dst_it == dst_end)
|
||||
goto done_with_line;
|
||||
}
|
||||
|
||||
scanline_address++;
|
||||
x++;
|
||||
++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_address >= image_address_fast<DstTraits>(dst, dst_x, dst_y));
|
||||
ASSERT(dst_address <= image_address_fast<DstTraits>(dst, dst_x+dst_w-1, dst_y));
|
||||
ASSERT(dst_address < dst_address_end);
|
||||
for (; x<src_w; ++x) {
|
||||
for (box_x=0; box_x<box_w; ++box_x) {
|
||||
ASSERT(dst_it != dst_end);
|
||||
|
||||
(*dst_address++) = (*scanline_address);
|
||||
*dst_it = *scanline_it;
|
||||
|
||||
if (dst_address >= dst_address_end)
|
||||
++dst_it;
|
||||
if (dst_it == dst_end)
|
||||
goto done_with_line;
|
||||
}
|
||||
|
||||
scanline_address++;
|
||||
++scanline_it;
|
||||
}
|
||||
|
||||
done_with_line:;
|
||||
|
||||
if (++dst_y > bottom)
|
||||
goto done_with_blit;
|
||||
}
|
||||
|
||||
// go to the next line in the source image
|
||||
src_y++;
|
||||
++src_y;
|
||||
}
|
||||
|
||||
done_with_blit:;
|
||||
delete[] scanline;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@ -420,7 +415,7 @@ Image* RenderEngine::renderSprite(int source_x, int source_y,
|
||||
if (need_checked_bg && draw_tiled_bg)
|
||||
renderCheckedBackground(image, source_x, source_y, zoom);
|
||||
else
|
||||
image_clear(image, bg_color);
|
||||
clear_image(image, bg_color);
|
||||
|
||||
// Onion-skin feature: draw the previous frame
|
||||
IDocumentSettings* docSettings = UIContext::instance()
|
||||
@ -525,10 +520,10 @@ void RenderEngine::renderCheckedBackground(Image* image,
|
||||
|
||||
// Draw checked background (tile by tile)
|
||||
int u_start = u;
|
||||
for (y=y_start-tile_h; y<image->h+tile_h; y+=tile_h) {
|
||||
for (x=x_start-tile_w; x<image->w+tile_w; x+=tile_w) {
|
||||
image_rectfill(image, x, y, x+tile_w-1, y+tile_h-1,
|
||||
(((u+v))&1)? c1: c2);
|
||||
for (y=y_start-tile_h; y<image->getHeight()+tile_h; y+=tile_h) {
|
||||
for (x=x_start-tile_w; x<image->getWidth()+tile_w; x+=tile_w) {
|
||||
fill_rect(image, x, y, x+tile_w-1, y+tile_h-1,
|
||||
(((u+v))&1)? c1: c2);
|
||||
++u;
|
||||
}
|
||||
u = u_start;
|
||||
@ -577,9 +572,9 @@ void RenderEngine::renderLayer(const Layer* layer,
|
||||
if (!layer->isReadable())
|
||||
return;
|
||||
|
||||
switch (layer->getType()) {
|
||||
switch (layer->type()) {
|
||||
|
||||
case GFXOBJ_LAYER_IMAGE: {
|
||||
case OBJECT_LAYER_IMAGE: {
|
||||
if ((!render_background && layer->isBackground()) ||
|
||||
(!render_transparent && !layer->isBackground()))
|
||||
break;
|
||||
@ -608,7 +603,7 @@ void RenderEngine::renderLayer(const Layer* layer,
|
||||
output_opacity = MID(0, cel->getOpacity(), 255);
|
||||
output_opacity = INT_MULT(output_opacity, global_opacity, t);
|
||||
|
||||
src_image->mask_color = m_sprite->getTransparentColor();
|
||||
src_image->setMaskColor(m_sprite->getTransparentColor());
|
||||
|
||||
(*zoomed_func)(image, src_image, m_sprite->getPalette(frame),
|
||||
(cel->getX() << zoom) - source_x,
|
||||
@ -620,7 +615,7 @@ void RenderEngine::renderLayer(const Layer* layer,
|
||||
break;
|
||||
}
|
||||
|
||||
case GFXOBJ_LAYER_FOLDER: {
|
||||
case OBJECT_LAYER_FOLDER: {
|
||||
LayerConstIterator it = static_cast<const LayerFolder*>(layer)->getLayerBegin();
|
||||
LayerConstIterator end = static_cast<const LayerFolder*>(layer)->getLayerEnd();
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "raster/image.h"
|
||||
#include "raster/layer.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/primitives.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "raster/stock.h"
|
||||
|
||||
@ -112,12 +113,12 @@ static void thumbnail_render(BITMAP* bmp, const Image* image, bool has_alpha, co
|
||||
|
||||
ASSERT(image != NULL);
|
||||
|
||||
sx = (double)image->w / (double)bmp->w;
|
||||
sy = (double)image->h / (double)bmp->h;
|
||||
sx = (double)image->getWidth() / (double)bmp->w;
|
||||
sy = (double)image->getHeight() / (double)bmp->h;
|
||||
scale = MAX(sx, sy);
|
||||
|
||||
w = image->w / scale;
|
||||
h = image->h / scale;
|
||||
w = image->getWidth() / scale;
|
||||
h = image->getHeight() / scale;
|
||||
w = MIN(bmp->w, w);
|
||||
h = MIN(bmp->h, h);
|
||||
|
||||
@ -137,38 +138,38 @@ static void thumbnail_render(BITMAP* bmp, const Image* image, bool has_alpha, co
|
||||
case IMAGE_RGB:
|
||||
for (y=0; y<h; y++)
|
||||
for (x=0; x<w; x++) {
|
||||
c = image_getpixel(image, x*scale, y*scale);
|
||||
c = get_pixel(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);
|
||||
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)));
|
||||
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);
|
||||
c = get_pixel(image, x*scale, y*scale);
|
||||
c2 = getpixel(bmp, x1+x, y1+y);
|
||||
c = _graya_blend_normal(_graya(getr(c2), 255), c, 255);
|
||||
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)));
|
||||
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);
|
||||
c = get_pixel(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)));
|
||||
putpixel(bmp, x1+x, y1+y, makecol(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c)));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -183,32 +184,32 @@ static void thumbnail_render(BITMAP* bmp, const Image* image, bool has_alpha, co
|
||||
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)));
|
||||
c = get_pixel(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)));
|
||||
c = get_pixel(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);
|
||||
c = get_pixel(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)));
|
||||
putpixel(bmp, x1+x, y1+y, makecol(rgba_getr(c),
|
||||
rgba_getg(c),
|
||||
rgba_getb(c)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
21
src/base/clamp.h
Normal file
21
src/base/clamp.h
Normal file
@ -0,0 +1,21 @@
|
||||
// Aseprite Base Library
|
||||
// Copyright (c) 2001-2013 David Capello
|
||||
//
|
||||
// This source file is distributed under MIT license,
|
||||
// please read LICENSE.txt for more information.
|
||||
|
||||
#ifndef BASE_CLAMP_H_INCLUDED
|
||||
#define BASE_CLAMP_H_INCLUDED
|
||||
|
||||
namespace base {
|
||||
|
||||
template<typename T>
|
||||
T clamp(const T& value, const T& low, const T& high) {
|
||||
return (value > high ? high:
|
||||
(value < low ? low:
|
||||
value));
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
|
||||
#endif
|
@ -76,17 +76,17 @@ void ColorCurveFilter::applyToRgba(FilterManager* filterMgr)
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
r = _rgba_getr(c);
|
||||
g = _rgba_getg(c);
|
||||
b = _rgba_getb(c);
|
||||
a = _rgba_geta(c);
|
||||
r = rgba_getr(c);
|
||||
g = rgba_getg(c);
|
||||
b = rgba_getb(c);
|
||||
a = rgba_geta(c);
|
||||
|
||||
if (target & TARGET_RED_CHANNEL) r = m_cmap[r];
|
||||
if (target & TARGET_GREEN_CHANNEL) g = m_cmap[g];
|
||||
if (target & TARGET_BLUE_CHANNEL) b = m_cmap[b];
|
||||
if (target & TARGET_ALPHA_CHANNEL) a = m_cmap[a];
|
||||
|
||||
*(dst_address++) = _rgba(r, g, b, a);
|
||||
*(dst_address++) = rgba(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,13 +107,13 @@ void ColorCurveFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
k = _graya_getv(c);
|
||||
a = _graya_geta(c);
|
||||
k = graya_getv(c);
|
||||
a = graya_geta(c);
|
||||
|
||||
if (target & TARGET_GRAY_CHANNEL) k = m_cmap[k];
|
||||
if (target & TARGET_ALPHA_CHANNEL) a = m_cmap[a];
|
||||
|
||||
*(dst_address++) = _graya(k, a);
|
||||
*(dst_address++) = graya(k, a);
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,9 +140,9 @@ void ColorCurveFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
c = m_cmap[c];
|
||||
}
|
||||
else {
|
||||
r = _rgba_getr(pal->getEntry(c));
|
||||
g = _rgba_getg(pal->getEntry(c));
|
||||
b = _rgba_getb(pal->getEntry(c));
|
||||
r = rgba_getr(pal->getEntry(c));
|
||||
g = rgba_getg(pal->getEntry(c));
|
||||
b = rgba_getb(pal->getEntry(c));
|
||||
|
||||
if (target & TARGET_RED_CHANNEL) r = m_cmap[r];
|
||||
if (target & TARGET_GREEN_CHANNEL) g = m_cmap[g];
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "filters/neighboring_pixels.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/primitives_fast.h"
|
||||
#include "raster/rgbmap.h"
|
||||
|
||||
namespace filters {
|
||||
@ -59,13 +60,13 @@ namespace {
|
||||
void operator()(RgbTraits::pixel_t color)
|
||||
{
|
||||
if (*matrixData) {
|
||||
if (_rgba_geta(color) == 0)
|
||||
if (rgba_geta(color) == 0)
|
||||
div -= *matrixData;
|
||||
else {
|
||||
r += _rgba_getr(color) * (*matrixData);
|
||||
g += _rgba_getg(color) * (*matrixData);
|
||||
b += _rgba_getb(color) * (*matrixData);
|
||||
a += _rgba_geta(color) * (*matrixData);
|
||||
r += rgba_getr(color) * (*matrixData);
|
||||
g += rgba_getg(color) * (*matrixData);
|
||||
b += rgba_getb(color) * (*matrixData);
|
||||
a += rgba_geta(color) * (*matrixData);
|
||||
}
|
||||
}
|
||||
matrixData++;
|
||||
@ -84,11 +85,11 @@ namespace {
|
||||
void operator()(GrayscaleTraits::pixel_t color)
|
||||
{
|
||||
if (*matrixData) {
|
||||
if (_graya_geta(color) == 0)
|
||||
if (graya_geta(color) == 0)
|
||||
div -= *matrixData;
|
||||
else {
|
||||
v += _graya_getv(color) * (*matrixData);
|
||||
a += _graya_geta(color) * (*matrixData);
|
||||
v += graya_getv(color) * (*matrixData);
|
||||
a += graya_geta(color) * (*matrixData);
|
||||
}
|
||||
}
|
||||
matrixData++;
|
||||
@ -110,9 +111,9 @@ namespace {
|
||||
void operator()(GrayscaleTraits::pixel_t color)
|
||||
{
|
||||
if (*matrixData) {
|
||||
r += _rgba_getr(pal->getEntry(color)) * (*matrixData);
|
||||
g += _rgba_getg(pal->getEntry(color)) * (*matrixData);
|
||||
b += _rgba_getb(pal->getEntry(color)) * (*matrixData);
|
||||
r += rgba_getr(pal->getEntry(color)) * (*matrixData);
|
||||
g += rgba_getg(pal->getEntry(color)) * (*matrixData);
|
||||
b += rgba_getb(pal->getEntry(color)) * (*matrixData);
|
||||
index += color * (*matrixData);
|
||||
}
|
||||
matrixData++;
|
||||
@ -173,7 +174,7 @@ void ConvolutionMatrixFilter::applyToRgba(FilterManager* filterMgr)
|
||||
m_matrix->getCenterY(),
|
||||
m_tiledMode, delegate);
|
||||
|
||||
color = image_getpixel_fast<RgbTraits>(src, x, y);
|
||||
color = get_pixel_fast<RgbTraits>(src, x, y);
|
||||
if (delegate.div == 0) {
|
||||
*(dst_address++) = color;
|
||||
continue;
|
||||
@ -184,30 +185,30 @@ void ConvolutionMatrixFilter::applyToRgba(FilterManager* filterMgr)
|
||||
delegate.r = MID(0, delegate.r, 255);
|
||||
}
|
||||
else
|
||||
delegate.r = _rgba_getr(color);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
delegate.a = rgba_geta(color);
|
||||
|
||||
*(dst_address++) = _rgba(delegate.r, delegate.g, delegate.b, delegate.a);
|
||||
*(dst_address++) = rgba(delegate.r, delegate.g, delegate.b, delegate.a);
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,7 +241,7 @@ void ConvolutionMatrixFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
m_matrix->getCenterY(),
|
||||
m_tiledMode, delegate);
|
||||
|
||||
color = image_getpixel_fast<GrayscaleTraits>(src, x, y);
|
||||
color = get_pixel_fast<GrayscaleTraits>(src, x, y);
|
||||
if (delegate.div == 0) {
|
||||
*(dst_address++) = color;
|
||||
continue;
|
||||
@ -251,16 +252,16 @@ void ConvolutionMatrixFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
delegate.v = MID(0, delegate.v, 255);
|
||||
}
|
||||
else
|
||||
delegate.v = _graya_getv(color);
|
||||
delegate.v = graya_getv(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 = _graya_geta(color);
|
||||
delegate.a = graya_geta(color);
|
||||
|
||||
*(dst_address++) = _graya(delegate.v, delegate.a);
|
||||
*(dst_address++) = graya(delegate.v, delegate.a);
|
||||
}
|
||||
}
|
||||
|
||||
@ -295,7 +296,7 @@ void ConvolutionMatrixFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
m_matrix->getCenterY(),
|
||||
m_tiledMode, delegate);
|
||||
|
||||
color = image_getpixel_fast<IndexedTraits>(src, x, y);
|
||||
color = get_pixel_fast<IndexedTraits>(src, x, y);
|
||||
if (delegate.div == 0) {
|
||||
*(dst_address++) = color;
|
||||
continue;
|
||||
@ -313,21 +314,21 @@ void ConvolutionMatrixFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
delegate.r = MID(0, delegate.r, 255);
|
||||
}
|
||||
else
|
||||
delegate.r = _rgba_getr(pal->getEntry(color));
|
||||
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));
|
||||
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));
|
||||
delegate.b = rgba_getb(pal->getEntry(color));
|
||||
|
||||
*(dst_address++) = rgbmap->mapColor(delegate.r, delegate.g, delegate.b);
|
||||
}
|
||||
|
@ -54,17 +54,17 @@ void InvertColorFilter::applyToRgba(FilterManager* filterMgr)
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
r = _rgba_getr(c);
|
||||
g = _rgba_getg(c);
|
||||
b = _rgba_getb(c);
|
||||
a = _rgba_geta(c);
|
||||
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);
|
||||
*(dst_address++) = rgba(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,13 +85,13 @@ void InvertColorFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
k = _graya_getv(c);
|
||||
a = _graya_geta(c);
|
||||
k = graya_getv(c);
|
||||
a = graya_geta(c);
|
||||
|
||||
if (target & TARGET_GRAY_CHANNEL) k ^= 0xff;
|
||||
if (target & TARGET_ALPHA_CHANNEL) a ^= 0xff;
|
||||
|
||||
*(dst_address++) = _graya(k, a);
|
||||
*(dst_address++) = graya(k, a);
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,9 +117,9 @@ void InvertColorFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
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));
|
||||
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;
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "filters/tiled_mode.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/primitives_fast.h"
|
||||
#include "raster/rgbmap.h"
|
||||
|
||||
#include <algorithm>
|
||||
@ -48,10 +49,10 @@ namespace {
|
||||
|
||||
void operator()(RgbTraits::pixel_t color)
|
||||
{
|
||||
channel[0][c] = _rgba_getr(color);
|
||||
channel[1][c] = _rgba_getg(color);
|
||||
channel[2][c] = _rgba_getb(color);
|
||||
channel[3][c] = _rgba_geta(color);
|
||||
channel[0][c] = rgba_getr(color);
|
||||
channel[1][c] = rgba_getg(color);
|
||||
channel[2][c] = rgba_getb(color);
|
||||
channel[3][c] = rgba_geta(color);
|
||||
c++;
|
||||
}
|
||||
};
|
||||
@ -66,8 +67,8 @@ namespace {
|
||||
|
||||
void operator()(GrayscaleTraits::pixel_t color)
|
||||
{
|
||||
channel[0][c] = _graya_getv(color);
|
||||
channel[1][c] = _graya_geta(color);
|
||||
channel[0][c] = graya_getv(color);
|
||||
channel[1][c] = graya_geta(color);
|
||||
c++;
|
||||
}
|
||||
};
|
||||
@ -89,9 +90,9 @@ namespace {
|
||||
channel[0][c] = color;
|
||||
}
|
||||
else {
|
||||
channel[0][c] = _rgba_getr(pal->getEntry(color));
|
||||
channel[1][c] = _rgba_getg(pal->getEntry(color));
|
||||
channel[2][c] = _rgba_getb(pal->getEntry(color));
|
||||
channel[0][c] = rgba_getr(pal->getEntry(color));
|
||||
channel[1][c] = rgba_getg(pal->getEntry(color));
|
||||
channel[2][c] = rgba_getb(pal->getEntry(color));
|
||||
}
|
||||
c++;
|
||||
}
|
||||
@ -150,37 +151,37 @@ void MedianFilter::applyToRgba(FilterManager* filterMgr)
|
||||
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);
|
||||
color = get_pixel_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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
a = rgba_geta(color);
|
||||
|
||||
*(dst_address++) = _rgba(r, g, b, a);
|
||||
*(dst_address++) = rgba(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
@ -206,23 +207,23 @@ void MedianFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
get_neighboring_pixels<GrayscaleTraits>(src, x, y, m_width, m_height, m_width/2, m_height/2,
|
||||
m_tiledMode, delegate);
|
||||
|
||||
color = image_getpixel_fast<GrayscaleTraits>(src, x, y);
|
||||
color = get_pixel_fast<GrayscaleTraits>(src, x, y);
|
||||
|
||||
if (target & TARGET_GRAY_CHANNEL) {
|
||||
std::sort(m_channel[0].begin(), m_channel[0].end());
|
||||
k = m_channel[0][m_ncolors/2];
|
||||
}
|
||||
else
|
||||
k = _graya_getv(color);
|
||||
k = graya_getv(color);
|
||||
|
||||
if (target & TARGET_ALPHA_CHANNEL) {
|
||||
std::sort(m_channel[1].begin(), m_channel[1].end());
|
||||
a = m_channel[1][m_ncolors/2];
|
||||
}
|
||||
else
|
||||
a = _graya_geta(color);
|
||||
a = graya_geta(color);
|
||||
|
||||
*(dst_address++) = _graya(k, a);
|
||||
*(dst_address++) = graya(k, a);
|
||||
}
|
||||
}
|
||||
|
||||
@ -255,28 +256,28 @@ void MedianFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
*(dst_address++) = m_channel[0][m_ncolors/2];
|
||||
}
|
||||
else {
|
||||
color = image_getpixel_fast<IndexedTraits>(src, x, y);
|
||||
color = get_pixel_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));
|
||||
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));
|
||||
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));
|
||||
b = rgba_getb(pal->getEntry(color));
|
||||
|
||||
*(dst_address++) = rgbmap->mapColor(r, g, b);
|
||||
}
|
||||
|
@ -45,17 +45,17 @@ namespace filters {
|
||||
int addx, addy = 0;
|
||||
if (gety < 0) {
|
||||
if (tiledMode & TILED_Y_AXIS)
|
||||
gety = sourceImage->h - (-(gety+1) % sourceImage->h) - 1;
|
||||
gety = sourceImage->getHeight() - (-(gety+1) % sourceImage->getHeight()) - 1;
|
||||
else {
|
||||
addy = -gety;
|
||||
gety = 0;
|
||||
}
|
||||
}
|
||||
else if (gety >= sourceImage->h) {
|
||||
else if (gety >= sourceImage->getHeight()) {
|
||||
if (tiledMode & TILED_Y_AXIS)
|
||||
gety = gety % sourceImage->h;
|
||||
gety = gety % sourceImage->getHeight();
|
||||
else
|
||||
gety = sourceImage->h-1;
|
||||
gety = sourceImage->getHeight()-1;
|
||||
}
|
||||
|
||||
for (dy=0; dy<height; ++dy) {
|
||||
@ -64,28 +64,28 @@ namespace filters {
|
||||
addx = 0;
|
||||
if (getx < 0) {
|
||||
if (tiledMode & TILED_X_AXIS)
|
||||
getx = sourceImage->w - (-(getx+1) % sourceImage->w) - 1;
|
||||
getx = sourceImage->getWidth() - (-(getx+1) % sourceImage->getWidth()) - 1;
|
||||
else {
|
||||
addx = -getx;
|
||||
getx = 0;
|
||||
}
|
||||
}
|
||||
else if (getx >= sourceImage->w) {
|
||||
else if (getx >= sourceImage->getWidth()) {
|
||||
if (tiledMode & TILED_X_AXIS)
|
||||
getx = getx % sourceImage->w;
|
||||
getx = getx % sourceImage->getWidth();
|
||||
else
|
||||
getx = sourceImage->w-1;
|
||||
getx = sourceImage->getWidth()-1;
|
||||
}
|
||||
|
||||
typename Traits::const_address_t srcAddress =
|
||||
image_address_fast<Traits>(sourceImage, getx, gety);
|
||||
reinterpret_cast<typename Traits::const_address_t>(sourceImage->getPixelAddress(getx, gety));
|
||||
|
||||
for (dx=0; dx<width; dx++) {
|
||||
// Call the delegate for each pixel value.
|
||||
delegate(*srcAddress);
|
||||
|
||||
// Update X position to get pixel.
|
||||
if (getx < sourceImage->w-1) {
|
||||
if (getx < sourceImage->getWidth()-1) {
|
||||
++getx;
|
||||
if (addx == 0)
|
||||
++srcAddress;
|
||||
@ -94,12 +94,13 @@ namespace filters {
|
||||
}
|
||||
else if (tiledMode & TILED_X_AXIS) {
|
||||
getx = 0;
|
||||
srcAddress = image_address_fast<Traits>(sourceImage, getx, gety);
|
||||
srcAddress =
|
||||
reinterpret_cast<typename Traits::const_address_t>(sourceImage->getPixelAddress(getx, gety));
|
||||
}
|
||||
}
|
||||
|
||||
// Update Y position to get pixel
|
||||
if (gety < sourceImage->h-1) {
|
||||
if (gety < sourceImage->getHeight()-1) {
|
||||
if (addy == 0)
|
||||
++gety;
|
||||
else
|
||||
|
@ -63,10 +63,10 @@ void ReplaceColorFilter::applyToRgba(FilterManager* filterMgr)
|
||||
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);
|
||||
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()) {
|
||||
@ -77,10 +77,10 @@ void ReplaceColorFilter::applyToRgba(FilterManager* filterMgr)
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
src_r = _rgba_getr(c);
|
||||
src_g = _rgba_getg(c);
|
||||
src_b = _rgba_getb(c);
|
||||
src_a = _rgba_geta(c);
|
||||
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) &&
|
||||
@ -101,8 +101,8 @@ void ReplaceColorFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
int dst_k, dst_a;
|
||||
int x, c;
|
||||
|
||||
dst_k = _graya_getv(m_from);
|
||||
dst_a = _graya_geta(m_from);
|
||||
dst_k = graya_getv(m_from);
|
||||
dst_a = graya_geta(m_from);
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
@ -113,8 +113,8 @@ void ReplaceColorFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
src_k = _graya_getv(c);
|
||||
src_a = _graya_geta(c);
|
||||
src_k = graya_getv(c);
|
||||
src_a = graya_geta(c);
|
||||
|
||||
if ((ABS(src_k-dst_k) <= m_tolerance) &&
|
||||
(ABS(src_a-dst_a) <= m_tolerance))
|
||||
|
@ -6,14 +6,17 @@ add_library(raster-lib
|
||||
algo_polygon.cpp
|
||||
algofill.cpp
|
||||
algorithm/flip_image.cpp
|
||||
algorithm/resize_image.cpp
|
||||
algorithm/shrink_bounds.cpp
|
||||
blend.cpp
|
||||
cel.cpp
|
||||
cel_io.cpp
|
||||
color_scales.cpp
|
||||
conversion_alleg.cpp
|
||||
dirty.cpp
|
||||
dirty_io.cpp
|
||||
file/col_file.cpp
|
||||
file/gpl_file.cpp
|
||||
gfxobj.cpp
|
||||
image.cpp
|
||||
image_io.cpp
|
||||
images_collector.cpp
|
||||
@ -21,9 +24,11 @@ add_library(raster-lib
|
||||
layer_io.cpp
|
||||
mask.cpp
|
||||
mask_io.cpp
|
||||
object.cpp
|
||||
palette.cpp
|
||||
palette_io.cpp
|
||||
pen.cpp
|
||||
primitives.cpp
|
||||
quantization.cpp
|
||||
rgbmap.cpp
|
||||
rotate.cpp
|
||||
|
@ -377,8 +377,8 @@ void algo_ellipsefill(int x1, int y1, int x2, int y2, void *data, AlgoHLine proc
|
||||
}
|
||||
}
|
||||
|
||||
/* Algorightm from Allegro (allegro/src/spline.c)
|
||||
Adapted for ASEPRITE by David A. Capello. */
|
||||
// Algorightm from Allegro (allegro/src/spline.c)
|
||||
// Adapted for Aseprite by David Capello.
|
||||
void algo_spline(double x0, double y0, double x1, double y1,
|
||||
double x2, double y2, double x3, double y3,
|
||||
void *data, AlgoLine proc)
|
||||
|
@ -1,6 +1,6 @@
|
||||
// The floodfill routine.
|
||||
// By Shawn Hargreaves.
|
||||
// Adapted to ASEPRITE by David Capello
|
||||
// Adapted to Aseprite by David Capello
|
||||
//
|
||||
// This source file is distributed under a Allegro license, please
|
||||
// read allegro4-LICENSE.txt for more information.
|
||||
@ -11,6 +11,7 @@
|
||||
|
||||
#include "raster/algo.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/primitives.h"
|
||||
|
||||
#include <allegro.h>
|
||||
#include <allegro/internal/aintern.h>
|
||||
@ -38,19 +39,19 @@ static int flood_count; /* number of flooded segments */
|
||||
|
||||
#define FLOOD_LINE(c) (((FLOODED_LINE *)_scratch_mem) + c)
|
||||
|
||||
static inline bool color_equal_32(uint32_t c1, uint32_t c2, int tolerance)
|
||||
static inline bool color_equal_32(color_t c1, color_t c2, int tolerance)
|
||||
{
|
||||
if (tolerance == 0)
|
||||
return (c1 == c2) || (_rgba_geta(c1) == 0 && _rgba_geta(c2) == 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);
|
||||
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;
|
||||
@ -62,15 +63,15 @@ static inline bool color_equal_32(uint32_t c1, uint32_t c2, int tolerance)
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool color_equal_16(uint16_t c1, uint16_t c2, int tolerance)
|
||||
static inline bool color_equal_16(color_t c1, color_t c2, int tolerance)
|
||||
{
|
||||
if (tolerance == 0)
|
||||
return (c1 == c2) || (_graya_geta(c1) == 0 && _graya_geta(c2) == 0);
|
||||
return (c1 == c2) || (graya_geta(c1) == 0 && graya_geta(c2) == 0);
|
||||
else {
|
||||
int k1 = _graya_getv(c1);
|
||||
int a1 = _graya_geta(c1);
|
||||
int k2 = _graya_getv(c2);
|
||||
int a2 = _graya_geta(c2);
|
||||
int k1 = graya_getv(c1);
|
||||
int a1 = graya_geta(c1);
|
||||
int k2 = graya_getv(c2);
|
||||
int a2 = graya_geta(c2);
|
||||
|
||||
if (a1 == 0 && a2 == 0)
|
||||
return true;
|
||||
@ -80,12 +81,12 @@ static inline bool color_equal_16(uint16_t c1, uint16_t c2, int tolerance)
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool color_equal_8(uint8_t c1, uint8_t c2, int tolerance)
|
||||
static inline bool color_equal_8(color_t c1, color_t c2, int tolerance)
|
||||
{
|
||||
if (tolerance == 0)
|
||||
return (c1 == c2);
|
||||
else
|
||||
return ABS(c1-c2) <= tolerance;
|
||||
return ABS((int)c1 - (int)c2) <= tolerance;
|
||||
}
|
||||
|
||||
|
||||
@ -95,8 +96,8 @@ static inline bool color_equal_8(uint8_t c1, uint8_t c2, int tolerance)
|
||||
* 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)
|
||||
static int flooder(Image *image, int x, int y,
|
||||
color_t src_color, int tolerance, void *data, AlgoHLine proc)
|
||||
{
|
||||
FLOODED_LINE *p;
|
||||
int left = 0, right = 0;
|
||||
@ -106,20 +107,20 @@ static int flooder (Image *image, int x, int y,
|
||||
|
||||
case IMAGE_RGB:
|
||||
{
|
||||
uint32_t* address = ((uint32_t**)image->line)[y];
|
||||
uint32_t* address = reinterpret_cast<uint32_t*>(image->getPixelAddress(0, y));
|
||||
|
||||
/* check start pixel */
|
||||
// Check start pixel
|
||||
if (!color_equal_32((int)*(address+x), src_color, tolerance))
|
||||
return x+1;
|
||||
|
||||
/* work left from starting point */
|
||||
// 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++) {
|
||||
// Work right from starting point
|
||||
for (right=x+1; right<image->getWidth(); right++) {
|
||||
if (!color_equal_32((int)*(address+right), src_color, tolerance))
|
||||
break;
|
||||
}
|
||||
@ -128,20 +129,20 @@ static int flooder (Image *image, int x, int y,
|
||||
|
||||
case IMAGE_GRAYSCALE:
|
||||
{
|
||||
uint16_t* address = ((uint16_t**)image->line)[y];
|
||||
uint16_t* address = reinterpret_cast<uint16_t*>(image->getPixelAddress(0, y));
|
||||
|
||||
/* check start pixel */
|
||||
// Check start pixel
|
||||
if (!color_equal_16((int)*(address+x), src_color, tolerance))
|
||||
return x+1;
|
||||
|
||||
/* work left from starting point */
|
||||
// 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++) {
|
||||
// Work right from starting point
|
||||
for (right=x+1; right<image->getWidth(); right++) {
|
||||
if (!color_equal_16((int)*(address+right), src_color, tolerance))
|
||||
break;
|
||||
}
|
||||
@ -150,20 +151,20 @@ static int flooder (Image *image, int x, int y,
|
||||
|
||||
case IMAGE_INDEXED:
|
||||
{
|
||||
uint8_t* address = ((uint8_t**)image->line)[y];
|
||||
uint8_t* address = image->getPixelAddress(0, y);
|
||||
|
||||
/* check start pixel */
|
||||
// Check start pixel
|
||||
if (!color_equal_8((int)*(address+x), src_color, tolerance))
|
||||
return x+1;
|
||||
|
||||
/* work left from starting point */
|
||||
// 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++) {
|
||||
// Work right from starting point
|
||||
for (right=x+1; right<image->getWidth(); right++) {
|
||||
if (!color_equal_8((int)*(address+right), src_color, tolerance))
|
||||
break;
|
||||
}
|
||||
@ -171,19 +172,19 @@ static int flooder (Image *image, int x, int y,
|
||||
break;
|
||||
|
||||
default:
|
||||
/* check start pixel */
|
||||
if (image_getpixel(image, x, y) != src_color)
|
||||
// Check start pixel
|
||||
if (get_pixel(image, x, y) != src_color)
|
||||
return x+1;
|
||||
|
||||
/* work left from starting point */
|
||||
// Work left from starting point
|
||||
for (left=x-1; left>=0; left--) {
|
||||
if (image_getpixel(image, left, y) != src_color)
|
||||
if (get_pixel(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)
|
||||
// Work right from starting point
|
||||
for (right=x+1; right<image->getWidth(); right++) {
|
||||
if (get_pixel(image, right, y) != src_color)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -219,7 +220,7 @@ static int flooder (Image *image, int x, int y,
|
||||
if (y > 0)
|
||||
p->flags |= FLOOD_TODO_ABOVE;
|
||||
|
||||
if (y+1 < image->h)
|
||||
if (y+1 < image->getHeight())
|
||||
p->flags |= FLOOD_TODO_BELOW;
|
||||
|
||||
return right+2;
|
||||
@ -270,21 +271,20 @@ static int check_flood_line(Image* image, int y, int left, int right,
|
||||
*/
|
||||
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))
|
||||
if ((x < 0) || (x >= image->getWidth()) ||
|
||||
(y < 0) || (y >= image->getHeight()))
|
||||
return;
|
||||
|
||||
/* what color to replace? */
|
||||
src_color = image_getpixel (image, x, y);
|
||||
color_t src_color = get_pixel(image, x, y);
|
||||
|
||||
/* set up the list of flooded segments */
|
||||
_grow_scratch_mem(sizeof(FLOODED_LINE) * image->h);
|
||||
flood_count = image->h;
|
||||
_grow_scratch_mem(sizeof(FLOODED_LINE) * image->getHeight());
|
||||
flood_count = image->getHeight();
|
||||
p = (FLOODED_LINE*)_scratch_mem;
|
||||
for (c=0; c<flood_count; c++) {
|
||||
p[c].flags = 0;
|
||||
@ -323,7 +323,7 @@ void algo_floodfill(Image* image, int x, int y, int tolerance, void *data, AlgoH
|
||||
src_color, tolerance, data, proc)) {
|
||||
done = false;
|
||||
/* special case shortcut for going backwards */
|
||||
if ((c < image->h) && (c > 0))
|
||||
if ((c < image->getHeight()) && (c > 0))
|
||||
c -= 2;
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "gfx/rect.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/primitives.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
@ -40,22 +41,22 @@ void flip_image(Image* image, const gfx::Rect& bounds, FlipType flipType)
|
||||
for (int y=bounds.y; y<bounds.y+bounds.h; ++y) {
|
||||
int u = bounds.x+bounds.w-1;
|
||||
for (int x=bounds.x; x<bounds.x+bounds.w/2; ++x, --u) {
|
||||
uint32_t c1 = image_getpixel(image, x, y);
|
||||
uint32_t c2 = image_getpixel(image, u, y);
|
||||
image_putpixel(image, x, y, c2);
|
||||
image_putpixel(image, u, y, c1);
|
||||
uint32_t c1 = get_pixel(image, x, y);
|
||||
uint32_t c2 = get_pixel(image, u, y);
|
||||
put_pixel(image, x, y, c2);
|
||||
put_pixel(image, u, y, c1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FlipVertical: {
|
||||
int section_size = image_line_size(image, bounds.w);
|
||||
int section_size = image->getRowStrideSize(bounds.w);
|
||||
std::vector<uint8_t> tmpline(section_size);
|
||||
|
||||
int v = bounds.y+bounds.h-1;
|
||||
for (int y=bounds.y; y<bounds.y+bounds.h/2; ++y, --v) {
|
||||
uint8_t* address1 = static_cast<uint8_t*>(image_address(image, bounds.x, y));
|
||||
uint8_t* address2 = static_cast<uint8_t*>(image_address(image, bounds.x, v));
|
||||
uint8_t* address1 = image->getPixelAddress(bounds.x, y);
|
||||
uint8_t* address2 = image->getPixelAddress(bounds.x, v);
|
||||
|
||||
// Swap lines.
|
||||
std::copy(address1, address1+section_size, tmpline.begin());
|
||||
@ -78,14 +79,14 @@ void flip_image_with_mask(Image* image, const Mask* mask, FlipType flipType, int
|
||||
|
||||
for (int y=bounds.y; y<bounds.y+bounds.h; ++y) {
|
||||
// Copy the current row.
|
||||
image_copy(originalRow, image, -bounds.x, -y);
|
||||
copy_image(originalRow, image, -bounds.x, -y);
|
||||
|
||||
int u = bounds.x+bounds.w-1;
|
||||
for (int x=bounds.x; x<bounds.x+bounds.w; ++x, --u) {
|
||||
if (mask->containsPoint(x, y)) {
|
||||
image_putpixel(image, u, y, image_getpixel(originalRow, x-bounds.x, 0));
|
||||
put_pixel(image, u, y, get_pixel(originalRow, x-bounds.x, 0));
|
||||
if (!mask->containsPoint(u, y))
|
||||
image_putpixel(image, x, y, bgcolor);
|
||||
put_pixel(image, x, y, bgcolor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -97,14 +98,14 @@ void flip_image_with_mask(Image* image, const Mask* mask, FlipType flipType, int
|
||||
|
||||
for (int x=bounds.x; x<bounds.x+bounds.w; ++x) {
|
||||
// Copy the current column.
|
||||
image_copy(originalCol, image, -x, -bounds.y);
|
||||
copy_image(originalCol, image, -x, -bounds.y);
|
||||
|
||||
int v = bounds.y+bounds.h-1;
|
||||
for (int y=bounds.y; y<bounds.y+bounds.h; ++y, --v) {
|
||||
if (mask->containsPoint(x, y)) {
|
||||
image_putpixel(image, x, v, image_getpixel(originalCol, 0, y-bounds.y));
|
||||
put_pixel(image, x, v, get_pixel(originalCol, 0, y-bounds.y));
|
||||
if (!mask->containsPoint(x, v))
|
||||
image_putpixel(image, x, y, bgcolor);
|
||||
put_pixel(image, x, y, bgcolor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "raster/algorithm/flip_type.h"
|
||||
|
||||
namespace raster {
|
||||
|
||||
class Image;
|
||||
class Mask;
|
||||
|
||||
|
244
src/raster/algorithm/resize_image.cpp
Normal file
244
src/raster/algorithm/resize_image.cpp
Normal file
@ -0,0 +1,244 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 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
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "raster/algorithm/resize_image.h"
|
||||
|
||||
#include "raster/image.h"
|
||||
#include "raster/image_bits.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/rgbmap.h"
|
||||
|
||||
namespace raster {
|
||||
namespace algorithm {
|
||||
|
||||
void resize_image(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->getWidth() * 1.0 / dst->getWidth();
|
||||
dv = src->getHeight() * 1.0 / dst->getHeight();
|
||||
for (y=0; y<dst->getHeight(); ++y) {
|
||||
for (x=0; x<dst->getWidth(); ++x) {
|
||||
color = src->getPixel(MID(0, u, src->getWidth()-1),
|
||||
MID(0, v, src->getHeight()-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->getWidth()-1) * 1.0 / (dst->getWidth()-1);
|
||||
dv = (src->getHeight()-1) * 1.0 / (dst->getHeight()-1);
|
||||
for (y=0; y<dst->getHeight(); ++y) {
|
||||
for (x=0; x<dst->getWidth(); ++x) {
|
||||
u_floor = floor(u);
|
||||
v_floor = floor(v);
|
||||
|
||||
if (u_floor > src->getWidth()-1) {
|
||||
u_floor = src->getWidth()-1;
|
||||
u_floor2 = src->getWidth()-1;
|
||||
}
|
||||
else if (u_floor == src->getWidth()-1)
|
||||
u_floor2 = u_floor;
|
||||
else
|
||||
u_floor2 = u_floor+1;
|
||||
|
||||
if (v_floor > src->getHeight()-1) {
|
||||
v_floor = src->getHeight()-1;
|
||||
v_floor2 = src->getHeight()-1;
|
||||
}
|
||||
else if (v_floor == src->getHeight()-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;
|
||||
}
|
||||
}
|
||||
|
||||
dst->putPixel(x, y, dst_color);
|
||||
u += du;
|
||||
}
|
||||
u = 0.0;
|
||||
v += dv;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void fixup_image_transparent_colors(Image* image)
|
||||
{
|
||||
int x, y, u, v;
|
||||
|
||||
switch (image->getPixelFormat()) {
|
||||
|
||||
case IMAGE_RGB: {
|
||||
int r, g, b, count;
|
||||
LockImageBits<RgbTraits> bits(image);
|
||||
LockImageBits<RgbTraits>::iterator it = bits.begin();
|
||||
|
||||
for (y=0; y<image->getHeight(); ++y) {
|
||||
for (x=0; x<image->getWidth(); ++x, ++it) {
|
||||
uint32_t c = *it;
|
||||
|
||||
// if this is a completelly-transparent pixel...
|
||||
if (rgba_geta(c) == 0) {
|
||||
count = 0;
|
||||
r = g = b = 0;
|
||||
|
||||
LockImageBits<RgbTraits>::iterator it2 =
|
||||
bits.begin_area(gfx::Rect(x-1, y-1, 3, 3));
|
||||
|
||||
for (v=y-1; v<=y+1; ++v) {
|
||||
for (u=x-1; u<=x+1; ++u, ++it2) {
|
||||
if ((u >= 0) && (v >= 0) && (u < image->getWidth()) && (v < image->getHeight())) {
|
||||
c = *it2;
|
||||
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;
|
||||
*it = rgba(r, g, b, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case IMAGE_GRAYSCALE: {
|
||||
int k, count;
|
||||
LockImageBits<GrayscaleTraits> bits(image);
|
||||
LockImageBits<GrayscaleTraits>::iterator it = bits.begin();
|
||||
|
||||
for (y=0; y<image->getHeight(); ++y) {
|
||||
for (x=0; x<image->getWidth(); ++x, ++it) {
|
||||
uint16_t c = *it;
|
||||
|
||||
// If this is a completelly-transparent pixel...
|
||||
if (graya_geta(c) == 0) {
|
||||
count = 0;
|
||||
k = 0;
|
||||
|
||||
LockImageBits<GrayscaleTraits>::iterator it2 =
|
||||
bits.begin_area(gfx::Rect(x-1, y-1, 3, 3));
|
||||
|
||||
for (v=y-1; v<=y+1; ++v) {
|
||||
for (u=x-1; u<=x+1; ++u, ++it2) {
|
||||
if ((u >= 0) && (v >= 0) && (u < image->getWidth()) && (v < image->getHeight())) {
|
||||
c = *it2;
|
||||
if (graya_geta(c) > 0) {
|
||||
k += graya_getv(c);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
k /= count;
|
||||
*it = graya(k, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace algorithm
|
||||
} // namespace raster
|
53
src/raster/algorithm/resize_image.h
Normal file
53
src/raster/algorithm/resize_image.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 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
|
||||
*/
|
||||
|
||||
#ifndef RASTER_ALGORITHM_RESIZE_IMAGE_H_INCLUDED
|
||||
#define RASTER_ALGORITHM_RESIZE_IMAGE_H_INCLUDED
|
||||
|
||||
#include "gfx/fwd.h"
|
||||
|
||||
namespace raster {
|
||||
class Image;
|
||||
class Palette;
|
||||
class RgbMap;
|
||||
|
||||
namespace algorithm {
|
||||
|
||||
enum ResizeMethod {
|
||||
RESIZE_METHOD_NEAREST_NEIGHBOR,
|
||||
RESIZE_METHOD_BILINEAR,
|
||||
};
|
||||
|
||||
// Resizes the source image 'src' to the destination image 'dst'.
|
||||
//
|
||||
// Warning: If you are using the RESIZE_METHOD_BILINEAR, it is
|
||||
// recommended to use 'fixup_image_transparent_colors' function
|
||||
// over the source image 'src' BEFORE using this routine.
|
||||
void resize_image(const Image* src, Image* dst, ResizeMethod method, const Palette* palette, const RgbMap* rgbmap);
|
||||
|
||||
// It 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. Useful if you
|
||||
// want to use resize_image() with images that contains
|
||||
// transparent pixels.
|
||||
void fixup_image_transparent_colors(Image* image);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
114
src/raster/algorithm/shrink_bounds.cpp
Normal file
114
src/raster/algorithm/shrink_bounds.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 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
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "raster/algorithm/shrink_bounds.h"
|
||||
|
||||
#include "raster/image.h"
|
||||
|
||||
namespace raster {
|
||||
namespace algorithm {
|
||||
|
||||
static bool is_same_pixel(PixelFormat pixelFormat, color_t pixel1, color_t pixel2)
|
||||
{
|
||||
switch (pixelFormat) {
|
||||
case IMAGE_RGB:
|
||||
if (rgba_geta(pixel1) == 0 && rgba_geta(pixel2) == 0)
|
||||
return true;
|
||||
break;
|
||||
case IMAGE_GRAYSCALE:
|
||||
if (graya_geta(pixel1) == 0 && graya_geta(pixel2) == 0)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
return pixel1 == pixel2;
|
||||
}
|
||||
|
||||
bool shrink_bounds(Image *image, gfx::Rect& bounds, color_t refpixel)
|
||||
{
|
||||
bool shrink;
|
||||
int u, v;
|
||||
|
||||
bounds = image->getBounds();
|
||||
|
||||
// Shrink left side
|
||||
for (u=bounds.x; u<bounds.x+bounds.w; ++u) {
|
||||
shrink = true;
|
||||
for (v=bounds.y; v<bounds.y+bounds.h; ++v) {
|
||||
if (!is_same_pixel(image->getPixelFormat(), image->getPixel(u, v), refpixel)) {
|
||||
shrink = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!shrink)
|
||||
break;
|
||||
++bounds.x;
|
||||
--bounds.w;
|
||||
}
|
||||
|
||||
// Shrink right side
|
||||
for (u=bounds.x+bounds.w-1; u>=bounds.x; --u) {
|
||||
shrink = true;
|
||||
for (v=bounds.y; v<bounds.y+bounds.h; ++v) {
|
||||
if (!is_same_pixel(image->getPixelFormat(), image->getPixel(u, v), refpixel)) {
|
||||
shrink = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!shrink)
|
||||
break;
|
||||
--bounds.w;
|
||||
}
|
||||
|
||||
// Shrink top side
|
||||
for (v=bounds.y; v<bounds.y+bounds.h; ++v) {
|
||||
shrink = true;
|
||||
for (u=bounds.x; u<bounds.x+bounds.w; ++u) {
|
||||
if (!is_same_pixel(image->getPixelFormat(), image->getPixel(u, v), refpixel)) {
|
||||
shrink = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!shrink)
|
||||
break;
|
||||
++bounds.y;
|
||||
--bounds.h;
|
||||
}
|
||||
|
||||
// Shrink bottom side
|
||||
for (v=bounds.y+bounds.h-1; v>=bounds.y; --v) {
|
||||
shrink = true;
|
||||
for (u=bounds.x; u<bounds.x+bounds.w; ++u) {
|
||||
if (!is_same_pixel(image->getPixelFormat(), image->getPixel(u, v), refpixel)) {
|
||||
shrink = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!shrink)
|
||||
break;
|
||||
--bounds.h;
|
||||
}
|
||||
|
||||
return (!bounds.isEmpty());
|
||||
}
|
||||
|
||||
} // namespace algorithm
|
||||
} // namespace raster
|
36
src/raster/algorithm/shrink_bounds.h
Normal file
36
src/raster/algorithm/shrink_bounds.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 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
|
||||
*/
|
||||
|
||||
#ifndef RASTER_ALGORITHM_SHRINK_BOUNDS_H_INCLUDED
|
||||
#define RASTER_ALGORITHM_SHRINK_BOUNDS_H_INCLUDED
|
||||
|
||||
#include "gfx/fwd.h"
|
||||
#include "raster/algorithm/flip_type.h"
|
||||
#include "raster/color.h"
|
||||
|
||||
namespace raster {
|
||||
class Image;
|
||||
|
||||
namespace algorithm {
|
||||
|
||||
bool shrink_bounds(Image* image, gfx::Rect& bounds, color_t refpixel);
|
||||
|
||||
} // algorithm
|
||||
} // raster
|
||||
|
||||
#endif
|
@ -25,30 +25,30 @@
|
||||
|
||||
namespace raster {
|
||||
|
||||
BLEND_COLOR _rgba_blenders[] =
|
||||
BLEND_COLOR rgba_blenders[] =
|
||||
{
|
||||
_rgba_blend_normal,
|
||||
_rgba_blend_copy,
|
||||
rgba_blend_normal,
|
||||
rgba_blend_copy,
|
||||
};
|
||||
|
||||
BLEND_COLOR _graya_blenders[] =
|
||||
BLEND_COLOR graya_blenders[] =
|
||||
{
|
||||
_graya_blend_normal,
|
||||
_graya_blend_copy,
|
||||
graya_blend_normal,
|
||||
graya_blend_copy,
|
||||
};
|
||||
|
||||
/**********************************************************************/
|
||||
/* RGB blenders */
|
||||
/**********************************************************************/
|
||||
|
||||
int _rgba_blend_normal(int back, int front, int opacity)
|
||||
int rgba_blend_normal(int back, int front, int opacity)
|
||||
{
|
||||
register int t;
|
||||
|
||||
if ((back & 0xff000000) == 0) {
|
||||
return
|
||||
(front & 0xffffff) |
|
||||
(INT_MULT(_rgba_geta(front), opacity, t) << _rgba_a_shift);
|
||||
(INT_MULT(rgba_geta(front), opacity, t) << rgba_a_shift);
|
||||
}
|
||||
else if ((front & 0xff000000) == 0) {
|
||||
return back;
|
||||
@ -58,15 +58,15 @@ int _rgba_blend_normal(int back, int front, int opacity)
|
||||
int F_r, F_g, F_b, F_a;
|
||||
int D_r, D_g, D_b, D_a;
|
||||
|
||||
B_r = _rgba_getr(back);
|
||||
B_g = _rgba_getg(back);
|
||||
B_b = _rgba_getb(back);
|
||||
B_a = _rgba_geta(back);
|
||||
B_r = rgba_getr(back);
|
||||
B_g = rgba_getg(back);
|
||||
B_b = rgba_getb(back);
|
||||
B_a = rgba_geta(back);
|
||||
|
||||
F_r = _rgba_getr(front);
|
||||
F_g = _rgba_getg(front);
|
||||
F_b = _rgba_getb(front);
|
||||
F_a = _rgba_geta(front);
|
||||
F_r = rgba_getr(front);
|
||||
F_g = rgba_getg(front);
|
||||
F_b = rgba_getb(front);
|
||||
F_a = rgba_geta(front);
|
||||
F_a = INT_MULT(F_a, opacity, t);
|
||||
|
||||
D_a = B_a + F_a - INT_MULT(B_a, F_a, t);
|
||||
@ -74,44 +74,44 @@ int _rgba_blend_normal(int back, int front, int opacity)
|
||||
D_g = B_g + (F_g-B_g) * F_a / D_a;
|
||||
D_b = B_b + (F_b-B_b) * F_a / D_a;
|
||||
|
||||
return _rgba(D_r, D_g, D_b, D_a);
|
||||
return rgba(D_r, D_g, D_b, D_a);
|
||||
}
|
||||
}
|
||||
|
||||
int _rgba_blend_copy(int back, int front, int opacity)
|
||||
int rgba_blend_copy(int back, int front, int opacity)
|
||||
{
|
||||
return front;
|
||||
}
|
||||
|
||||
int _rgba_blend_forpath(int back, int front, int opacity)
|
||||
int rgba_blend_forpath(int back, int front, int opacity)
|
||||
{
|
||||
int F_r, F_g, F_b, F_a;
|
||||
register int t;
|
||||
|
||||
F_r = _rgba_getr(front);
|
||||
F_g = _rgba_getg(front);
|
||||
F_b = _rgba_getb(front);
|
||||
F_a = _rgba_geta(front);
|
||||
F_r = rgba_getr(front);
|
||||
F_g = rgba_getg(front);
|
||||
F_b = rgba_getb(front);
|
||||
F_a = rgba_geta(front);
|
||||
F_a = INT_MULT(F_a, opacity, t);
|
||||
|
||||
return _rgba(F_r, F_g, F_b, F_a);
|
||||
return rgba(F_r, F_g, F_b, F_a);
|
||||
}
|
||||
|
||||
int _rgba_blend_merge(int back, int front, int opacity)
|
||||
int rgba_blend_merge(int back, int front, int opacity)
|
||||
{
|
||||
int B_r, B_g, B_b, B_a;
|
||||
int F_r, F_g, F_b, F_a;
|
||||
int D_r, D_g, D_b, D_a;
|
||||
|
||||
B_r = _rgba_getr(back);
|
||||
B_g = _rgba_getg(back);
|
||||
B_b = _rgba_getb(back);
|
||||
B_a = _rgba_geta(back);
|
||||
B_r = rgba_getr(back);
|
||||
B_g = rgba_getg(back);
|
||||
B_b = rgba_getb(back);
|
||||
B_a = rgba_geta(back);
|
||||
|
||||
F_r = _rgba_getr(front);
|
||||
F_g = _rgba_getg(front);
|
||||
F_b = _rgba_getb(front);
|
||||
F_a = _rgba_geta(front);
|
||||
F_r = rgba_getr(front);
|
||||
F_g = rgba_getg(front);
|
||||
F_b = rgba_getb(front);
|
||||
F_a = rgba_geta(front);
|
||||
|
||||
if (B_a == 0) {
|
||||
D_r = F_r;
|
||||
@ -130,21 +130,21 @@ int _rgba_blend_merge(int back, int front, int opacity)
|
||||
}
|
||||
D_a = B_a + (F_a-B_a) * opacity / 255;
|
||||
|
||||
return _rgba(D_r, D_g, D_b, D_a);
|
||||
return rgba(D_r, D_g, D_b, D_a);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/* Grayscale blenders */
|
||||
/**********************************************************************/
|
||||
|
||||
int _graya_blend_normal(int back, int front, int opacity)
|
||||
int graya_blend_normal(int back, int front, int opacity)
|
||||
{
|
||||
register int t;
|
||||
|
||||
if ((back & 0xff00) == 0) {
|
||||
return
|
||||
(front & 0xff) |
|
||||
(INT_MULT(_graya_geta (front), opacity, t) << _graya_a_shift);
|
||||
(INT_MULT(graya_geta (front), opacity, t) << graya_a_shift);
|
||||
}
|
||||
else if ((front & 0xff00) == 0) {
|
||||
return back;
|
||||
@ -154,48 +154,48 @@ int _graya_blend_normal(int back, int front, int opacity)
|
||||
int F_g, F_a;
|
||||
int D_g, D_a;
|
||||
|
||||
B_g = _graya_getv(back);
|
||||
B_a = _graya_geta(back);
|
||||
B_g = graya_getv(back);
|
||||
B_a = graya_geta(back);
|
||||
|
||||
F_g = _graya_getv(front);
|
||||
F_a = _graya_geta(front);
|
||||
F_g = graya_getv(front);
|
||||
F_a = graya_geta(front);
|
||||
F_a = INT_MULT(F_a, opacity, t);
|
||||
|
||||
D_a = B_a + F_a - INT_MULT(B_a, F_a, t);
|
||||
D_g = B_g + (F_g-B_g) * F_a / D_a;
|
||||
|
||||
return _graya(D_g, D_a);
|
||||
return graya(D_g, D_a);
|
||||
}
|
||||
}
|
||||
|
||||
int _graya_blend_copy(int back, int front, int opacity)
|
||||
int graya_blend_copy(int back, int front, int opacity)
|
||||
{
|
||||
return front;
|
||||
}
|
||||
|
||||
int _graya_blend_forpath(int back, int front, int opacity)
|
||||
int graya_blend_forpath(int back, int front, int opacity)
|
||||
{
|
||||
int F_k, F_a;
|
||||
register int t;
|
||||
|
||||
F_k = _graya_getv(front);
|
||||
F_a = _graya_geta(front);
|
||||
F_k = graya_getv(front);
|
||||
F_a = graya_geta(front);
|
||||
F_a = INT_MULT(F_a, opacity, t);
|
||||
|
||||
return _graya(F_k, F_a);
|
||||
return graya(F_k, F_a);
|
||||
}
|
||||
|
||||
int _graya_blend_merge(int back, int front, int opacity)
|
||||
int graya_blend_merge(int back, int front, int opacity)
|
||||
{
|
||||
int B_k, B_a;
|
||||
int F_k, F_a;
|
||||
int D_k, D_a;
|
||||
|
||||
B_k = _graya_getv(back);
|
||||
B_a = _graya_geta(back);
|
||||
B_k = graya_getv(back);
|
||||
B_a = graya_geta(back);
|
||||
|
||||
F_k = _graya_getv(front);
|
||||
F_a = _graya_geta(front);
|
||||
F_k = graya_getv(front);
|
||||
F_a = graya_geta(front);
|
||||
|
||||
if (B_a == 0) {
|
||||
D_k = F_k;
|
||||
@ -208,7 +208,7 @@ int _graya_blend_merge(int back, int front, int opacity)
|
||||
}
|
||||
D_a = B_a + (F_a-B_a) * opacity / 255;
|
||||
|
||||
return _graya(D_k, D_a);
|
||||
return graya(D_k, D_a);
|
||||
}
|
||||
|
||||
} // namespace raster
|
||||
|
@ -32,18 +32,18 @@ namespace raster {
|
||||
|
||||
typedef int (*BLEND_COLOR)(int back, int front, int opacity);
|
||||
|
||||
extern BLEND_COLOR _rgba_blenders[];
|
||||
extern BLEND_COLOR _graya_blenders[];
|
||||
extern BLEND_COLOR rgba_blenders[];
|
||||
extern BLEND_COLOR graya_blenders[];
|
||||
|
||||
int _rgba_blend_normal(int back, int front, int opacity);
|
||||
int _rgba_blend_copy(int back, int front, int opacity);
|
||||
int _rgba_blend_forpath(int back, int front, int opacity);
|
||||
int _rgba_blend_merge(int back, int front, int opacity);
|
||||
int rgba_blend_normal(int back, int front, int opacity);
|
||||
int rgba_blend_copy(int back, int front, int opacity);
|
||||
int rgba_blend_forpath(int back, int front, int opacity);
|
||||
int rgba_blend_merge(int back, int front, int opacity);
|
||||
|
||||
int _graya_blend_normal(int back, int front, int opacity);
|
||||
int _graya_blend_copy(int back, int front, int opacity);
|
||||
int _graya_blend_forpath(int back, int front, int opacity);
|
||||
int _graya_blend_merge(int back, int front, int opacity);
|
||||
int graya_blend_normal(int back, int front, int opacity);
|
||||
int graya_blend_copy(int back, int front, int opacity);
|
||||
int graya_blend_forpath(int back, int front, int opacity);
|
||||
int graya_blend_merge(int back, int front, int opacity);
|
||||
|
||||
} // namespace raster
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
namespace raster {
|
||||
|
||||
Cel::Cel(FrameNumber frame, int image)
|
||||
: GfxObj(GFXOBJ_CEL)
|
||||
: Object(OBJECT_CEL)
|
||||
, m_frame(frame)
|
||||
, m_image(image)
|
||||
{
|
||||
@ -35,7 +35,7 @@ Cel::Cel(FrameNumber frame, int image)
|
||||
}
|
||||
|
||||
Cel::Cel(const Cel& cel)
|
||||
: GfxObj(cel)
|
||||
: Object(cel)
|
||||
, m_frame(cel.m_frame)
|
||||
, m_image(cel.m_image)
|
||||
{
|
||||
|
@ -20,13 +20,13 @@
|
||||
#define RASTER_CEL_H_INCLUDED
|
||||
|
||||
#include "raster/frame_number.h"
|
||||
#include "raster/gfxobj.h"
|
||||
#include "raster/object.h"
|
||||
|
||||
namespace raster {
|
||||
|
||||
class LayerImage;
|
||||
|
||||
class Cel : public GfxObj {
|
||||
class Cel : public Object {
|
||||
public:
|
||||
Cel(FrameNumber frame, int image);
|
||||
Cel(const Cel& cel);
|
||||
|
80
src/raster/color.h
Normal file
80
src/raster/color.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 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
|
||||
*/
|
||||
|
||||
#ifndef RASTER_COLOR_H_INCLUDED
|
||||
#define RASTER_COLOR_H_INCLUDED
|
||||
|
||||
namespace raster {
|
||||
|
||||
// The greatest int type to storage a color for an image in the
|
||||
// available pixel formats.
|
||||
typedef uint32_t color_t;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// RGBA
|
||||
|
||||
const int rgba_r_shift = 0;
|
||||
const int rgba_g_shift = 8;
|
||||
const int rgba_b_shift = 16;
|
||||
const int rgba_a_shift = 24;
|
||||
|
||||
inline uint8_t rgba_getr(uint32_t c) {
|
||||
return (c >> rgba_r_shift) & 0xff;
|
||||
}
|
||||
|
||||
inline uint8_t rgba_getg(uint32_t c) {
|
||||
return (c >> rgba_g_shift) & 0xff;
|
||||
}
|
||||
|
||||
inline uint8_t rgba_getb(uint32_t c) {
|
||||
return (c >> rgba_b_shift) & 0xff;
|
||||
}
|
||||
|
||||
inline uint8_t rgba_geta(uint32_t c) {
|
||||
return (c >> rgba_a_shift) & 0xff;
|
||||
}
|
||||
|
||||
inline uint32_t rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
||||
return ((r << rgba_r_shift) |
|
||||
(g << rgba_g_shift) |
|
||||
(b << rgba_b_shift) |
|
||||
(a << rgba_a_shift));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Grayscale
|
||||
|
||||
const int graya_v_shift = 0;
|
||||
const int graya_a_shift = 8;
|
||||
|
||||
inline uint8_t graya_getv(uint16_t c) {
|
||||
return (c >> graya_v_shift) & 0xff;
|
||||
}
|
||||
|
||||
inline uint8_t graya_geta(uint16_t c) {
|
||||
return (c >> graya_a_shift) & 0xff;
|
||||
}
|
||||
|
||||
inline uint16_t graya(uint8_t v, uint8_t a) {
|
||||
return ((v << graya_v_shift) |
|
||||
(a << graya_a_shift));
|
||||
}
|
||||
|
||||
} // namespace raster
|
||||
|
||||
#endif
|
@ -19,7 +19,9 @@
|
||||
#ifndef RASTER_COLOR_HISTOGRAM_H_INCLUDED
|
||||
#define RASTER_COLOR_HISTOGRAM_H_INCLUDED
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include "raster/image.h"
|
||||
#include "raster/image_traits.h"
|
||||
#include "raster/median_cut.h"
|
||||
@ -115,9 +117,9 @@ namespace quantization {
|
||||
// parameters.
|
||||
size_t histogramIndex(uint32_t color) const
|
||||
{
|
||||
return histogramIndex((_rgba_getr(color) >> (8 - RBits)),
|
||||
(_rgba_getg(color) >> (8 - GBits)),
|
||||
(_rgba_getb(color) >> (8 - BBits)));
|
||||
return histogramIndex((rgba_getr(color) >> (8 - RBits)),
|
||||
(rgba_getg(color) >> (8 - GBits)),
|
||||
(rgba_getb(color) >> (8 - BBits)));
|
||||
}
|
||||
|
||||
size_t histogramIndex(int i, int j, int k) const
|
||||
|
60
src/raster/color_scales.cpp
Normal file
60
src/raster/color_scales.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 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
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "base/clamp.h"
|
||||
|
||||
// Based on Allegro _rgb_scale_5 and _rgb_scale_6 tables
|
||||
|
||||
namespace raster {
|
||||
|
||||
int scale_5bits_to_8bits(int channel5bits)
|
||||
{
|
||||
static int scale[32] = {
|
||||
0, 8, 16, 24, 33, 41, 49, 57,
|
||||
66, 74, 82, 90, 99, 107, 115, 123,
|
||||
132, 140, 148, 156, 165, 173, 181, 189,
|
||||
198, 206, 214, 222, 231, 239, 247, 255
|
||||
};
|
||||
|
||||
ASSERT(channel5bits >= 0);
|
||||
ASSERT(channel5bits < 32);
|
||||
return scale[channel5bits];
|
||||
}
|
||||
|
||||
int scale_6bits_to_8bits(int channel6bits)
|
||||
{
|
||||
static int scale[64] = {
|
||||
0, 4, 8, 12, 16, 20, 24, 28,
|
||||
32, 36, 40, 44, 48, 52, 56, 60,
|
||||
65, 69, 73, 77, 81, 85, 89, 93,
|
||||
97, 101, 105, 109, 113, 117, 121, 125,
|
||||
130, 134, 138, 142, 146, 150, 154, 158,
|
||||
162, 166, 170, 174, 178, 182, 186, 190,
|
||||
195, 199, 203, 207, 211, 215, 219, 223,
|
||||
227, 231, 235, 239, 243, 247, 251, 255
|
||||
};
|
||||
ASSERT(channel6bits >= 0);
|
||||
ASSERT(channel6bits < 64);
|
||||
return scale[channel6bits];
|
||||
}
|
||||
|
||||
} // namespace raster
|
34
src/raster/color_scales.h
Normal file
34
src/raster/color_scales.h
Normal file
@ -0,0 +1,34 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 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
|
||||
*/
|
||||
|
||||
#ifndef RASTER_COLOR_SCALES_H_INCLUDED
|
||||
#define RASTER_COLOR_SCALES_H_INCLUDED
|
||||
|
||||
#include "raster/frame_number.h"
|
||||
#include "raster/object.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace raster {
|
||||
|
||||
int scale_5bits_to_8bits(int channel5bits);
|
||||
int scale_6bits_to_8bits(int channel6bits);
|
||||
|
||||
} // namespace raster
|
||||
|
||||
#endif
|
315
src/raster/conversion_alleg.cpp
Normal file
315
src/raster/conversion_alleg.cpp
Normal file
@ -0,0 +1,315 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 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
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "raster/conversion_alleg.h"
|
||||
|
||||
#include "raster/algo.h"
|
||||
#include "raster/blend.h"
|
||||
#include "raster/color_scales.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/image_impl.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/rgbmap.h"
|
||||
|
||||
#include <allegro.h>
|
||||
|
||||
namespace raster {
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename ImageTraits, int color_depth>
|
||||
int convert_color_to_allegro(color_t color, const Palette* palette) {
|
||||
// Error, it must use a specialization
|
||||
|
||||
// TODO Use a static_assert(false)
|
||||
}
|
||||
|
||||
template<>
|
||||
int convert_color_to_allegro<RgbTraits, 8>(color_t c, const Palette* palette) {
|
||||
return makecol8(rgba_getr(c), rgba_getg(c), rgba_getb(c));
|
||||
}
|
||||
template<>
|
||||
int convert_color_to_allegro<RgbTraits, 15>(color_t c, const Palette* palette) {
|
||||
return makecol15(rgba_getr(c), rgba_getg(c), rgba_getb(c));
|
||||
}
|
||||
template<>
|
||||
int convert_color_to_allegro<RgbTraits, 16>(color_t c, const Palette* palette) {
|
||||
return makecol16(rgba_getr(c), rgba_getg(c), rgba_getb(c));
|
||||
}
|
||||
template<>
|
||||
int convert_color_to_allegro<RgbTraits, 24>(color_t c, const Palette* palette) {
|
||||
return makecol24(rgba_getr(c), rgba_getg(c), rgba_getb(c));
|
||||
}
|
||||
template<>
|
||||
int convert_color_to_allegro<RgbTraits, 32>(color_t c, const Palette* palette) {
|
||||
return makeacol32(rgba_getr(c), rgba_getg(c), rgba_getb(c), rgba_geta(c));
|
||||
}
|
||||
|
||||
template<>
|
||||
int convert_color_to_allegro<GrayscaleTraits, 8>(color_t c, const Palette* palette) {
|
||||
return makecol8(graya_getv(c), graya_getv(c), graya_getv(c));
|
||||
}
|
||||
template<>
|
||||
int convert_color_to_allegro<GrayscaleTraits, 15>(color_t c, const Palette* palette) {
|
||||
return makecol15(graya_getv(c), graya_getv(c), graya_getv(c));
|
||||
}
|
||||
template<>
|
||||
int convert_color_to_allegro<GrayscaleTraits, 16>(color_t c, const Palette* palette) {
|
||||
return makecol16(graya_getv(c), graya_getv(c), graya_getv(c));
|
||||
}
|
||||
template<>
|
||||
int convert_color_to_allegro<GrayscaleTraits, 24>(color_t c, const Palette* palette) {
|
||||
return makecol24(graya_getv(c), graya_getv(c), graya_getv(c));
|
||||
}
|
||||
template<>
|
||||
int convert_color_to_allegro<GrayscaleTraits, 32>(color_t c, const Palette* palette) {
|
||||
return makeacol32(graya_getv(c), graya_getv(c), graya_getv(c), graya_geta(c));
|
||||
}
|
||||
|
||||
template<>
|
||||
int convert_color_to_allegro<IndexedTraits, 8>(color_t color, const Palette* palette) {
|
||||
return color;
|
||||
}
|
||||
template<>
|
||||
int convert_color_to_allegro<IndexedTraits, 15>(color_t color, const Palette* palette) {
|
||||
color_t c = palette->getEntry(color);
|
||||
return makecol15(rgba_getr(c), rgba_getg(c), rgba_getb(c));
|
||||
}
|
||||
template<>
|
||||
int convert_color_to_allegro<IndexedTraits, 16>(color_t color, const Palette* palette) {
|
||||
color_t c = palette->getEntry(color);
|
||||
return makecol16(rgba_getr(c), rgba_getg(c), rgba_getb(c));
|
||||
}
|
||||
template<>
|
||||
int convert_color_to_allegro<IndexedTraits, 24>(color_t color, const Palette* palette) {
|
||||
color_t c = palette->getEntry(color);
|
||||
return makecol24(rgba_getr(c), rgba_getg(c), rgba_getb(c));
|
||||
}
|
||||
template<>
|
||||
int convert_color_to_allegro<IndexedTraits, 32>(color_t color, const Palette* palette) {
|
||||
color_t c = palette->getEntry(color);
|
||||
return makeacol32(rgba_getr(c), rgba_getg(c), rgba_getb(c), 255);
|
||||
}
|
||||
|
||||
template<>
|
||||
int convert_color_to_allegro<BitmapTraits, 8>(color_t color, const Palette* palette) {
|
||||
return color;
|
||||
}
|
||||
template<>
|
||||
int convert_color_to_allegro<BitmapTraits, 15>(color_t color, const Palette* palette) {
|
||||
color_t c = palette->getEntry(color);
|
||||
return makecol15(rgba_getr(c), rgba_getg(c), rgba_getb(c));
|
||||
}
|
||||
template<>
|
||||
int convert_color_to_allegro<BitmapTraits, 16>(color_t color, const Palette* palette) {
|
||||
color_t c = palette->getEntry(color);
|
||||
return makecol16(rgba_getr(c), rgba_getg(c), rgba_getb(c));
|
||||
}
|
||||
template<>
|
||||
int convert_color_to_allegro<BitmapTraits, 24>(color_t color, const Palette* palette) {
|
||||
color_t c = palette->getEntry(color);
|
||||
return makecol24(rgba_getr(c), rgba_getg(c), rgba_getb(c));
|
||||
}
|
||||
template<>
|
||||
int convert_color_to_allegro<BitmapTraits, 32>(color_t color, const Palette* palette) {
|
||||
color_t c = palette->getEntry(color);
|
||||
return makeacol32(rgba_getr(c), rgba_getg(c), rgba_getb(c), rgba_geta(c));
|
||||
}
|
||||
|
||||
template<typename ImageTraits>
|
||||
void convert_image_to_allegro_templ(const Image* image, BITMAP* bmp, int _x, int _y, const Palette* palette)
|
||||
{
|
||||
const LockImageBits<ImageTraits> bits(image);
|
||||
typename LockImageBits<ImageTraits>::const_iterator src_it = bits.begin(), src_end = bits.end();
|
||||
int depth = bitmap_color_depth(bmp);
|
||||
int x, y, w = image->getWidth(), h = image->getHeight();
|
||||
unsigned long bmp_address;
|
||||
|
||||
bmp_select(bmp);
|
||||
|
||||
switch (depth) {
|
||||
|
||||
case 8:
|
||||
#if defined GFX_MODEX && !defined ALLEGRO_UNIX && !defined ALLEGRO_MACOSX
|
||||
if (is_planar_bitmap (bmp)) {
|
||||
for (y=0; y<h; ++y) {
|
||||
bmp_address = (unsigned long)bmp->line[_y];
|
||||
|
||||
for (x=0; x<w; ++x) {
|
||||
ASSERT(src_it != src_end);
|
||||
|
||||
outportw(0x3C4, (0x100<<((_x+x)&3))|2);
|
||||
bmp_write8(bmp_address+((_x+x)>>2),
|
||||
(convert_color_to_allegro<ImageTraits, 8>(*src_it, palette)));
|
||||
|
||||
++src_it;
|
||||
address++;
|
||||
}
|
||||
|
||||
_y++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
for (y=0; y<h; ++y) {
|
||||
bmp_address = bmp_write_line(bmp, _y)+_x;
|
||||
|
||||
for (x=0; x<w; ++x) {
|
||||
ASSERT(src_it != src_end);
|
||||
|
||||
bmp_write8(bmp_address,
|
||||
(convert_color_to_allegro<ImageTraits, 8>(*src_it, palette)));
|
||||
|
||||
++bmp_address;
|
||||
++src_it;
|
||||
}
|
||||
|
||||
_y++;
|
||||
}
|
||||
#if defined GFX_MODEX && !defined ALLEGRO_UNIX && !defined ALLEGRO_MACOSX
|
||||
}
|
||||
#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) {
|
||||
ASSERT(src_it != src_end);
|
||||
|
||||
bmp_write15(bmp_address,
|
||||
(convert_color_to_allegro<ImageTraits, 15>(*src_it, palette)));
|
||||
|
||||
bmp_address += 2;
|
||||
++src_it;
|
||||
}
|
||||
|
||||
_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) {
|
||||
ASSERT(src_it != src_end);
|
||||
|
||||
bmp_write16(bmp_address,
|
||||
(convert_color_to_allegro<ImageTraits, 16>(*src_it, palette)));
|
||||
|
||||
bmp_address += 2;
|
||||
++src_it;
|
||||
}
|
||||
|
||||
_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) {
|
||||
ASSERT(src_it != src_end);
|
||||
|
||||
bmp_write24(bmp_address,
|
||||
(convert_color_to_allegro<ImageTraits, 24>(*src_it, palette)));
|
||||
|
||||
bmp_address += 3;
|
||||
++src_it;
|
||||
}
|
||||
|
||||
_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) {
|
||||
ASSERT(src_it != src_end);
|
||||
|
||||
bmp_write32(bmp_address,
|
||||
(convert_color_to_allegro<ImageTraits, 32>(*src_it, palette)));
|
||||
|
||||
bmp_address += 4;
|
||||
++src_it;
|
||||
}
|
||||
|
||||
_y++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
bmp_unwrite_line(bmp);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void convert_image_to_allegro(const Image* image, BITMAP* bmp, int x, int y, const Palette* palette)
|
||||
{
|
||||
switch (image->getPixelFormat()) {
|
||||
case IMAGE_RGB: convert_image_to_allegro_templ<RgbTraits>(image, bmp, x, y, palette); break;
|
||||
case IMAGE_GRAYSCALE: convert_image_to_allegro_templ<GrayscaleTraits>(image, bmp, x, y, palette); break;
|
||||
case IMAGE_INDEXED: convert_image_to_allegro_templ<IndexedTraits>(image, bmp, x, y, palette); break;
|
||||
case IMAGE_BITMAP: convert_image_to_allegro_templ<BitmapTraits>(image, bmp, x, y, palette); break;
|
||||
}
|
||||
}
|
||||
|
||||
void convert_palette_to_allegro(const Palette* palette, RGB* rgb)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<palette->size(); ++i) {
|
||||
color_t c = palette->getEntry(i);
|
||||
rgb[i].r = rgba_getr(c) / 4;
|
||||
rgb[i].g = rgba_getg(c) / 4;
|
||||
rgb[i].b = rgba_getb(c) / 4;
|
||||
}
|
||||
for (; i<Palette::MaxColors; ++i) {
|
||||
rgb[i].r = 0;
|
||||
rgb[i].g = 0;
|
||||
rgb[i].b = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void convert_palette_from_allegro(const RGB* rgb, Palette* palette)
|
||||
{
|
||||
palette->resize(Palette::MaxColors);
|
||||
for (int i=0; i<Palette::MaxColors; ++i) {
|
||||
palette->setEntry(i, rgba(scale_6bits_to_8bits(rgb[i].r),
|
||||
scale_6bits_to_8bits(rgb[i].g),
|
||||
scale_6bits_to_8bits(rgb[i].b), 255));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace raster
|
36
src/raster/conversion_alleg.h
Normal file
36
src/raster/conversion_alleg.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 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
|
||||
*/
|
||||
|
||||
#ifndef RASTER_CONVERSION_ALLEG_H_INCLUDED
|
||||
#define RASTER_CONVERSION_ALLEG_H_INCLUDED
|
||||
|
||||
#include <allegro/color.h>
|
||||
|
||||
struct BITMAP;
|
||||
|
||||
namespace raster {
|
||||
class Image;
|
||||
class Palette;
|
||||
|
||||
void convert_image_to_allegro(const Image* image, BITMAP* bmp, int x, int y, const Palette* palette);
|
||||
void convert_palette_to_allegro(const Palette* palette, RGB* rgb);
|
||||
void convert_palette_from_allegro(const RGB* rgb, Palette* palette);
|
||||
|
||||
} // namespace raster
|
||||
|
||||
#endif
|
@ -21,7 +21,9 @@
|
||||
#endif
|
||||
|
||||
#include "raster/dirty.h"
|
||||
|
||||
#include "raster/image.h"
|
||||
#include "raster/primitives.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@ -59,14 +61,14 @@ Dirty::Dirty(const Dirty& src)
|
||||
Dirty::Dirty(Image* image, Image* image_diff)
|
||||
: m_format(image->getPixelFormat())
|
||||
, m_x1(0), m_y1(0)
|
||||
, m_x2(image->w-1), m_y2(image->h-1)
|
||||
, m_x2(image->getWidth()-1), m_y2(image->getHeight()-1)
|
||||
{
|
||||
int x, y, x1, x2;
|
||||
|
||||
for (y=0; y<image->h; y++) {
|
||||
for (y=0; y<image->getHeight(); y++) {
|
||||
x1 = -1;
|
||||
for (x=0; x<image->w; x++) {
|
||||
if (image_getpixel(image, x, y) != image_getpixel(image_diff, x, y)) {
|
||||
for (x=0; x<image->getWidth(); x++) {
|
||||
if (get_pixel(image, x, y) != get_pixel(image_diff, x, y)) {
|
||||
x1 = x;
|
||||
break;
|
||||
}
|
||||
@ -74,8 +76,8 @@ Dirty::Dirty(Image* image, Image* image_diff)
|
||||
if (x1 < 0)
|
||||
continue;
|
||||
|
||||
for (x2=image->w-1; x2>x1; x2--) {
|
||||
if (image_getpixel(image, x2, y) != image_getpixel(image_diff, x2, y))
|
||||
for (x2=image->getWidth()-1; x2>x1; x2--) {
|
||||
if (get_pixel(image, x2, y) != get_pixel(image_diff, x2, y))
|
||||
break;
|
||||
}
|
||||
|
||||
@ -137,7 +139,7 @@ void Dirty::saveImagePixels(Image* image)
|
||||
for (; col_it != col_end; ++col_it) {
|
||||
Col* col = *col_it;
|
||||
|
||||
uint8_t* address = (uint8_t*)image_address(image, col->x, row->y);
|
||||
uint8_t* address = (uint8_t*)image->getPixelAddress(col->x, row->y);
|
||||
std::copy(address, address+getLineSize(col->w), col->data.begin());
|
||||
}
|
||||
}
|
||||
@ -155,7 +157,7 @@ void Dirty::swapImagePixels(Image* image)
|
||||
for (; col_it != col_end; ++col_it) {
|
||||
Col* col = *col_it;
|
||||
|
||||
uint8_t* address = (uint8_t*)image_address(image, col->x, row->y);
|
||||
uint8_t* address = (uint8_t*)image->getPixelAddress(col->x, row->y);
|
||||
std::swap_ranges(address, address+getLineSize(col->w), col->data.begin());
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ namespace raster {
|
||||
const Row& getRow(int i) const { return *m_rows[i]; }
|
||||
|
||||
inline int getLineSize(int width) const {
|
||||
return pixelformat_line_size(m_format, width);
|
||||
return calculate_rowstride_bytes(m_format, width);
|
||||
}
|
||||
|
||||
void saveImagePixels(Image* image);
|
||||
|
@ -21,10 +21,11 @@
|
||||
#endif
|
||||
|
||||
#include "base/cfile.h"
|
||||
#include "base/clamp.h"
|
||||
#include "raster/color_scales.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
|
||||
#include <allegro.h>
|
||||
#include <cstdio>
|
||||
|
||||
#define PROCOL_MAGIC_NUMBER 0xB123
|
||||
@ -37,27 +38,27 @@ using namespace base;
|
||||
// Loads a COL file (Animator and Animator Pro format)
|
||||
Palette* load_col_file(const char* filename)
|
||||
{
|
||||
#if (MAKE_VERSION(4, 2, 1) >= MAKE_VERSION(ALLEGRO_VERSION, \
|
||||
ALLEGRO_SUB_VERSION, \
|
||||
ALLEGRO_WIP_VERSION))
|
||||
int size = file_size(filename);
|
||||
#else
|
||||
int size = file_size_ex(filename);
|
||||
#endif
|
||||
int pro = (size == 768)? false: true; /* is Animator Pro format? */
|
||||
div_t d = div(size-8, 3);
|
||||
Palette *pal = NULL;
|
||||
int c, r, g, b;
|
||||
FILE *f;
|
||||
|
||||
if (!(size) || (pro && d.rem)) /* invalid format */
|
||||
return NULL;
|
||||
|
||||
f = fopen(filename, "rb");
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
/* Animator format */
|
||||
// Get file size.
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t size = ftell(f);
|
||||
div_t d = div(size-8, 3);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
bool pro = (size == 768)? false: true; // is Animator Pro format?
|
||||
if (!(size) || (pro && d.rem)) { // Invalid format
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Animator format
|
||||
if (!pro) {
|
||||
pal = new Palette(FrameNumber(0), 256);
|
||||
|
||||
@ -68,20 +69,20 @@ Palette* load_col_file(const char* filename)
|
||||
if (ferror(f))
|
||||
break;
|
||||
|
||||
pal->setEntry(c, _rgba(_rgb_scale_6[MID(0, r, 63)],
|
||||
_rgb_scale_6[MID(0, g, 63)],
|
||||
_rgb_scale_6[MID(0, b, 63)], 255));
|
||||
pal->setEntry(c, rgba(scale_6bits_to_8bits(base::clamp(r, 0, 63)),
|
||||
scale_6bits_to_8bits(base::clamp(g, 0, 63)),
|
||||
scale_6bits_to_8bits(base::clamp(b, 0, 63)), 255));
|
||||
}
|
||||
}
|
||||
/* Animator Pro format */
|
||||
// Animator Pro format
|
||||
else {
|
||||
int magic, version;
|
||||
|
||||
fgetl(f); /* skip file size */
|
||||
magic = fgetw(f); /* file format identifier */
|
||||
version = fgetw(f); /* version file */
|
||||
fgetl(f); // Skip file size
|
||||
magic = fgetw(f); // File format identifier
|
||||
version = fgetw(f); // Version file
|
||||
|
||||
/* unknown format */
|
||||
// Unknown format
|
||||
if (magic != PROCOL_MAGIC_NUMBER || version != 0) {
|
||||
fclose(f);
|
||||
return NULL;
|
||||
@ -96,9 +97,9 @@ Palette* load_col_file(const char* filename)
|
||||
if (ferror(f))
|
||||
break;
|
||||
|
||||
pal->setEntry(c, _rgba(MID(0, r, 255),
|
||||
MID(0, g, 255),
|
||||
MID(0, b, 255), 255));
|
||||
pal->setEntry(c, rgba(base::clamp(r, 0, 255),
|
||||
base::clamp(g, 0, 255),
|
||||
base::clamp(b, 0, 255), 255));
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,17 +114,17 @@ bool save_col_file(const Palette* pal, const char* filename)
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
fputl(8+768, f); /* file size */
|
||||
fputw(PROCOL_MAGIC_NUMBER, f); /* file format identifier */
|
||||
fputw(0, f); /* version file */
|
||||
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);
|
||||
fputc(rgba_getr(c), f);
|
||||
fputc(rgba_getg(c), f);
|
||||
fputc(rgba_getb(c), f);
|
||||
if (ferror(f))
|
||||
break;
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ Palette* load_gpl_file(const char *filename)
|
||||
std::istringstream lineIn(line);
|
||||
lineIn >> r >> g >> b;
|
||||
if (lineIn.good()) {
|
||||
pal->setEntry(entryCounter, _rgba(r, g, b, 255));
|
||||
pal->setEntry(entryCounter, rgba(r, g, b, 255));
|
||||
++entryCounter;
|
||||
if (entryCounter >= Palette::MaxColors)
|
||||
break;
|
||||
@ -80,9 +80,9 @@ bool save_gpl_file(const Palette *pal, const char *filename)
|
||||
|
||||
for (int i=0; i<pal->size(); ++i) {
|
||||
uint32_t col = pal->getEntry(i);
|
||||
f << std::setfill(' ') << std::setw(3) << ((int)_rgba_getr(col)) << " "
|
||||
<< std::setfill(' ') << std::setw(3) << ((int)_rgba_getg(col)) << " "
|
||||
<< std::setfill(' ') << std::setw(3) << ((int)_rgba_getb(col)) << "\tUntitled\n";
|
||||
f << std::setfill(' ') << std::setw(3) << ((int)rgba_getr(col)) << " "
|
||||
<< std::setfill(' ') << std::setw(3) << ((int)rgba_getg(col)) << " "
|
||||
<< std::setfill(' ') << std::setw(3) << ((int)rgba_getb(col)) << "\tUntitled\n";
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -20,57 +20,54 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <allegro.h>
|
||||
#include <string.h>
|
||||
#include <stdexcept>
|
||||
#include "raster/image.h"
|
||||
|
||||
#include "raster/algo.h"
|
||||
#include "raster/blend.h"
|
||||
#include "raster/pen.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/image_impl.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/pen.h"
|
||||
#include "raster/primitives.h"
|
||||
#include "raster/rgbmap.h"
|
||||
|
||||
namespace raster {
|
||||
|
||||
Image::Image(PixelFormat format, int w, int h)
|
||||
: GfxObj(GFXOBJ_IMAGE)
|
||||
Image::Image(PixelFormat format, int width, int height)
|
||||
: Object(OBJECT_IMAGE)
|
||||
, m_format(format)
|
||||
{
|
||||
this->w = w;
|
||||
this->h = h;
|
||||
this->dat = NULL;
|
||||
this->line = NULL;
|
||||
this->mask_color = 0;
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_maskColor = 0;
|
||||
}
|
||||
|
||||
Image::~Image()
|
||||
{
|
||||
if (this->dat) delete[] this->dat;
|
||||
if (this->line) delete[] this->line;
|
||||
}
|
||||
|
||||
int Image::getMemSize() const
|
||||
{
|
||||
int scanline_size = 0;
|
||||
return sizeof(Image) + getRowStrideSize()*m_height;
|
||||
}
|
||||
|
||||
if (m_format == IMAGE_BITMAP)
|
||||
scanline_size = BitmapTraits::scanline_size(this->w);
|
||||
else
|
||||
scanline_size = image_line_size(this, this->w);
|
||||
int Image::getRowStrideSize() const
|
||||
{
|
||||
return getRowStrideSize(m_width);
|
||||
}
|
||||
|
||||
return sizeof(Image) + scanline_size*this->h;
|
||||
int Image::getRowStrideSize(int pixels_per_row) const
|
||||
{
|
||||
return calculate_rowstride_bytes(getPixelFormat(), m_width);
|
||||
}
|
||||
|
||||
// static
|
||||
Image* Image::create(PixelFormat format, int w, int h)
|
||||
Image* Image::create(PixelFormat format, int width, int height)
|
||||
{
|
||||
switch (format) {
|
||||
case IMAGE_RGB: return new ImageImpl<RgbTraits>(w, h);
|
||||
case IMAGE_GRAYSCALE: return new ImageImpl<GrayscaleTraits>(w, h);
|
||||
case IMAGE_INDEXED: return new ImageImpl<IndexedTraits>(w, h);
|
||||
case IMAGE_BITMAP: return new ImageImpl<BitmapTraits>(w, h);
|
||||
case IMAGE_RGB: return new ImageImpl<RgbTraits>(width, height);
|
||||
case IMAGE_GRAYSCALE: return new ImageImpl<GrayscaleTraits>(width, height);
|
||||
case IMAGE_INDEXED: return new ImageImpl<IndexedTraits>(width, height);
|
||||
case IMAGE_BITMAP: return new ImageImpl<BitmapTraits>(width, height);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -79,639 +76,7 @@ Image* Image::create(PixelFormat format, int w, int h)
|
||||
Image* Image::createCopy(const Image* image)
|
||||
{
|
||||
ASSERT(image);
|
||||
return image_crop(image, 0, 0, image->w, image->h, 0);
|
||||
}
|
||||
|
||||
int image_getpixel(const Image* image, int x, int y)
|
||||
{
|
||||
if ((x >= 0) && (y >= 0) && (x < image->w) && (y < image->h))
|
||||
return image->getpixel(x, y);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void image_putpixel(Image* image, int x, int y, int color)
|
||||
{
|
||||
if ((x >= 0) && (y >= 0) && (x < image->w) && (y < image->h))
|
||||
image->putpixel(x, y, color);
|
||||
}
|
||||
|
||||
void image_putpen(Image* image, Pen* pen, int x, int y, int fg_color, int bg_color)
|
||||
{
|
||||
Image* pen_image = pen->get_image();
|
||||
const gfx::Rect& penBounds = pen->getBounds();
|
||||
|
||||
x += penBounds.x;
|
||||
y += penBounds.y;
|
||||
|
||||
if (fg_color == bg_color) {
|
||||
image_rectfill(image, x, y, x+penBounds.w-1, y+penBounds.h-1, bg_color);
|
||||
}
|
||||
else {
|
||||
int u, v;
|
||||
for (v=0; v<penBounds.h; v++) {
|
||||
for (u=0; u<penBounds.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void image_clear(Image* image, int color)
|
||||
{
|
||||
image->clear(color);
|
||||
}
|
||||
|
||||
void image_copy(Image* dst, const Image* src, int x, int y)
|
||||
{
|
||||
dst->copy(src, x, y);
|
||||
}
|
||||
|
||||
void image_merge(Image* dst, const Image* src, int x, int y, int opacity, int blend_mode)
|
||||
{
|
||||
dst->merge(src, x, y, opacity, blend_mode);
|
||||
}
|
||||
|
||||
Image* image_crop(const Image* image, int x, int y, int w, int h, int bgcolor)
|
||||
{
|
||||
if (w < 1) throw std::invalid_argument("image_crop: Width is less than 1");
|
||||
if (h < 1) throw std::invalid_argument("image_crop: Height is less than 1");
|
||||
|
||||
Image* trim = Image::create(image->getPixelFormat(), w, h);
|
||||
trim->mask_color = image->mask_color;
|
||||
|
||||
image_clear(trim, bgcolor);
|
||||
image_copy(trim, image, -x, -y);
|
||||
|
||||
return trim;
|
||||
}
|
||||
|
||||
void image_rotate(const Image* src, Image* dst, int angle)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
switch (angle) {
|
||||
|
||||
case 180:
|
||||
ASSERT(dst->w == src->w);
|
||||
ASSERT(dst->h == src->h);
|
||||
|
||||
for (y=0; y<src->h; ++y)
|
||||
for (x=0; x<src->w; ++x)
|
||||
dst->putpixel(src->w - x - 1,
|
||||
src->h - y - 1, src->getpixel(x, y));
|
||||
break;
|
||||
|
||||
case 90:
|
||||
ASSERT(dst->w == src->h);
|
||||
ASSERT(dst->h == src->w);
|
||||
|
||||
for (y=0; y<src->h; ++y)
|
||||
for (x=0; x<src->w; ++x)
|
||||
dst->putpixel(src->h - y - 1, x, src->getpixel(x, y));
|
||||
break;
|
||||
|
||||
case -90:
|
||||
ASSERT(dst->w == src->h);
|
||||
ASSERT(dst->h == src->w);
|
||||
|
||||
for (y=0; y<src->h; ++y)
|
||||
for (x=0; x<src->w; ++x)
|
||||
dst->putpixel(y, src->w - x - 1, src->getpixel(x, y));
|
||||
break;
|
||||
|
||||
// bad angle
|
||||
default:
|
||||
throw std::invalid_argument("Invalid angle specified to rotate the image");
|
||||
}
|
||||
}
|
||||
|
||||
void image_hline(Image* image, int x1, int y, int x2, int color)
|
||||
{
|
||||
int t;
|
||||
|
||||
if (x1 > x2) {
|
||||
t = x1;
|
||||
x1 = x2;
|
||||
x2 = t;
|
||||
}
|
||||
|
||||
if ((x2 < 0) || (x1 >= image->w) || (y < 0) || (y >= image->h))
|
||||
return;
|
||||
|
||||
if (x1 < 0) x1 = 0;
|
||||
if (x2 >= image->w) x2 = image->w-1;
|
||||
|
||||
image->hline(x1, y, x2, color);
|
||||
}
|
||||
|
||||
void image_vline(Image* image, int x, int y1, int y2, int color)
|
||||
{
|
||||
int t;
|
||||
|
||||
if (y1 > y2) {
|
||||
t = y1;
|
||||
y1 = y2;
|
||||
y2 = t;
|
||||
}
|
||||
|
||||
if ((y2 < 0) || (y1 >= image->h) || (x < 0) || (x >= image->w))
|
||||
return;
|
||||
|
||||
if (y1 < 0) y1 = 0;
|
||||
if (y2 >= image->h) y2 = image->h-1;
|
||||
|
||||
for (t=y1; t<=y2; t++)
|
||||
image->putpixel(x, t, color);
|
||||
}
|
||||
|
||||
void image_rect(Image* image, int x1, int y1, int x2, int y2, int color)
|
||||
{
|
||||
int t;
|
||||
|
||||
if (x1 > x2) {
|
||||
t = x1;
|
||||
x1 = x2;
|
||||
x2 = t;
|
||||
}
|
||||
|
||||
if (y1 > y2) {
|
||||
t = y1;
|
||||
y1 = y2;
|
||||
y2 = t;
|
||||
}
|
||||
|
||||
if ((x2 < 0) || (x1 >= image->w) || (y2 < 0) || (y1 >= image->h))
|
||||
return;
|
||||
|
||||
image_hline(image, x1, y1, x2, color);
|
||||
image_hline(image, x1, y2, x2, color);
|
||||
if (y2-y1 > 1) {
|
||||
image_vline(image, x1, y1+1, y2-1, color);
|
||||
image_vline(image, x2, y1+1, y2-1, color);
|
||||
}
|
||||
}
|
||||
|
||||
void image_rectfill(Image* image, int x1, int y1, int x2, int y2, int color)
|
||||
{
|
||||
int t;
|
||||
|
||||
if (x1 > x2) {
|
||||
t = x1;
|
||||
x1 = x2;
|
||||
x2 = t;
|
||||
}
|
||||
|
||||
if (y1 > y2) {
|
||||
t = y1;
|
||||
y1 = y2;
|
||||
y2 = t;
|
||||
}
|
||||
|
||||
if ((x2 < 0) || (x1 >= image->w) || (y2 < 0) || (y1 >= image->h))
|
||||
return;
|
||||
|
||||
if (x1 < 0) x1 = 0;
|
||||
if (y1 < 0) y1 = 0;
|
||||
if (x2 >= image->w) x2 = image->w-1;
|
||||
if (y2 >= image->h) y2 = image->h-1;
|
||||
|
||||
image->rectfill(x1, y1, x2, y2, color);
|
||||
}
|
||||
|
||||
void image_rectblend(Image* image, int x1, int y1, int x2, int y2, int color, int opacity)
|
||||
{
|
||||
int t;
|
||||
|
||||
if (x1 > x2) {
|
||||
t = x1;
|
||||
x1 = x2;
|
||||
x2 = t;
|
||||
}
|
||||
|
||||
if (y1 > y2) {
|
||||
t = y1;
|
||||
y1 = y2;
|
||||
y2 = t;
|
||||
}
|
||||
|
||||
if ((x2 < 0) || (x1 >= image->w) || (y2 < 0) || (y1 >= image->h))
|
||||
return;
|
||||
|
||||
if (x1 < 0) x1 = 0;
|
||||
if (y1 < 0) y1 = 0;
|
||||
if (x2 >= image->w) x2 = image->w-1;
|
||||
if (y2 >= image->h) y2 = image->h-1;
|
||||
|
||||
image->rectblend(x1, y1, x2, y2, color, opacity);
|
||||
}
|
||||
|
||||
typedef struct Data
|
||||
{
|
||||
Image* image;
|
||||
int color;
|
||||
} Data;
|
||||
|
||||
static void pixel_for_image(int x, int y, Data *data)
|
||||
{
|
||||
image_putpixel(data->image, x, y, data->color);
|
||||
}
|
||||
|
||||
static void hline_for_image(int x1, int y, int x2, Data *data)
|
||||
{
|
||||
image_hline(data->image, x1, y, x2, data->color);
|
||||
}
|
||||
|
||||
void image_line(Image* image, int x1, int y1, int x2, int y2, int color)
|
||||
{
|
||||
Data data = { image, color };
|
||||
algo_line(x1, y1, x2, y2, &data, (AlgoPixel)pixel_for_image);
|
||||
}
|
||||
|
||||
void image_ellipse(Image* image, int x1, int y1, int x2, int y2, int color)
|
||||
{
|
||||
Data data = { image, color };
|
||||
algo_ellipse(x1, y1, x2, y2, &data, (AlgoPixel)pixel_for_image);
|
||||
}
|
||||
|
||||
void image_ellipsefill(Image* image, int x1, int y1, int x2, int y2, int color)
|
||||
{
|
||||
Data data = { image, color };
|
||||
algo_ellipsefill(x1, y1, x2, y2, &data, (AlgoHLine)hline_for_image);
|
||||
}
|
||||
|
||||
void image_to_allegro(const Image* image, BITMAP *bmp, int x, int y, const Palette* palette)
|
||||
{
|
||||
image->to_allegro(bmp, x, y, palette);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int image_count_diff(const Image* i1, const Image* i2)
|
||||
{
|
||||
int c, size, diff = 0;
|
||||
|
||||
if ((i1->getPixelFormat() != i2->getPixelFormat()) ||
|
||||
(i1->w != i2->w) || (i1->h != i2->h))
|
||||
return -1;
|
||||
|
||||
size = i1->w * i1->h;
|
||||
|
||||
switch (i1->getPixelFormat()) {
|
||||
|
||||
case IMAGE_RGB:
|
||||
{
|
||||
uint32_t* address1 = (uint32_t*)i1->dat;
|
||||
uint32_t* address2 = (uint32_t*)i2->dat;
|
||||
for (c=0; c<size; c++)
|
||||
if (*(address1++) != *(address2++))
|
||||
diff++;
|
||||
}
|
||||
break;
|
||||
|
||||
case IMAGE_GRAYSCALE:
|
||||
{
|
||||
uint16_t* address1 = (uint16_t*)i1->dat;
|
||||
uint16_t* address2 = (uint16_t*)i2->dat;
|
||||
for (c=0; c<size; c++)
|
||||
if (*(address1++) != *(address2++))
|
||||
diff++;
|
||||
}
|
||||
break;
|
||||
|
||||
case IMAGE_INDEXED:
|
||||
{
|
||||
uint8_t* address1 = (uint8_t*)i1->dat;
|
||||
uint8_t* address2 = (uint8_t*)i2->dat;
|
||||
for (c=0; c<size; c++)
|
||||
if (*(address1++) != *(address2++))
|
||||
diff++;
|
||||
}
|
||||
break;
|
||||
|
||||
case IMAGE_BITMAP:
|
||||
/* TODO test it */
|
||||
{
|
||||
uint8_t* address1 = (uint8_t*)i1->dat;
|
||||
uint8_t* address2 = (uint8_t*)i2->dat;
|
||||
div_t d1 = div (0, 8);
|
||||
div_t d2 = div (0, 8);
|
||||
for (c=0; c<size; c++) {
|
||||
if (((*address1) & (1<<d1.rem)) !=
|
||||
((*address2) & (1<<d2.rem)))
|
||||
diff++;
|
||||
_image_bitmap_next_bit(d1, address1);
|
||||
_image_bitmap_next_bit(d2, address2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
static bool is_same_pixel(PixelFormat pixelFormat, int pixel1, int pixel2)
|
||||
{
|
||||
switch (pixelFormat) {
|
||||
case IMAGE_RGB:
|
||||
if (_rgba_geta(pixel1) == 0 && _rgba_geta(pixel2) == 0)
|
||||
return true;
|
||||
break;
|
||||
case IMAGE_GRAYSCALE:
|
||||
if (_graya_geta(pixel1) == 0 && _graya_geta(pixel2) == 0)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
return pixel1 == pixel2;
|
||||
}
|
||||
|
||||
bool image_shrink_rect(Image *image, gfx::Rect& bounds, int refpixel)
|
||||
{
|
||||
bool shrink;
|
||||
int u, v;
|
||||
|
||||
bounds = gfx::Rect(0, 0, image->w, image->h);
|
||||
|
||||
// Shrink left side
|
||||
for (u=bounds.x; u<bounds.x+bounds.w; ++u) {
|
||||
shrink = true;
|
||||
for (v=bounds.y; v<bounds.y+bounds.h; ++v) {
|
||||
if (!is_same_pixel(image->getPixelFormat(), image->getpixel(u, v), refpixel)) {
|
||||
shrink = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!shrink)
|
||||
break;
|
||||
++bounds.x;
|
||||
--bounds.w;
|
||||
}
|
||||
|
||||
// Shrink right side
|
||||
for (u=bounds.x+bounds.w-1; u>=bounds.x; --u) {
|
||||
shrink = true;
|
||||
for (v=bounds.y; v<bounds.y+bounds.h; ++v) {
|
||||
if (!is_same_pixel(image->getPixelFormat(), image->getpixel(u, v), refpixel)) {
|
||||
shrink = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!shrink)
|
||||
break;
|
||||
--bounds.w;
|
||||
}
|
||||
|
||||
// Shrink top side
|
||||
for (v=bounds.y; v<bounds.y+bounds.h; ++v) {
|
||||
shrink = true;
|
||||
for (u=bounds.x; u<bounds.x+bounds.w; ++u) {
|
||||
if (!is_same_pixel(image->getPixelFormat(), image->getpixel(u, v), refpixel)) {
|
||||
shrink = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!shrink)
|
||||
break;
|
||||
++bounds.y;
|
||||
--bounds.h;
|
||||
}
|
||||
|
||||
// Shrink bottom side
|
||||
for (v=bounds.y+bounds.h-1; v>=bounds.y; --v) {
|
||||
shrink = true;
|
||||
for (u=bounds.x; u<bounds.x+bounds.w; ++u) {
|
||||
if (!is_same_pixel(image->getPixelFormat(), image->getpixel(u, v), refpixel)) {
|
||||
shrink = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!shrink)
|
||||
break;
|
||||
--bounds.h;
|
||||
}
|
||||
|
||||
return (!bounds.isEmpty());
|
||||
return crop_image(image, 0, 0, image->getWidth(), image->getHeight(), 0);
|
||||
}
|
||||
|
||||
} // namespace raster
|
||||
|
@ -19,86 +19,84 @@
|
||||
#ifndef RASTER_IMAGE_H_INCLUDED
|
||||
#define RASTER_IMAGE_H_INCLUDED
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "gfx/size.h"
|
||||
#include "raster/blend.h"
|
||||
#include "raster/gfxobj.h"
|
||||
#include "raster/color.h"
|
||||
#include "raster/object.h"
|
||||
#include "raster/pixel_format.h"
|
||||
|
||||
#include <allegro/color.h>
|
||||
|
||||
struct BITMAP;
|
||||
|
||||
namespace raster {
|
||||
|
||||
template<typename ImageTraits> class ImageBits;
|
||||
class Palette;
|
||||
class Pen;
|
||||
class RgbMap;
|
||||
|
||||
enum ResizeMethod {
|
||||
RESIZE_METHOD_NEAREST_NEIGHBOR,
|
||||
RESIZE_METHOD_BILINEAR,
|
||||
};
|
||||
|
||||
class Image : public GfxObj {
|
||||
class Image : public Object {
|
||||
public:
|
||||
int w, h;
|
||||
uint8_t* dat; // Pixmap data.
|
||||
uint8_t** line; // Start of each scanline.
|
||||
uint32_t mask_color; // Skipped color in merge process.
|
||||
enum LockType {
|
||||
ReadLock, // Read-only lock
|
||||
WriteLock, // Write-only lock
|
||||
ReadWriteLock // Read and write
|
||||
};
|
||||
|
||||
static Image* create(PixelFormat format, int w, int h);
|
||||
static Image* create(PixelFormat format, int width, int height);
|
||||
static Image* createCopy(const Image* image);
|
||||
|
||||
Image(PixelFormat format, int w, int h);
|
||||
virtual ~Image();
|
||||
|
||||
PixelFormat getPixelFormat() const { return m_format; }
|
||||
int getWidth() const { return m_width; }
|
||||
int getHeight() const { return m_height; }
|
||||
gfx::Size getSize() const { return gfx::Size(m_width, m_height); }
|
||||
gfx::Rect getBounds() const { return gfx::Rect(0, 0, m_width, m_height); }
|
||||
color_t getMaskColor() const { return m_maskColor; }
|
||||
void setMaskColor(color_t c) { m_maskColor = c; }
|
||||
|
||||
int getMemSize() const;
|
||||
int getMemSize() const OVERRIDE;
|
||||
int getRowStrideSize() const;
|
||||
int getRowStrideSize(int pixels_per_row) const;
|
||||
|
||||
virtual int getpixel(int x, int y) const = 0;
|
||||
virtual void putpixel(int x, int y, int color) = 0;
|
||||
virtual void clear(int color) = 0;
|
||||
template<typename ImageTraits>
|
||||
ImageBits<ImageTraits> lockBits(LockType lockType, const gfx::Rect& bounds) {
|
||||
return ImageBits<ImageTraits>(this, bounds);
|
||||
}
|
||||
|
||||
template<typename ImageTraits>
|
||||
ImageBits<ImageTraits> lockBits(LockType lockType, const gfx::Rect& bounds) const {
|
||||
return ImageBits<ImageTraits>(const_cast<Image*>(this), bounds);
|
||||
}
|
||||
|
||||
template<typename ImageTraits>
|
||||
void unlockBits(ImageBits<ImageTraits>& imageBits) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
// Warning: These functions doesn't have (and shouldn't have)
|
||||
// bounds checks. Use the primitives defined in raster/primitives.h
|
||||
// in case that you need bounds check.
|
||||
virtual uint8_t* getPixelAddress(int x, int y) const = 0;
|
||||
virtual color_t getPixel(int x, int y) const = 0;
|
||||
virtual void putPixel(int x, int y, color_t color) = 0;
|
||||
virtual void clear(color_t color) = 0;
|
||||
virtual void copy(const Image* src, int x, int y) = 0;
|
||||
virtual void merge(const Image* src, int x, int y, int opacity, int blend_mode) = 0;
|
||||
virtual void hline(int x1, int y, int x2, int color) = 0;
|
||||
virtual void rectfill(int x1, int y1, int x2, int y2, int color) = 0;
|
||||
virtual void rectblend(int x1, int y1, int x2, int y2, int color, int opacity) = 0;
|
||||
virtual void to_allegro(BITMAP* bmp, int x, int y, const Palette* palette) const = 0;
|
||||
virtual void drawHLine(int x1, int y, int x2, color_t color) = 0;
|
||||
virtual void fillRect(int x1, int y1, int x2, int y2, color_t color) = 0;
|
||||
virtual void blendRect(int x1, int y1, int x2, int y2, color_t color, int opacity) = 0;
|
||||
|
||||
protected:
|
||||
Image(PixelFormat format, int width, int height);
|
||||
|
||||
private:
|
||||
PixelFormat m_format;
|
||||
int m_width;
|
||||
int m_height;
|
||||
color_t m_maskColor; // Skipped color in merge process.
|
||||
};
|
||||
|
||||
int image_getpixel(const Image* image, int x, int y);
|
||||
void image_putpixel(Image* image, int x, int y, int color);
|
||||
void image_putpen(Image* image, Pen* pen, int x, int y, int fg_color, int bg_color);
|
||||
|
||||
void image_clear(Image* image, int color);
|
||||
|
||||
void image_copy(Image* dst, const Image* src, int x, int y);
|
||||
void image_merge(Image* dst, const Image* src, int x, int y, int opacity,
|
||||
int blend_mode);
|
||||
|
||||
Image* image_crop(const Image* image, int x, int y, int w, int h, int bgcolor);
|
||||
void image_rotate(const Image* src, Image* dst, int angle);
|
||||
|
||||
void image_hline(Image* image, int x1, int y, int x2, int color);
|
||||
void image_vline(Image* image, int x, int y1, int y2, int color);
|
||||
void image_rect(Image* image, int x1, int y1, int x2, int y2, int color);
|
||||
void image_rectfill(Image* image, int x1, int y1, int x2, int y2, int color);
|
||||
void image_rectblend(Image* image, int x1, int y1, int x2, int y2, int color, int opacity);
|
||||
void image_line(Image* image, int x1, int y1, int x2, int y2, int color);
|
||||
void image_ellipse(Image* image, int x1, int y1, int x2, int y2, int color);
|
||||
void image_ellipsefill(Image* image, int x1, int y1, int x2, int y2, int color);
|
||||
|
||||
void image_to_allegro(const Image* image, BITMAP* bmp, int x, int y, const Palette* palette);
|
||||
|
||||
void image_fixup_transparent_colors(Image* image);
|
||||
void image_resize(const Image* src, Image* dst, ResizeMethod method, const Palette* palette, const RgbMap* rgbmap);
|
||||
int image_count_diff(const Image* i1, const Image* i2);
|
||||
bool image_shrink_rect(Image *image, gfx::Rect& bounds, int refpixel);
|
||||
|
||||
} // namespace raster
|
||||
|
||||
// It's here because it needs a complete definition of Image class,
|
||||
@ -107,27 +105,17 @@ namespace raster {
|
||||
|
||||
namespace raster {
|
||||
|
||||
inline int pixelformat_line_size(PixelFormat pixelFormat, int width)
|
||||
inline int calculate_rowstride_bytes(PixelFormat pixelFormat, int pixels_per_row)
|
||||
{
|
||||
switch (pixelFormat) {
|
||||
case IMAGE_RGB: return RgbTraits::scanline_size(width);
|
||||
case IMAGE_GRAYSCALE: return GrayscaleTraits::scanline_size(width);
|
||||
case IMAGE_INDEXED: return IndexedTraits::scanline_size(width);
|
||||
case IMAGE_BITMAP: return BitmapTraits::scanline_size(width);
|
||||
case IMAGE_RGB: return RgbTraits::getRowStrideBytes(pixels_per_row);
|
||||
case IMAGE_GRAYSCALE: return GrayscaleTraits::getRowStrideBytes(pixels_per_row);
|
||||
case IMAGE_INDEXED: return IndexedTraits::getRowStrideBytes(pixels_per_row);
|
||||
case IMAGE_BITMAP: return BitmapTraits::getRowStrideBytes(pixels_per_row);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline int image_line_size(const Image* image, int width)
|
||||
{
|
||||
return pixelformat_line_size(image->getPixelFormat(), width);
|
||||
}
|
||||
|
||||
inline void* image_address(Image* image, int x, int y)
|
||||
{
|
||||
return ((void *)(image->line[y] + image_line_size(image, x)));
|
||||
}
|
||||
|
||||
} // namespace raster
|
||||
|
||||
#endif
|
||||
|
167
src/raster/image_bits.h
Normal file
167
src/raster/image_bits.h
Normal file
@ -0,0 +1,167 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 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
|
||||
*/
|
||||
|
||||
#ifndef RASTER_IMAGE_BITS_H_INCLUDED
|
||||
#define RASTER_IMAGE_BITS_H_INCLUDED
|
||||
|
||||
#include "raster/image.h"
|
||||
#include "raster/image_iterator.h"
|
||||
|
||||
namespace raster {
|
||||
|
||||
template<typename ImageTraits>
|
||||
class ImageBits {
|
||||
public:
|
||||
typedef typename ImageTraits::address_t address_t;
|
||||
typedef ImageIterator<ImageTraits> iterator;
|
||||
typedef ImageConstIterator<ImageTraits> const_iterator;
|
||||
|
||||
ImageBits() :
|
||||
m_image(NULL),
|
||||
m_bounds(0, 0, 0, 0) {
|
||||
}
|
||||
|
||||
ImageBits(const ImageBits& other) :
|
||||
m_image(other.m_image),
|
||||
m_bounds(other.m_bounds) {
|
||||
}
|
||||
|
||||
ImageBits(Image* image, const gfx::Rect& bounds) :
|
||||
m_image(image),
|
||||
m_bounds(bounds) {
|
||||
ASSERT(bounds.x >= 0 && bounds.x+bounds.w <= image->getWidth() &&
|
||||
bounds.y >= 0 && bounds.y+bounds.h <= image->getHeight());
|
||||
}
|
||||
|
||||
ImageBits& operator=(const ImageBits& other) {
|
||||
m_image = other.m_image;
|
||||
m_bounds = other.m_bounds;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Iterate over the full area.
|
||||
iterator begin() {
|
||||
return iterator(m_image, m_bounds, m_bounds.x, m_bounds.y);
|
||||
}
|
||||
iterator end() {
|
||||
iterator it(m_image, m_bounds, m_bounds.x+m_bounds.w-1, m_bounds.y+m_bounds.h-1);
|
||||
++it;
|
||||
return it;
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return const_iterator(m_image, m_bounds, m_bounds.x, m_bounds.y);
|
||||
}
|
||||
const_iterator end() const {
|
||||
const_iterator it(m_image, m_bounds, m_bounds.x+m_bounds.w-1, m_bounds.y+m_bounds.h-1);
|
||||
++it;
|
||||
return it;
|
||||
}
|
||||
|
||||
// Iterate over a sub-area.
|
||||
iterator begin_area(const gfx::Rect& area) {
|
||||
ASSERT(m_bounds.contains(area));
|
||||
return iterator(m_image, area, area.x, area.y);
|
||||
}
|
||||
iterator end_area(const gfx::Rect& area) {
|
||||
ASSERT(m_bounds.contains(area));
|
||||
iterator it(m_image, area, area.x+area.w-1, area.y+area.h-1);
|
||||
++it;
|
||||
return it;
|
||||
}
|
||||
|
||||
const_iterator begin_area(const gfx::Rect& area) const {
|
||||
ASSERT(m_bounds.contains(area));
|
||||
return const_iterator(m_image, area, area.x, area.y);
|
||||
}
|
||||
const_iterator end_area(const gfx::Rect& area) const {
|
||||
ASSERT(m_bounds.contains(area));
|
||||
const_iterator it(m_image, area, area.x+area.w-1, area.y+area.h-1);
|
||||
++it;
|
||||
return it;
|
||||
}
|
||||
|
||||
Image* image() const { return m_image; }
|
||||
const gfx::Rect& bounds() { return m_bounds; }
|
||||
|
||||
Image* image() { return m_image; }
|
||||
|
||||
void unlock() {
|
||||
if (m_image) {
|
||||
m_image->unlockBits(*this);
|
||||
m_image = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Image* m_image;
|
||||
gfx::Rect m_bounds;
|
||||
};
|
||||
|
||||
template<typename ImageTraits>
|
||||
class LockImageBits {
|
||||
public:
|
||||
typedef ImageBits<ImageTraits> Bits;
|
||||
typedef typename Bits::iterator iterator;
|
||||
typedef typename Bits::const_iterator const_iterator;
|
||||
|
||||
explicit LockImageBits(const Image* image)
|
||||
: m_bits(image->lockBits<ImageTraits>(Image::ReadLock, image->getBounds())) {
|
||||
}
|
||||
|
||||
LockImageBits(const Image* image, const gfx::Rect& bounds)
|
||||
: m_bits(image->lockBits<ImageTraits>(Image::ReadLock, bounds)) {
|
||||
}
|
||||
|
||||
LockImageBits(Image* image, Image::LockType lockType)
|
||||
: m_bits(image->lockBits<ImageTraits>(lockType, image->getBounds())) {
|
||||
}
|
||||
|
||||
LockImageBits(Image* image, Image::LockType lockType, const gfx::Rect& bounds)
|
||||
: m_bits(image->lockBits<ImageTraits>(lockType, bounds)) {
|
||||
}
|
||||
|
||||
~LockImageBits() {
|
||||
m_bits.image()->unlockBits(m_bits);
|
||||
}
|
||||
|
||||
// Iterators.
|
||||
iterator begin() { return m_bits.begin(); }
|
||||
iterator end() { return m_bits.end(); }
|
||||
const_iterator begin() const { return m_bits.begin(); }
|
||||
const_iterator end() const { return m_bits.end(); }
|
||||
|
||||
iterator begin_area(const gfx::Rect& area) { return m_bits.begin_area(area); }
|
||||
iterator end_area(const gfx::Rect& area) { return m_bits.end_area(area); }
|
||||
const_iterator begin_area(const gfx::Rect& area) const { return m_bits.begin_area(area); }
|
||||
const_iterator end_area(const gfx::Rect& area) const { return m_bits.end_area(area); }
|
||||
|
||||
const Image* image() const { return m_bits.image(); }
|
||||
const gfx::Rect& bounds() const { return m_bits.bounds(); }
|
||||
|
||||
Image* image() { return m_bits.image(); }
|
||||
|
||||
private:
|
||||
Bits m_bits;
|
||||
|
||||
LockImageBits(); // Undefined
|
||||
};
|
||||
|
||||
} // namespace raster
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -48,13 +48,13 @@ using namespace base::serialization::little_endian;
|
||||
void write_image(std::ostream& os, Image* image)
|
||||
{
|
||||
write8(os, image->getPixelFormat()); // Pixel format
|
||||
write16(os, image->w); // Width
|
||||
write16(os, image->h); // Height
|
||||
write32(os, image->mask_color); // Mask color
|
||||
write16(os, image->getWidth()); // Width
|
||||
write16(os, image->getHeight()); // Height
|
||||
write32(os, image->getMaskColor()); // Mask color
|
||||
|
||||
int size = image_line_size(image, image->w);
|
||||
for (int c=0; c<image->h; c++)
|
||||
os.write((char*)image->line[c], size);
|
||||
int size = image->getRowStrideSize();
|
||||
for (int c=0; c<image->getHeight(); c++)
|
||||
os.write((char*)image->getPixelAddress(0, c), size);
|
||||
}
|
||||
|
||||
Image* read_image(std::istream& is)
|
||||
@ -65,12 +65,12 @@ Image* read_image(std::istream& is)
|
||||
uint32_t maskColor = read32(is); // Mask color
|
||||
|
||||
base::UniquePtr<Image> image(Image::create(static_cast<PixelFormat>(pixelFormat), width, height));
|
||||
int size = image_line_size(image, image->w);
|
||||
int size = image->getRowStrideSize();
|
||||
|
||||
for (int c=0; c<image->h; c++)
|
||||
is.read((char*)image->line[c], size);
|
||||
for (int c=0; c<image->getHeight(); c++)
|
||||
is.read((char*)image->getPixelAddress(0, c), size);
|
||||
|
||||
image->mask_color = maskColor;
|
||||
image->setMaskColor(maskColor);
|
||||
return image.release();
|
||||
}
|
||||
|
||||
|
506
src/raster/image_iterator.h
Normal file
506
src/raster/image_iterator.h
Normal file
@ -0,0 +1,506 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2013 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
|
||||
*/
|
||||
|
||||
#ifndef RASTER_IMAGE_ITERATOR_H_INCLUDED
|
||||
#define RASTER_IMAGE_ITERATOR_H_INCLUDED
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define RASTER_DEBUG_ITERATORS
|
||||
#endif
|
||||
|
||||
#include "gfx/rect.h"
|
||||
#include "raster/color.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/image_traits.h"
|
||||
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
#include "gfx/point.h"
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace raster {
|
||||
|
||||
template<typename ImageTraits,
|
||||
typename PointerType,
|
||||
typename ReferenceType>
|
||||
class ImageIteratorT : public std::iterator<std::forward_iterator_tag,
|
||||
typename ImageTraits::pixel_t,
|
||||
ptrdiff_t,
|
||||
PointerType,
|
||||
ReferenceType> {
|
||||
public:
|
||||
// GCC 4.6 needs these re-definitions here.
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef PointerType pointer;
|
||||
typedef ReferenceType reference;
|
||||
|
||||
ImageIteratorT() : m_ptr(NULL) {
|
||||
}
|
||||
|
||||
ImageIteratorT(const ImageIteratorT& other) :
|
||||
m_ptr(other.m_ptr),
|
||||
m_x(other.m_x),
|
||||
m_width(other.m_width),
|
||||
m_nextRow(other.m_nextRow)
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
, m_image(other.m_image)
|
||||
, m_X0(other.m_X0), m_X(other.m_X), m_Y(other.m_Y)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
ImageIteratorT(const Image* image, const gfx::Rect& bounds, int x, int y) :
|
||||
m_ptr((pointer)image->getPixelAddress(x, y)),
|
||||
m_x(x - bounds.x),
|
||||
m_width(bounds.w),
|
||||
m_nextRow(image->getWidth() - bounds.w)
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
, m_image(const_cast<Image*>(image))
|
||||
, m_X0(bounds.x)
|
||||
, m_X(x), m_Y(y)
|
||||
#endif
|
||||
{
|
||||
ASSERT(bounds.contains(gfx::Point(x, y)));
|
||||
}
|
||||
|
||||
ImageIteratorT& operator=(const ImageIteratorT& other) {
|
||||
m_ptr = other.m_ptr;
|
||||
m_x = other.m_x;
|
||||
m_width = other.m_width;
|
||||
m_nextRow = other.m_nextRow;
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
m_image = other.m_image;
|
||||
m_X0 = other.m_X0;
|
||||
m_X = other.m_X;
|
||||
m_Y = other.m_Y;
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const ImageIteratorT& other) const {
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
if (m_ptr == other.m_ptr) {
|
||||
ASSERT(m_X == other.m_X && m_Y == other.m_Y);
|
||||
}
|
||||
else {
|
||||
ASSERT(m_X != other.m_X || m_Y != other.m_Y);
|
||||
}
|
||||
#endif
|
||||
return m_ptr == other.m_ptr;
|
||||
}
|
||||
bool operator!=(const ImageIteratorT& other) const {
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
if (m_ptr != other.m_ptr) {
|
||||
ASSERT(m_X != other.m_X || m_Y != other.m_Y);
|
||||
}
|
||||
else {
|
||||
ASSERT(m_X == other.m_X && m_Y == other.m_Y);
|
||||
}
|
||||
#endif
|
||||
return m_ptr != other.m_ptr;
|
||||
}
|
||||
bool operator<(const ImageIteratorT& other) const { return m_ptr < other.m_ptr; }
|
||||
bool operator>(const ImageIteratorT& other) const { return m_ptr > other.m_ptr; }
|
||||
bool operator<=(const ImageIteratorT& other) const { return m_ptr <= other.m_ptr; }
|
||||
bool operator>=(const ImageIteratorT& other) const { return m_ptr >= other.m_ptr; }
|
||||
|
||||
ImageIteratorT& operator++() {
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
ASSERT(m_image->getBounds().contains(gfx::Point(m_X, m_Y)));
|
||||
#endif
|
||||
|
||||
++m_ptr;
|
||||
++m_x;
|
||||
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
++m_X;
|
||||
#endif
|
||||
|
||||
if (m_x == m_width) {
|
||||
m_ptr += m_nextRow;
|
||||
m_x = 0;
|
||||
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
m_X = m_X0;
|
||||
++m_Y;
|
||||
|
||||
if (m_Y < m_image->getHeight()) {
|
||||
pointer expected_ptr = (pointer)m_image->getPixelAddress(m_X, m_Y);
|
||||
ASSERT(expected_ptr == m_ptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
else {
|
||||
pointer expected_ptr = (pointer)m_image->getPixelAddress(m_X, m_Y);
|
||||
ASSERT(expected_ptr == m_ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ImageIteratorT& operator+=(int diff) {
|
||||
while (diff-- > 0)
|
||||
operator++();
|
||||
return *this;
|
||||
}
|
||||
|
||||
ImageIteratorT operator++(int) {
|
||||
ImageIteratorT tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
reference operator*() { return *m_ptr; }
|
||||
|
||||
private:
|
||||
pointer m_ptr;
|
||||
int m_bit;
|
||||
int m_x;
|
||||
int m_width;
|
||||
int m_nextRow;
|
||||
#ifdef RASTER_DEBUG_ITERATORS // Data used for debugging purposes.
|
||||
Image* m_image;
|
||||
int m_X0, m_X, m_Y;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<typename ImageTraits>
|
||||
class ImageIterator : public ImageIteratorT<ImageTraits,
|
||||
typename ImageTraits::pixel_t *,
|
||||
typename ImageTraits::pixel_t&> {
|
||||
public:
|
||||
// GCC 4.6 needs these re-definitions here.
|
||||
typedef typename ImageTraits::pixel_t* pointer;
|
||||
typedef typename ImageTraits::pixel_t& reference;
|
||||
|
||||
ImageIterator() {
|
||||
}
|
||||
|
||||
ImageIterator(const Image* image, const gfx::Rect& bounds, int x, int y) :
|
||||
ImageIteratorT<ImageTraits,
|
||||
pointer,
|
||||
reference>(image, bounds, x, y) {
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ImageTraits>
|
||||
class ImageConstIterator : public ImageIteratorT<ImageTraits,
|
||||
typename ImageTraits::pixel_t const *,
|
||||
typename ImageTraits::pixel_t const &> {
|
||||
public:
|
||||
// GCC 4.6 needs these re-definitions here.
|
||||
typedef typename ImageTraits::pixel_t const* pointer;
|
||||
typedef typename ImageTraits::pixel_t const& reference;
|
||||
|
||||
ImageConstIterator() {
|
||||
}
|
||||
|
||||
ImageConstIterator(const Image* image, const gfx::Rect& bounds, int x, int y) :
|
||||
ImageIteratorT<ImageTraits,
|
||||
pointer,
|
||||
reference>(image, bounds, x, y) {
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Iterator for BitmapTraits
|
||||
|
||||
class BitPixelAccess {
|
||||
public:
|
||||
BitPixelAccess() :
|
||||
m_ptr(NULL),
|
||||
m_bit(0) {
|
||||
}
|
||||
|
||||
void reset(BitmapTraits::address_t ptr, int bit) {
|
||||
m_ptr = ptr;
|
||||
m_bit = bit;
|
||||
}
|
||||
|
||||
void reset(BitmapTraits::pixel_t const* ptr, int bit) {
|
||||
m_ptr = const_cast<BitmapTraits::address_t>(ptr);
|
||||
m_bit = bit;
|
||||
}
|
||||
|
||||
operator color_t() const {
|
||||
return (*m_ptr & m_bit) ? 1: 0;
|
||||
}
|
||||
|
||||
BitPixelAccess& operator=(color_t value) {
|
||||
if (value)
|
||||
*m_ptr |= m_bit;
|
||||
else
|
||||
*m_ptr &= ~m_bit;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// It doesn't copy the BitPixelAccess, it must copy the bit from
|
||||
// "other" to "this".
|
||||
BitPixelAccess& operator=(const BitPixelAccess& other) {
|
||||
return this->operator=((color_t)other);
|
||||
}
|
||||
|
||||
bool operator==(int b) const {
|
||||
return (color_t(*this) == b);
|
||||
}
|
||||
|
||||
bool operator==(color_t b) const {
|
||||
return (color_t(*this) == b);
|
||||
}
|
||||
|
||||
bool operator==(const BitPixelAccess& b) const {
|
||||
return (color_t(*this) == color_t(b));
|
||||
}
|
||||
|
||||
bool operator!=(int b) const {
|
||||
return (color_t(*this) != b);
|
||||
}
|
||||
|
||||
bool operator!=(color_t b) const {
|
||||
return (color_t(*this) != b);
|
||||
}
|
||||
|
||||
bool operator!=(const BitPixelAccess& b) const {
|
||||
return (color_t(*this) != color_t(b));
|
||||
}
|
||||
|
||||
private:
|
||||
// Non-copyable by copy constructor.
|
||||
BitPixelAccess(const BitPixelAccess& other);
|
||||
|
||||
BitmapTraits::address_t m_ptr;
|
||||
int m_bit;
|
||||
};
|
||||
|
||||
inline bool operator==(int a, const BitPixelAccess& b) {
|
||||
return (a == color_t(b));
|
||||
}
|
||||
|
||||
inline bool operator==(color_t a, const BitPixelAccess& b) {
|
||||
return (a == color_t(b));
|
||||
}
|
||||
|
||||
inline bool operator!=(int a, const BitPixelAccess& b) {
|
||||
return (a != color_t(b));
|
||||
}
|
||||
|
||||
inline bool operator!=(color_t a, const BitPixelAccess& b) {
|
||||
return (a != color_t(b));
|
||||
}
|
||||
|
||||
template<typename PointerType,
|
||||
typename ReferenceType>
|
||||
class ImageIteratorT<BitmapTraits, PointerType, ReferenceType>
|
||||
: public std::iterator<std::forward_iterator_tag,
|
||||
BitmapTraits::pixel_t,
|
||||
ptrdiff_t,
|
||||
PointerType,
|
||||
ReferenceType> {
|
||||
public:
|
||||
// GCC 4.6 needs these re-definitions here.
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef PointerType pointer;
|
||||
typedef ReferenceType reference;
|
||||
enum { pixels_per_byte = BitmapTraits::pixels_per_byte };
|
||||
|
||||
ImageIteratorT() : m_ptr(NULL) {
|
||||
}
|
||||
|
||||
ImageIteratorT(const ImageIteratorT& other) :
|
||||
m_ptr(other.m_ptr),
|
||||
m_x(other.m_x),
|
||||
m_subPixel(other.m_subPixel),
|
||||
m_subPixel0(other.m_subPixel0),
|
||||
m_width(other.m_width),
|
||||
m_nextRow(other.m_nextRow)
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
, m_image(other.m_image)
|
||||
, m_X0(other.m_X0), m_X(other.m_X), m_Y(other.m_Y)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
ImageIteratorT(const Image* image, const gfx::Rect& bounds, int x, int y) :
|
||||
m_ptr((pointer)image->getPixelAddress(x, y)),
|
||||
m_x(x - bounds.x),
|
||||
m_subPixel(x % 8),
|
||||
m_subPixel0(bounds.x % 8),
|
||||
m_width(bounds.w),
|
||||
m_nextRow(// Bytes on the right of this row to jump to the beginning of the next one
|
||||
BitmapTraits::getRowStrideBytes((pixels_per_byte*BitmapTraits::getRowStrideBytes(image->getWidth()))
|
||||
- (bounds.x+bounds.w))
|
||||
// Bytes on the left of the next row to go to bounds.x byte
|
||||
+ bounds.x/pixels_per_byte)
|
||||
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
, m_image(const_cast<Image*>(image))
|
||||
, m_X0(bounds.x)
|
||||
, m_X(x), m_Y(y)
|
||||
#endif
|
||||
{
|
||||
ASSERT(bounds.contains(gfx::Point(x, y)));
|
||||
}
|
||||
|
||||
ImageIteratorT& operator=(const ImageIteratorT& other) {
|
||||
m_ptr = other.m_ptr;
|
||||
m_x = other.m_x;
|
||||
m_subPixel = other.m_subPixel;
|
||||
m_subPixel0 = other.m_subPixel0;
|
||||
m_width = other.m_width;
|
||||
m_nextRow = other.m_nextRow;
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
m_image = other.m_image;
|
||||
m_X0 = other.m_X0;
|
||||
m_X = other.m_X;
|
||||
m_Y = other.m_Y;
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const ImageIteratorT& other) const {
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
if (m_ptr == other.m_ptr &&
|
||||
m_subPixel == other.m_subPixel) {
|
||||
ASSERT(m_X == other.m_X && m_Y == other.m_Y);
|
||||
}
|
||||
else {
|
||||
ASSERT(m_X != other.m_X || m_Y != other.m_Y);
|
||||
}
|
||||
#endif
|
||||
return m_ptr == other.m_ptr;
|
||||
}
|
||||
bool operator!=(const ImageIteratorT& other) const {
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
if (m_ptr != other.m_ptr ||
|
||||
m_subPixel != other.m_subPixel) {
|
||||
ASSERT(m_X != other.m_X || m_Y != other.m_Y);
|
||||
}
|
||||
else {
|
||||
ASSERT(m_X == other.m_X && m_Y == other.m_Y);
|
||||
}
|
||||
#endif
|
||||
return m_ptr != other.m_ptr;
|
||||
}
|
||||
|
||||
ImageIteratorT& operator++() {
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
ASSERT(m_image->getBounds().contains(gfx::Point(m_X, m_Y)));
|
||||
#endif
|
||||
|
||||
++m_x;
|
||||
++m_subPixel;
|
||||
|
||||
if (m_subPixel == 8) {
|
||||
m_subPixel = 0;
|
||||
++m_ptr;
|
||||
}
|
||||
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
++m_X;
|
||||
#endif
|
||||
|
||||
if (m_x == m_width) {
|
||||
m_ptr += m_nextRow;
|
||||
m_x = 0;
|
||||
m_subPixel = m_subPixel0;
|
||||
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
m_X = m_X0;
|
||||
++m_Y;
|
||||
|
||||
if (m_Y < m_image->getHeight()) {
|
||||
pointer expected_ptr = (pointer)m_image->getPixelAddress(m_X, m_Y);
|
||||
ASSERT(expected_ptr == m_ptr);
|
||||
ASSERT(m_subPixel == m_X % 8);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#ifdef RASTER_DEBUG_ITERATORS
|
||||
else {
|
||||
pointer expected_ptr = (pointer)m_image->getPixelAddress(m_X, m_Y);
|
||||
ASSERT(expected_ptr == m_ptr);
|
||||
ASSERT(m_subPixel == m_X % 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ImageIteratorT operator++(int) {
|
||||
ImageIteratorT tmp(*this);
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
reference operator*() const {
|
||||
m_access.reset(m_ptr, 1 << m_subPixel);
|
||||
return m_access;
|
||||
}
|
||||
|
||||
reference operator*() {
|
||||
m_access.reset(m_ptr, 1 << m_subPixel);
|
||||
return m_access;
|
||||
}
|
||||
|
||||
private:
|
||||
pointer m_ptr;
|
||||
int m_x, m_subPixel, m_subPixel0;
|
||||
int m_width;
|
||||
int m_nextRow;
|
||||
mutable BitPixelAccess m_access;
|
||||
#ifdef RASTER_DEBUG_ITERATORS // Data used for debugging purposes.
|
||||
Image* m_image;
|
||||
int m_X0, m_X, m_Y;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<>
|
||||
class ImageIterator<BitmapTraits> : public ImageIteratorT<BitmapTraits,
|
||||
uint8_t*,
|
||||
BitPixelAccess&> {
|
||||
public:
|
||||
ImageIterator() {
|
||||
}
|
||||
|
||||
ImageIterator(const Image* image, const gfx::Rect& bounds, int x, int y) :
|
||||
ImageIteratorT(image, bounds, x, y) {
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class ImageConstIterator<BitmapTraits> : public ImageIteratorT<BitmapTraits,
|
||||
uint8_t const*,
|
||||
const BitPixelAccess&> {
|
||||
public:
|
||||
ImageConstIterator() {
|
||||
}
|
||||
|
||||
ImageConstIterator(const Image* image, const gfx::Rect& bounds, int x, int y) :
|
||||
ImageIteratorT(image, bounds, x, y) {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace raster
|
||||
|
||||
#endif
|
@ -19,215 +19,118 @@
|
||||
#ifndef RASTER_IMAGE_TRAITS_H_INCLUDED
|
||||
#define RASTER_IMAGE_TRAITS_H_INCLUDED
|
||||
|
||||
#define _rgba_r_shift 0
|
||||
#define _rgba_g_shift 8
|
||||
#define _rgba_b_shift 16
|
||||
#define _rgba_a_shift 24
|
||||
|
||||
#define _graya_v_shift 0
|
||||
#define _graya_a_shift 8
|
||||
|
||||
#define _image_bitmap_next_bit(d, a) \
|
||||
if (d.rem < 7) \
|
||||
d.rem++; \
|
||||
else { \
|
||||
a++; \
|
||||
d.rem = 0; \
|
||||
}
|
||||
#include "raster/pixel_format.h"
|
||||
|
||||
namespace raster {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// RGBA
|
||||
|
||||
inline uint8_t _rgba_getr(uint32_t c) {
|
||||
return (c >> _rgba_r_shift) & 0xff;
|
||||
}
|
||||
|
||||
inline uint8_t _rgba_getg(uint32_t c) {
|
||||
return (c >> _rgba_g_shift) & 0xff;
|
||||
}
|
||||
|
||||
inline uint8_t _rgba_getb(uint32_t c) {
|
||||
return (c >> _rgba_b_shift) & 0xff;
|
||||
}
|
||||
|
||||
inline uint8_t _rgba_geta(uint32_t c) {
|
||||
return (c >> _rgba_a_shift) & 0xff;
|
||||
}
|
||||
|
||||
inline uint32_t _rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
|
||||
return ((r << _rgba_r_shift) |
|
||||
(g << _rgba_g_shift) |
|
||||
(b << _rgba_b_shift) |
|
||||
(a << _rgba_a_shift));
|
||||
}
|
||||
|
||||
struct RgbTraits {
|
||||
static const PixelFormat pixel_format = IMAGE_RGB;
|
||||
|
||||
enum {
|
||||
pixel_format = IMAGE_RGB,
|
||||
bits_per_pixel = 32,
|
||||
bytes_per_pixel = 4,
|
||||
pixels_per_byte = 0,
|
||||
channels = 4,
|
||||
has_alpha = true,
|
||||
is_binary = false,
|
||||
};
|
||||
|
||||
typedef uint32_t pixel_t;
|
||||
typedef pixel_t* address_t;
|
||||
typedef const pixel_t* const_address_t;
|
||||
|
||||
static inline int scanline_size(int w)
|
||||
static const pixel_t min_value = 0x00000000l;
|
||||
static const pixel_t max_value = 0xffffffffl;
|
||||
|
||||
static inline int getRowStrideBytes(int pixels_per_row)
|
||||
{
|
||||
return bytes_per_pixel*w;
|
||||
return bytes_per_pixel * pixels_per_row;
|
||||
}
|
||||
|
||||
static inline BLEND_COLOR get_blender(int blend_mode)
|
||||
{
|
||||
ASSERT(blend_mode >= 0 && blend_mode < BLEND_MODE_MAX);
|
||||
return _rgba_blenders[blend_mode];
|
||||
return rgba_blenders[blend_mode];
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Grayscale
|
||||
|
||||
inline uint8_t _graya_getv(uint16_t c) {
|
||||
return (c >> _graya_v_shift) & 0xff;
|
||||
}
|
||||
|
||||
inline uint8_t _graya_geta(uint16_t c) {
|
||||
return (c >> _graya_a_shift) & 0xff;
|
||||
}
|
||||
|
||||
inline uint16_t _graya(uint8_t v, uint8_t a) {
|
||||
return ((v << _graya_v_shift) |
|
||||
(a << _graya_a_shift));
|
||||
}
|
||||
|
||||
struct GrayscaleTraits {
|
||||
static const PixelFormat pixel_format = IMAGE_GRAYSCALE;
|
||||
|
||||
enum {
|
||||
pixel_format = IMAGE_GRAYSCALE,
|
||||
bits_per_pixel = 16,
|
||||
bytes_per_pixel = 2,
|
||||
pixels_per_byte = 0,
|
||||
channels = 2,
|
||||
has_alpha = true,
|
||||
is_binary = false,
|
||||
};
|
||||
|
||||
typedef uint16_t pixel_t;
|
||||
typedef pixel_t* address_t;
|
||||
typedef const pixel_t* const_address_t;
|
||||
|
||||
static inline int scanline_size(int w)
|
||||
static const pixel_t min_value = 0x0000;
|
||||
static const pixel_t max_value = 0xffff;
|
||||
|
||||
static inline int getRowStrideBytes(int pixels_per_row)
|
||||
{
|
||||
return bytes_per_pixel*w;
|
||||
return bytes_per_pixel * pixels_per_row;
|
||||
}
|
||||
|
||||
static inline BLEND_COLOR get_blender(int blend_mode)
|
||||
{
|
||||
ASSERT(blend_mode >= 0 && blend_mode < BLEND_MODE_MAX);
|
||||
return _graya_blenders[blend_mode];
|
||||
return graya_blenders[blend_mode];
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Indexed
|
||||
|
||||
struct IndexedTraits {
|
||||
static const PixelFormat pixel_format = IMAGE_INDEXED;
|
||||
|
||||
enum {
|
||||
pixel_format = IMAGE_INDEXED,
|
||||
bits_per_pixel = 8,
|
||||
bytes_per_pixel = 1,
|
||||
pixels_per_byte = 1,
|
||||
channels = 1,
|
||||
has_alpha = false,
|
||||
is_binary = false,
|
||||
};
|
||||
|
||||
typedef uint8_t pixel_t;
|
||||
typedef pixel_t* address_t;
|
||||
typedef const pixel_t* const_address_t;
|
||||
|
||||
static inline int scanline_size(int w)
|
||||
static const pixel_t min_value = 0x00;
|
||||
static const pixel_t max_value = 0xff;
|
||||
|
||||
static inline int getRowStrideBytes(int pixels_per_row)
|
||||
{
|
||||
return bytes_per_pixel*w;
|
||||
return bytes_per_pixel * pixels_per_row;
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Bitmap
|
||||
|
||||
struct BitmapTraits {
|
||||
static const PixelFormat pixel_format = IMAGE_BITMAP;
|
||||
|
||||
enum {
|
||||
pixel_format = IMAGE_BITMAP,
|
||||
bits_per_pixel = 1,
|
||||
bytes_per_pixel = 1,
|
||||
pixels_per_byte = 8,
|
||||
channels = 1,
|
||||
has_alpha = false,
|
||||
is_binary = true,
|
||||
};
|
||||
|
||||
typedef uint8_t pixel_t;
|
||||
typedef pixel_t* address_t;
|
||||
typedef const pixel_t* const_address_t;
|
||||
|
||||
static inline int scanline_size(int w) {
|
||||
return ((w+7)/8);
|
||||
static const pixel_t min_value = 0;
|
||||
static const pixel_t max_value = 1;
|
||||
|
||||
static inline int getRowStrideBytes(int pixels_per_row)
|
||||
{
|
||||
return ((pixels_per_row+7) / 8);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class Traits>
|
||||
inline typename Traits::address_t image_address_fast(const Image* image, int x, int y)
|
||||
{
|
||||
ASSERT(x >= 0 && x < image->w);
|
||||
ASSERT(y >= 0 && y < image->h);
|
||||
|
||||
return ((((typename Traits::pixel_t**)image->line)[y])+x);
|
||||
}
|
||||
|
||||
template<class Traits>
|
||||
inline typename Traits::pixel_t image_getpixel_fast(const Image* image, int x, int y)
|
||||
{
|
||||
ASSERT(x >= 0 && x < image->w);
|
||||
ASSERT(y >= 0 && y < image->h);
|
||||
|
||||
return *((((typename Traits::pixel_t**)image->line)[y])+x);
|
||||
}
|
||||
|
||||
template<class Traits>
|
||||
inline void image_putpixel_fast(Image* image, int x, int y, typename Traits::pixel_t color)
|
||||
{
|
||||
ASSERT(x >= 0 && x < image->w);
|
||||
ASSERT(y >= 0 && y < image->h);
|
||||
|
||||
*((((typename Traits::pixel_t**)image->line)[y])+x) = color;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline BitmapTraits::pixel_t image_getpixel_fast<BitmapTraits>(const Image* image, int x, int y)
|
||||
{
|
||||
ASSERT(x >= 0 && x < image->w);
|
||||
ASSERT(y >= 0 && y < image->h);
|
||||
|
||||
div_t d = div(x, 8);
|
||||
return ((*(((BitmapTraits::pixel_t**)image->line)[y]+d.quot)) & (1<<d.rem)) ? 1: 0;
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void image_putpixel_fast<BitmapTraits>(Image* image, int x, int y, BitmapTraits::pixel_t color)
|
||||
{
|
||||
ASSERT(x >= 0 && x < image->w);
|
||||
ASSERT(y >= 0 && y < image->h);
|
||||
|
||||
div_t d = div(x, 8);
|
||||
if (color)
|
||||
*(((BitmapTraits::pixel_t**)image->line)[y]+d.quot) |= (1<<d.rem);
|
||||
else
|
||||
*(((BitmapTraits::pixel_t**)image->line)[y]+d.quot) &= ~(1<<d.rem);
|
||||
}
|
||||
|
||||
} // namespace raster
|
||||
|
||||
#endif
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user