From e5ba8e0922e066e7b521b149007a74aa00a9a25b Mon Sep 17 00:00:00 2001 From: David Capello Date: Sat, 9 Nov 2013 19:59:05 -0300 Subject: [PATCH] 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 --- TODO.md | 2 + src/CMakeLists.txt | 6 +- src/app/color.cpp | 55 +- src/app/color.h | 3 +- src/app/color_utils.cpp | 40 +- src/app/color_utils.h | 9 +- src/app/commands/cmd_cel_properties.cpp | 10 +- src/app/commands/cmd_export_sprite_sheet.cpp | 3 +- src/app/commands/cmd_flip.cpp | 12 +- src/app/commands/cmd_import_sprite_sheet.cpp | 3 +- src/app/commands/cmd_invert_mask.cpp | 17 +- src/app/commands/cmd_merge_down_layer.cpp | 23 +- src/app/commands/cmd_new_file.cpp | 3 +- src/app/commands/cmd_palette_editor.cpp | 14 +- src/app/commands/cmd_play_animation.cpp | 5 +- src/app/commands/cmd_preview.cpp | 6 +- src/app/commands/cmd_rotate_canvas.cpp | 20 +- src/app/commands/cmd_sprite_size.cpp | 41 +- .../commands/filters/filter_manager_impl.cpp | 59 +- .../commands/filters/filter_manager_impl.h | 8 +- src/app/commands/filters/filter_preview.cpp | 6 + src/app/document.cpp | 10 +- src/app/document_api.cpp | 92 +- src/app/drop_files.cpp | 12 +- src/app/file/ase_format.cpp | 108 +- src/app/file/bmp_format.cpp | 74 +- src/app/file/file.cpp | 10 +- src/app/file/file_unittest.cpp | 4 +- src/app/file/fli_format.cpp | 36 +- src/app/file/gif_format.cpp | 122 +-- src/app/file/ico_format.cpp | 70 +- src/app/file/jpeg_format.cpp | 37 +- src/app/file/pcx_format.cpp | 57 +- src/app/file/png_format.cpp | 52 +- src/app/file/tga_format.cpp | 82 +- src/app/flatten.cpp | 6 +- src/app/modules/gfx.cpp | 8 +- src/app/modules/palettes.cpp | 15 +- src/app/thumbnail_generator.cpp | 20 +- src/app/tools/ink_processing.h | 865 ++++++++-------- src/app/tools/inks.h | 2 +- src/app/tools/point_shape.cpp | 10 +- src/app/tools/tool_loop_manager.cpp | 9 +- src/app/ui/context_bar.cpp | 17 +- src/app/ui/editor/cursor.cpp | 17 +- src/app/ui/editor/editor.cpp | 55 +- src/app/ui/editor/pixels_movement.cpp | 28 +- src/app/ui/editor/select_box_state.cpp | 8 +- src/app/ui/editor/standby_state.cpp | 6 +- src/app/ui/palette_view.cpp | 6 +- src/app/undoers/flip_image.cpp | 2 +- src/app/undoers/image_area.cpp | 8 +- src/app/util/autocrop.cpp | 44 +- src/app/util/boundary.cpp | 36 +- src/app/util/celmove.cpp | 13 +- src/app/util/clipboard.cpp | 14 +- src/app/util/clipboard_win32.h | 100 +- src/app/util/expand_cel_canvas.cpp | 17 +- src/app/util/misc.cpp | 28 +- src/app/util/msk_file.cpp | 5 +- src/app/util/pic_file.cpp | 47 +- src/app/util/render.cpp | 193 ++-- src/app/util/thmbnail.cpp | 61 +- src/base/clamp.h | 21 + src/filters/color_curve_filter.cpp | 22 +- src/filters/convolution_matrix_filter.cpp | 51 +- src/filters/invert_color_filter.cpp | 22 +- src/filters/median_filter.cpp | 47 +- src/filters/neighboring_pixels.h | 25 +- src/filters/replace_color_filter.cpp | 24 +- src/raster/CMakeLists.txt | 7 +- src/raster/algo.cpp | 4 +- src/raster/algofill.cpp | 102 +- src/raster/algorithm/flip_image.cpp | 27 +- src/raster/algorithm/flip_image.h | 1 - src/raster/algorithm/resize_image.cpp | 244 +++++ src/raster/algorithm/resize_image.h | 53 + src/raster/algorithm/shrink_bounds.cpp | 114 +++ src/raster/algorithm/shrink_bounds.h | 36 + src/raster/blend.cpp | 104 +- src/raster/blend.h | 20 +- src/raster/cel.cpp | 4 +- src/raster/cel.h | 4 +- src/raster/color.h | 80 ++ src/raster/color_histogram.h | 8 +- src/raster/color_scales.cpp | 60 ++ src/raster/color_scales.h | 34 + src/raster/conversion_alleg.cpp | 315 ++++++ src/raster/conversion_alleg.h | 36 + src/raster/dirty.cpp | 18 +- src/raster/dirty.h | 2 +- src/raster/file/col_file.cpp | 63 +- src/raster/file/gpl_file.cpp | 8 +- src/raster/image.cpp | 681 +------------ src/raster/image.h | 126 ++- src/raster/image_bits.h | 167 ++++ src/raster/image_impl.h | 933 ++++-------------- src/raster/image_io.cpp | 20 +- src/raster/image_iterator.h | 506 ++++++++++ src/raster/image_traits.h | 169 +--- src/raster/image_unittest.cpp | 198 ++++ src/raster/images_collector.cpp | 6 +- src/raster/layer.cpp | 29 +- src/raster/layer.h | 10 +- src/raster/layer_io.cpp | 12 +- src/raster/mask.cpp | 225 ++--- src/raster/mask.h | 9 +- src/raster/mask_io.cpp | 8 +- src/raster/median_cut.h | 8 +- src/raster/{gfxobj.cpp => object.cpp} | 14 +- src/raster/{gfxobj.h => object.h} | 40 +- src/raster/palette.cpp | 186 ++-- src/raster/palette.h | 17 +- src/raster/path.cpp | 10 +- src/raster/path.h | 4 +- src/raster/pen.cpp | 32 +- src/raster/primitives.cpp | 337 +++++++ src/raster/primitives.h | 54 + src/raster/primitives_fast.h | 67 ++ src/raster/quantization.cpp | 248 ++--- src/raster/raster.h | 9 +- src/raster/rgbmap.cpp | 5 +- src/raster/rgbmap.h | 4 +- src/raster/rotate.cpp | 147 +-- src/raster/sprite.cpp | 27 +- src/raster/sprite.h | 4 +- src/raster/stock.cpp | 4 +- src/raster/stock.h | 4 +- 128 files changed, 4893 insertions(+), 3734 deletions(-) create mode 100644 src/base/clamp.h create mode 100644 src/raster/algorithm/resize_image.cpp create mode 100644 src/raster/algorithm/resize_image.h create mode 100644 src/raster/algorithm/shrink_bounds.cpp create mode 100644 src/raster/algorithm/shrink_bounds.h create mode 100644 src/raster/color.h create mode 100644 src/raster/color_scales.cpp create mode 100644 src/raster/color_scales.h create mode 100644 src/raster/conversion_alleg.cpp create mode 100644 src/raster/conversion_alleg.h create mode 100644 src/raster/image_bits.h create mode 100644 src/raster/image_iterator.h create mode 100644 src/raster/image_unittest.cpp rename src/raster/{gfxobj.cpp => object.cpp} (82%) rename src/raster/{gfxobj.h => object.h} (73%) create mode 100644 src/raster/primitives.cpp create mode 100644 src/raster/primitives.h create mode 100644 src/raster/primitives_fast.h diff --git a/TODO.md b/TODO.md index 906a79baa..de948a2aa 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,7 @@ # Very high priority (next release?) +* Remove Image::getPixelAddress() shouldn't be public, and almost + everywhere we should use iterators for images. * Warning icon when selecting RGB/HSB color in indexed image. * Warning message when we open a file that is already opened file (show an option to create a second view, or maybe this should diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f1a200edb..6bdbc2269 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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}) diff --git a/src/app/color.cpp b/src/app/color.cpp index 44b7d728d..706a9563c 100644 --- a/src/app/color.cpp +++ b/src/app/color.cpp @@ -28,6 +28,7 @@ #include "gfx/rgb.h" #include "raster/image.h" #include "raster/palette.h" +#include "raster/primitives.h" #include #include @@ -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; } } diff --git a/src/app/color.h b/src/app/color.h index 45b8fb7bf..3c775c922 100644 --- a/src/app/color.h +++ b/src/app/color.h @@ -19,6 +19,7 @@ #ifndef APP_COLOR_H_INCLUDED #define APP_COLOR_H_INCLUDED +#include "raster/color.h" #include "raster/pixel_format.h" #include @@ -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); diff --git a/src/app/color_utils.cpp b/src/app/color_utils.cpp index e8982ba13..c9484b2a4 100644 --- a/src/app/color_utils.cpp +++ b/src/app/color_utils.cpp @@ -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; } diff --git a/src/app/color_utils.h b/src/app/color_utils.h index 4303de9db..cb0e23925 100644 --- a/src/app/color_utils.h +++ b/src/app/color_utils.h @@ -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 diff --git a/src/app/commands/cmd_cel_properties.cpp b/src/app/commands/cmd_cel_properties.cpp index b272eb782..a80a311cb 100644 --- a/src/app/commands/cmd_cel_properties.cpp +++ b/src/app/commands/cmd_cel_properties.cpp @@ -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 diff --git a/src/app/commands/cmd_export_sprite_sheet.cpp b/src/app/commands/cmd_export_sprite_sheet.cpp index b510326fe..a33b42457 100644 --- a/src/app/commands/cmd_export_sprite_sheet.cpp +++ b/src/app/commands/cmd_export_sprite_sheet.cpp @@ -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 resultImage(Image::create(sprite->getPixelFormat(), sheet_w, sheet_h)); base::UniquePtr 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); framew, 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 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); } } diff --git a/src/app/commands/cmd_import_sprite_sheet.cpp b/src/app/commands/cmd_import_sprite_sheet.cpp index 1760ee798..8fa775796 100644 --- a/src/app/commands/cmd_import_sprite_sheet.cpp +++ b/src/app/commands/cmd_import_sprite_sheet.cpp @@ -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 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); diff --git a/src/app/commands/cmd_invert_mask.cpp b/src/app/commands/cmd_invert_mask.cpp index 0cf66aa50..bbad613f6 100644 --- a/src/app/commands/cmd_invert_mask.cpp +++ b/src/app/commands/cmd_invert_mask.cpp @@ -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 diff --git a/src/app/commands/cmd_merge_down_layer.cpp b/src/app/commands/cmd_merge_down_layer.cpp index 6f6d993f9..c22b8b392 100644 --- a/src/app/commands/cmd_merge_down_layer.cpp +++ b/src/app/commands/cmd_merge_down_layer.cpp @@ -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(src_layer)->getBlendMode()); + raster::composite_image(new_image, src_image, + src_cel->getX()-x1, + src_cel->getY()-y1, + src_cel->getOpacity(), + static_cast(src_layer)->getBlendMode()); if (undo.isEnabled()) undo.pushUndoer(new undoers::SetCelPosition(undo.getObjects(), dst_cel)); diff --git a/src/app/commands/cmd_new_file.cpp b/src/app/commands/cmd_new_file.cpp index 7d5d40cc8..860c2378a 100644 --- a/src/app/commands/cmd_new_file.cpp +++ b/src/app/commands/cmd_new_file.cpp @@ -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)); } } diff --git a/src/app/commands/cmd_palette_editor.cpp b/src/app/commands/cmd_palette_editor.cpp index b133cc755..812aea571 100644 --- a/src/app/commands/cmd_palette_editor.cpp +++ b/src/app/commands/cmd_palette_editor.cpp @@ -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; csize(); 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)); } } } diff --git a/src/app/commands/cmd_play_animation.cpp b/src/app/commands/cmd_play_animation.cpp index 0b8ec2ede..5c13ff14e 100644 --- a/src/app/commands/cmd_play_animation.cpp +++ b/src/app/commands/cmd_play_animation.cpp @@ -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; } diff --git a/src/app/commands/cmd_preview.cpp b/src/app/commands/cmd_preview.cpp index 6781254c7..fa320c331 100644 --- a/src/app/commands/cmd_preview.cpp +++ b/src/app/commands/cmd_preview.cpp @@ -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 diff --git a/src/app/commands/cmd_rotate_canvas.cpp b/src/app/commands/cmd_rotate_canvas.cpp index b162d3806..87148db7f 100644 --- a/src/app/commands/cmd_rotate_canvas.cpp +++ b/src/app/commands/cmd_rotate_canvas.cpp @@ -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); diff --git a/src/app/commands/cmd_sprite_size.cpp b/src/app/commands/cmd_sprite_size.cpp index 51e490ef4..0f2ec10bf 100644 --- a/src/app/commands/cmd_sprite_size.cpp +++ b/src/app/commands/cmd_sprite_size.cpp @@ -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 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 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(); diff --git a/src/app/commands/filters/filter_manager_impl.cpp b/src/app/commands/filters/filter_manager_impl.cpp index ce19d45bf..f6df0b8b2 100644 --- a/src/app/commands/filters/filter_manager_impl.cpp +++ b/src/app/commands/filters/filter_manager_impl.cpp @@ -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(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<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)) { diff --git a/src/app/commands/filters/filter_manager_impl.h b/src/app/commands/filters/filter_manager_impl.h index a8f9e558a..cf7f95509 100644 --- a/src/app/commands/filters/filter_manager_impl.h +++ b/src/app/commands/filters/filter_manager_impl.h @@ -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 #include 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 m_preview_mask; - unsigned char* m_mask_address; - div_t m_d; + raster::ImageBits m_maskBits; + raster::ImageBits::iterator m_maskIterator; Target m_targetOrig; // Original targets Target m_target; // Filtered targets diff --git a/src/app/commands/filters/filter_preview.cpp b/src/app/commands/filters/filter_preview.cpp index 114f5b306..a9024ad08 100644 --- a/src/app/commands/filters/filter_preview.cpp +++ b/src/app/commands/filters/filter_preview.cpp @@ -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(); } diff --git a/src/app/document.cpp b/src/app/document.cpp index 0b3bd8e28..5a7da50e3 100644 --- a/src/app/document.cpp +++ b/src/app/document.cpp @@ -100,7 +100,7 @@ Document* Document::createBasicDocument(PixelFormat format, int width, int heigh base::UniquePtr 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()); } } diff --git a/src/app/document_api.cpp b/src/app/document_api.cpp index 5c170a04b..e18467310 100644 --- a/src/app/document_api.cpp +++ b/src/app/document_api.cpp @@ -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_wrap(Image::create(sprite->getPixelFormat(), - sprite->getWidth(), - sprite->getHeight())); + sprite->getWidth(), + sprite->getHeight())); Image* image = image_wrap.get(); for (FrameNumber frame(0); framegetTotalFrames(); ++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(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(layer)->getLayerBegin(); LayerIterator end = static_cast(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(layer)->getCel(frame)) removeCel(static_cast(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(layer)->getLayerBegin(); LayerIterator end = static_cast(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(layer)->getLayerBegin(); LayerIterator end = static_cast(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); framegetTotalFrames(); ++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; vgetBounds().h; v++) { - div_t d = div(0, 8); - uint8_t* address = ((uint8_t**)mask->getBitmap()->line)[v]+d.quot; + const LockImageBits maskBits(mask->getBitmap()); + LockImageBits::const_iterator it = maskBits.begin(); - for (u=0; ugetBounds().w; u++) { - if ((*address & (1<getBounds().h; ++v) { + for (u=0; ugetBounds().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 } diff --git a/src/app/drop_files.cpp b/src/app/drop_files.cpp index 34c509956..4e7903aed 100644 --- a/src/app/drop_files.cpp +++ b/src/app/drop_files.cpp @@ -35,18 +35,18 @@ #ifdef ALLEGRO_WINDOWS #include + + #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* dropped_files; static base::mutex* dropped_files_mutex = NULL; diff --git a/src/app/file/ase_format.cpp b/src/app/file/ase_format.cpp index 438be277c..a5f25eb3b 100644 --- a/src/app/file/ase_format.cpp +++ b/src/app/file/ase_format.cpp @@ -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; csize(); 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 -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 -{ +class PixelIO { 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 -class PixelIO -{ +class PixelIO { 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 -class PixelIO -{ +class PixelIO { 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 pixel_io; int x, y; - for (y=0; yh; y++) { - for (x=0; xw; x++) - image_putpixel_fast(image, x, y, pixel_io.read_pixel(f)); + for (y=0; ygetHeight(); y++) { + for (x=0; xgetWidth(); x++) + put_pixel_fast(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 pixel_io; int x, y; - for (y=0; yh; y++) - for (x=0; xw; x++) - pixel_io.write_pixel(f, image_getpixel_fast(image, x, y)); + for (y=0; ygetHeight(); y++) + for (x=0; xgetWidth(); x++) + pixel_io.write_pixel(f, get_pixel_fast(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 scanline(ImageTraits::scanline_size(image->w)); - std::vector uncompressed(image->h * ImageTraits::scanline_size(image->w)); + std::vector scanline(ImageTraits::getRowStrideBytes(image->getWidth())); + std::vector uncompressed(image->getHeight() * ImageTraits::getRowStrideBytes(image->getWidth())); std::vector 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; yh; y++) { - typename ImageTraits::address_t address = image_address_fast(image, 0, y); - pixel_io.read_scanline(address, image->w, &uncompressed[uncompressed_offset]); + for (y=0; ygetHeight(); 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 scanline(ImageTraits::scanline_size(image->w)); + std::vector scanline(ImageTraits::getRowStrideBytes(image->getWidth())); std::vector compressed(4096); - for (y=0; yh; y++) { - typename ImageTraits::address_t address = image_address_fast(image, 0, y); - pixel_io.write_scanline(address, image->w, &scanline[0]); + for (y=0; ygetHeight(); 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); } diff --git a/src/app/file/bmp_format.cpp b/src/app/file/bmp_format.cpp index f78c23682..30a6ead69 100644 --- a/src/app/file/bmp_format.cpp +++ b/src/app/file/bmp_format.cpp @@ -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> 4) & 15; for (j=0; j> 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(image, j, line, _rgba(r, g, b, 255)); + put_pixel_fast(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; jw; j++) { + for (i=image->getHeight()-1; i>=0; i--) { + for (j=0; jgetWidth(); j++) { if (bpp == 8) { if (image->getPixelFormat() == IMAGE_INDEXED) - fputc(image_getpixel_fast(image, j, i), f); + fputc(get_pixel_fast(image, j, i), f); else if (image->getPixelFormat() == IMAGE_GRAYSCALE) - fputc(_graya_getv(image_getpixel_fast(image, j, i)), f); + fputc(graya_getv(get_pixel_fast(image, j, i)), f); } else { - c = image_getpixel_fast(image, j, i); - fputc(_rgba_getb(c), f); - fputc(_rgba_getg(c), f); - fputc(_rgba_getr(c), f); + c = get_pixel_fast(image, j, i); + fputc(rgba_getb(c), f); + fputc(rgba_getg(c), f); + fputc(rgba_getr(c), f); } } for (j=0; jh-i) / (float)image->h); + fop_progress(fop, (float)(image->getHeight()-i) / (float)image->getHeight()); } if (ferror(f)) { diff --git a/src/app/file/file.cpp b/src/app/file/file.cpp index 8e422f116..dc6d7fa58 100644 --- a/src/app/file/file.cpp +++ b/src/app/file/file.cpp @@ -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 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) diff --git a/src/app/file/file_unittest.cpp b/src/app/file/file_unittest.cpp index 0fdad53b4..71c2cfaa6 100644 --- a/src/app/file/file_unittest.cpp +++ b/src/app/file/file_unittest.cpp @@ -55,7 +55,7 @@ TEST(File, SeveralSizes) int c = std::rand()%256; for (int y=0; y(image, x, y, c); + put_pixel_fast(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(image, x, y)); + ASSERT_EQ(c, get_pixel_fast(image, x, y)); if ((std::rand()&4) == 0) c = std::rand()%256; } diff --git a/src/app/file/fli_format.cpp b/src/app/file/fli_format.cpp index 246f9b3ea..6ded888ec 100644 --- a/src/app/file/fli_format.cpp +++ b/src/app/file/fli_format.cpp @@ -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 bmp(Image::create(IMAGE_INDEXED, w, h)); - UniquePtr old(Image::create(IMAGE_INDEXED, w, h)); - UniquePtr pal(new Palette(FrameNumber(0), 256)); + base::UniquePtr bmp(Image::create(IMAGE_INDEXED, w, h)); + base::UniquePtr old(Image::create(IMAGE_INDEXED, w, h)); + base::UniquePtr 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 bmp(Image::create(IMAGE_INDEXED, sprite->getWidth(), sprite->getHeight())); - UniquePtr old(Image::create(IMAGE_INDEXED, sprite->getWidth(), sprite->getHeight())); + base::UniquePtr bmp(Image::create(IMAGE_INDEXED, sprite->getWidth(), sprite->getHeight())); + base::UniquePtr 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); } diff --git a/src/app/file/gif_format.cpp b/src/app/file/gif_format.cpp index ac2871fa9..0794f24a3 100644 --- a/src/app/file/gif_format.cpp +++ b/src/app/file/gif_format.cpp @@ -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; iColorCount; ++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; iColorCount; ++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(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(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; yimage->h; ++y) { - for (int x=0; ximage->w; ++x) { - int pixel_index = image_getpixel_fast(frame_it->image, x, y); + for (int y=0; yimage->getHeight(); ++y) { + for (int x=0; ximage->getWidth(); ++x) { + int pixel_index = get_pixel_fast(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 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(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(frame_it->image, x, y); if (pixel_index != frame_it->mask_index) - image_putpixel_fast(current_image, - frame_it->x + x, - frame_it->y + y, - pixel_index); + put_pixel_fast(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(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(frame_it->image, x, y); if (pixel_index != frame_it->mask_index) - image_putpixel_fast(current_image, - frame_it->x + x, - frame_it->y + y, - current_palette->getEntry(pixel_index)); + put_pixel_fast(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_numgetTotalFrames(); ++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(buffer_image, x, y); - image_putpixel_fast(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(buffer_image, x, y); + put_pixel_fast(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(buffer_image, x, y); - image_putpixel_fast(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(buffer_image, x, y); + put_pixel_fast(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(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(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; diff --git a/src/app/file/ico_format.cpp b/src/app/file/ico_format.cpp index 785303e6c..3ece5e627 100644 --- a/src/app/file/ico_format.cpp +++ b/src/app/file/ico_format.cpp @@ -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; xw; ++x) { + for (y=image->getHeight()-1; y>=0; --y) { + for (x=0; xgetWidth(); ++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); ngetFolder(), 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; xw; ++x) { + for (y=image->getHeight()-1; y>=0; --y) { + for (x=0; xgetWidth(); ++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; diff --git a/src/app/file/jpeg_format.cpp b/src/app/file/jpeg_format.cpp index 28fd142bf..4bf6093ce 100644 --- a/src/app/file/jpeg_format.cpp +++ b/src/app/file/jpeg_format.cpp @@ -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; xw; x++) { + for (x=0; xgetWidth(); 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; xw; x++) - *(dst_address++) = _graya(*(src_address++), 255); + for (x=0; xgetWidth(); 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; xw; x++) { + + for (x=0; xgetWidth(); ++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; xw; x++) - *(dst_address++) = _graya_getv(*(src_address++)); + for (x=0; xgetWidth(); ++x) + *(dst_address++) = graya_getv(*(src_address++)); } } jpeg_write_scanlines(&cinfo, buffer, buffer_height); diff --git a/src/app/file/pcx_format.cpp b/src/app/file/pcx_format.cpp index 674685c4b..870225c3c 100644 --- a/src/app/file/pcx_format.cpp +++ b/src/app/file/pcx_format.cpp @@ -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; yw) - *(((uint8_t**)image->line)[y]+x) = ch; + if (x < image->getWidth()) + put_pixel_fast(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(image, xx, y, + get_pixel_fast(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; yh; y++) { /* for each scanline... */ + for (y=0; ygetHeight(); y++) { /* for each scanline... */ runcount = 0; runchar = 0; - for (x=0; xw*planes; x++) { /* for each pixel... */ + for (x=0; xgetWidth()*planes; x++) { /* for each pixel... */ if (depth == 8) { if (image->getPixelFormat() == IMAGE_INDEXED) - ch = image_getpixel_fast(image, x, y); + ch = get_pixel_fast(image, x, y); else if (image->getPixelFormat() == IMAGE_GRAYSCALE) { - c = image_getpixel_fast(image, x, y); - ch = _graya_getv(c); + c = get_pixel_fast(image, x, y); + ch = graya_getv(c); } } else { - if (x < image->w) { - c = image_getpixel_fast(image, x, y); - ch = _rgba_getr(c); + if (x < image->getWidth()) { + c = get_pixel_fast(image, x, y); + ch = rgba_getr(c); } - else if (xw*2) { - c = image_getpixel_fast(image, x-image->w, y); - ch = _rgba_getg(c); + else if (xgetWidth()*2) { + c = get_pixel_fast(image, x-image->getWidth(), y); + ch = rgba_getg(c); } else { - c = image_getpixel_fast(image, x-image->w*2, y); - ch = _rgba_getb(c); + c = get_pixel_fast(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 */ diff --git a/src/app/file/png_format.cpp b/src/app/file/png_format.cpp index e7840835b..cf3326fb2 100644 --- a/src/app/file/png_format.cpp +++ b/src/app/file/png_format.cpp @@ -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; xline)[y]; + register uint32_t* dst_address = (uint32_t*)image->getPixelAddress(0, y); register unsigned int x, r, g, b; for (x=0; xline)[y]; + register uint16_t* dst_address = (uint16_t*)image->getPixelAddress(0, y); register unsigned int x, k, a; for (x=0; xline)[y]; + register uint16_t* dst_address = (uint16_t*)image->getPixelAddress(0, y); register unsigned int x, k; for (x=0; xline)[y]; + register uint8_t* dst_address = (uint8_t*)image->getPixelAddress(0, y); register unsigned int x, c; for (x=0; xw; - 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; xline)[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; xline)[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; xline)[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; xline)[y]; + register uint8_t* src_address = (uint8_t*)image->getPixelAddress(0, y); register uint8_t* dst_address = row_pointer; register unsigned int x; diff --git a/src/app/file/tga_format.cpp b/src/app/file/tga_format.cpp index c90dd9109..3a875a259 100644 --- a/src/app/file/tga_format.cpp +++ b/src/app/file/tga_format.cpp @@ -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; xline)[yc]+x) = - _graya(fgetc(f), 255); + put_pixel_fast(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; xline)[yc]+x) = - _rgba(rgb[2], rgb[1], rgb[0], rgb[3]); + put_pixel_fast(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; xline)[yc]+x) = - _rgba(rgb[2], rgb[1], rgb[0], 255); + put_pixel_fast(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; xline)[yc]+x) = - _rgba(((c >> 10) & 0x1F), - ((c >> 5) & 0x1F), - (c & 0x1F), 255); + put_pixel_fast(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; xw; 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; xgetWidth(); 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; xw; x++) - fputc(_graya_getv(image_getpixel(image, x, y)), f); + for (y=image->getHeight()-1; y>=0; y--) { + for (x=0; xgetWidth(); 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; xw; x++) - fputc(image_getpixel(image, x, y), f); + for (y=image->getHeight()-1; y>=0; y--) { + for (x=0; xgetWidth(); 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; } diff --git a/src/app/flatten.cpp b/src/app/flatten.cpp index 9d8b05ff7..7c6f32f62 100644 --- a/src/app/flatten.cpp +++ b/src/app/flatten.cpp @@ -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(layer)->getCel(frame) ? true: false; - case GFXOBJ_LAYER_FOLDER: { + case OBJECT_LAYER_FOLDER: { LayerConstIterator it = static_cast(layer)->getLayerBegin(); LayerConstIterator end = static_cast(layer)->getLayerEnd(); diff --git a/src/app/modules/gfx.cpp b/src/app/modules/gfx.cpp index d9463e5bb..781e09c42 100644 --- a/src/app/modules/gfx.cpp +++ b/src/app/modules/gfx.cpp @@ -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)); } diff --git a/src/app/modules/palettes.cpp b/src/app/modules/palettes.cpp index b0d9d9845..988604035 100644 --- a/src/app/modules/palettes.cpp +++ b/src/app/modules/palettes.cpp @@ -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; diff --git a/src/app/thumbnail_generator.cpp b/src/app/thumbnail_generator.cpp index 65dfd9297..aada7b2c1 100644 --- a/src/app/thumbnail_generator.cpp +++ b/src/app/thumbnail_generator.cpp @@ -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(&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 m_thumbnail; - BITMAP* m_thumbnailBitmap; base::UniquePtr m_palette; base::thread m_thread; }; diff --git a/src/app/tools/ink_processing.h b/src/app/tools/ink_processing.h index ab1603d81..476152c71 100644 --- a/src/app/tools/ink_processing.h +++ b/src/app/tools/ink_processing.h @@ -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 +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(this)->initIterators(loop, x1, y); + + for (x=x1; x<=x2; ++x) { + if (bitmap->getPixel(x-maskOrigin.x, y-maskOrigin.y)) + static_cast(this)->processPixel(x, y); + + static_cast(this)->moveIterators(); + } + return; + } + } + + static_cast(this)->initIterators(loop, x1, y); + for (x=x1; x<=x2; ++x) { + static_cast(this)->processPixel(x, y); + static_cast(this)->moveIterators(); + } + } +}; + +template +class SimpleInkProcessing : public InkProcessing { +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 +class DoubleInkProcessing : public InkProcessing { +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 +class OpaqueInkProcessing : public SimpleInkProcessing, ImageTraits> { +public: + OpaqueInkProcessing(ToolLoop* loop) { + m_color = loop->getPrimaryColor(); + } - DEFINE_INK_PROCESSING_DST - (RgbTraits, - *dst_address = c ); -} + void processPixel(int x, int y) { + *SimpleInkProcessing, 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 +class PutAlphaInkProcessing : public SimpleInkProcessing, 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::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::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::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 +class TransparentInkProcessing : public DoubleInkProcessing, 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::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::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 : public DoubleInkProcessing, 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 +class BlurInkProcessing : public DoubleInkProcessing, ImageTraits> { +public: + BlurInkProcessing(ToolLoop* loop) { + } + void processPixel(int x, int y) { + // Do nothing (it's specialized for each case) + } +}; + +template<> +class BlurInkProcessing : public DoubleInkProcessing, 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(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 : public DoubleInkProcessing, 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(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 : public DoubleInkProcessing, 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(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(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(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(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 +class ReplaceInkProcessing : public DoubleInkProcessing, 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::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::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 : public DoubleInkProcessing, 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 +class JumbleInkProcessing : public DoubleInkProcessing, 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::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::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::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 +class ShadingInkProcessing : public DoubleInkProcessing, 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 : public DoubleInkProcessing, 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 +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(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 >, \ + ink_processing_algo >, \ + ink_processing_algo > } + + 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 diff --git a/src/app/tools/inks.h b/src/app/tools/inks.h index 75e0aad38..bff0fce21 100644 --- a/src/app/tools/inks.h +++ b/src/app/tools/inks.h @@ -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) diff --git a/src/app/tools/point_shape.cpp b/src/app/tools/point_shape.cpp index c141261bb..dcad468b5 100644 --- a/src/app/tools/point_shape.cpp +++ b/src/app/tools/point_shape.cpp @@ -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; diff --git a/src/app/tools/tool_loop_manager.cpp b/src/app/tools/tool_loop_manager.cpp index b229ae276..1ea74ca90 100644 --- a/src/app/tools/tool_loop_manager.cpp +++ b/src/app/tools/tool_loop_manager.cpp @@ -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; } diff --git a/src/app/ui/context_bar.cpp b/src/app/ui/context_bar.cpp index a94f0a0ab..a72adfc87 100644 --- a/src/app/ui/context_bar.cpp +++ b/src/app/ui/context_bar.cpp @@ -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(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(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(); } diff --git a/src/app/ui/editor/cursor.cpp b/src/app/ui/editor/cursor.cpp index 2e24efbdc..56001f2c9 100644 --- a/src/app/ui/editor/cursor.cpp +++ b/src/app/ui/editor/cursor.cpp @@ -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); diff --git a/src/app/ui/editor/editor.cpp b/src/app/ui/editor/editor.cpp index 7a8619930..f3c5981de 100644 --- a/src/app/ui/editor/editor.cpp +++ b/src/app/ui/editor/editor.cpp @@ -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; vh; ++v) { - for (u=0; uw; ++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; vgetHeight(); ++v) { + for (u=0; ugetWidth(); ++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; } } diff --git a/src/app/ui/editor/pixels_movement.cpp b/src/app/ui/editor/pixels_movement.cpp index 10b75824e..8b249ee60 100644 --- a/src/app/ui/editor/pixels_movement.cpp +++ b/src/app/ui/editor/pixels_movement.cpp @@ -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::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, diff --git a/src/app/ui/editor/select_box_state.cpp b/src/app/ui/editor/select_box_state.cpp index a78d337d5..257bb524d 100644 --- a/src/app/ui/editor/select_box_state.cpp +++ b/src/app/ui/editor/select_box_state.cpp @@ -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) diff --git a/src/app/ui/editor/standby_state.cpp b/src/app/ui/editor/standby_state.cpp index 9f609090d..bf7f00e09 100644 --- a/src/app/ui/editor/standby_state.cpp +++ b/src/app/ui/editor/standby_state.cpp @@ -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]; diff --git a/src/app/ui/palette_view.cpp b/src/app/ui/palette_view.cpp index 473e0551e..584abc24a 100644 --- a/src/app/ui/palette_view.cpp +++ b/src/app/ui/palette_view.cpp @@ -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); diff --git a/src/app/undoers/flip_image.cpp b/src/app/undoers/flip_image.cpp index 36c703af9..df6302479 100644 --- a/src/app/undoers/flip_image.cpp +++ b/src/app/undoers/flip_image.cpp @@ -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() diff --git a/src/app/undoers/image_area.cpp b/src/app/undoers/image_area.cpp index 3227dd93f..24a5216b0 100644 --- a/src/app/undoers/image_area.cpp +++ b/src/app/undoers/image_area.cpp @@ -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; vgetPixelAddress(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; vgetPixelAddress(m_x, m_y+v), &m_data[m_lineSize*v], m_lineSize); } } // namespace undoers diff --git a/src/app/util/autocrop.cpp b/src/app/util/autocrop.cpp index c99450989..32b76a031 100644 --- a/src/app/util/autocrop.cpp +++ b/src/app/util/autocrop.cpp @@ -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; diff --git a/src/app/util/boundary.cpp b/src/app/util/boundary.cpp index 40b34b51b..e77fc54f9 100644 --- a/src/app/util/boundary.cpp +++ b/src/app/util/boundary.cpp @@ -33,6 +33,7 @@ #include #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 bits(maskPR, gfx::Rect(start, scanline, end - start, 1)); + LockImageBits::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<= 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<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 */ diff --git a/src/app/util/celmove.cpp b/src/app/util/celmove.cpp index 5228dbf38..06800710f 100644 --- a/src/app/util/celmove.cpp +++ b/src/app/util/celmove.cpp @@ -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; diff --git a/src/app/util/clipboard.cpp b/src/app/util/clipboard.cpp index 84fd22563..5e5ad1f9f 100644 --- a/src/app/util/clipboard.cpp +++ b/src/app/util/clipboard.cpp @@ -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 diff --git a/src/app/util/clipboard_win32.h b/src/app/util/clipboard_win32.h index 76b551a91..0e6f1d28c 100644 --- a/src/app/util/clipboard_win32.h +++ b/src/app/util/clipboard_win32.h @@ -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; xw; ++x) { - c = image_getpixel_fast(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; xgetWidth(); ++x) { + c = get_pixel_fast(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; xw; ++x) { - c = image_getpixel_fast(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; xgetWidth(); ++x) { + c = get_pixel_fast(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; isize(); ++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; xw; ++x) { - *(dst++) = image_getpixel_fast(image, x, y); + for (int y=image->getHeight()-1; y>=0; --y) { + for (int x=0; xgetWidth(); ++x) { + *(dst++) = get_pixel_fast(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; xw; ++x) { + for (int x=0; xgetWidth(); ++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; xw; ++x) { + for (int x=0; xgetWidth(); ++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; xw; ++x) { + for (int x=0; xgetWidth(); ++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; xw; ++x) { + for (int y=image->getHeight()-1; y>=0; --y) { + for (int x=0; xgetWidth(); ++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(image, x, y, _rgba(r, g, b, 255)); + put_pixel_fast(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; csetEntry(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; xw; ++x) { + for (int y=image->getHeight()-1; y>=0; --y) { + for (int x=0; xgetWidth(); ++x) { int c = *(src++); - image_putpixel_fast(image, x, y, MID(0, c, colors-1)); + put_pixel_fast(image, x, y, MID(0, c, colors-1)); } src += padding; diff --git a/src/app/util/expand_cel_canvas.cpp b/src/app/util/expand_cel_canvas.cpp index 0bb5296a5..9f9e46dfd 100644 --- a/src/app/util/expand_cel_canvas.cpp +++ b/src/app/util/expand_cel_canvas.cpp @@ -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 diff --git a/src/app/util/misc.cpp b/src/app/util/misc.cpp index cff2323f1..50736d559 100644 --- a/src/app/util/misc.cpp +++ b/src/app/util/misc.cpp @@ -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; vline)[v]+d.quot; + const LockImageBits maskBits(srcMaskBitmap, gfx::Rect(0, 0, srcBounds.w, srcBounds.h)); + LockImageBits::const_iterator mask_it = maskBits.begin(); - for (u=0; u= 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); } } diff --git a/src/app/util/msk_file.cpp b/src/app/util/msk_file.cpp index c7d305510..3755a01fc 100644 --- a/src/app/util/msk_file.cpp +++ b/src/app/util/msk_file.cpp @@ -60,9 +60,8 @@ Mask* load_msk_file(const char* filename) // Just load an Animator Pro PIC file base::UniquePtr 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; diff --git a/src/app/util/pic_file.cpp b/src/app/util/pic_file.cpp index 45ef92261..d7574afbe 100644 --- a/src/app/util/pic_file.cpp +++ b/src/app/util/pic_file.cpp @@ -22,6 +22,7 @@ #include "base/unique_ptr.h" #include "raster/image.h" +#include "raster/primitives.h" #include #include @@ -86,7 +87,7 @@ Image* load_pic_file(const char* filename, int* x, int* y, RGB* palette) for (v=0; vputpixel(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; vputpixel(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; vh; 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; vgetHeight(); 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; vh; v++) /* image data */ - for (u=0; uw; 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; vgetHeight(); v++) // Image data + for (u=0; ugetWidth(); u++) + pack_putc(image->getPixel(u, v), f); } pack_fclose (f); diff --git a/src/app/util/render.cpp b/src/app/util/render.cpp index bd121998b..6d232fc74 100644 --- a/src/app/util/render.cpp +++ b/src/app/util/render.cpp @@ -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 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<h<getWidth()<getHeight()< 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 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= 0 && src_x < src->w); - ASSERT(dst_x >= 0 && dst_x < dst->w); + // Lock all necessary bits + const LockImageBits srcBits(src, gfx::Rect(src_x, src_y, src_w, src_h)); + LockImageBits dstBits(dst, gfx::Rect(dst_x, dst_y, dst_w, dst_h)); + typename LockImageBits::const_iterator src_it = srcBits.begin(), src_end = srcBits.end(); + typename LockImageBits::iterator dst_it, dst_end; - // get addresses to each line (beginning of 'src', 'dst', etc.) - src_address = image_address_fast(src, src_x, src_y); - dst_address = image_address_fast(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= 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= 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(src, src_x, src_y)); - ASSERT(src_address <= image_address_fast(src, src_x+src_w-1, src_y)); - ASSERT(dst_address >= image_address_fast(dst, dst_x, dst_y)); - ASSERT(dst_address <= image_address_fast(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(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 0) { - for (box_x=0; box_x= scanline); - ASSERT(scanline_address < scanline + src_w); - ASSERT(dst_address >= image_address_fast(dst, dst_x, dst_y)); - ASSERT(dst_address <= image_address_fast(dst, dst_x+dst_w-1, dst_y)); - ASSERT(dst_address < dst_address_end); + for (box_x=0; box_x= 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= image_address_fast(dst, dst_x, dst_y)); - ASSERT(dst_address <= image_address_fast(dst, dst_x+dst_w-1, dst_y)); - ASSERT(dst_address < dst_address_end); + for (; x= 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; yh+tile_h; y+=tile_h) { - for (x=x_start-tile_w; xw+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; ygetHeight()+tile_h; y+=tile_h) { + for (x=x_start-tile_w; xgetWidth()+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(layer)->getLayerBegin(); LayerConstIterator end = static_cast(layer)->getLayerEnd(); diff --git a/src/app/util/thmbnail.cpp b/src/app/util/thmbnail.cpp index 182367a3f..d12ed2f6e 100644 --- a/src/app/util/thmbnail.cpp +++ b/src/app/util/thmbnail.cpp @@ -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= 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= 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; } diff --git a/src/base/clamp.h b/src/base/clamp.h new file mode 100644 index 000000000..603d7818c --- /dev/null +++ b/src/base/clamp.h @@ -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 + T clamp(const T& value, const T& low, const T& high) { + return (value > high ? high: + (value < low ? low: + value)); + } + +} // namespace base + +#endif diff --git a/src/filters/color_curve_filter.cpp b/src/filters/color_curve_filter.cpp index ba2ab9970..2ef22d9ee 100644 --- a/src/filters/color_curve_filter.cpp +++ b/src/filters/color_curve_filter.cpp @@ -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]; diff --git a/src/filters/convolution_matrix_filter.cpp b/src/filters/convolution_matrix_filter.cpp index c0c34ef14..55f657ac7 100644 --- a/src/filters/convolution_matrix_filter.cpp +++ b/src/filters/convolution_matrix_filter.cpp @@ -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(src, x, y); + color = get_pixel_fast(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(src, x, y); + color = get_pixel_fast(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(src, x, y); + color = get_pixel_fast(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); } diff --git a/src/filters/invert_color_filter.cpp b/src/filters/invert_color_filter.cpp index d94b81436..09c3e9e71 100644 --- a/src/filters/invert_color_filter.cpp +++ b/src/filters/invert_color_filter.cpp @@ -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; diff --git a/src/filters/median_filter.cpp b/src/filters/median_filter.cpp index bbacce5fb..9abc412ce 100644 --- a/src/filters/median_filter.cpp +++ b/src/filters/median_filter.cpp @@ -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 @@ -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(src, x, y, m_width, m_height, m_width/2, m_height/2, m_tiledMode, delegate); - color = image_getpixel_fast(src, x, y); + color = get_pixel_fast(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(src, x, y, m_width, m_height, m_width/2, m_height/2, m_tiledMode, delegate); - color = image_getpixel_fast(src, x, y); + color = get_pixel_fast(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(src, x, y); + color = get_pixel_fast(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); } diff --git a/src/filters/neighboring_pixels.h b/src/filters/neighboring_pixels.h index bfc4dc981..c13109816 100644 --- a/src/filters/neighboring_pixels.h +++ b/src/filters/neighboring_pixels.h @@ -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; dyw - (-(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(sourceImage, getx, gety); + reinterpret_cast(sourceImage->getPixelAddress(getx, gety)); for (dx=0; dxw-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(sourceImage, getx, gety); + srcAddress = + reinterpret_cast(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 diff --git a/src/filters/replace_color_filter.cpp b/src/filters/replace_color_filter.cpp index 4eb46c9bc..ebacc3370 100644 --- a/src/filters/replace_color_filter.cpp +++ b/src/filters/replace_color_filter.cpp @@ -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; xskipPixel()) { @@ -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; xskipPixel()) { @@ -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)) diff --git a/src/raster/CMakeLists.txt b/src/raster/CMakeLists.txt index 35465184a..d9f314edc 100644 --- a/src/raster/CMakeLists.txt +++ b/src/raster/CMakeLists.txt @@ -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 diff --git a/src/raster/algo.cpp b/src/raster/algo.cpp index 7243686f1..a6c1476a5 100644 --- a/src/raster/algo.cpp +++ b/src/raster/algo.cpp @@ -377,8 +377,8 @@ void algo_ellipsefill(int x1, int y1, int x2, int y2, void *data, AlgoHLine proc } } -/* Algorightm from Allegro (allegro/src/spline.c) - Adapted for ASEPRITE by David A. Capello. */ +// Algorightm from Allegro (allegro/src/spline.c) +// Adapted for Aseprite by David Capello. void algo_spline(double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3, void *data, AlgoLine proc) diff --git a/src/raster/algofill.cpp b/src/raster/algofill.cpp index 61109ae74..8f726623c 100644 --- a/src/raster/algofill.cpp +++ b/src/raster/algofill.cpp @@ -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 #include @@ -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(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; rightw; right++) { + // Work right from starting point + for (right=x+1; rightgetWidth(); 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(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; rightw; right++) { + // Work right from starting point + for (right=x+1; rightgetWidth(); 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; rightw; right++) { + // Work right from starting point + for (right=x+1; rightgetWidth(); 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; rightw; right++) { - if (image_getpixel(image, right, y) != src_color) + // Work right from starting point + for (right=x+1; rightgetWidth(); 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; ch) && (c > 0)) + if ((c < image->getHeight()) && (c > 0)) c -= 2; } } diff --git a/src/raster/algorithm/flip_image.cpp b/src/raster/algorithm/flip_image.cpp index 988480410..0256072b5 100644 --- a/src/raster/algorithm/flip_image.cpp +++ b/src/raster/algorithm/flip_image.cpp @@ -26,6 +26,7 @@ #include "gfx/rect.h" #include "raster/image.h" #include "raster/mask.h" +#include "raster/primitives.h" #include @@ -40,22 +41,22 @@ void flip_image(Image* image, const gfx::Rect& bounds, FlipType flipType) for (int y=bounds.y; ygetRowStrideSize(bounds.w); std::vector tmpline(section_size); int v = bounds.y+bounds.h-1; for (int y=bounds.y; y(image_address(image, bounds.x, y)); - uint8_t* address2 = static_cast(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; ycontainsPoint(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; xcontainsPoint(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); } } } diff --git a/src/raster/algorithm/flip_image.h b/src/raster/algorithm/flip_image.h index 168dc9538..1db43767e 100644 --- a/src/raster/algorithm/flip_image.h +++ b/src/raster/algorithm/flip_image.h @@ -23,7 +23,6 @@ #include "raster/algorithm/flip_type.h" namespace raster { - class Image; class Mask; diff --git a/src/raster/algorithm/resize_image.cpp b/src/raster/algorithm/resize_image.cpp new file mode 100644 index 000000000..b536b9768 --- /dev/null +++ b/src/raster/algorithm/resize_image.cpp @@ -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; ygetHeight(); ++y) { + for (x=0; xgetWidth(); ++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; ygetHeight(); ++y) { + for (x=0; xgetWidth(); ++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 bits(image); + LockImageBits::iterator it = bits.begin(); + + for (y=0; ygetHeight(); ++y) { + for (x=0; xgetWidth(); ++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::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 bits(image); + LockImageBits::iterator it = bits.begin(); + + for (y=0; ygetHeight(); ++y) { + for (x=0; xgetWidth(); ++x, ++it) { + uint16_t c = *it; + + // If this is a completelly-transparent pixel... + if (graya_geta(c) == 0) { + count = 0; + k = 0; + + LockImageBits::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 diff --git a/src/raster/algorithm/resize_image.h b/src/raster/algorithm/resize_image.h new file mode 100644 index 000000000..992798cdb --- /dev/null +++ b/src/raster/algorithm/resize_image.h @@ -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 diff --git a/src/raster/algorithm/shrink_bounds.cpp b/src/raster/algorithm/shrink_bounds.cpp new file mode 100644 index 000000000..d544a3fbb --- /dev/null +++ b/src/raster/algorithm/shrink_bounds.cpp @@ -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; ugetPixelFormat(), 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; vgetPixelFormat(), image->getPixel(u, v), refpixel)) { + shrink = false; + break; + } + } + if (!shrink) + break; + --bounds.w; + } + + // Shrink top side + for (v=bounds.y; vgetPixelFormat(), 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; ugetPixelFormat(), image->getPixel(u, v), refpixel)) { + shrink = false; + break; + } + } + if (!shrink) + break; + --bounds.h; + } + + return (!bounds.isEmpty()); +} + +} // namespace algorithm +} // namespace raster diff --git a/src/raster/algorithm/shrink_bounds.h b/src/raster/algorithm/shrink_bounds.h new file mode 100644 index 000000000..d1f648022 --- /dev/null +++ b/src/raster/algorithm/shrink_bounds.h @@ -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 diff --git a/src/raster/blend.cpp b/src/raster/blend.cpp index 03c639106..8481d14ee 100644 --- a/src/raster/blend.cpp +++ b/src/raster/blend.cpp @@ -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 diff --git a/src/raster/blend.h b/src/raster/blend.h index 74b69719d..4ca1a24df 100644 --- a/src/raster/blend.h +++ b/src/raster/blend.h @@ -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 diff --git a/src/raster/cel.cpp b/src/raster/cel.cpp index 5c9b0ce6a..fb8877217 100644 --- a/src/raster/cel.cpp +++ b/src/raster/cel.cpp @@ -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) { diff --git a/src/raster/cel.h b/src/raster/cel.h index 69384e158..a2ad4a529 100644 --- a/src/raster/cel.h +++ b/src/raster/cel.h @@ -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); diff --git a/src/raster/color.h b/src/raster/color.h new file mode 100644 index 000000000..6b77fa450 --- /dev/null +++ b/src/raster/color.h @@ -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 diff --git a/src/raster/color_histogram.h b/src/raster/color_histogram.h index 5435c82cc..114f366e0 100644 --- a/src/raster/color_histogram.h +++ b/src/raster/color_histogram.h @@ -19,7 +19,9 @@ #ifndef RASTER_COLOR_HISTOGRAM_H_INCLUDED #define RASTER_COLOR_HISTOGRAM_H_INCLUDED +#include #include + #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 diff --git a/src/raster/color_scales.cpp b/src/raster/color_scales.cpp new file mode 100644 index 000000000..39cd3a7e0 --- /dev/null +++ b/src/raster/color_scales.cpp @@ -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 diff --git a/src/raster/color_scales.h b/src/raster/color_scales.h new file mode 100644 index 000000000..31a2dbf7a --- /dev/null +++ b/src/raster/color_scales.h @@ -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 + +namespace raster { + + int scale_5bits_to_8bits(int channel5bits); + int scale_6bits_to_8bits(int channel6bits); + +} // namespace raster + +#endif diff --git a/src/raster/conversion_alleg.cpp b/src/raster/conversion_alleg.cpp new file mode 100644 index 000000000..927e0b32b --- /dev/null +++ b/src/raster/conversion_alleg.cpp @@ -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 + +namespace raster { + +namespace { + +template +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(color_t c, const Palette* palette) { + return makecol8(rgba_getr(c), rgba_getg(c), rgba_getb(c)); +} +template<> +int convert_color_to_allegro(color_t c, const Palette* palette) { + return makecol15(rgba_getr(c), rgba_getg(c), rgba_getb(c)); +} +template<> +int convert_color_to_allegro(color_t c, const Palette* palette) { + return makecol16(rgba_getr(c), rgba_getg(c), rgba_getb(c)); +} +template<> +int convert_color_to_allegro(color_t c, const Palette* palette) { + return makecol24(rgba_getr(c), rgba_getg(c), rgba_getb(c)); +} +template<> +int convert_color_to_allegro(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(color_t c, const Palette* palette) { + return makecol8(graya_getv(c), graya_getv(c), graya_getv(c)); +} +template<> +int convert_color_to_allegro(color_t c, const Palette* palette) { + return makecol15(graya_getv(c), graya_getv(c), graya_getv(c)); +} +template<> +int convert_color_to_allegro(color_t c, const Palette* palette) { + return makecol16(graya_getv(c), graya_getv(c), graya_getv(c)); +} +template<> +int convert_color_to_allegro(color_t c, const Palette* palette) { + return makecol24(graya_getv(c), graya_getv(c), graya_getv(c)); +} +template<> +int convert_color_to_allegro(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(color_t color, const Palette* palette) { + return color; +} +template<> +int convert_color_to_allegro(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(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(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(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(color_t color, const Palette* palette) { + return color; +} +template<> +int convert_color_to_allegro(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(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(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(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 +void convert_image_to_allegro_templ(const Image* image, BITMAP* bmp, int _x, int _y, const Palette* palette) +{ + const LockImageBits bits(image); + typename LockImageBits::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; yline[_y]; + + for (x=0; x>2), + (convert_color_to_allegro(*src_it, palette))); + + ++src_it; + address++; + } + + _y++; + } + } + else { +#endif + for (y=0; y(*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(*src_it, palette))); + + bmp_address += 2; + ++src_it; + } + + _y++; + } + break; + + case 16: + _x <<= 1; + + for (y=0; y(*src_it, palette))); + + bmp_address += 2; + ++src_it; + } + + _y++; + } + break; + + case 24: + _x *= 3; + + for (y=0; y(*src_it, palette))); + + bmp_address += 3; + ++src_it; + } + + _y++; + } + break; + + case 32: + _x <<= 2; + + for (y=0; y(*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(image, bmp, x, y, palette); break; + case IMAGE_GRAYSCALE: convert_image_to_allegro_templ(image, bmp, x, y, palette); break; + case IMAGE_INDEXED: convert_image_to_allegro_templ(image, bmp, x, y, palette); break; + case IMAGE_BITMAP: convert_image_to_allegro_templ(image, bmp, x, y, palette); break; + } +} + +void convert_palette_to_allegro(const Palette* palette, RGB* rgb) +{ + int i; + for (i=0; isize(); ++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 (; iresize(Palette::MaxColors); + for (int i=0; isetEntry(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 diff --git a/src/raster/conversion_alleg.h b/src/raster/conversion_alleg.h new file mode 100644 index 000000000..22e419a81 --- /dev/null +++ b/src/raster/conversion_alleg.h @@ -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 + +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 diff --git a/src/raster/dirty.cpp b/src/raster/dirty.cpp index da7e98abd..a1a490974 100644 --- a/src/raster/dirty.cpp +++ b/src/raster/dirty.cpp @@ -21,7 +21,9 @@ #endif #include "raster/dirty.h" + #include "raster/image.h" +#include "raster/primitives.h" #include @@ -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; yh; y++) { + for (y=0; ygetHeight(); y++) { x1 = -1; - for (x=0; xw; x++) { - if (image_getpixel(image, x, y) != image_getpixel(image_diff, x, y)) { + for (x=0; xgetWidth(); 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()); } } diff --git a/src/raster/dirty.h b/src/raster/dirty.h index 2fa63339a..d949fbdc2 100644 --- a/src/raster/dirty.h +++ b/src/raster/dirty.h @@ -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); diff --git a/src/raster/file/col_file.cpp b/src/raster/file/col_file.cpp index 98d1386ee..e8d383ab8 100644 --- a/src/raster/file/col_file.cpp +++ b/src/raster/file/col_file.cpp @@ -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 #include #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; } diff --git a/src/raster/file/gpl_file.cpp b/src/raster/file/gpl_file.cpp index 0f5c41677..1acda707d 100644 --- a/src/raster/file/gpl_file.cpp +++ b/src/raster/file/gpl_file.cpp @@ -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; isize(); ++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; diff --git a/src/raster/image.cpp b/src/raster/image.cpp index 90555a1c7..0e636a341 100644 --- a/src/raster/image.cpp +++ b/src/raster/image.cpp @@ -20,57 +20,54 @@ #include "config.h" #endif -#include -#include -#include +#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(w, h); - case IMAGE_GRAYSCALE: return new ImageImpl(w, h); - case IMAGE_INDEXED: return new ImageImpl(w, h); - case IMAGE_BITMAP: return new ImageImpl(w, h); + case IMAGE_RGB: return new ImageImpl(width, height); + case IMAGE_GRAYSCALE: return new ImageImpl(width, height); + case IMAGE_INDEXED: return new ImageImpl(width, height); + case IMAGE_BITMAP: return new ImageImpl(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; vclear(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; yh; ++y) - for (x=0; xw; ++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; yh; ++y) - for (x=0; xw; ++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; yh; ++y) - for (x=0; xw; ++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; yh; ++y) { - for (x=0; xw; ++x) { - c = image_getpixel_fast(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(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(image, x, y, _rgba(r, g, b, 0)); - } - } - } - } - break; - } - - case IMAGE_GRAYSCALE: { - uint16_t c; - int k, count; - - for (y=0; yh; ++y) { - for (x=0; xw; ++x) { - c = image_getpixel_fast(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(image, u, v); - if (_graya_geta(c) > 0) { - k += _graya_getv(c); - ++count; - } - } - } - } - - if (count > 0) { - k /= count; - image_putpixel_fast(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; yh; ++y) { - for (x=0; xw; ++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; yh; ++y) { - for (x=0; xw; ++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; cdat; - uint16_t* address2 = (uint16_t*)i2->dat; - for (c=0; cdat; - uint8_t* address2 = (uint8_t*)i2->dat; - for (c=0; cdat; - uint8_t* address2 = (uint8_t*)i2->dat; - div_t d1 = div (0, 8); - div_t d2 = div (0, 8); - for (c=0; cw, image->h); - - // Shrink left side - for (u=bounds.x; ugetPixelFormat(), 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; vgetPixelFormat(), image->getpixel(u, v), refpixel)) { - shrink = false; - break; - } - } - if (!shrink) - break; - --bounds.w; - } - - // Shrink top side - for (v=bounds.y; vgetPixelFormat(), 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; ugetPixelFormat(), 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 diff --git a/src/raster/image.h b/src/raster/image.h index afee0d2ea..c0cea2d74 100644 --- a/src/raster/image.h +++ b/src/raster/image.h @@ -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 - -struct BITMAP; - namespace raster { + template 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 + ImageBits lockBits(LockType lockType, const gfx::Rect& bounds) { + return ImageBits(this, bounds); + } + + template + ImageBits lockBits(LockType lockType, const gfx::Rect& bounds) const { + return ImageBits(const_cast(this), bounds); + } + + template + void unlockBits(ImageBits& 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 diff --git a/src/raster/image_bits.h b/src/raster/image_bits.h new file mode 100644 index 000000000..04c7feecc --- /dev/null +++ b/src/raster/image_bits.h @@ -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 + class ImageBits { + public: + typedef typename ImageTraits::address_t address_t; + typedef ImageIterator iterator; + typedef ImageConstIterator 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 + class LockImageBits { + public: + typedef ImageBits Bits; + typedef typename Bits::iterator iterator; + typedef typename Bits::const_iterator const_iterator; + + explicit LockImageBits(const Image* image) + : m_bits(image->lockBits(Image::ReadLock, image->getBounds())) { + } + + LockImageBits(const Image* image, const gfx::Rect& bounds) + : m_bits(image->lockBits(Image::ReadLock, bounds)) { + } + + LockImageBits(Image* image, Image::LockType lockType) + : m_bits(image->lockBits(lockType, image->getBounds())) { + } + + LockImageBits(Image* image, Image::LockType lockType, const gfx::Rect& bounds) + : m_bits(image->lockBits(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 diff --git a/src/raster/image_impl.h b/src/raster/image_impl.h index c70b2a127..c4d5415bb 100644 --- a/src/raster/image_impl.h +++ b/src/raster/image_impl.h @@ -21,79 +21,97 @@ #include "raster/blend.h" #include "raster/image.h" +#include "raster/image_bits.h" +#include "raster/image_iterator.h" #include "raster/palette.h" namespace raster { template class ImageImpl : public Image { + private: typedef typename Traits::address_t address_t; typedef typename Traits::const_address_t const_address_t; - public: // raw access to pixel-data + address_t m_bits; // Pixmap data. + address_t* m_rows; // Start of each scanline. - inline address_t raw_pixels() { - return (address_t)dat; + inline address_t getBitsAddress() { + return m_bits; } - inline const_address_t raw_pixels() const { - return (address_t)dat; + inline const_address_t getBitsAddress() const { + return m_bits; } - inline address_t line_address(int y) { - ASSERT(y >= 0 && y < h); - return ((address_t*)line)[y]; + inline address_t getLineAddress(int y) { + ASSERT(y >= 0 && y < getHeight()); + return m_rows[y]; } - inline const_address_t line_address(int y) const { - ASSERT(y >= 0 && y < h); - return ((const_address_t*)line)[y]; + inline const_address_t getLineAddress(int y) const { + ASSERT(y >= 0 && y < getHeight()); + return m_rows[y]; } public: - - ImageImpl(int w, int h) - : Image(static_cast(Traits::pixel_format), w, h) + ImageImpl(int width, int height) + : Image(static_cast(Traits::pixel_format), width, height) { - int bytes_per_line = Traits::scanline_size(w); + int rowstrideBytes = Traits::getRowStrideBytes(width); - dat = new uint8_t[bytes_per_line*h]; + m_bits = (address_t)new uint8_t[rowstrideBytes * height]; try { - line = (uint8_t**)new address_t*[h]; + m_rows = new address_t[height]; } catch (...) { - delete[] dat; + delete[] m_bits; throw; } - address_t addr = raw_pixels(); - for (int y=0; y(this, x, y); + ~ImageImpl() { + if (m_bits) delete[] m_bits; + if (m_rows) delete[] m_rows; } - virtual void putpixel(int x, int y, int color) - { - image_putpixel_fast(this, x, y, color); + uint8_t* getPixelAddress(int x, int y) const OVERRIDE { + ASSERT(x >= 0 && x < getWidth()); + ASSERT(y >= 0 && y < getHeight()); + + return (uint8_t*)(m_rows[y] + x); } - virtual void clear(int color) - { - address_t addr = raw_pixels(); - unsigned int c, size = w*h; + color_t getPixel(int x, int y) const OVERRIDE { + ASSERT(x >= 0 && x < getWidth()); + ASSERT(y >= 0 && y < getHeight()); - for (c=0; c= 0 && x < getWidth()); + ASSERT(y >= 0 && y < getHeight()); + + *(address_t)getPixelAddress(x, y) = color; + } + + void clear(color_t color) OVERRIDE { + LockImageBits bits(this); + LockImageBits::iterator it(bits.begin()); + LockImageBits::iterator end(bits.end()); + + for (; it != end; ++it) + *it = color; + } + + void copy(const Image* src, int x, int y) OVERRIDE { Image* dst = this; address_t src_address; address_t dst_address; @@ -101,18 +119,18 @@ namespace raster { int ybeg, yend, ysrc, ydst; int bytes; - // clipping + // Clipping xsrc = 0; ysrc = 0; xbeg = x; ybeg = y; - xend = x+src->w-1; - yend = y+src->h-1; + xend = x+src->getWidth()-1; + yend = y+src->getHeight()-1; - if ((xend < 0) || (xbeg >= dst->w) || - (yend < 0) || (ybeg >= dst->h)) + if ((xend < 0) || (xbeg >= dst->getWidth()) || + (yend < 0) || (ybeg >= dst->getHeight())) return; if (xbeg < 0) { @@ -125,28 +143,27 @@ namespace raster { ybeg = 0; } - if (xend >= dst->w) - xend = dst->w-1; + if (xend >= dst->getWidth()) + xend = dst->getWidth()-1; - if (yend >= dst->h) - yend = dst->h-1; + if (yend >= dst->getHeight()) + yend = dst->getHeight()-1; - // copy process + // Copy process - bytes = Traits::scanline_size(xend - xbeg + 1); + bytes = Traits::getRowStrideBytes(xend - xbeg + 1); - for (ydst=ybeg; ydst<=yend; ydst++, ysrc++) { - src_address = ((ImageImpl*)src)->line_address(ysrc)+xsrc; - dst_address = ((ImageImpl*)dst)->line_address(ydst)+xbeg; + for (ydst=ybeg; ydst<=yend; ++ydst, ++ysrc) { + src_address = (address_t)src->getPixelAddress(xsrc, ysrc); + dst_address = (address_t)dst->getPixelAddress(xbeg, ydst); memcpy(dst_address, src_address, bytes); } } - virtual void merge(const Image* src, int x, int y, int opacity, int blend_mode) - { + void merge(const Image* src, int x, int y, int opacity, int blend_mode) OVERRIDE { BLEND_COLOR blender = Traits::get_blender(blend_mode); - register uint32_t mask_color = src->mask_color; + register uint32_t mask_color = src->getMaskColor(); Image* dst = this; address_t src_address; address_t dst_address; @@ -164,11 +181,11 @@ namespace raster { xbeg = x; ybeg = y; - xend = x+src->w-1; - yend = y+src->h-1; + xend = x+src->getWidth()-1; + yend = y+src->getHeight()-1; - if ((xend < 0) || (xbeg >= dst->w) || - (yend < 0) || (ybeg >= dst->h)) + if ((xend < 0) || (xbeg >= dst->getWidth()) || + (yend < 0) || (ybeg >= dst->getHeight())) return; if (xbeg < 0) { @@ -181,84 +198,92 @@ namespace raster { ybeg = 0; } - if (xend >= dst->w) - xend = dst->w-1; + if (xend >= dst->getWidth()) + xend = dst->getWidth()-1; - if (yend >= dst->h) - yend = dst->h-1; + if (yend >= dst->getHeight()) + yend = dst->getHeight()-1; - // merge process + // Merge process - for (ydst=ybeg; ydst<=yend; ydst++, ysrc++) { - src_address = ((ImageImpl*)src)->line_address(ysrc)+xsrc; - dst_address = ((ImageImpl*)dst)->line_address(ydst)+xbeg; + for (ydst=ybeg; ydst<=yend; ++ydst, ++ysrc) { + src_address = (address_t)src->getPixelAddress(xsrc, ysrc); + dst_address = (address_t)dst->getPixelAddress(xbeg, ydst); - for (xdst=xbeg; xdst<=xend; xdst++) { + for (xdst=xbeg; xdst<=xend; ++xdst) { if (*src_address != mask_color) *dst_address = (*blender)(*dst_address, *src_address, opacity); - dst_address++; - src_address++; + ++dst_address; + ++src_address; } } } - virtual void hline(int x1, int y, int x2, int color) - { - address_t addr = line_address(y)+x1; + void drawHLine(int x1, int y, int x2, color_t color) OVERRIDE { + LockImageBits bits(this, gfx::Rect(x1, y, x2 - x1 + 1, 1)); + LockImageBits::iterator it(bits.begin()); + LockImageBits::iterator end(bits.end()); - for (int x=x1; x<=x2; ++x) - *(addr++) = color; + for (; it != end; ++it) + *it = color; } - virtual void rectfill(int x1, int y1, int x2, int y2, int color) - { - address_t addr; - int x, y; - - for (y=y1; y<=y2; ++y) { - addr = line_address(y)+x1; - for (x=x1; x<=x2; ++x) - *(addr++) = color; - } + void fillRect(int x1, int y1, int x2, int y2, color_t color) OVERRIDE { + for (int y=y1; y<=y2; ++y) + ImageImpl::drawHLine(x1, y, x2, color); } - virtual void rectblend(int x1, int y1, int x2, int y2, int color, int opacity) - { - rectfill(x1, y1, x2, y2, color); + void blendRect(int x1, int y1, int x2, int y2, color_t color, int opacity) OVERRIDE { + fillRect(x1, y1, x2, y2, color); } - - virtual void to_allegro(BITMAP* bmp, int x, int y, const Palette* palette) const; - }; ////////////////////////////////////////////////////////////////////// // Specializations template<> - void ImageImpl::rectblend(int x1, int y1, int x2, int y2, int color, int opacity) - { + inline uint8_t* ImageImpl::getPixelAddress(int x, int y) const { + return (uint8_t*)(m_rows[y] + x/8); + } + + template<> + inline color_t ImageImpl::getPixel(int x, int y) const { + ASSERT(x >= 0 && x < getWidth()); + ASSERT(y >= 0 && y < getHeight()); + + div_t d = div(x, 8); + return ((*(m_rows[y] + d.quot)) & (1< + inline void ImageImpl::putPixel(int x, int y, color_t color) { + ASSERT(x >= 0 && x < getWidth()); + ASSERT(y >= 0 && y < getHeight()); + + div_t d = div(x, 8); + if (color) + (*(m_rows[y] + d.quot)) |= (1 << d.rem); + else + (*(m_rows[y] + d.quot)) &= ~(1 << d.rem); + } + + template<> + inline void ImageImpl::blendRect(int x1, int y1, int x2, int y2, color_t color, int opacity) { address_t addr; int x, y; for (y=y1; y<=y2; ++y) { - addr = line_address(y)+x1; + addr = (address_t)getPixelAddress(x1, y); for (x=x1; x<=x2; ++x) { - *addr = _rgba_blend_normal(*addr, color, opacity); + *addr = rgba_blend_normal(*addr, color, opacity); ++addr; } } } template<> - void ImageImpl::clear(int color) - { - memset(raw_pixels(), color, w*h); - } - - template<> - void ImageImpl::merge(const Image* src, int x, int y, int opacity, int blend_mode) - { + inline void ImageImpl::merge(const Image* src, int x, int y, int opacity, int blend_mode) { Image* dst = this; address_t src_address; address_t dst_address; @@ -272,11 +297,11 @@ namespace raster { xbeg = x; ybeg = y; - xend = x+src->w-1; - yend = y+src->h-1; + xend = x+src->getWidth()-1; + yend = y+src->getHeight()-1; - if ((xend < 0) || (xbeg >= dst->w) || - (yend < 0) || (ybeg >= dst->h)) + if ((xend < 0) || (xbeg >= dst->getWidth()) || + (yend < 0) || (ybeg >= dst->getHeight())) return; if (xbeg < 0) { @@ -289,107 +314,52 @@ namespace raster { ybeg = 0; } - if (xend >= dst->w) - xend = dst->w-1; + if (xend >= dst->getWidth()) + xend = dst->getWidth()-1; - if (yend >= dst->h) - yend = dst->h-1; + if (yend >= dst->getHeight()) + yend = dst->getHeight()-1; // merge process // direct copy if (blend_mode == BLEND_MODE_COPY) { - for (ydst=ybeg; ydst<=yend; ydst++, ysrc++) { - src_address = ((ImageImpl*)src)->line_address(ysrc)+xsrc; - dst_address = ((ImageImpl*)dst)->line_address(ydst)+xbeg; + for (ydst=ybeg; ydst<=yend; ++ydst, ++ysrc) { + src_address = src->getPixelAddress(xsrc, ysrc); + dst_address = dst->getPixelAddress(xbeg, ydst); for (xdst=xbeg; xdst<=xend; xdst++) { *dst_address = (*src_address); - dst_address++; - src_address++; + ++dst_address; + ++src_address; } } } // with mask else { - register int mask_color = src->mask_color; + register int mask_color = src->getMaskColor(); - for (ydst=ybeg; ydst<=yend; ydst++, ysrc++) { - src_address = ((ImageImpl*)src)->line_address(ysrc)+xsrc; - dst_address = ((ImageImpl*)dst)->line_address(ydst)+xbeg; + for (ydst=ybeg; ydst<=yend; ++ydst, ++ysrc) { + src_address = src->getPixelAddress(xsrc, ysrc); + dst_address = dst->getPixelAddress(xbeg, ydst); - for (xdst=xbeg; xdst<=xend; xdst++) { + for (xdst=xbeg; xdst<=xend; ++xdst) { if (*src_address != mask_color) *dst_address = (*src_address); - dst_address++; - src_address++; + ++dst_address; + ++src_address; } } } } template<> - void ImageImpl::clear(int color) - { - memset(raw_pixels(), color ? 0xff: 0x00, ((w+7)/8) * h); - } - -#define BITMAP_HLINE(op) \ - for (x=x1; x<=x2; x++) { \ - *addr op (1< - void ImageImpl::hline(int x1, int y, int x2, int color) - { - div_t d = div(x1, 8); - address_t addr = line_address(y)+d.quot; - int x; - - if (color) { - BITMAP_HLINE( |= ); - } - else { - BITMAP_HLINE( &= ~ ); - } - } - - template<> - void ImageImpl::rectfill(int x1, int y1, int x2, int y2, int color) - { - div_t d, beg_d = div(x1, 8); - address_t addr; - int x, y; - - if (color) { - for (y=y1; y<=y2; y++) { - d = beg_d; - addr = line_address(y)+d.quot; - BITMAP_HLINE( |= ); - } - } - else { - for (y=y1; y<=y2; y++) { - d = beg_d; - addr = line_address(y)+d.quot; - BITMAP_HLINE( &= ~ ); - } - } - } - - template<> - void ImageImpl::copy(const Image* src, int x, int y) - { + inline void ImageImpl::copy(const Image* src, int x, int y) { Image* dst = this; - address_t src_address; - address_t dst_address; int xbeg, xend, xsrc, xdst; int ybeg, yend, ysrc, ydst; - div_t src_d, src_beg_d; - div_t dst_d, dst_beg_d; // clipping @@ -398,11 +368,11 @@ namespace raster { xbeg = x; ybeg = y; - xend = x+src->w-1; - yend = y+src->h-1; + xend = x+src->getWidth()-1; + yend = y+src->getHeight()-1; - if ((xend < 0) || (xbeg >= dst->w) || - (yend < 0) || (ybeg >= dst->h)) + if ((xend < 0) || (xbeg >= dst->getWidth()) || + (yend < 0) || (ybeg >= dst->getHeight())) return; if (xbeg < 0) { @@ -415,46 +385,33 @@ namespace raster { ybeg = 0; } - if (xend >= dst->w) - xend = dst->w-1; + if (xend >= dst->getWidth()) + xend = dst->getWidth()-1; - if (yend >= dst->h) - yend = dst->h-1; + if (yend >= dst->getHeight()) + yend = dst->getHeight()-1; // copy process - src_beg_d = div(xsrc, 8); - dst_beg_d = div(xbeg, 8); + int w = xend - xbeg + 1; + int h = yend - ybeg + 1; + ImageConstIterator src_it(src, gfx::Rect(xsrc, ysrc, w, h), xsrc, ysrc); + ImageIterator dst_it(dst, gfx::Rect(xbeg, ybeg, w, h), xbeg, ybeg); - for (ydst=ybeg; ydst<=yend; ydst++, ysrc++) { - src_d = src_beg_d; - dst_d = dst_beg_d; - - src_address = ((ImageImpl*)src)->line_address(ysrc)+src_d.quot; - dst_address = ((ImageImpl*)dst)->line_address(ydst)+dst_d.quot; - - for (xdst=xbeg; xdst<=xend; xdst++) { - if ((*src_address & (1< - void ImageImpl::merge(const Image* src, int x, int y, int opacity, int blend_mode) - { + inline void ImageImpl::merge(const Image* src, int x, int y, int opacity, int blend_mode) { Image* dst = this; - address_t src_address; - address_t dst_address; int xbeg, xend, xsrc, xdst; int ybeg, yend, ysrc, ydst; - div_t src_d, src_beg_d; - div_t dst_d, dst_beg_d; // clipping @@ -463,11 +420,11 @@ namespace raster { xbeg = x; ybeg = y; - xend = x+src->w-1; - yend = y+src->h-1; + xend = x+src->getWidth()-1; + yend = y+src->getHeight()-1; - if ((xend < 0) || (xbeg >= dst->w) || - (yend < 0) || (ybeg >= dst->h)) + if ((xend < 0) || (xbeg >= dst->getWidth()) || + (yend < 0) || (ybeg >= dst->getHeight())) return; if (xbeg < 0) { @@ -480,551 +437,29 @@ namespace raster { ybeg = 0; } - if (xend >= dst->w) - xend = dst->w-1; + if (xend >= dst->getWidth()) + xend = dst->getWidth()-1; - if (yend >= dst->h) - yend = dst->h-1; + if (yend >= dst->getHeight()) + yend = dst->getHeight()-1; - // copy process + // merge process - src_beg_d = div(xsrc, 8); - dst_beg_d = div(xbeg, 8); + int w = xend - xbeg + 1; + int h = yend - ybeg + 1; + ImageConstIterator src_it(src, gfx::Rect(xsrc, ysrc, w, h), xsrc, ysrc); + ImageIterator dst_it(dst, gfx::Rect(xbeg, ybeg, w, h), xbeg, ybeg); - for (ydst=ybeg; ydst<=yend; ydst++, ysrc++) { - src_d = src_beg_d; - dst_d = dst_beg_d; - - src_address = ((ImageImpl*)src)->line_address(ysrc)+src_d.quot; - dst_address = ((ImageImpl*)dst)->line_address(ydst)+dst_d.quot; - - for (xdst=xbeg; xdst<=xend; xdst++) { - if ((*src_address & (1< - void ImageImpl::to_allegro(BITMAP *bmp, int _x, int _y, const Palette* palette) const - { - const_address_t addr = raw_pixels(); - unsigned long bmp_address; - int depth = bitmap_color_depth(bmp); - int x, y; - - bmp_select(bmp); - - switch (depth) { - - case 8: -#if defined GFX_MODEX && !defined ALLEGRO_UNIX && !defined ALLEGRO_MACOSX - if (is_planar_bitmap(bmp)) { - for (y=0; yline[_y]; - - for (x=0; xw; x++) { - outportw(0x3C4, (0x100<<((_x+x)&3))|2); - bmp_write8(bmp_address+((_x+x)>>2), - makecol8((*addr) & 0xff, - ((*addr)>>8) & 0xff, - ((*addr)>>16) & 0xff)); - addr++; - } - - _y++; - } - } - else { -#endif - for (y=0; y>8) & 0xff, - ((*addr)>>16) & 0xff)); - addr++; - bmp_address++; - } - - _y++; - } -#if defined GFX_MODEX && !defined ALLEGRO_UNIX && !defined ALLEGRO_MACOSX - } -#endif - break; - - case 15: - _x <<= 1; - - for (y=0; y>8) & 0xff, - ((*addr)>>16) & 0xff)); - addr++; - bmp_address += 2; - } - - _y++; - } - break; - - case 16: - _x <<= 1; - - for (y=0; y>8) & 0xff, - ((*addr)>>16) & 0xff)); - addr++; - bmp_address += 2; - } - - _y++; - } - break; - - case 24: - _x *= 3; - - for (y=0; y>8) & 0xff, - ((*addr)>>16) & 0xff)); - addr++; - bmp_address += 3; - } - - _y++; - } - break; - - case 32: - _x <<= 2; - - for (y=0; y>8) & 0xff, - ((*addr)>>16) & 0xff, - ((*addr)>>24) & 0xff)); - addr++; - bmp_address += 4; - } - - _y++; - } - break; - } - - bmp_unwrite_line(bmp); - } - - template<> - void ImageImpl::to_allegro(BITMAP *bmp, int _x, int _y, const Palette* palette) const - { - const_address_t addr = raw_pixels(); - unsigned long bmp_address; - int depth = bitmap_color_depth(bmp); - int x, y; - - bmp_select(bmp); - - switch (depth) { - - case 8: -#if defined GFX_MODEX && !defined ALLEGRO_UNIX && !defined ALLEGRO_MACOSX - if (is_planar_bitmap(bmp)) { - for (y=0; yline[_y]; - - for (x=0; x>2), (*addr) & 0xff); - addr++; - } - - _y++; - } - } - else { -#endif - for (y=0; y - void ImageImpl::to_allegro(BITMAP *bmp, int _x, int _y, const Palette* palette) const - { - const_address_t addr = raw_pixels(); - unsigned long bmp_address; - int depth = bitmap_color_depth(bmp); - int x, y; - uint32_t c; - - 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; yline[_y]; - - for (x=0; x>2), (*addr)); - address++; - } - - _y++; - } - } - else { -#endif - for (y=0; ygetEntry(*addr); - bmp_write15(bmp_address, makecol15(_rgba_getr(c), _rgba_getg(c), _rgba_getb(c))); - addr++; - bmp_address += 2; - } - - _y++; - } - break; - - case 16: - _x <<= 1; - - for (y=0; ygetEntry(*addr); - bmp_write16(bmp_address, makecol16(_rgba_getr(c), _rgba_getg(c), _rgba_getb(c))); - addr++; - bmp_address += 2; - } - - _y++; - } - break; - - case 24: - _x *= 3; - - for (y=0; ygetEntry(*addr); - bmp_write24(bmp_address, makecol24(_rgba_getr(c), _rgba_getg(c), _rgba_getb(c))); - addr++; - bmp_address += 3; - } - - _y++; - } - break; - - case 32: - _x <<= 2; - - for (y=0; ygetEntry(*addr); - bmp_write32(bmp_address, makeacol32(_rgba_getr(c), _rgba_getg(c), _rgba_getb(c), 255)); - addr++; - bmp_address += 4; - } - - _y++; - } - break; - } - - bmp_unwrite_line(bmp); - } - - template<> - void ImageImpl::to_allegro(BITMAP *bmp, int _x, int _y, const Palette* palette) const - { - const_address_t addr; - unsigned long bmp_address; - int depth = bitmap_color_depth(bmp); - div_t d, beg_d = div(0, 8); - int color[2]; - int x, y; - - bmp_select(bmp); - - switch (depth) { - - case 8: - color[0] = makecol8(0, 0, 0); - color[1] = makecol8(255, 255, 255); - -#if defined GFX_MODEX && !defined ALLEGRO_UNIX && !defined ALLEGRO_MACOSX - if (is_planar_bitmap(bmp)) { - for (y=0; yline[_y]; - - d = beg_d; - for (x=0; x>2), - color[((*addr) & (1<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; ch; c++) - os.write((char*)image->line[c], size); + int size = image->getRowStrideSize(); + for (int c=0; cgetHeight(); 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::create(static_cast(pixelFormat), width, height)); - int size = image_line_size(image, image->w); + int size = image->getRowStrideSize(); - for (int c=0; ch; c++) - is.read((char*)image->line[c], size); + for (int c=0; cgetHeight(); c++) + is.read((char*)image->getPixelAddress(0, c), size); - image->mask_color = maskColor; + image->setMaskColor(maskColor); return image.release(); } diff --git a/src/raster/image_iterator.h b/src/raster/image_iterator.h new file mode 100644 index 000000000..680849355 --- /dev/null +++ b/src/raster/image_iterator.h @@ -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 +#include + +#include + +namespace raster { + + template + class ImageIteratorT : public std::iterator { + 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)) + , 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 + class ImageIterator : public ImageIteratorT { + 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(image, bounds, x, y) { + } + }; + + template + class ImageConstIterator : public ImageIteratorT { + 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(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(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 + class ImageIteratorT + : public std::iterator { + 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)) + , 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 : public ImageIteratorT { + public: + ImageIterator() { + } + + ImageIterator(const Image* image, const gfx::Rect& bounds, int x, int y) : + ImageIteratorT(image, bounds, x, y) { + } + }; + + template<> + class ImageConstIterator : public ImageIteratorT { + public: + ImageConstIterator() { + } + + ImageConstIterator(const Image* image, const gfx::Rect& bounds, int x, int y) : + ImageIteratorT(image, bounds, x, y) { + } + }; + +} // namespace raster + +#endif diff --git a/src/raster/image_traits.h b/src/raster/image_traits.h index 75f153c74..8b8b2be6d 100644 --- a/src/raster/image_traits.h +++ b/src/raster/image_traits.h @@ -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 - 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 - 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 - 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(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< - inline void image_putpixel_fast(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<line)[y]+d.quot) &= ~(1< + +#include "base/unique_ptr.h" +#include "raster/image.h" +#include "raster/image_bits.h" +#include "raster/primitives.h" + +using namespace base; +using namespace raster; + +template +class ImageAllTypes : public testing::Test { +protected: + ImageAllTypes() { } +}; + +typedef testing::Types ImageAllTraits; +TYPED_TEST_CASE(ImageAllTypes, ImageAllTraits); + +TYPED_TEST(ImageAllTypes, PutGetAndIterators) +{ + typedef TypeParam ImageTraits; + + std::vector lengths; + lengths.push_back(1); + lengths.push_back(4); + lengths.push_back(7); + lengths.push_back(8); + lengths.push_back(9); + lengths.push_back(15); + lengths.push_back(16); + lengths.push_back(17); + lengths.push_back(31); + lengths.push_back(32); + lengths.push_back(33); + + std::vector sizes; + for (size_t i=0; i::iterator sizes_it=sizes.begin(); sizes_it!=sizes.end(); ++sizes_it) { + int w = sizes_it->w; + int h = sizes_it->h; + UniquePtr image(Image::create(ImageTraits::pixel_format, w, h)); + std::vector data(w*h); + + for (int y=0; y areas; + + // Read-only iterator (whole image) + { + const LockImageBits bits((const Image*)image); + typename LockImageBits::const_iterator + begin = bits.begin(), + it = begin, + end = bits.end(); + + for (int i=0; it != end; ++it, ++i) { + assert(data[i] == *it); + ASSERT_EQ(data[i], *it); + } + } + + // Read-only iterator (areas) + for (int i=0; ; ++i) { + gfx::Rect bounds(i, i, w-i*2, h-i*2); + if (bounds.w <= 0 || bounds.h <= 0) + break; + + const LockImageBits bits((const Image*)image, bounds); + typename LockImageBits::const_iterator + begin = bits.begin(), + it = begin, + end = bits.end(); + + for (int y=bounds.y; y bits(image, Image::WriteLock); + typename LockImageBits::iterator + begin = bits.begin(), + it = begin, + end = bits.end(); + + for (int i=0; it != end; ++it, ++i) { + *it = 1; + EXPECT_EQ(1, *it); + } + + it = begin; + for (int i=0; it != end; ++it, ++i) { + EXPECT_EQ(1, *it); + } + } + } +} + +TEST(Image, DiffRgbImages) +{ + UniquePtr a(Image::create(IMAGE_RGB, 32, 32)); + UniquePtr b(Image::create(IMAGE_RGB, 32, 32)); + + clear_image(a, rgba(0, 0, 0, 0)); + clear_image(b, rgba(0, 0, 0, 0)); + + ASSERT_EQ(0, count_diff_between_images(a, b)); + + put_pixel(a, 0, 0, rgba(255, 0, 0, 0)); + ASSERT_EQ(1, count_diff_between_images(a, b)); + + put_pixel(a, 1, 1, rgba(0, 0, 255, 0)); + ASSERT_EQ(2, count_diff_between_images(a, b)); +} + +TYPED_TEST(ImageAllTypes, DrawHLine) +{ + typedef TypeParam ImageTraits; + + std::vector lengths; + lengths.push_back(7); + lengths.push_back(8); + lengths.push_back(9); + lengths.push_back(15); + lengths.push_back(16); + lengths.push_back(17); + lengths.push_back(31); + lengths.push_back(32); + lengths.push_back(33); + + std::vector sizes; + for (size_t i=0; i::iterator sizes_it=sizes.begin(); sizes_it!=sizes.end(); ++sizes_it) { + int w = sizes_it->w; + int h = sizes_it->h; + UniquePtr image(Image::create(ImageTraits::pixel_format, w, h)); + image->clear(0); + + for (int c=0; c<100; ++c) { + int x = rand() % w; + int y = rand() % h; + int x2 = x + (rand() % (w-x)); + image->drawHLine(x, y, x2, rand() % ImageTraits::max_value); + } + } +} + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/src/raster/images_collector.cpp b/src/raster/images_collector.cpp index f9f3367be..43421806e 100644 --- a/src/raster/images_collector.cpp +++ b/src/raster/images_collector.cpp @@ -50,9 +50,9 @@ void ImagesCollector::collectFromLayer(Layer* layer, FrameNumber frame) if (m_forWrite && !layer->isWritable()) return; - switch (layer->getType()) { + switch (layer->type()) { - case GFXOBJ_LAYER_IMAGE: { + case OBJECT_LAYER_IMAGE: { if (m_allFrames) { for (FrameNumber frame(0); framegetTotalFrames(); ++frame) { Cel* cel = static_cast(layer)->getCel(frame); @@ -68,7 +68,7 @@ void ImagesCollector::collectFromLayer(Layer* layer, FrameNumber frame) break; } - case GFXOBJ_LAYER_FOLDER: { + case OBJECT_LAYER_FOLDER: { LayerIterator it = static_cast(layer)->getLayerBegin(); LayerIterator end = static_cast(layer)->getLayerEnd(); diff --git a/src/raster/layer.cpp b/src/raster/layer.cpp index 38ec02c1b..b85411869 100644 --- a/src/raster/layer.cpp +++ b/src/raster/layer.cpp @@ -25,6 +25,7 @@ #include "raster/blend.h" #include "raster/cel.h" #include "raster/image.h" +#include "raster/primitives.h" #include "raster/sprite.h" #include "raster/stock.h" @@ -33,10 +34,10 @@ namespace raster { -Layer::Layer(GfxObjType type, Sprite* sprite) - : GfxObj(type) +Layer::Layer(ObjectType type, Sprite* sprite) + : Object(type) { - ASSERT(type == GFXOBJ_LAYER_IMAGE || type == GFXOBJ_LAYER_FOLDER); + ASSERT(type == OBJECT_LAYER_IMAGE || type == OBJECT_LAYER_FOLDER); setName("Layer"); @@ -92,7 +93,7 @@ Layer* Layer::getNext() const // LayerImage class LayerImage::LayerImage(Sprite* sprite) - : Layer(GFXOBJ_LAYER_IMAGE, sprite) + : Layer(OBJECT_LAYER_IMAGE, sprite) { } @@ -215,7 +216,7 @@ void LayerImage::configureAsBackground() // LayerFolder class LayerFolder::LayerFolder(Sprite* sprite) - : Layer(GFXOBJ_LAYER_FOLDER, sprite) + : Layer(OBJECT_LAYER_FOLDER, sprite) { setName("Layer Set"); } @@ -304,9 +305,9 @@ void layer_render(const Layer* layer, Image* image, int x, int y, FrameNumber fr if (!layer->isReadable()) return; - switch (layer->getType()) { + switch (layer->type()) { - case GFXOBJ_LAYER_IMAGE: { + case OBJECT_LAYER_IMAGE: { const Cel* cel = static_cast(layer)->getCel(frame); Image* src_image; @@ -317,18 +318,18 @@ void layer_render(const Layer* layer, Image* image, int x, int y, FrameNumber fr src_image = layer->getSprite()->getStock()->getImage(cel->getImage()); ASSERT(src_image != NULL); - src_image->mask_color = layer->getSprite()->getTransparentColor(); + src_image->setMaskColor(layer->getSprite()->getTransparentColor()); - image_merge(image, src_image, - cel->getX() + x, - cel->getY() + y, - MID (0, cel->getOpacity(), 255), - static_cast(layer)->getBlendMode()); + composite_image(image, src_image, + cel->getX() + x, + cel->getY() + y, + MID (0, cel->getOpacity(), 255), + static_cast(layer)->getBlendMode()); } break; } - case GFXOBJ_LAYER_FOLDER: { + case OBJECT_LAYER_FOLDER: { LayerConstIterator it = static_cast(layer)->getLayerBegin(); LayerConstIterator end = static_cast(layer)->getLayerEnd(); diff --git a/src/raster/layer.h b/src/raster/layer.h index 9380f77ec..ca3024d11 100644 --- a/src/raster/layer.h +++ b/src/raster/layer.h @@ -21,7 +21,7 @@ #include "raster/blend.h" #include "raster/frame_number.h" -#include "raster/gfxobj.h" +#include "raster/object.h" #include @@ -44,9 +44,9 @@ namespace raster { LAYER_IS_BACKGROUND = 0x0008, }; - class Layer : public GfxObj { + class Layer : public Object { protected: - Layer(GfxObjType type, Sprite* sprite); + Layer(ObjectType type, Sprite* sprite); public: virtual ~Layer(); @@ -64,8 +64,8 @@ namespace raster { Layer* getPrevious() const; Layer* getNext() const; - bool isImage() const { return getType() == GFXOBJ_LAYER_IMAGE; } - bool isFolder() const { return getType() == GFXOBJ_LAYER_FOLDER; } + bool isImage() const { return type() == OBJECT_LAYER_IMAGE; } + bool isFolder() const { return type() == OBJECT_LAYER_FOLDER; } bool isBackground() const { return (m_flags & LAYER_IS_BACKGROUND) == LAYER_IS_BACKGROUND; } bool isMoveable() const { return (m_flags & LAYER_IS_LOCKMOVE) == 0; } bool isReadable() const { return (m_flags & LAYER_IS_READABLE) == LAYER_IS_READABLE; } diff --git a/src/raster/layer_io.cpp b/src/raster/layer_io.cpp index f060cc028..7d00e89b8 100644 --- a/src/raster/layer_io.cpp +++ b/src/raster/layer_io.cpp @@ -48,11 +48,11 @@ void write_layer(std::ostream& os, LayerSubObjectsSerializer* subObjects, Layer* os.write(name.c_str(), name.size()); // Name write32(os, layer->getFlags()); // Flags - write16(os, layer->getType()); // Type + write16(os, layer->type()); // Type - switch (layer->getType()) { + switch (layer->type()) { - case GFXOBJ_LAYER_IMAGE: { + case OBJECT_LAYER_IMAGE: { // Number of cels write16(os, static_cast(layer)->getCelsCount()); @@ -71,7 +71,7 @@ void write_layer(std::ostream& os, LayerSubObjectsSerializer* subObjects, Layer* break; } - case GFXOBJ_LAYER_FOLDER: { + case OBJECT_LAYER_FOLDER: { LayerIterator it = static_cast(layer)->getLayerBegin(); LayerIterator end = static_cast(layer)->getLayerEnd(); @@ -104,7 +104,7 @@ Layer* read_layer(std::istream& is, LayerSubObjectsSerializer* subObjects, Sprit switch (layer_type) { - case GFXOBJ_LAYER_IMAGE: { + case OBJECT_LAYER_IMAGE: { // Create layer layer.reset(new LayerImage(sprite)); @@ -125,7 +125,7 @@ Layer* read_layer(std::istream& is, LayerSubObjectsSerializer* subObjects, Sprit break; } - case GFXOBJ_LAYER_FOLDER: { + case OBJECT_LAYER_FOLDER: { // Create the layer set layer.reset(new LayerFolder(sprite)); diff --git a/src/raster/mask.cpp b/src/raster/mask.cpp index 6a9f16be3..05e625501 100644 --- a/src/raster/mask.cpp +++ b/src/raster/mask.cpp @@ -24,6 +24,7 @@ #include "base/memory.h" #include "raster/image.h" +#include "raster/image_bits.h" #include #include @@ -31,22 +32,22 @@ namespace raster { Mask::Mask() - : GfxObj(GFXOBJ_MASK) + : Object(OBJECT_MASK) { initialize(); } Mask::Mask(const Mask& mask) - : GfxObj(mask) + : Object(mask) { initialize(); copyFrom(&mask); } Mask::Mask(int x, int y, Image* bitmap) - : GfxObj(GFXOBJ_MASK) + : Object(OBJECT_MASK) , m_freeze_count(0) - , m_bounds(x, y, bitmap->w, bitmap->h) + , m_bounds(x, y, bitmap->getWidth(), bitmap->getHeight()) , m_bitmap(bitmap) { } @@ -95,16 +96,12 @@ bool Mask::isRectangular() const if (!m_bitmap) return false; - for (int y=0; yh; ++y) { - uint8_t* address = ((uint8_t**)m_bitmap->line)[y]; - div_t d = div(0, 8); + LockImageBits bits(m_bitmap); + LockImageBits::iterator it = bits.begin(), end = bits.end(); - for (int x=0; xw; ++x) { - if (((*address) & (1 << d.rem)) == 0) - return false; - - _image_bitmap_next_bit(d, address); - } + for (; it != end; ++it) { + if (*it == 0) + return false; } return true; @@ -120,7 +117,7 @@ void Mask::copyFrom(const Mask* sourceMask) add(sourceMask->getBounds()); // And copy the "mask" bitmap - image_copy(m_bitmap, sourceMask->m_bitmap, 0, 0); + copy_image(m_bitmap, sourceMask->m_bitmap, 0, 0); } } @@ -141,18 +138,11 @@ void Mask::clear() void Mask::invert() { if (m_bitmap) { - uint8_t* address; - int u, v; - div_t d; + LockImageBits bits(m_bitmap); + LockImageBits::iterator it = bits.begin(), end = bits.end(); - for (v=0; vline)[v]; - for (u=0; uw, src->h); + replace(0, 0, src->getWidth(), src->getHeight()); Image* dst = m_bitmap; switch (src->getPixelFormat()) { case IMAGE_RGB: { - uint32_t* src_address; - uint8_t* dst_address; + const LockImageBits srcBits(src); + LockImageBits dstBits(dst, Image::WriteLock); + LockImageBits::const_iterator src_it = srcBits.begin(), src_end = srcBits.end(); + LockImageBits::iterator dst_it = dstBits.begin(), dst_end = dstBits.end(); int src_r, src_g, src_b, src_a; int dst_r, dst_g, dst_b, dst_a; - int u, v, c; - div_t d; + color_t c; - dst_r = _rgba_getr(color); - dst_g = _rgba_getg(color); - dst_b = _rgba_getb(color); - dst_a = _rgba_geta(color); + dst_r = rgba_getr(color); + dst_g = rgba_getg(color); + dst_b = rgba_getb(color); + dst_a = rgba_geta(color); - for (v=0; vh; v++) { - src_address = ((uint32_t**)src->line)[v]; - dst_address = ((uint8_t**)dst->line)[v]; + for (; src_it != src_end; ++src_it, ++dst_it) { + ASSERT(dst_it != dst_end); + c = *src_it; - d = div (0, 8); + src_r = rgba_getr(c); + src_g = rgba_getg(c); + src_b = rgba_getb(c); + src_a = rgba_geta(c); - for (u=0; uw; u++) { - c = *(src_address++); - - src_r = _rgba_getr(c); - src_g = _rgba_getg(c); - src_b = _rgba_getb(c); - src_a = _rgba_geta(c); - - if (!((src_r >= dst_r-fuzziness) && (src_r <= dst_r+fuzziness) && - (src_g >= dst_g-fuzziness) && (src_g <= dst_g+fuzziness) && - (src_b >= dst_b-fuzziness) && (src_b <= dst_b+fuzziness) && - (src_a >= dst_a-fuzziness) && (src_a <= dst_a+fuzziness))) - (*dst_address) ^= (1 << d.rem); - - _image_bitmap_next_bit(d, dst_address); - } + if (!((src_r >= dst_r-fuzziness) && (src_r <= dst_r+fuzziness) && + (src_g >= dst_g-fuzziness) && (src_g <= dst_g+fuzziness) && + (src_b >= dst_b-fuzziness) && (src_b <= dst_b+fuzziness) && + (src_a >= dst_a-fuzziness) && (src_a <= dst_a+fuzziness))) + (*dst_it) = 1; } - } break; + ASSERT(dst_it == dst_end); + break; + } case IMAGE_GRAYSCALE: { - uint16_t* src_address; - uint8_t* dst_address; + const LockImageBits srcBits(src); + LockImageBits dstBits(dst, Image::WriteLock); + LockImageBits::const_iterator src_it = srcBits.begin(), src_end = srcBits.end(); + LockImageBits::iterator dst_it = dstBits.begin(), dst_end = dstBits.end(); int src_k, src_a; int dst_k, dst_a; - int u, v, c; - div_t d; + color_t c; - dst_k = _graya_getv(color); - dst_a = _graya_geta(color); + dst_k = graya_getv(color); + dst_a = graya_geta(color); - for (v=0; vh; v++) { - src_address = ((uint16_t**)src->line)[v]; - dst_address = ((uint8_t**)dst->line)[v]; + for (; src_it != src_end; ++src_it, ++dst_it) { + ASSERT(dst_it != dst_end); + c = *src_it; - d = div (0, 8); + src_k = graya_getv(c); + src_a = graya_geta(c); - for (u=0; uw; u++) { - c = *(src_address++); - - src_k = _graya_getv(c); - src_a = _graya_geta(c); - - if (!((src_k >= dst_k-fuzziness) && (src_k <= dst_k+fuzziness) && - (src_a >= dst_a-fuzziness) && (src_a <= dst_a+fuzziness))) - (*dst_address) ^= (1 << d.rem); - - _image_bitmap_next_bit(d, dst_address); - } + if (!((src_k >= dst_k-fuzziness) && (src_k <= dst_k+fuzziness) && + (src_a >= dst_a-fuzziness) && (src_a <= dst_a+fuzziness))) + *dst_it = 1; } - } break; + ASSERT(dst_it == dst_end); + break; + } case IMAGE_INDEXED: { - uint8_t* src_address; - uint8_t* dst_address; - int u, v, c; - div_t d; + const LockImageBits srcBits(src); + LockImageBits dstBits(dst, Image::WriteLock); + LockImageBits::const_iterator src_it = srcBits.begin(), src_end = srcBits.end(); + LockImageBits::iterator dst_it = dstBits.begin(), dst_end = dstBits.end(); + color_t c, min, max; - for (v=0; vh; v++) { - src_address = ((uint8_t**)src->line)[v]; - dst_address = ((uint8_t**)dst->line)[v]; + for (; src_it != src_end; ++src_it, ++dst_it) { + ASSERT(dst_it != dst_end); + c = *src_it; - d = div (0, 8); + if (color > fuzziness) + min = color-fuzziness; + else + min = 0; + max = color + fuzziness; - for (u=0; uw; u++) { - c = *(src_address++); - - if (!((c >= color-fuzziness) && (c <= color+fuzziness))) - (*dst_address) ^= (1 << d.rem); - - _image_bitmap_next_bit(d, dst_address); - } + if (!((c >= min) && (c <= max))) + (*dst_it) = 1; } - } break; + ASSERT(dst_it == dst_end); + break; + } } shrink(); @@ -367,20 +358,20 @@ void Mask::crop(const Image *image) /* left */ ADVANCE(x1, x2, y2, <=, ++, - image_getpixel(image, x1, c=beg_y1), - image_getpixel(image, x1, c)); + get_pixel(image, x1, c=beg_y1), + get_pixel(image, x1, c)); /* right */ ADVANCE(x2, x1, y2, >=, --, - image_getpixel(image, x2, c=beg_y1), - image_getpixel(image, x2, c)); + get_pixel(image, x2, c=beg_y1), + get_pixel(image, x2, c)); /* top */ ADVANCE(y1, y2, x2, <=, ++, - image_getpixel(image, c=beg_x1, y1), - image_getpixel(image, c, y1)); + get_pixel(image, c=beg_x1, y1), + get_pixel(image, c, y1)); /* bottom */ ADVANCE(y2, y1, x2, >=, --, - image_getpixel(image, c=beg_x1, y2), - image_getpixel(image, c, y2)); + get_pixel(image, c=beg_x1, y2), + get_pixel(image, c, y2)); if (done_count < 4) intersect(x1, y1, x2, y2); @@ -400,7 +391,7 @@ void Mask::reserve(int x, int y, int w, int h) m_bounds.w = w; m_bounds.h = h; m_bitmap = Image::create(IMAGE_BITMAP, w, h); - image_clear(m_bitmap, 0); + clear_image(m_bitmap, 0); } else { int x1 = m_bounds.x; @@ -421,7 +412,7 @@ void Mask::reserve(int x, int y, int w, int h) m_bounds.w = new_mask_w; m_bounds.h = new_mask_h; - Image* image = image_crop(m_bitmap, m_bounds.x-x1, m_bounds.y-y1, m_bounds.w, m_bounds.h, 0); + Image* image = crop_image(m_bitmap, m_bounds.x-x1, m_bounds.y-y1, m_bounds.w, m_bounds.h, 0); delete m_bitmap; // image m_bitmap = image; } @@ -439,7 +430,7 @@ void Mask::shrink() { \ 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 (m_bitmap->getpixel(U, V)) \ + if (m_bitmap->getPixel(U, V)) \ break; \ } \ if (v == v_final) \ @@ -481,7 +472,7 @@ void Mask::shrink() m_bounds.w = x2 - x1 + 1; m_bounds.h = y2 - y1 + 1; - Image* image = image_crop(m_bitmap, m_bounds.x-u, m_bounds.y-v, m_bounds.w, m_bounds.h, 0); + Image* image = crop_image(m_bitmap, m_bounds.x-u, m_bounds.y-v, m_bounds.w, m_bounds.h, 0); delete m_bitmap; m_bitmap = image; } diff --git a/src/raster/mask.h b/src/raster/mask.h index 863593520..b92e2d047 100644 --- a/src/raster/mask.h +++ b/src/raster/mask.h @@ -20,15 +20,16 @@ #define RASTER_MASK_H_INCLUDED #include "gfx/rect.h" -#include "raster/gfxobj.h" #include "raster/image.h" +#include "raster/object.h" +#include "raster/primitives.h" #include namespace raster { // Represents the selection (selected pixels, 0/1, 0=non-selected, 1=selected) - class Mask : public GfxObj { + class Mask : public Object { public: Mask(); Mask(const Mask& mask); @@ -54,7 +55,7 @@ namespace raster { return (m_bitmap && u >= m_bounds.x && u < m_bounds.x+m_bounds.w && v >= m_bounds.y && v < m_bounds.y+m_bounds.h && - image_getpixel(m_bitmap, u-m_bounds.x, v-m_bounds.y)); + get_pixel(m_bitmap, u-m_bounds.x, v-m_bounds.y)); } const gfx::Rect& getBounds() const { @@ -96,7 +97,9 @@ namespace raster { void add(const gfx::Rect& bounds); void subtract(int x, int y, int w, int h); + void subtract(const gfx::Rect& bounds); void intersect(int x, int y, int w, int h); + void intersect(const gfx::Rect& bounds); void byColor(const Image* image, int color, int fuzziness); void crop(const Image* image); diff --git a/src/raster/mask_io.cpp b/src/raster/mask_io.cpp index 1bf86f376..fb6729408 100644 --- a/src/raster/mask_io.cpp +++ b/src/raster/mask_io.cpp @@ -51,10 +51,10 @@ void write_mask(std::ostream& os, Mask* mask) write16(os, mask->getBitmap() ? bounds.h: 0); // Height if (mask->getBitmap()) { - int size = BitmapTraits::scanline_size(bounds.w); + int size = BitmapTraits::getRowStrideBytes(bounds.w); for (int c=0; cgetBitmap()->line[c], size); + os.write((char*)mask->getBitmap()->getPixelAddress(0, c), size); } } @@ -68,11 +68,11 @@ Mask* read_mask(std::istream& is) base::UniquePtr mask(new Mask()); if (w > 0 && h > 0) { - int size = BitmapTraits::scanline_size(w); + int size = BitmapTraits::getRowStrideBytes(w); mask->add(x, y, w, h); for (int c=0; cgetBounds().h; c++) - is.read((char*)mask->getBitmap()->line[c], size); + is.read((char*)mask->getBitmap()->getPixelAddress(0, c), size); } return mask.release(); diff --git a/src/raster/median_cut.h b/src/raster/median_cut.h index 107149c20..bf6b8b4a0 100644 --- a/src/raster/median_cut.h +++ b/src/raster/median_cut.h @@ -109,12 +109,12 @@ namespace quantization { // No colors in the box? This should not be possible. assert(count > 0 && "Box without histogram points, you must fill the histogram before using this function."); if (count == 0) - return _rgba(0, 0, 0, 255); + return rgba(0, 0, 0, 255); // Returns the mean. - return _rgba((255 * r / (Histogram::RElements-1)) / count, - (255 * g / (Histogram::GElements-1)) / count, - (255 * b / (Histogram::BElements-1)) / count, 255); + return rgba((255 * r / (Histogram::RElements-1)) / count, + (255 * g / (Histogram::GElements-1)) / count, + (255 * b / (Histogram::BElements-1)) / count, 255); } // The boxes will be sort in the priority_queue by volume. diff --git a/src/raster/gfxobj.cpp b/src/raster/object.cpp similarity index 82% rename from src/raster/gfxobj.cpp rename to src/raster/object.cpp index b20346ac3..96fed401d 100644 --- a/src/raster/gfxobj.cpp +++ b/src/raster/object.cpp @@ -20,27 +20,27 @@ #include "config.h" #endif -#include "raster/gfxobj.h" +#include "raster/object.h" namespace raster { -GfxObj::GfxObj(GfxObjType type) +Object::Object(ObjectType type) { m_type = type; } -GfxObj::GfxObj(const GfxObj& gfxobj) +Object::Object(const Object& object) { - m_type = gfxobj.m_type; + m_type = object.m_type; } -GfxObj::~GfxObj() +Object::~Object() { } -int GfxObj::getMemSize() const +int Object::getMemSize() const { - return sizeof(GfxObj); + return sizeof(Object); } } // namespace raster diff --git a/src/raster/gfxobj.h b/src/raster/object.h similarity index 73% rename from src/raster/gfxobj.h rename to src/raster/object.h index 3306de8fa..67d6c23f1 100644 --- a/src/raster/gfxobj.h +++ b/src/raster/object.h @@ -16,24 +16,24 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef RASTER_GFXOBJ_H_INCLUDED -#define RASTER_GFXOBJ_H_INCLUDED +#ifndef RASTER_OBJECT_H_INCLUDED +#define RASTER_OBJECT_H_INCLUDED #include namespace raster { - enum GfxObjType { - GFXOBJ_CEL, - GFXOBJ_IMAGE, - GFXOBJ_LAYER_IMAGE, - GFXOBJ_LAYER_FOLDER, - GFXOBJ_MASK, - GFXOBJ_PALETTE, - GFXOBJ_PATH, - GFXOBJ_SPRITE, - GFXOBJ_STOCK, - GFXOBJ_RGBMAP, + enum ObjectType { + OBJECT_CEL, + OBJECT_IMAGE, + OBJECT_LAYER_IMAGE, + OBJECT_LAYER_FOLDER, + OBJECT_MASK, + OBJECT_PALETTE, + OBJECT_PATH, + OBJECT_SPRITE, + OBJECT_STOCK, + OBJECT_RGBMAP, }; class Cel; @@ -47,22 +47,22 @@ namespace raster { typedef std::list::iterator LayerIterator; typedef std::list::const_iterator LayerConstIterator; - class GfxObj { + class Object { public: - GfxObj(GfxObjType type); - GfxObj(const GfxObj& gfxobj); - virtual ~GfxObj(); + Object(ObjectType type); + Object(const Object& object); + virtual ~Object(); - GfxObjType getType() const { return m_type; } + ObjectType type() const { return m_type; } // Returns the approximate amount of memory (in bytes) which this // object use. virtual int getMemSize() const; private: - GfxObjType m_type; + ObjectType m_type; - GfxObj& operator=(const GfxObj&); + Object& operator=(const Object&); }; } // namespace raster diff --git a/src/raster/palette.cpp b/src/raster/palette.cpp index e4a31b312..bf5319f19 100644 --- a/src/raster/palette.cpp +++ b/src/raster/palette.cpp @@ -20,22 +20,26 @@ #include "config.h" #endif -#include -#include +#include "raster/palette.h" +#include "base/path.h" #include "gfx/hsv.h" #include "gfx/rgb.h" -#include "raster/image.h" -#include "raster/palette.h" -#include "raster/file/col_file.h" // TODO Remove circular dependency between "raster" <-> "util" +#include "raster/conversion_alleg.h" +#include "raster/file/col_file.h" #include "raster/file/gpl_file.h" +#include "raster/image.h" + +#include + +#include // TODO Remove this dependency namespace raster { using namespace gfx; Palette::Palette(FrameNumber frame, int ncolors) - : GfxObj(GFXOBJ_PALETTE) + : Object(OBJECT_PALETTE) { ASSERT(ncolors >= 1 && ncolors <= MaxColors); @@ -43,11 +47,11 @@ Palette::Palette(FrameNumber frame, int ncolors) m_colors.resize(ncolors); m_modifications = 0; - std::fill(m_colors.begin(), m_colors.end(), _rgba(0, 0, 0, 255)); + std::fill(m_colors.begin(), m_colors.end(), rgba(0, 0, 0, 255)); } Palette::Palette(const Palette& palette) - : GfxObj(palette) + : Object(palette) { m_frame = palette.m_frame; m_colors = palette.m_colors; @@ -62,7 +66,7 @@ Palette* Palette::createGrayscale() { Palette* graypal = new Palette(FrameNumber(0), MaxColors); for (int c=0; csetEntry(c, _rgba(c, c, c, 255)); + graypal->setEntry(c, rgba(c, c, c, 255)); return graypal; } @@ -77,7 +81,7 @@ void Palette::resize(int ncolors) // Fill new colors with black std::fill(m_colors.begin()+old_size, m_colors.begin()+m_colors.size(), - _rgba(0, 0, 0, 255)); + rgba(0, 0, 0, 255)); } ++m_modifications; @@ -90,10 +94,9 @@ void Palette::setFrame(FrameNumber frame) m_frame = frame; } -void Palette::setEntry(int i, uint32_t color) +void Palette::setEntry(int i, color_t color) { ASSERT(i >= 0 && i < size()); - ASSERT(_rgba_geta(color) == 255); m_colors[i] = color; ++m_modifications; @@ -134,7 +137,7 @@ int Palette::countDiff(const Palette* other, int* from, int* to) const bool Palette::isBlack() const { for (size_t c=0; c // End of Sort stuff ////////////////////////////////////////////////////////////////////// -/** - * @param pal The ASEPRITE color palette to copy. - * @param rgb An Allegro's PALETTE. - * - * @return The same @a rgb pointer specified in the parameters. - */ -void Palette::toAllegro(RGB *rgb) const -{ - int i; - for (i=0; ifromAllegro(rgbpal); + convert_palette_from_allegro(rgbpal, pal); } } - else if (ustricmp(ext, "col") == 0) { + else if (ext == "col") { pal = raster::file::load_col_file(filename); } - else if (ustricmp(ext, "gpl") == 0) { + else if (ext == "gpl") { pal = raster::file::load_gpl_file(filename); } @@ -463,17 +431,15 @@ Palette* Palette::load(const char *filename) bool Palette::save(const char *filename) const { + base::string ext = base::string_to_lower(base::get_file_extension(filename)); bool success = false; - char ext[64]; - ustrcpy(ext, get_extension(filename)); - - if ((ustricmp(ext, "png") == 0) || - (ustricmp(ext, "pcx") == 0) || - (ustricmp(ext, "bmp") == 0) || - (ustricmp(ext, "tga") == 0)) { + if (ext == "png" || + ext == "pcx" || + ext == "bmp" || + ext == "tga") { PALETTE rgbpal; - BITMAP *bmp; + BITMAP* bmp; int c, x, y; bmp = create_bitmap_ex(8, 16, 16); @@ -481,23 +447,23 @@ bool Palette::save(const char *filename) const for (x=0; x<16; x++) putpixel(bmp, x, y, c++); - toAllegro(rgbpal); + convert_palette_to_allegro(this, rgbpal); success = (save_bitmap(filename, bmp, rgbpal) == 0); destroy_bitmap(bmp); } - else if (ustricmp(ext, "col") == 0) { + else if (ext == "col") { success = raster::file::save_col_file(this, filename); } - else if (ustricmp(ext, "gpl") == 0) { + else if (ext == "gpl") { success = raster::file::save_gpl_file(this, filename); } return success; } -/**********************************************************************/ -/* Based on Allegro's bestfit_color */ +////////////////////////////////////////////////////////////////////// +// Based on Allegro's bestfit_color static unsigned int col_diff[3*128]; @@ -538,13 +504,13 @@ int Palette::findBestfit(int r, int g, int b) const i = 1; while (i < size()) { - uint32_t rgb = m_colors[i]; + color_t rgb = m_colors[i]; - coldiff = (col_diff + 0) [ ((_rgba_getg(rgb)>>3) - g) & 0x7F ]; + coldiff = (col_diff + 0) [ ((rgba_getg(rgb)>>3) - g) & 0x7F ]; if (coldiff < lowest) { - coldiff += (col_diff + 128) [ ((_rgba_getr(rgb)>>3) - r) & 0x7F ]; + coldiff += (col_diff + 128) [ ((rgba_getr(rgb)>>3) - r) & 0x7F ]; if (coldiff < lowest) { - coldiff += (col_diff + 256) [ ((_rgba_getb(rgb)>>3) - b) & 0x7F ]; + coldiff += (col_diff + 256) [ ((rgba_getb(rgb)>>3) - b) & 0x7F ]; if (coldiff < lowest) { bestfit = i; if (coldiff == 0) diff --git a/src/raster/palette.h b/src/raster/palette.h index 465d95d5c..3e34eced7 100644 --- a/src/raster/palette.h +++ b/src/raster/palette.h @@ -19,10 +19,10 @@ #ifndef RASTER_PALETTE_H_INCLUDED #define RASTER_PALETTE_H_INCLUDED +#include "raster/color.h" #include "raster/frame_number.h" -#include "raster/gfxobj.h" +#include "raster/object.h" -#include #include namespace raster { @@ -45,7 +45,7 @@ namespace raster { void addChain(SortPalette* chain); - bool operator()(uint32_t c1, uint32_t c2); + bool operator()(color_t c1, color_t c2); private: Channel m_channel; @@ -53,7 +53,7 @@ namespace raster { SortPalette* m_chain; }; - class Palette : public GfxObj { + class Palette : public Object { public: enum { MaxColors = 256 }; @@ -71,12 +71,12 @@ namespace raster { FrameNumber getFrame() const { return m_frame; } void setFrame(FrameNumber frame); - uint32_t getEntry(int i) const { + color_t getEntry(int i) const { ASSERT(i >= 0 && i < size()); return m_colors[i]; } - void setEntry(int i, uint32_t color); + void setEntry(int i, color_t color); void copyColorsTo(Palette* dst) const; @@ -91,9 +91,6 @@ namespace raster { void makeRectRamp(int from, int to, int columns); void sort(int from, int to, SortPalette* sort_palette, std::vector& mapping); - void toAllegro(RGB* rgb) const; - void fromAllegro(const RGB* rgb); - static Palette* load(const char *filename); bool save(const char *filename) const; @@ -101,7 +98,7 @@ namespace raster { private: FrameNumber m_frame; - std::vector m_colors; + std::vector m_colors; int m_modifications; }; diff --git a/src/raster/path.cpp b/src/raster/path.cpp index e046c4e72..656524afa 100644 --- a/src/raster/path.cpp +++ b/src/raster/path.cpp @@ -38,7 +38,7 @@ static void draw_path(Path* path, Image *image, int color, double brush_size, in ////////////////////////////////////////////////////////////////////// Path::Path(const char* name) - : GfxObj(GFXOBJ_PATH) + : Object(OBJECT_PATH) , name(name) { this->join = PATH_JOIN_ROUND; @@ -52,7 +52,7 @@ Path::Path(const char* name) } Path::Path(const Path& path) - : GfxObj(path) + : Object(path) , name(path.name) { this->join = path.join; @@ -237,7 +237,7 @@ static void blend_rgb_hline(Image *image, int x1, int y, int x2, int rgb, int a) int x; for (x=x1; x<=x2; x++) { - *address = _rgba_blend_normal (*address, rgb, a); + *address = rgba_blend_normal (*address, rgb, a); address++; } } @@ -248,7 +248,7 @@ static void blend_grayscale_hline(Image *image, int x1, int y, int x2, int k, in int x; for (x=x1; x<=x2; x++) { - *address = _graya_blend_normal(*address, k, a); + *address = graya_blend_normal(*address, k, a); address++; } } @@ -353,7 +353,7 @@ static void art_image_svp_aa (const ArtSVP *svp, data.hline = blend_indexed_hline; break; - /* TODO make something for IMAGE_BITMAP */ + // TODO make something for IMAGE_BITMAP default: return; } diff --git a/src/raster/path.h b/src/raster/path.h index 65bb8d630..135027be9 100644 --- a/src/raster/path.h +++ b/src/raster/path.h @@ -21,7 +21,7 @@ #error This file is deprecated -#include "raster/gfxobj.h" +#include "raster/object.h" #include namespace raster { @@ -43,7 +43,7 @@ namespace raster { PATH_CAP_SQUARE, }; - class Path : public GfxObj { + class Path : public Object { public: std::string name; int join, cap; diff --git a/src/raster/pen.cpp b/src/raster/pen.cpp index dd5c87d89..b271e8e96 100644 --- a/src/raster/pen.cpp +++ b/src/raster/pen.cpp @@ -20,9 +20,11 @@ #include "config.h" #endif -#include "raster/algo.h" #include "raster/pen.h" + +#include "raster/algo.h" #include "raster/image.h" +#include "raster/primitives.h" #include @@ -93,7 +95,7 @@ void Pen::clean_pen() static void algo_hline(int x1, int y, int x2, void *data) { - image_hline(reinterpret_cast(data), x1, y, x2, 1); + draw_hline(reinterpret_cast(data), x1, y, x2, BitmapTraits::max_value); } // Regenerates the pen bitmap and its rectangle's region. @@ -110,20 +112,20 @@ void Pen::regenerate_pen() m_image = Image::create(IMAGE_BITMAP, size, size); if (size == 1) { - image_clear(m_image, 1); + clear_image(m_image, BitmapTraits::max_value); } else { - image_clear(m_image, 0); + clear_image(m_image, BitmapTraits::min_value); switch (m_type) { case PEN_TYPE_CIRCLE: - image_ellipsefill(m_image, 0, 0, size-1, size-1, 1); + fill_ellipse(m_image, 0, 0, size-1, size-1, BitmapTraits::max_value); break; case PEN_TYPE_SQUARE: if (m_angle == 0 || size <= 2) { - image_clear(m_image, 1); + clear_image(m_image, BitmapTraits::max_value); } else { double a = PI * m_angle / 180; @@ -153,22 +155,22 @@ void Pen::regenerate_pen() int x2 = x1 + d*cos(a); int y2 = y1 - d*sin(a); - image_line(m_image, x1, y1, x2, y2, 1); + draw_line(m_image, x1, y1, x2, y2, BitmapTraits::max_value); break; } } } - m_scanline.resize(m_image->h); - for (int y=0; yh; y++) { + m_scanline.resize(m_image->getHeight()); + for (int y=0; ygetHeight(); y++) { m_scanline[y].state = false; - for (int x=0; xw; x++) { - if (image_getpixel(m_image, x, y)) { + for (int x=0; xgetWidth(); x++) { + if (get_pixel(m_image, x, y)) { m_scanline[y].x1 = x; - for (; xw; x++) - if (!image_getpixel(m_image, x, y)) + for (; xgetWidth(); x++) + if (!get_pixel(m_image, x, y)) break; m_scanline[y].x2 = x-1; @@ -178,8 +180,8 @@ void Pen::regenerate_pen() } } - m_bounds = gfx::Rect(-m_image->w/2, -m_image->h/2, - m_image->w, m_image->h); + m_bounds = gfx::Rect(-m_image->getWidth()/2, -m_image->getHeight()/2, + m_image->getWidth(), m_image->getHeight()); } } // namespace raster diff --git a/src/raster/primitives.cpp b/src/raster/primitives.cpp new file mode 100644 index 000000000..1f2695fe6 --- /dev/null +++ b/src/raster/primitives.cpp @@ -0,0 +1,337 @@ +/* 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/primitives.h" + +#include "raster/algo.h" +#include "raster/blend.h" +#include "raster/image.h" +#include "raster/image_impl.h" +#include "raster/palette.h" +#include "raster/pen.h" +#include "raster/rgbmap.h" + +#include + +namespace raster { + +color_t get_pixel(const Image* image, int x, int y) +{ + if ((x >= 0) && (y >= 0) && (x < image->getWidth()) && (y < image->getHeight())) + return image->getPixel(x, y); + else + return -1; +} + +void put_pixel(Image* image, int x, int y, color_t color) +{ + if ((x >= 0) && (y >= 0) && (x < image->getWidth()) && (y < image->getHeight())) + image->putPixel(x, y, color); +} + +void put_pen(Image* image, Pen* pen, int x, int y, color_t fg, color_t bg) +{ + Image* pen_image = pen->get_image(); + const gfx::Rect& penBounds = pen->getBounds(); + + x += penBounds.x; + y += penBounds.y; + + if (fg == bg) { + fill_rect(image, x, y, x+penBounds.w-1, y+penBounds.h-1, bg); + } + else { + int u, v; + for (v=0; vclear(color); +} + +void copy_image(Image* dst, const Image* src, int x, int y) +{ + dst->copy(src, x, y); +} + +void composite_image(Image* dst, const Image* src, int x, int y, int opacity, int blend_mode) +{ + dst->merge(src, x, y, opacity, blend_mode); +} + +Image* crop_image(const Image* image, int x, int y, int w, int h, color_t bg) +{ + 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->setMaskColor(image->getMaskColor()); + + clear_image(trim, bg); + copy_image(trim, image, -x, -y); + + return trim; +} + +void rotate_image(const Image* src, Image* dst, int angle) +{ + int x, y; + + switch (angle) { + + case 180: + ASSERT(dst->getWidth() == src->getWidth()); + ASSERT(dst->getHeight() == src->getHeight()); + + for (y=0; ygetHeight(); ++y) + for (x=0; xgetWidth(); ++x) + dst->putPixel(src->getWidth() - x - 1, + src->getHeight() - y - 1, src->getPixel(x, y)); + break; + + case 90: + ASSERT(dst->getWidth() == src->getHeight()); + ASSERT(dst->getHeight() == src->getWidth()); + + for (y=0; ygetHeight(); ++y) + for (x=0; xgetWidth(); ++x) + dst->putPixel(src->getHeight() - y - 1, x, src->getPixel(x, y)); + break; + + case -90: + ASSERT(dst->getWidth() == src->getHeight()); + ASSERT(dst->getHeight() == src->getWidth()); + + for (y=0; ygetHeight(); ++y) + for (x=0; xgetWidth(); ++x) + dst->putPixel(y, src->getWidth() - x - 1, src->getPixel(x, y)); + break; + + // bad angle + default: + throw std::invalid_argument("Invalid angle specified to rotate the image"); + } +} + +void draw_hline(Image* image, int x1, int y, int x2, color_t color) +{ + int t; + + if (x1 > x2) { + t = x1; + x1 = x2; + x2 = t; + } + + if ((x2 < 0) || (x1 >= image->getWidth()) || (y < 0) || (y >= image->getHeight())) + return; + + if (x1 < 0) x1 = 0; + if (x2 >= image->getWidth()) x2 = image->getWidth()-1; + + image->drawHLine(x1, y, x2, color); +} + +void draw_vline(Image* image, int x, int y1, int y2, color_t color) +{ + int t; + + if (y1 > y2) { + t = y1; + y1 = y2; + y2 = t; + } + + if ((y2 < 0) || (y1 >= image->getHeight()) || (x < 0) || (x >= image->getWidth())) + return; + + if (y1 < 0) y1 = 0; + if (y2 >= image->getHeight()) y2 = image->getHeight()-1; + + for (t=y1; t<=y2; t++) + image->putPixel(x, t, color); +} + +void draw_rect(Image* image, int x1, int y1, int x2, int y2, color_t 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->getWidth()) || (y2 < 0) || (y1 >= image->getHeight())) + return; + + draw_hline(image, x1, y1, x2, color); + draw_hline(image, x1, y2, x2, color); + if (y2-y1 > 1) { + draw_vline(image, x1, y1+1, y2-1, color); + draw_vline(image, x2, y1+1, y2-1, color); + } +} + +void fill_rect(Image* image, int x1, int y1, int x2, int y2, color_t 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->getWidth()) || (y2 < 0) || (y1 >= image->getHeight())) + return; + + if (x1 < 0) x1 = 0; + if (y1 < 0) y1 = 0; + if (x2 >= image->getWidth()) x2 = image->getWidth()-1; + if (y2 >= image->getHeight()) y2 = image->getHeight()-1; + + image->fillRect(x1, y1, x2, y2, color); +} + +void blend_rect(Image* image, int x1, int y1, int x2, int y2, color_t 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->getWidth()) || (y2 < 0) || (y1 >= image->getHeight())) + return; + + if (x1 < 0) x1 = 0; + if (y1 < 0) y1 = 0; + if (x2 >= image->getWidth()) x2 = image->getWidth()-1; + if (y2 >= image->getHeight()) y2 = image->getHeight()-1; + + image->blendRect(x1, y1, x2, y2, color, opacity); +} + +struct Data { + Image* image; + color_t color; +}; + +static void pixel_for_image(int x, int y, Data* data) +{ + put_pixel(data->image, x, y, data->color); +} + +static void hline_for_image(int x1, int y, int x2, Data* data) +{ + draw_hline(data->image, x1, y, x2, data->color); +} + +void draw_line(Image* image, int x1, int y1, int x2, int y2, color_t color) +{ + Data data = { image, color }; + algo_line(x1, y1, x2, y2, &data, (AlgoPixel)pixel_for_image); +} + +void draw_ellipse(Image* image, int x1, int y1, int x2, int y2, color_t color) +{ + Data data = { image, color }; + algo_ellipse(x1, y1, x2, y2, &data, (AlgoPixel)pixel_for_image); +} + +void fill_ellipse(Image* image, int x1, int y1, int x2, int y2, color_t color) +{ + Data data = { image, color }; + algo_ellipsefill(x1, y1, x2, y2, &data, (AlgoHLine)hline_for_image); +} + +namespace { + +template +int count_diff_between_images_templ(const Image* i1, const Image* i2) +{ + int diff = 0; + const LockImageBits bits1(i1); + const LockImageBits bits2(i2); + typename LockImageBits::const_iterator it1, it2, end1, end2; + for (it1 = bits1.begin(), end1 = bits1.end(), + it2 = bits2.begin(), end2 = bits2.end(); + it1 != end1 && it2 != end2; ++it1, ++it2) { + if (*it1 != *it2) + diff++; + } + + ASSERT(it1 == end1); + ASSERT(it2 == end2); + return diff; +} + +} // anonymous namespace + +int count_diff_between_images(const Image* i1, const Image* i2) +{ + if ((i1->getPixelFormat() != i2->getPixelFormat()) || + (i1->getWidth() != i2->getWidth()) || (i1->getHeight() != i2->getHeight())) + return -1; + + switch (i1->getPixelFormat()) { + case IMAGE_RGB: return count_diff_between_images_templ(i1, i2); + case IMAGE_GRAYSCALE: return count_diff_between_images_templ(i1, i2); + case IMAGE_INDEXED: return count_diff_between_images_templ(i1, i2); + case IMAGE_BITMAP: return count_diff_between_images_templ(i1, i2); + } + + ASSERT(false); + return -1; +} + +} // namespace raster diff --git a/src/raster/primitives.h b/src/raster/primitives.h new file mode 100644 index 000000000..62a8cc1bc --- /dev/null +++ b/src/raster/primitives.h @@ -0,0 +1,54 @@ +/* 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_PRIMITIVES_H_INCLUDED +#define RASTER_PRIMITIVES_H_INCLUDED + +#include "raster/color.h" + +namespace raster { + class Image; + class Palette; + class Pen; + + color_t get_pixel(const Image* image, int x, int y); + void put_pixel(Image* image, int x, int y, color_t c); + void put_pen(Image* image, Pen* pen, int x, int y, color_t fg, color_t bg); + + void clear_image(Image* image, color_t bg); + + void copy_image(Image* dst, const Image* src, int x, int y); + void composite_image(Image* dst, const Image* src, int x, int y, int opacity, int blend_mode); + + Image* crop_image(const Image* image, int x, int y, int w, int h, color_t bg); + void rotate_image(const Image* src, Image* dst, int angle); + + void draw_hline(Image* image, int x1, int y, int x2, color_t c); + void draw_vline(Image* image, int x, int y1, int y2, color_t c); + void draw_rect(Image* image, int x1, int y1, int x2, int y2, color_t c); + void fill_rect(Image* image, int x1, int y1, int x2, int y2, color_t c); + void blend_rect(Image* image, int x1, int y1, int x2, int y2, color_t c, int opacity); + void draw_line(Image* image, int x1, int y1, int x2, int y2, color_t c); + void draw_ellipse(Image* image, int x1, int y1, int x2, int y2, color_t c); + void fill_ellipse(Image* image, int x1, int y1, int x2, int y2, color_t c); + + int count_diff_between_images(const Image* i1, const Image* i2); + +} // namespace raster + +#endif diff --git a/src/raster/primitives_fast.h b/src/raster/primitives_fast.h new file mode 100644 index 000000000..48542b210 --- /dev/null +++ b/src/raster/primitives_fast.h @@ -0,0 +1,67 @@ +/* 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_PRIMITIVES_FAST_H_INCLUDED +#define RASTER_PRIMITIVES_FAST_H_INCLUDED + +#include "raster/color.h" + +namespace raster { + class Image; + + template + inline typename Traits::pixel_t get_pixel_fast(const Image* image, int x, int y) { + ASSERT(x >= 0 && x < image->getWidth()); + ASSERT(y >= 0 && y < image->getHeight()); + + return *((typename Traits::address_t)image->getPixelAddress(x, y)); + } + + template + inline void put_pixel_fast(Image* image, int x, int y, typename Traits::pixel_t color) { + ASSERT(x >= 0 && x < image->getWidth()); + ASSERT(y >= 0 && y < image->getHeight()); + + *((typename Traits::address_t)image->getPixelAddress(x, y)) = color; + } + + ////////////////////////////////////////////////////////////////////// + // Bitmap specialization + + template<> + inline BitmapTraits::pixel_t get_pixel_fast(const Image* image, int x, int y) { + ASSERT(x >= 0 && x < image->getWidth()); + ASSERT(y >= 0 && y < image->getHeight()); + + return (*image->getPixelAddress(x, y)) & (1 << (x % 8)) ? 1: 0; + } + + template<> + inline void put_pixel_fast(Image* image, int x, int y, BitmapTraits::pixel_t color) { + ASSERT(x >= 0 && x < image->getWidth()); + ASSERT(y >= 0 && y < image->getHeight()); + + if (color) + *image->getPixelAddress(x, y) |= (1 << (x % 8)); + else + *image->getPixelAddress(x, y) &= ~(1 << (x % 8)); + } + +} // namespace raster + +#endif diff --git a/src/raster/quantization.cpp b/src/raster/quantization.cpp index 3183933c0..a312c5fc8 100644 --- a/src/raster/quantization.cpp +++ b/src/raster/quantization.cpp @@ -20,22 +20,25 @@ #include "config.h" #endif -#include -#include -#include +#include "raster/quantization.h" #include "gfx/hsv.h" #include "gfx/rgb.h" #include "raster/blend.h" #include "raster/color_histogram.h" #include "raster/image.h" +#include "raster/image_bits.h" #include "raster/images_collector.h" #include "raster/layer.h" #include "raster/palette.h" -#include "raster/quantization.h" +#include "raster/primitives.h" #include "raster/rgbmap.h" #include "raster/sprite.h" +#include +#include +#include + namespace raster { namespace quantization { @@ -62,7 +65,7 @@ Palette* create_palette_from_rgb(const Sprite* sprite, FrameNumber frameNumber) // Add a flat image with the current sprite's frame rendered flat_image = Image::create(sprite->getPixelFormat(), sprite->getWidth(), sprite->getHeight()); - image_clear(flat_image, 0); + clear_image(flat_image, 0); sprite->render(flat_image, 0, 0, frameNumber); // Create an array of images @@ -88,13 +91,6 @@ Image* convert_pixel_format(const Image* image, const Palette* palette, bool has_background_layer) { - uint32_t* rgb_address; - uint16_t* gray_address; - uint8_t* idx_address; - uint32_t c; - int i, r, g, b, size; - Image *new_image; - // no convertion if (image->getPixelFormat() == pixelFormat) return NULL; @@ -105,132 +101,158 @@ Image* convert_pixel_format(const Image* image, return ordered_dithering(image, 0, 0, rgbmap, palette); } - new_image = Image::create(pixelFormat, image->w, image->h); - if (!new_image) - return NULL; - - size = image->w*image->h; + Image* new_image = Image::create(pixelFormat, image->getWidth(), image->getHeight()); + color_t c; + int r, g, b; switch (image->getPixelFormat()) { - case IMAGE_RGB: - rgb_address = (uint32_t*)image->dat; + case IMAGE_RGB: { + const LockImageBits srcBits(image); + LockImageBits::const_iterator src_it = srcBits.begin(), src_end = srcBits.end(); switch (new_image->getPixelFormat()) { // RGB -> Grayscale - case IMAGE_GRAYSCALE: - gray_address = (uint16_t*)new_image->dat; - for (i=0; i dstBits(new_image, Image::WriteLock); + LockImageBits::iterator dst_it = dstBits.begin(), dst_end = dstBits.end(); - g = 255 * Hsv(Rgb(_rgba_getr(c), - _rgba_getg(c), - _rgba_getb(c))).valueInt() / 100; - *gray_address = _graya(g, _rgba_geta(c)); + for (; src_it != src_end; ++src_it, ++dst_it) { + ASSERT(dst_it != dst_end); + c = *src_it; - rgb_address++; - gray_address++; + g = 255 * Hsv(Rgb(rgba_getr(c), + rgba_getg(c), + rgba_getb(c))).valueInt() / 100; + + *dst_it = graya(g, rgba_geta(c)); } + ASSERT(dst_it == dst_end); break; + } // RGB -> Indexed - case IMAGE_INDEXED: - idx_address = new_image->dat; - for (i=0; i dstBits(new_image, Image::WriteLock); + LockImageBits::iterator dst_it = dstBits.begin(), dst_end = dstBits.end(); + + for (; src_it != src_end; ++src_it, ++dst_it) { + ASSERT(dst_it != dst_end); + c = *src_it; + + r = rgba_getr(c); + g = rgba_getg(c); + b = rgba_getb(c); + if (rgba_geta(c) == 0) + *dst_it = 0; else - *idx_address = rgbmap->mapColor(r, g, b); - rgb_address++; - idx_address++; + *dst_it = rgbmap->mapColor(r, g, b); } + ASSERT(dst_it == dst_end); break; + } } break; + } - case IMAGE_GRAYSCALE: - gray_address = (uint16_t*)image->dat; + case IMAGE_GRAYSCALE: { + const LockImageBits srcBits(image); + LockImageBits::const_iterator src_it = srcBits.begin(), src_end = srcBits.end(); switch (new_image->getPixelFormat()) { // Grayscale -> RGB - case IMAGE_RGB: - rgb_address = (uint32_t*)new_image->dat; - for (i=0; i dstBits(new_image, Image::WriteLock); + LockImageBits::iterator dst_it = dstBits.begin(), dst_end = dstBits.end(); + + for (; src_it != src_end; ++src_it, ++dst_it) { + ASSERT(dst_it != dst_end); + c = *src_it; + + g = graya_getv(c); + + *dst_it = rgba(g, g, g, graya_geta(c)); } + ASSERT(dst_it == dst_end); break; + } // Grayscale -> Indexed - case IMAGE_INDEXED: - idx_address = new_image->dat; - for (i=0; i dstBits(new_image, Image::WriteLock); + LockImageBits::iterator dst_it = dstBits.begin(), dst_end = dstBits.end(); + + for (; src_it != src_end; ++src_it, ++dst_it) { + ASSERT(dst_it != dst_end); + c = *src_it; + + if (graya_geta(c) == 0) + *dst_it = 0; else - *idx_address = _graya_getv(c); - gray_address++; - idx_address++; + *dst_it = graya_getv(c); } + ASSERT(dst_it == dst_end); break; + } } break; + } - case IMAGE_INDEXED: - idx_address = image->dat; + case IMAGE_INDEXED: { + const LockImageBits srcBits(image); + LockImageBits::const_iterator src_it = srcBits.begin(), src_end = srcBits.end(); switch (new_image->getPixelFormat()) { // Indexed -> RGB - case IMAGE_RGB: - rgb_address = (uint32_t*)new_image->dat; - for (i=0; i dstBits(new_image, Image::WriteLock); + LockImageBits::iterator dst_it = dstBits.begin(), dst_end = dstBits.end(); + + for (; src_it != src_end; ++src_it, ++dst_it) { + ASSERT(dst_it != dst_end); + c = *src_it; if (c == 0 && !has_background_layer) - *rgb_address = 0; + *dst_it = 0; else - *rgb_address = _rgba(_rgba_getr(palette->getEntry(c)), - _rgba_getg(palette->getEntry(c)), - _rgba_getb(palette->getEntry(c)), 255); - idx_address++; - rgb_address++; + *dst_it = rgba(rgba_getr(palette->getEntry(c)), + rgba_getg(palette->getEntry(c)), + rgba_getb(palette->getEntry(c)), 255); } + ASSERT(dst_it == dst_end); break; + } // Indexed -> Grayscale - case IMAGE_GRAYSCALE: - gray_address = (uint16_t*)new_image->dat; - for (i=0; i dstBits(new_image, Image::WriteLock); + LockImageBits::iterator dst_it = dstBits.begin(), dst_end = dstBits.end(); + + for (; src_it != src_end; ++src_it, ++dst_it) { + ASSERT(dst_it != dst_end); + c = *src_it; if (c == 0 && !has_background_layer) - *gray_address = 0; + *dst_it = 0; else { - r = _rgba_getr(palette->getEntry(c)); - g = _rgba_getg(palette->getEntry(c)); - b = _rgba_getb(palette->getEntry(c)); + r = rgba_getr(palette->getEntry(c)); + g = rgba_getg(palette->getEntry(c)); + b = rgba_getb(palette->getEntry(c)); g = 255 * Hsv(Rgb(r, g, b)).valueInt() / 100; - *gray_address = _graya(g, 255); + *dst_it = graya(g, 255); } - idx_address++; - gray_address++; } + ASSERT(dst_it == dst_end); break; + } } break; + } } return new_image; @@ -278,27 +300,36 @@ static Image* ordered_dithering(const Image* src_image, int nr, ng, nb; int r, g, b, a; int nearestcm; - int c, x, y; + int x, y; + color_t c; - dst_image = Image::create(IMAGE_INDEXED, src_image->w, src_image->h); + dst_image = Image::create(IMAGE_INDEXED, src_image->getWidth(), src_image->getHeight()); if (!dst_image) return NULL; - for (y=0; yh; y++) { - for (x=0; xw; x++) { - c = image_getpixel_fast(src_image, x, y); + const LockImageBits src_bits(src_image); + LockImageBits dst_bits(dst_image); + LockImageBits::const_iterator src_it = src_bits.begin(); + LockImageBits::iterator dst_it = dst_bits.begin(); - r = _rgba_getr(c); - g = _rgba_getg(c); - b = _rgba_getb(c); - a = _rgba_geta(c); + for (y=0; ygetHeight(); ++y) { + for (x=0; xgetWidth(); ++x, ++src_it, ++dst_it) { + ASSERT(src_it != src_bits.end()); + ASSERT(dst_it != dst_bits.end()); + + c = *src_it; + + r = rgba_getr(c); + g = rgba_getg(c); + b = rgba_getb(c); + a = rgba_geta(c); if (a != 0) { nearestcm = rgbmap->mapColor(r, g, b); /* rgb values for nearest color */ - nr = _rgba_getr(palette->getEntry(nearestcm)); - ng = _rgba_getg(palette->getEntry(nearestcm)); - nb = _rgba_getb(palette->getEntry(nearestcm)); + nr = rgba_getr(palette->getEntry(nearestcm)); + ng = rgba_getg(palette->getEntry(nearestcm)); + nb = rgba_getb(palette->getEntry(nearestcm)); /* Color as far from rgb as nrngnb but in the other direction */ oppr = MID(0, 2*r - nr, 255); oppg = MID(0, 2*g - ng, 255); @@ -314,9 +345,9 @@ static Image* ordered_dithering(const Image* src_image, case the r-nr distance can actually be less than the nr-oppr distance. */ if (oppnrcm != nearestcm) { - oppr = _rgba_getr(palette->getEntry(oppnrcm)); - oppg = _rgba_getg(palette->getEntry(oppnrcm)); - oppb = _rgba_getb(palette->getEntry(oppnrcm)); + oppr = rgba_getr(palette->getEntry(oppnrcm)); + oppg = rgba_getg(palette->getEntry(oppnrcm)); + oppb = rgba_getb(palette->getEntry(oppnrcm)); dither_const = DIST(nr, ng, nb, oppr, oppg, oppb); if (dither_const != 0) { @@ -331,7 +362,7 @@ static Image* ordered_dithering(const Image* src_image, else nearestcm = 0; - image_putpixel_fast(dst_image, x, y, nearestcm); + *dst_it = nearestcm; } } @@ -346,7 +377,6 @@ static void create_palette_from_bitmaps(const std::vector& images, Palet { quantization::ColorHistogram<5, 6, 5> histogram; uint32_t color; - RgbTraits::address_t address; // If the sprite has a background layer, the first entry can be // used, in other case the 0 indexed will be the mask color, so it @@ -356,19 +386,15 @@ static void create_palette_from_bitmaps(const std::vector& images, Palet for (int i=0; i<(int)images.size(); ++i) { const Image* image = images[i]; + const LockImageBits bits(image); + LockImageBits::const_iterator it = bits.begin(), end = bits.end(); - for (int y=0; yh; ++y) { - address = image_address_fast(image, 0, y); + for (; it != end; ++it) { + color = *it; - for (int x=0; xw; ++x) { - color = *address; - - if (_rgba_geta(color) > 0) { - color |= _rgba(0, 0, 0, 255); - histogram.addSamples(color, 1); - } - - ++address; + if (rgba_geta(color) > 0) { + color |= rgba(0, 0, 0, 255); + histogram.addSamples(color, 1); } } } diff --git a/src/raster/raster.h b/src/raster/raster.h index ec0fc3d21..69fdceac9 100644 --- a/src/raster/raster.h +++ b/src/raster/raster.h @@ -22,14 +22,21 @@ #include "raster/algo.h" #include "raster/blend.h" #include "raster/cel.h" +#include "raster/color.h" +#include "raster/color_scales.h" #include "raster/dirty.h" #include "raster/frame_number.h" -#include "raster/gfxobj.h" #include "raster/image.h" +#include "raster/image_bits.h" #include "raster/layer.h" #include "raster/mask.h" +#include "raster/object.h" #include "raster/palette.h" #include "raster/pen.h" +#include "raster/pixel_format.h" +#include "raster/primitives.h" +#include "raster/primitives_fast.h" +#include "raster/quantization.h" #include "raster/rgbmap.h" #include "raster/rotate.h" #include "raster/sprite.h" diff --git a/src/raster/rgbmap.cpp b/src/raster/rgbmap.cpp index 752f77734..0fb6d3cff 100644 --- a/src/raster/rgbmap.cpp +++ b/src/raster/rgbmap.cpp @@ -22,6 +22,7 @@ #include "raster/rgbmap.h" +#include "raster/conversion_alleg.h" #include "raster/palette.h" #include @@ -50,7 +51,7 @@ public: m_modifications = palette->getModifications(); PALETTE allegPal; - palette->toAllegro(allegPal); + convert_palette_to_allegro(palette, allegPal); create_rgb_table(m_allegMap, allegPal, NULL); for (int r=0; r<32; ++r) @@ -77,7 +78,7 @@ private: }; RgbMap::RgbMap() - : GfxObj(GFXOBJ_RGBMAP) + : Object(OBJECT_RGBMAP) { m_impl = new RgbMapImpl; } diff --git a/src/raster/rgbmap.h b/src/raster/rgbmap.h index 9389a11eb..b5f0da249 100644 --- a/src/raster/rgbmap.h +++ b/src/raster/rgbmap.h @@ -20,13 +20,13 @@ #define RASTER_RGBMAP_H_INCLUDED #include "base/disable_copying.h" -#include "raster/gfxobj.h" +#include "raster/object.h" namespace raster { class Palette; - class RgbMap : public GfxObj { + class RgbMap : public Object { public: RgbMap(); virtual ~RgbMap(); diff --git a/src/raster/rotate.cpp b/src/raster/rotate.cpp index e05e34c7b..e3552994e 100644 --- a/src/raster/rotate.cpp +++ b/src/raster/rotate.cpp @@ -11,13 +11,15 @@ #include "config.h" #endif +#include "raster/blend.h" +#include "raster/image.h" +#include "raster/image_bits.h" +#include "raster/primitives.h" + #include #include #include -#include "raster/blend.h" -#include "raster/image.h" - #ifndef _AL_SINCOS #if defined (__i386__) && defined (__GNUC__) #define _AL_SINCOS(x, s, c) __asm__ ("fsincos" : "=t" (c), "=u" (s) : "0" (x)) @@ -39,33 +41,32 @@ static void ase_rotate_scale_flip_coordinates(fixed w, fixed h, void image_scale(Image *dst, Image *src, int x, int y, int w, int h) { - if (w == src->w && src->h == h) - image_merge (dst, src, x, y, 255, BLEND_MODE_NORMAL); + if (w == src->getWidth() && src->getHeight() == h) + composite_image(dst, src, x, y, 255, BLEND_MODE_NORMAL); else { BLEND_COLOR blender = NULL; int u, v, c; if (dst->getPixelFormat() == IMAGE_RGB) - blender = _rgba_blenders[BLEND_MODE_NORMAL]; + blender = rgba_blenders[BLEND_MODE_NORMAL]; else if (dst->getPixelFormat() == IMAGE_GRAYSCALE) - blender = _graya_blenders[BLEND_MODE_NORMAL]; + blender = graya_blenders[BLEND_MODE_NORMAL]; for (v=0; vw*u/w, src->h*v/h); + c = get_pixel(src, src->getWidth()*u/w, src->getHeight()*v/h); switch (dst->getPixelFormat()) { case IMAGE_RGB: case IMAGE_GRAYSCALE: - image_putpixel (dst, x+u, y+v, - blender (image_getpixel (dst, x+u, y+v), c, - 255)); + put_pixel(dst, x+u, y+v, + blender(get_pixel(dst, x+u, y+v), c, 255)); break; case IMAGE_INDEXED: if (c != 0) - image_putpixel (dst, x+u, y+v, c); + put_pixel(dst, x+u, y+v, c); break; } } @@ -78,13 +79,13 @@ void image_rotate(Image *dst, Image *src, int x, int y, int w, int h, { fixed xs[4], ys[4]; - ase_rotate_scale_flip_coordinates (itofix (src->w), itofix (src->h), - itofix (x), itofix (y), - itofix (cx), itofix (cy), - ftofix (256 * angle / PI), - fixdiv (itofix (w), itofix (src->w)), - fixdiv (itofix (h), itofix (src->h)), - false, false, xs, ys); + ase_rotate_scale_flip_coordinates(itofix(src->getWidth()), itofix (src->getHeight()), + itofix(x), itofix(y), + itofix(cx), itofix(cy), + ftofix(256 * angle / PI), + fixdiv(itofix(w), itofix(src->getWidth())), + fixdiv(itofix(h), itofix(src->getHeight())), + false, false, xs, ys); ase_parallelogram_map_standard (dst, src, xs, ys); } @@ -120,15 +121,13 @@ static void draw_scanline(Image *bmp, Image *spr, fixed l_spr_x, fixed l_spr_y, fixed spr_dx, fixed spr_dy) { - Delegate delegate; - r_bmp_x >>= 16; l_bmp_x >>= 16; - delegate.startScan(bmp, l_bmp_x, bmp_y_i); + Delegate delegate(bmp, gfx::Rect(l_bmp_x, bmp_y_i, r_bmp_x - l_bmp_x + 1, 1)); for (int x=(int)l_bmp_x; x<=(int)r_bmp_x; ++x) { - delegate.feedLine(spr, l_spr_x, l_spr_y); + delegate.feedLine(spr, l_spr_x>>16, l_spr_y>>16); l_spr_x += spr_dx; l_spr_y += spr_dy; @@ -137,61 +136,81 @@ static void draw_scanline(Image *bmp, Image *spr, template class GenericDelegate { -protected: - typename Traits::address_t m_addr; public: - void startScan(Image* bmp, int x, int y) { - m_addr = ((typename Traits::address_t*)bmp->line)[y]+x; + GenericDelegate(Image* bmp, const gfx::Rect& bounds) : + m_bits(bmp, Image::ReadWriteLock, bounds), + m_it(m_bits.begin()), + m_end(m_bits.end()) { } + +private: + LockImageBits m_bits; + +protected: + typename LockImageBits::iterator m_it, m_end; }; class RgbDelegate : public GenericDelegate { BLEND_COLOR m_blender; public: - RgbDelegate() : m_blender(_rgba_blenders[BLEND_MODE_NORMAL]) { } + RgbDelegate(Image* bmp, const gfx::Rect& bounds) : + GenericDelegate(bmp, bounds), + m_blender(rgba_blenders[BLEND_MODE_NORMAL]) { + } - void feedLine(Image* spr, fixed l_spr_x, fixed l_spr_y) { - *m_addr = m_blender(*m_addr, image_getpixel_fast(spr, l_spr_x>>16, l_spr_y>>16), 255); - ++m_addr; + void feedLine(Image* spr, int spr_x, int spr_y) { + ASSERT(m_it != m_end); + + *m_it = m_blender(*m_it, spr->getPixel(spr_x, spr_y), 255); + ++m_it; } }; class GrayscaleDelegate : public GenericDelegate { BLEND_COLOR m_blender; public: - GrayscaleDelegate() : m_blender(_graya_blenders[BLEND_MODE_NORMAL]) { } + GrayscaleDelegate(Image* bmp, const gfx::Rect& bounds) : + GenericDelegate(bmp, bounds), + m_blender(graya_blenders[BLEND_MODE_NORMAL]) { + } - void feedLine(Image* spr, fixed l_spr_x, fixed l_spr_y) { - *m_addr = m_blender(*m_addr, image_getpixel_fast(spr, l_spr_x>>16, l_spr_y>>16), 255); - ++m_addr; + void feedLine(Image* spr, int spr_x, int spr_y) { + ASSERT(m_it != m_end); + + *m_it = m_blender(*m_it, spr->getPixel(spr_x, spr_y), 255); + ++m_it; } }; class IndexedDelegate : public GenericDelegate { public: - void feedLine(Image* spr, fixed l_spr_x, fixed l_spr_y) { - register int c = image_getpixel_fast(spr, l_spr_x>>16, l_spr_y>>16); + IndexedDelegate(Image* bmp, const gfx::Rect& bounds) : + GenericDelegate(bmp, bounds) { + } + + void feedLine(Image* spr, int spr_x, int spr_y) { + ASSERT(m_it != m_end); + + register int c = spr->getPixel(spr_x, spr_y); if (c != 0) // TODO - *m_addr = c; - ++m_addr; + *m_it = c; + ++m_it; } }; class BitmapDelegate : public GenericDelegate { - div_t m_d; public: - void startScan(Image* bmp, int x, int y) { - m_d = div(x, 8); - m_addr = ((BitmapTraits::address_t*)bmp->line)[y] + m_d.quot; + BitmapDelegate(Image* bmp, const gfx::Rect& bounds) : + GenericDelegate(bmp, bounds) { } - void feedLine(Image* spr, fixed l_spr_x, fixed l_spr_y) { - if (image_getpixel_fast(spr, l_spr_x>>16, l_spr_y>>16)) - *m_addr |= (1<getPixel(spr_x, spr_y); + if (c != 0) // TODO + *m_it = c; + ++m_it; } }; @@ -296,11 +315,11 @@ static void ase_parallelogram_map(Image *bmp, Image *spr, fixed xs[4], fixed ys[ corner_spr_y[i] = 0; else /* Need `- 1' since otherwise it would be outside sprite. */ - corner_spr_y[i] = (spr->h << 16) - 1; + corner_spr_y[i] = (spr->getHeight() << 16) - 1; if ((index == 0) || (index == 3)) corner_spr_x[i] = 0; else - corner_spr_x[i] = (spr->w << 16) - 1; + corner_spr_x[i] = (spr->getWidth() << 16) - 1; index = (index + right_index) & 3; } @@ -326,7 +345,7 @@ static void ase_parallelogram_map(Image *bmp, Image *spr, fixed xs[4], fixed ys[ /* Calculate left and right clipping. */ clip_left = 0; - clip_right = (bmp->w << 16) - 1; + clip_right = (bmp->getWidth() << 16) - 1; /* Quit if we're totally outside. */ if ((left_bmp_x > clip_right) && @@ -344,8 +363,8 @@ static void ase_parallelogram_map(Image *bmp, Image *spr, fixed xs[4], fixed ys[ else clip_bottom_i = (bottom_bmp_y + 0x8000) >> 16; - if (clip_bottom_i > bmp->h) - clip_bottom_i = bmp->h; + if (clip_bottom_i > bmp->getHeight()) + clip_bottom_i = bmp->getHeight(); /* Calculate y coordinate of first scanline. */ if (sub_pixel_accuracy) @@ -406,10 +425,10 @@ static void ase_parallelogram_map(Image *bmp, Image *spr, fixed xs[4], fixed ys[ We'd better use double to get this as exact as possible, since any errors will be accumulated along the scanline. */ - spr_dx = (fixed)((ys[3] - ys[0]) * 65536.0 * (65536.0 * spr->w) / + spr_dx = (fixed)((ys[3] - ys[0]) * 65536.0 * (65536.0 * spr->getWidth()) / ((xs[1] - xs[0]) * (double)(ys[3] - ys[0]) - (xs[3] - xs[0]) * (double)(ys[1] - ys[0]))); - spr_dy = (fixed)((ys[1] - ys[0]) * 65536.0 * (65536.0 * spr->h) / + spr_dy = (fixed)((ys[1] - ys[0]) * 65536.0 * (65536.0 * spr->getHeight()) / ((xs[3] - xs[0]) * (double)(ys[1] - ys[0]) - (xs[1] - xs[0]) * (double)(ys[3] - ys[0]))); @@ -516,7 +535,7 @@ static void ase_parallelogram_map(Image *bmp, Image *spr, fixed xs[4], fixed ys[ Drawing a sprite with that routine took about 25% longer time though. */ - if ((unsigned)(l_spr_x_rounded >> 16) >= (unsigned)spr->w) { + if ((unsigned)(l_spr_x_rounded >> 16) >= (unsigned)spr->getWidth()) { if (((l_spr_x_rounded < 0) && (spr_dx <= 0)) || ((l_spr_x_rounded > 0) && (spr_dx >= 0))) { /* This can happen. */ @@ -530,14 +549,14 @@ static void ase_parallelogram_map(Image *bmp, Image *spr, fixed xs[4], fixed ys[ if (l_bmp_x_rounded > r_bmp_x_rounded) goto skip_draw; } while ((unsigned)(l_spr_x_rounded >> 16) >= - (unsigned)spr->w); + (unsigned)spr->getWidth()); } } right_edge_test = l_spr_x_rounded + ((r_bmp_x_rounded - l_bmp_x_rounded) >> 16) * spr_dx; - if ((unsigned)(right_edge_test >> 16) >= (unsigned)spr->w) { + if ((unsigned)(right_edge_test >> 16) >= (unsigned)spr->getWidth()) { if (((right_edge_test < 0) && (spr_dx <= 0)) || ((right_edge_test > 0) && (spr_dx >= 0))) { /* This can happen. */ @@ -547,14 +566,14 @@ static void ase_parallelogram_map(Image *bmp, Image *spr, fixed xs[4], fixed ys[ if (l_bmp_x_rounded > r_bmp_x_rounded) goto skip_draw; } while ((unsigned)(right_edge_test >> 16) >= - (unsigned)spr->w); + (unsigned)spr->getWidth()); } else { /* I don't think this can happen, but I can't prove it. */ goto skip_draw; } } - if ((unsigned)(l_spr_y_rounded >> 16) >= (unsigned)spr->h) { + if ((unsigned)(l_spr_y_rounded >> 16) >= (unsigned)spr->getHeight()) { if (((l_spr_y_rounded < 0) && (spr_dy <= 0)) || ((l_spr_y_rounded > 0) && (spr_dy >= 0))) { /* This can happen. */ @@ -568,13 +587,13 @@ static void ase_parallelogram_map(Image *bmp, Image *spr, fixed xs[4], fixed ys[ if (l_bmp_x_rounded > r_bmp_x_rounded) goto skip_draw; } while (((unsigned)l_spr_y_rounded >> 16) >= - (unsigned)spr->h); + (unsigned)spr->getHeight()); } } right_edge_test = l_spr_y_rounded + ((r_bmp_x_rounded - l_bmp_x_rounded) >> 16) * spr_dy; - if ((unsigned)(right_edge_test >> 16) >= (unsigned)spr->h) { + if ((unsigned)(right_edge_test >> 16) >= (unsigned)spr->getHeight()) { if (((right_edge_test < 0) && (spr_dy <= 0)) || ((right_edge_test > 0) && (spr_dy >= 0))) { /* This can happen. */ @@ -584,7 +603,7 @@ static void ase_parallelogram_map(Image *bmp, Image *spr, fixed xs[4], fixed ys[ if (l_bmp_x_rounded > r_bmp_x_rounded) goto skip_draw; } while ((unsigned)(right_edge_test >> 16) >= - (unsigned)spr->h); + (unsigned)spr->getHeight()); } else { /* I don't think this can happen, but I can't prove it. */ diff --git a/src/raster/sprite.cpp b/src/raster/sprite.cpp index 75d2cfb39..d74237712 100644 --- a/src/raster/sprite.cpp +++ b/src/raster/sprite.cpp @@ -25,6 +25,8 @@ #include "base/memory.h" #include "base/remove_from_container.h" #include "base/unique_ptr.h" +#include "raster/image_bits.h" +#include "raster/primitives.h" #include "raster/raster.h" #include @@ -39,7 +41,7 @@ static LayerIndex layer2index(const Layer* layer, const Layer* find_layer, int* // Constructors/Destructor Sprite::Sprite(PixelFormat format, int width, int height, int ncolors) - : GfxObj(GFXOBJ_SPRITE) + : Object(OBJECT_SPRITE) , m_format(format) , m_width(width) , m_height(height) @@ -68,7 +70,7 @@ Sprite::Sprite(PixelFormat format, int width, int height, int ncolors) for (int c=0; csize(); i++) { image = m_stock->getImage(i); if (image != NULL) - size += image_line_size(image, image->w) * image->h; + size += image->getRowStrideSize() * image->getHeight(); } return size; @@ -358,12 +360,13 @@ void Sprite::remapImages(FrameNumber frameFrom, FrameNumber frameTo, const std:: if (cel->getFrame() >= frameFrom && cel->getFrame() <= frameTo) { Image* image = getStock()->getImage(cel->getImage()); + LockImageBits bits(image); + LockImageBits::iterator + it = bits.begin(), + end = bits.end(); - for (int y=0; yh; ++y) { - IndexedTraits::address_t ptr = image_address_fast(image, 0, y); - for (int x=0; xw; ++x, ++ptr) - *ptr = mapping[*ptr]; - } + for (; it != end; ++it) + *it = mapping[*it]; } } } @@ -373,8 +376,8 @@ void Sprite::remapImages(FrameNumber frameFrom, FrameNumber frameTo, const std:: void Sprite::render(Image* image, int x, int y, FrameNumber frame) const { - image_rectfill(image, x, y, x+m_width-1, y+m_height-1, - (m_format == IMAGE_INDEXED ? getTransparentColor(): 0)); + fill_rect(image, x, y, x+m_width-1, y+m_height-1, + (m_format == IMAGE_INDEXED ? getTransparentColor(): 0)); layer_render(getFolder(), image, x, y, frame); } @@ -385,9 +388,9 @@ int Sprite::getPixel(int x, int y, FrameNumber frame) const if ((x >= 0) && (y >= 0) && (x < m_width) && (y < m_height)) { base::UniquePtr image(Image::create(m_format, 1, 1)); - image_clear(image, (m_format == IMAGE_INDEXED ? getTransparentColor(): 0)); + clear_image(image, (m_format == IMAGE_INDEXED ? getTransparentColor(): 0)); render(image, -x, -y, frame); - color = image_getpixel(image, 0, 0); + color = get_pixel(image, 0, 0); } return color; diff --git a/src/raster/sprite.h b/src/raster/sprite.h index a937e4334..003a3b594 100644 --- a/src/raster/sprite.h +++ b/src/raster/sprite.h @@ -22,7 +22,7 @@ #include "base/disable_copying.h" #include "raster/frame_number.h" #include "raster/layer_index.h" -#include "raster/gfxobj.h" +#include "raster/object.h" #include "raster/pixel_format.h" #include "raster/sprite_position.h" @@ -44,7 +44,7 @@ namespace raster { typedef std::vector PalettesList; // The main structure used in the whole program to handle a sprite. - class Sprite : public GfxObj { + class Sprite : public Object { public: //////////////////////////////////////// diff --git a/src/raster/stock.cpp b/src/raster/stock.cpp index 7f28cf721..f2635f265 100644 --- a/src/raster/stock.cpp +++ b/src/raster/stock.cpp @@ -29,7 +29,7 @@ namespace raster { Stock::Stock(PixelFormat format) - : GfxObj(GFXOBJ_STOCK) + : Object(OBJECT_STOCK) , m_format(format) { // Image with index=0 is always NULL. @@ -37,7 +37,7 @@ Stock::Stock(PixelFormat format) } Stock::Stock(const Stock& stock) - : GfxObj(stock) + : Object(stock) , m_format(stock.getPixelFormat()) { try { diff --git a/src/raster/stock.h b/src/raster/stock.h index 7e0dc511f..9a849b34a 100644 --- a/src/raster/stock.h +++ b/src/raster/stock.h @@ -19,7 +19,7 @@ #ifndef RASTER_STOCK_H_INCLUDED #define RASTER_STOCK_H_INCLUDED -#include "raster/gfxobj.h" +#include "raster/object.h" #include "raster/pixel_format.h" #include @@ -30,7 +30,7 @@ namespace raster { typedef std::vector ImagesList; - class Stock : public GfxObj { + class Stock : public Object { public: Stock(PixelFormat format); Stock(const Stock& stock);