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:
David Capello 2013-11-09 19:59:05 -03:00
parent 7657461162
commit e5ba8e0922
128 changed files with 4893 additions and 3734 deletions

View File

@ -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

View File

@ -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})

View File

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

View File

@ -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);

View File

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

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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

View File

@ -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));

View File

@ -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));
}
}

View File

@ -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));
}
}
}

View File

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

View File

@ -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

View File

@ -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);

View File

@ -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();

View File

@ -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)) {

View File

@ -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

View File

@ -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();
}

View File

@ -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());
}
}

View File

@ -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
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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)) {

View File

@ -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)

View File

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

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

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

View File

@ -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();

View File

@ -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));
}

View File

@ -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;

View File

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

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

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

View File

@ -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();
}

View File

@ -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);

View File

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

View File

@ -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,

View File

@ -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)

View File

@ -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];

View File

@ -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);

View File

@ -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()

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);

View File

@ -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();

View File

@ -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
View 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

View File

@ -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];

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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)

View File

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

View File

@ -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);
}
}
}

View File

@ -23,7 +23,6 @@
#include "raster/algorithm/flip_type.h"
namespace raster {
class Image;
class Mask;

View 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

View 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

View 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

View 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

View File

@ -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

View File

@ -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

View File

@ -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)
{

View File

@ -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
View 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

View File

@ -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

View 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
View 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

View 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

View 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

View File

@ -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());
}
}

View File

@ -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);

View File

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

View File

@ -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;

View File

@ -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

View File

@ -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
View 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

View File

@ -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
View 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

View File

@ -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