mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-30 04:20:23 +00:00
Refactor filters (effects).
+ Added Filter, FilterManager, and FilterIndexedData interfaces. + Moved all widgets related to filters to src/commands/filters. + Added the filters library. + Added FilterWindow and one derived window for each filter.
This commit is contained in:
parent
d20bd1a31b
commit
a8d9636467
@ -1,19 +1,6 @@
|
||||
<!-- ASE - Allegro Sprite Editor -->
|
||||
<!-- Copyright (C) 2001-2011 by David Capello -->
|
||||
<jinete>
|
||||
<window text="Color Curve" name="color_curve">
|
||||
<box vertical="true">
|
||||
<box horizontal="true" expansive="true">
|
||||
<view expansive="true" name="curve" /><!-- custom widget -->
|
||||
<box vertical="true">
|
||||
<button text="&OK" closewindow="true" name="button_ok" magnetic="true" />
|
||||
<button text="&Cancel" closewindow="true" />
|
||||
<box name="target" />
|
||||
<check text="&Preview" name="preview" />
|
||||
</box>
|
||||
</box>
|
||||
</box>
|
||||
</window>
|
||||
<window text="Point Properties" name="point_properties">
|
||||
<box vertical="true">
|
||||
<box horizontal="true" expansive="true">
|
||||
|
@ -1,64 +1,12 @@
|
||||
<!-- ASE - Allegro Sprite Editor -->
|
||||
<!-- Copyright (C) 2001-2011 by David Capello -->
|
||||
<jinete>
|
||||
<window text="Convolution Matrix" name="convolution_matrix">
|
||||
<box vertical="true">
|
||||
<box horizontal="true" expansive="true">
|
||||
<view expansive="true" name="view" /><!-- custom widget -->
|
||||
<box vertical="true">
|
||||
<button text="&OK" closewindow="true" name="button_ok" magnetic="true" />
|
||||
<button text="&Cancel" closewindow="true" />
|
||||
<box name="target" />
|
||||
<check text="&Preview" name="preview" />
|
||||
<check text="&Tiled" name="tiled" />
|
||||
</box>
|
||||
</box>
|
||||
<box vertical="true" name="controls" expansive="true">
|
||||
<view expansive="true" name="view" minwidth="128" minheight="64">
|
||||
<listbox name="stock" />
|
||||
</view>
|
||||
<box horizontal="true">
|
||||
<button text="&Reload Stock" name="reload" />
|
||||
<button text="&Generate" name="generate" />
|
||||
</box>
|
||||
</box>
|
||||
</window>
|
||||
<window text="Generate New Matrix" name="generate_convolution_matrix">
|
||||
<box vertical="true">
|
||||
<box horizontal="true" expansive="true" homogeneous="true">
|
||||
<box vertical="true" expansive="true">
|
||||
<label text="X axis" />
|
||||
<view expansive="true" name="view_x" /><!-- custom widget -->
|
||||
</box>
|
||||
<box vertical="true" expansive="true">
|
||||
<label text="Y axis" />
|
||||
<view expansive="true" name="view_y" /><!-- custom widget -->
|
||||
</box>
|
||||
</box>
|
||||
<box horizontal="true" homogeneous="true">
|
||||
<box horizontal="true">
|
||||
<box vertical="true" homogeneous="true">
|
||||
<label text="Width:" />
|
||||
<label text="Height:" />
|
||||
</box>
|
||||
<box vertical="true" homogeneous="true" expansive="true">
|
||||
<slider min="1" max="31" name="width" />
|
||||
<slider min="1" max="31" name="height" />
|
||||
</box>
|
||||
<box vertical="true" homogeneous="true">
|
||||
<label text="Div:" />
|
||||
<label text="Bias:" />
|
||||
</box>
|
||||
<box vertical="true" homogeneous="true" expansive="true">
|
||||
<entry maxsize="32" name="div" />
|
||||
<entry maxsize="32" name="bias" />
|
||||
</box>
|
||||
<box vertical="true" homogeneous="true">
|
||||
<check text="Auto" name="div_auto" />
|
||||
<check text="Auto" name="bias_auto" />
|
||||
</box>
|
||||
</box>
|
||||
</box>
|
||||
<box horizontal="true" homogeneous="true">
|
||||
<button text="&OK" closewindow="true" name="button_ok" magnetic="true" />
|
||||
<button text="&Cancel" closewindow="true" />
|
||||
</box>
|
||||
</box>
|
||||
</window>
|
||||
</jinete>
|
||||
|
10
data/widgets/despeckle.xml
Normal file
10
data/widgets/despeckle.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<!-- ASE - Allegro Sprite Editor -->
|
||||
<!-- Copyright (C) 2001-2011 by David Capello -->
|
||||
<jinete>
|
||||
<grid columns="2" name="controls">
|
||||
<label text="Width:" />
|
||||
<entry name="width" maxsize="4" cell_align="horizontal" />
|
||||
<label text="Height:" />
|
||||
<entry name="height" maxsize="4" cell_align="horizontal" />
|
||||
</grid>
|
||||
</jinete>
|
@ -1,14 +0,0 @@
|
||||
<!-- ASE - Allegro Sprite Editor -->
|
||||
<!-- Copyright (C) 2001-2011 by David Capello -->
|
||||
<jinete>
|
||||
<window text="Invert Color" name="invert_color">
|
||||
<box vertical="true">
|
||||
<box vertical="true" expansive="true" name="target" />
|
||||
<check text="&Preview" name="preview" />
|
||||
<box horizontal="true" homogeneous="true">
|
||||
<button text="&OK" closewindow="true" name="button_ok" magnetic="true" />
|
||||
<button text="&Cancel" closewindow="true" />
|
||||
</box>
|
||||
</box>
|
||||
</window>
|
||||
</jinete>
|
@ -1,29 +0,0 @@
|
||||
<!-- ASE - Allegro Sprite Editor -->
|
||||
<!-- Copyright (C) 2001-2011 by David Capello -->
|
||||
<jinete>
|
||||
<window text="Median Blur" name="median">
|
||||
<box vertical="true">
|
||||
<box horizontal="true">
|
||||
<box horizontal="true" expansive="true">
|
||||
<box vertical="true" homogeneous="true">
|
||||
<label text="Width:" />
|
||||
<label text="Height:" />
|
||||
</box>
|
||||
<box vertical="true" homogeneous="true" expansive="true">
|
||||
<entry expansive="true" name="width" maxsize="4" />
|
||||
<entry expansive="true" name="height" maxsize="4" />
|
||||
</box>
|
||||
</box>
|
||||
<box vertical="true">
|
||||
<box name="target" />
|
||||
<check text="&Preview" name="preview" />
|
||||
<check text="&Tiled" name="tiled" />
|
||||
</box>
|
||||
</box>
|
||||
<box horizontal="true" homogeneous="true" expansive="true">
|
||||
<button text="&OK" closewindow="true" name="button_ok" magnetic="true" />
|
||||
<button text="&Cancel" closewindow="true" />
|
||||
</box>
|
||||
</box>
|
||||
</window>
|
||||
</jinete>
|
@ -1,25 +1,16 @@
|
||||
<!-- ASE - Allegro Sprite Editor -->
|
||||
<!-- Copyright (C) 2001-2011 by David Capello -->
|
||||
<jinete>
|
||||
<window text="Replace Color" name="replace_color">
|
||||
<box horizontal="true">
|
||||
<box vertical="true" expansive="true">
|
||||
<box horizontal="true" expansive="true">
|
||||
<box vertical="true" homogeneous="true">
|
||||
<label text="From:" />
|
||||
<label text="To:" />
|
||||
</box>
|
||||
<box vertical="true" homogeneous="true" expansive="true" name="color_buttons_box" />
|
||||
</box>
|
||||
<label text="Tolerance:" />
|
||||
<slider min="0" max="255" name="tolerance" />
|
||||
</box>
|
||||
<box vertical="true">
|
||||
<button text="&OK" closewindow="true" name="button_ok" magnetic="true" />
|
||||
<button text="&Cancel" closewindow="true" />
|
||||
<box name="target" />
|
||||
<check text="&Preview" name="preview" />
|
||||
<box vertical="true" expansive="true" name="controls">
|
||||
<box horizontal="true" expansive="true">
|
||||
<grid columns="2" name="controls">
|
||||
<label text="From:" />
|
||||
<colorpicker name="from" cell_align="horizontal" />
|
||||
<label text="To:" />
|
||||
<colorpicker name="to" cell_align="horizontal" />
|
||||
</grid>
|
||||
</box>
|
||||
<label text="Tolerance:" />
|
||||
<slider min="0" max="255" name="tolerance" />
|
||||
</box>
|
||||
</window>
|
||||
</jinete>
|
||||
|
@ -43,7 +43,7 @@ else()
|
||||
endif()
|
||||
|
||||
# All libraries for .exe files
|
||||
set(all_libs aseprite-library gui-lib gfx-lib base-lib ${libs3rdparty} allegro ${sys_libs})
|
||||
set(all_libs filters-lib aseprite-library gui-lib gfx-lib base-lib ${libs3rdparty} allegro ${sys_libs})
|
||||
|
||||
# Directories where .h files can be found
|
||||
include_directories(
|
||||
@ -63,6 +63,7 @@ add_subdirectory(allegro)
|
||||
add_subdirectory(base)
|
||||
add_subdirectory(gfx)
|
||||
add_subdirectory(gui)
|
||||
add_subdirectory(filters)
|
||||
|
||||
######################################################################
|
||||
# aseprite library
|
||||
@ -151,12 +152,18 @@ add_library(aseprite-library
|
||||
commands/cmd_undo.cpp
|
||||
commands/command.cpp
|
||||
commands/commands.cpp
|
||||
commands/fx/cmd_color_curve.cpp
|
||||
commands/fx/cmd_convolution_matrix.cpp
|
||||
commands/fx/cmd_despeckle.cpp
|
||||
commands/fx/cmd_invert_color.cpp
|
||||
commands/fx/cmd_replace_color.cpp
|
||||
commands/fx/effectbg.cpp
|
||||
commands/filters/cmd_color_curve.cpp
|
||||
commands/filters/cmd_convolution_matrix.cpp
|
||||
commands/filters/cmd_despeckle.cpp
|
||||
commands/filters/cmd_invert_color.cpp
|
||||
commands/filters/cmd_replace_color.cpp
|
||||
commands/filters/color_curve_editor.cpp
|
||||
commands/filters/convolution_matrix_stock.cpp
|
||||
commands/filters/filter_manager_impl.cpp
|
||||
commands/filters/filter_preview.cpp
|
||||
commands/filters/filter_target_buttons.cpp
|
||||
commands/filters/filter_window.cpp
|
||||
commands/filters/filter_worker.cpp
|
||||
core/cfg.cpp
|
||||
core/drop_files.cpp
|
||||
core/file_system.cpp
|
||||
@ -168,12 +175,6 @@ add_library(aseprite-library
|
||||
dialogs/playfli.cpp
|
||||
dialogs/repo.cpp
|
||||
dialogs/vectmap.cpp
|
||||
effect/colcurve.cpp
|
||||
effect/convmatr.cpp
|
||||
effect/effect.cpp
|
||||
effect/invrtcol.cpp
|
||||
effect/median.cpp
|
||||
effect/replcol.cpp
|
||||
file/ase_format.cpp
|
||||
file/bmp_format.cpp
|
||||
file/file.cpp
|
||||
@ -234,7 +235,6 @@ add_library(aseprite-library
|
||||
widgets/color_button.cpp
|
||||
widgets/color_selector.cpp
|
||||
widgets/color_sliders.cpp
|
||||
widgets/curvedit.cpp
|
||||
widgets/editor/click.cpp
|
||||
widgets/editor/cursor.cpp
|
||||
widgets/editor/editor.cpp
|
||||
@ -245,10 +245,8 @@ add_library(aseprite-library
|
||||
widgets/hex_color_entry.cpp
|
||||
widgets/menuitem.cpp
|
||||
widgets/palette_view.cpp
|
||||
widgets/preview.cpp
|
||||
widgets/statebar.cpp
|
||||
widgets/tabs.cpp
|
||||
widgets/target.cpp
|
||||
widgets/toolbar.cpp)
|
||||
|
||||
######################################################################
|
||||
|
149
src/commands/filters/cmd_color_curve.cpp
Normal file
149
src/commands/filters/cmd_color_curve.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "app.h"
|
||||
#include "app/color.h"
|
||||
#include "base/bind.h"
|
||||
#include "commands/command.h"
|
||||
#include "commands/filters/color_curve_editor.h"
|
||||
#include "commands/filters/filter_manager_impl.h"
|
||||
#include "commands/filters/filter_window.h"
|
||||
#include "core/cfg.h"
|
||||
#include "filters/color_curve.h"
|
||||
#include "filters/color_curve_filter.h"
|
||||
#include "gui/gui.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "sprite_wrappers.h"
|
||||
#include "widgets/color_button.h"
|
||||
|
||||
static ColorCurve* the_curve = NULL;
|
||||
|
||||
// Slot for App::Exit signal
|
||||
static void on_exit_delete_curve()
|
||||
{
|
||||
delete the_curve;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Color Curve window
|
||||
|
||||
class ColorCurveWindow : public FilterWindow
|
||||
{
|
||||
public:
|
||||
ColorCurveWindow(ColorCurveFilter& filter, FilterManagerImpl& filterMgr)
|
||||
: FilterWindow("Color Curve", "ColorCurve", &filterMgr,
|
||||
WithChannelsSelector,
|
||||
WithoutTiledCheckBox)
|
||||
, m_filter(filter)
|
||||
, m_editor(filter.getCurve(), 0, 0, 255, 255)
|
||||
{
|
||||
m_view.attachToView(&m_editor);
|
||||
jwidget_expansive(&m_view, true);
|
||||
jwidget_set_min_size(&m_view, 128, 64);
|
||||
|
||||
jwidget_add_child(getContainer(), &m_view);
|
||||
|
||||
m_editor.CurveEditorChange.connect(&ColorCurveWindow::onCurveChange, this);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void onCurveChange()
|
||||
{
|
||||
// The color curve in the filter is the same refereced by the
|
||||
// editor. But anyway, we have to re-set the same curve in the
|
||||
// filter to regenerate the map used internally by the filter
|
||||
// (which is calculated inside setCurve() method).
|
||||
m_filter.setCurve(m_editor.getCurve());
|
||||
|
||||
restartPreview();
|
||||
}
|
||||
|
||||
private:
|
||||
ColorCurveFilter& m_filter;
|
||||
View m_view;
|
||||
ColorCurveEditor m_editor;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Color Curve command
|
||||
|
||||
class ColorCurveCommand : public Command
|
||||
{
|
||||
public:
|
||||
ColorCurveCommand();
|
||||
Command* clone() const { return new ColorCurveCommand(*this); }
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* context);
|
||||
void onExecute(Context* context);
|
||||
};
|
||||
|
||||
ColorCurveCommand::ColorCurveCommand()
|
||||
: Command("ColorCurve",
|
||||
"Color Curve",
|
||||
CmdRecordableFlag)
|
||||
{
|
||||
}
|
||||
|
||||
bool ColorCurveCommand::onEnabled(Context* context)
|
||||
{
|
||||
const CurrentSpriteReader sprite(context);
|
||||
return sprite != NULL;
|
||||
}
|
||||
|
||||
void ColorCurveCommand::onExecute(Context* context)
|
||||
{
|
||||
// Default curve
|
||||
if (!the_curve) {
|
||||
// TODO load the curve?
|
||||
|
||||
the_curve = new ColorCurve(ColorCurve::Linear);
|
||||
the_curve->addPoint(gfx::Point(0, 0));
|
||||
the_curve->addPoint(gfx::Point(255, 255));
|
||||
|
||||
App::instance()->Exit.connect(&on_exit_delete_curve);
|
||||
}
|
||||
|
||||
ColorCurveFilter filter;
|
||||
filter.setCurve(the_curve);
|
||||
|
||||
FilterManagerImpl filterMgr(context->getCurrentSprite(), &filter);
|
||||
filterMgr.setTarget(TARGET_RED_CHANNEL |
|
||||
TARGET_GREEN_CHANNEL |
|
||||
TARGET_BLUE_CHANNEL |
|
||||
TARGET_GRAY_CHANNEL |
|
||||
TARGET_ALPHA_CHANNEL);
|
||||
|
||||
ColorCurveWindow window(filter, filterMgr);
|
||||
if (window.doModal()) {
|
||||
// TODO save the curve?
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CommandFactory
|
||||
|
||||
Command* CommandFactory::createColorCurveCommand()
|
||||
{
|
||||
return new ColorCurveCommand;
|
||||
}
|
221
src/commands/filters/cmd_convolution_matrix.cpp
Normal file
221
src/commands/filters/cmd_convolution_matrix.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "app/color.h"
|
||||
#include "base/bind.h"
|
||||
#include "commands/command.h"
|
||||
#include "commands/filters/convolution_matrix_stock.h"
|
||||
#include "commands/filters/filter_manager_impl.h"
|
||||
#include "commands/filters/filter_window.h"
|
||||
#include "core/cfg.h"
|
||||
#include "filters/convolution_matrix.h"
|
||||
#include "filters/convolution_matrix_filter.h"
|
||||
#include "gui/button.h"
|
||||
#include "gui/frame.h"
|
||||
#include "gui/label.h"
|
||||
#include "gui/list.h"
|
||||
#include "gui/listbox.h"
|
||||
#include "gui/slider.h"
|
||||
#include "gui/view.h"
|
||||
#include "gui/widget.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "sprite_wrappers.h"
|
||||
|
||||
static const char* ConfigSection = "ConvolutionMatrix";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Convolution Matrix window
|
||||
|
||||
class ConvolutionMatrixWindow : public FilterWindow
|
||||
{
|
||||
public:
|
||||
ConvolutionMatrixWindow(ConvolutionMatrixFilter& filter, FilterManagerImpl& filterMgr, ConvolutionMatrixStock& stock)
|
||||
: FilterWindow("Convolution Matrix", ConfigSection, &filterMgr,
|
||||
WithChannelsSelector,
|
||||
WithTiledCheckBox,
|
||||
filter.getTiledMode())
|
||||
, m_filter(filter)
|
||||
, m_controlsWidget(load_widget("convolution_matrix.xml", "controls"))
|
||||
, m_stock(stock)
|
||||
{
|
||||
get_widgets(m_controlsWidget,
|
||||
"view", &m_view,
|
||||
"stock", &m_stockListBox,
|
||||
"reload", &m_reloadButton, NULL);
|
||||
|
||||
jwidget_add_child(getContainer(), m_controlsWidget);
|
||||
|
||||
m_reloadButton->Click.connect(&ConvolutionMatrixWindow::onReloadStock, this);
|
||||
// TODO convert listbox to c++ class ListBox
|
||||
//m_stockListBox->Change.connect(Bind<void>(&ConvolutionMatrixWindow::onMatrixChange, this));
|
||||
hook_signal(m_stockListBox, JI_SIGNAL_LISTBOX_CHANGE, &ConvolutionMatrixWindow::listboxChangeHandler, this);
|
||||
|
||||
fillStockListBox();
|
||||
}
|
||||
|
||||
private:
|
||||
void onReloadStock(Event& ev)
|
||||
{
|
||||
m_stock.reloadStock();
|
||||
fillStockListBox();
|
||||
}
|
||||
|
||||
void setupTiledMode(TiledMode tiledMode)
|
||||
{
|
||||
m_filter.setTiledMode(tiledMode);
|
||||
}
|
||||
|
||||
void fillStockListBox()
|
||||
{
|
||||
const char* oldSelected = (m_filter.getMatrix() ? m_filter.getMatrix()->getName(): NULL);
|
||||
JLink link, next;
|
||||
|
||||
// Clean the list
|
||||
JI_LIST_FOR_EACH_SAFE(m_stockListBox->children, link, next) {
|
||||
Widget* listitem = reinterpret_cast<Widget*>(link->data);
|
||||
jwidget_remove_child(m_stockListBox, listitem);
|
||||
jwidget_free(listitem);
|
||||
}
|
||||
|
||||
for (ConvolutionMatrixStock::iterator it = m_stock.begin(), end = m_stock.end();
|
||||
it != end; ++it) {
|
||||
SharedPtr<ConvolutionMatrix> matrix = *it;
|
||||
Widget* listitem = jlistitem_new(matrix->getName()); // TODO convert listitem to a class
|
||||
jwidget_add_child(m_stockListBox, listitem);
|
||||
}
|
||||
|
||||
selectMatrixByName(oldSelected);
|
||||
}
|
||||
|
||||
void selectMatrixByName(const char* oldSelected)
|
||||
{
|
||||
Widget* select_this = reinterpret_cast<Widget*>(jlist_first_data(m_stockListBox->children));
|
||||
|
||||
if (oldSelected) {
|
||||
JLink link;
|
||||
JI_LIST_FOR_EACH(m_stockListBox->children, link) {
|
||||
Widget* child = reinterpret_cast<Widget*>(link->data);
|
||||
|
||||
if (strcmp(child->getText(), oldSelected) == 0) {
|
||||
select_this = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (select_this) {
|
||||
select_this->setSelected(true);
|
||||
onMatrixChange();
|
||||
}
|
||||
|
||||
m_view->updateView();
|
||||
}
|
||||
|
||||
void onMatrixChange()
|
||||
{
|
||||
Widget* selected = jlistbox_get_selected_child(m_stockListBox);
|
||||
SharedPtr<ConvolutionMatrix> matrix = m_stock.getByName(selected->getText());
|
||||
Target newTarget = matrix->getDefaultTarget();
|
||||
|
||||
m_filter.setMatrix(matrix);
|
||||
|
||||
setNewTarget(newTarget);
|
||||
|
||||
restartPreview();
|
||||
}
|
||||
|
||||
// TODO This function must be removed if ListBox C++ class is added.
|
||||
static bool listboxChangeHandler(Widget* widget, void *data)
|
||||
{
|
||||
ConvolutionMatrixWindow* window = (ConvolutionMatrixWindow*)data;
|
||||
window->onMatrixChange();
|
||||
return true;
|
||||
}
|
||||
|
||||
ConvolutionMatrixFilter& m_filter;
|
||||
WidgetPtr m_controlsWidget;
|
||||
ConvolutionMatrixStock& m_stock;
|
||||
View* m_view;
|
||||
Widget* m_stockListBox;
|
||||
Button* m_reloadButton;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Convolution Matrix command
|
||||
|
||||
class ConvolutionMatrixCommand : public Command
|
||||
{
|
||||
public:
|
||||
ConvolutionMatrixCommand();
|
||||
Command* clone() const { return new ConvolutionMatrixCommand(*this); }
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* context);
|
||||
void onExecute(Context* context);
|
||||
};
|
||||
|
||||
ConvolutionMatrixCommand::ConvolutionMatrixCommand()
|
||||
: Command("ConvolutionMatrix",
|
||||
"Convolution Matrix",
|
||||
CmdRecordableFlag)
|
||||
{
|
||||
}
|
||||
|
||||
bool ConvolutionMatrixCommand::onEnabled(Context* context)
|
||||
{
|
||||
const CurrentSpriteReader sprite(context);
|
||||
return sprite != NULL;
|
||||
}
|
||||
|
||||
void ConvolutionMatrixCommand::onExecute(Context* context)
|
||||
{
|
||||
// Load stock
|
||||
ConvolutionMatrixStock m_stock;
|
||||
|
||||
// Get last used (selected) matrix
|
||||
SharedPtr<ConvolutionMatrix> matrix =
|
||||
m_stock.getByName(get_config_string(ConfigSection, "Selected", ""));
|
||||
|
||||
// Create the filter and setup initial settings
|
||||
ConvolutionMatrixFilter filter;
|
||||
filter.setTiledMode(context->getSettings()->getTiledMode());
|
||||
if (matrix != 0)
|
||||
filter.setMatrix(matrix);
|
||||
|
||||
FilterManagerImpl filterMgr(context->getCurrentSprite(), &filter);
|
||||
|
||||
ConvolutionMatrixWindow window(filter, filterMgr, m_stock);
|
||||
if (window.doModal()) {
|
||||
if (filter.getMatrix() != NULL)
|
||||
set_config_string(ConfigSection, "Selected", filter.getMatrix()->getName());
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CommandFactory
|
||||
|
||||
Command* CommandFactory::createConvolutionMatrixCommand()
|
||||
{
|
||||
return new ConvolutionMatrixCommand;
|
||||
}
|
142
src/commands/filters/cmd_despeckle.cpp
Normal file
142
src/commands/filters/cmd_despeckle.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "commands/command.h"
|
||||
#include "commands/filters/filter_manager_impl.h"
|
||||
#include "commands/filters/filter_window.h"
|
||||
#include "core/cfg.h"
|
||||
#include "filters/median_filter.h"
|
||||
#include "gui/button.h"
|
||||
#include "gui/entry.h"
|
||||
#include "gui/frame.h"
|
||||
#include "gui/grid.h"
|
||||
#include "gui/widget.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "settings/settings.h"
|
||||
#include "sprite_wrappers.h"
|
||||
|
||||
static const char* ConfigSection = "Despeckle";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Despeckle window
|
||||
|
||||
class DespeckleWindow : public FilterWindow
|
||||
{
|
||||
public:
|
||||
DespeckleWindow(MedianFilter& filter, FilterManagerImpl& filterMgr)
|
||||
: FilterWindow("Median Blur", ConfigSection, &filterMgr,
|
||||
WithChannelsSelector,
|
||||
WithTiledCheckBox,
|
||||
filter.getTiledMode())
|
||||
, m_filter(filter)
|
||||
, m_controlsWidget(load_widget("despeckle.xml", "controls"))
|
||||
{
|
||||
get_widgets(m_controlsWidget,
|
||||
"width", &m_widthEntry,
|
||||
"height", &m_heightEntry, NULL);
|
||||
|
||||
jwidget_add_child(getContainer(), m_controlsWidget);
|
||||
|
||||
m_widthEntry->setTextf("%d", m_filter.getWidth());
|
||||
m_heightEntry->setTextf("%d", m_filter.getHeight());
|
||||
|
||||
m_widthEntry->EntryChange.connect(&DespeckleWindow::onSizeChange, this);
|
||||
m_heightEntry->EntryChange.connect(&DespeckleWindow::onSizeChange, this);
|
||||
}
|
||||
|
||||
private:
|
||||
void onSizeChange()
|
||||
{
|
||||
m_filter.setSize(m_widthEntry->getTextInt(),
|
||||
m_heightEntry->getTextInt());
|
||||
restartPreview();
|
||||
}
|
||||
|
||||
void setupTiledMode(TiledMode tiledMode)
|
||||
{
|
||||
m_filter.setTiledMode(tiledMode);
|
||||
}
|
||||
|
||||
MedianFilter& m_filter;
|
||||
WidgetPtr m_controlsWidget;
|
||||
Entry* m_widthEntry;
|
||||
Entry* m_heightEntry;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Despeckle command
|
||||
|
||||
class DespeckleCommand : public Command
|
||||
{
|
||||
public:
|
||||
DespeckleCommand();
|
||||
Command* clone() const { return new DespeckleCommand(*this); }
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* context);
|
||||
void onExecute(Context* context);
|
||||
};
|
||||
|
||||
DespeckleCommand::DespeckleCommand()
|
||||
: Command("Despeckle",
|
||||
"Despeckle",
|
||||
CmdRecordableFlag)
|
||||
{
|
||||
}
|
||||
|
||||
bool DespeckleCommand::onEnabled(Context* context)
|
||||
{
|
||||
const CurrentSpriteReader sprite(context);
|
||||
return sprite != NULL;
|
||||
}
|
||||
|
||||
void DespeckleCommand::onExecute(Context* context)
|
||||
{
|
||||
MedianFilter filter;
|
||||
filter.setTiledMode(context->getSettings()->getTiledMode());
|
||||
filter.setSize(get_config_int(ConfigSection, "Width", 3),
|
||||
get_config_int(ConfigSection, "Height", 3));
|
||||
|
||||
FilterManagerImpl filterMgr(context->getCurrentSprite(), &filter);
|
||||
filterMgr.setTarget(TARGET_RED_CHANNEL |
|
||||
TARGET_GREEN_CHANNEL |
|
||||
TARGET_BLUE_CHANNEL |
|
||||
TARGET_GRAY_CHANNEL);
|
||||
|
||||
DespeckleWindow window(filter, filterMgr);
|
||||
if (window.doModal()) {
|
||||
set_config_int(ConfigSection, "Width", filter.getWidth());
|
||||
set_config_int(ConfigSection, "Height", filter.getHeight());
|
||||
context->getSettings()->setTiledMode(filter.getTiledMode());
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CommandFactory
|
||||
|
||||
Command* CommandFactory::createDespeckleCommand()
|
||||
{
|
||||
return new DespeckleCommand;
|
||||
}
|
106
src/commands/filters/cmd_invert_color.cpp
Normal file
106
src/commands/filters/cmd_invert_color.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "app/color.h"
|
||||
#include "base/bind.h"
|
||||
#include "commands/command.h"
|
||||
#include "commands/filters/filter_manager_impl.h"
|
||||
#include "commands/filters/filter_window.h"
|
||||
#include "core/cfg.h"
|
||||
#include "filters/invert_color_filter.h"
|
||||
#include "gui/button.h"
|
||||
#include "gui/frame.h"
|
||||
#include "gui/label.h"
|
||||
#include "gui/slider.h"
|
||||
#include "gui/widget.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "sprite_wrappers.h"
|
||||
#include "widgets/color_button.h"
|
||||
|
||||
static const char* ConfigSection = "InvertColor";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Invert Color window
|
||||
|
||||
class InvertColorWindow : public FilterWindow
|
||||
{
|
||||
public:
|
||||
InvertColorWindow(InvertColorFilter& filter, FilterManagerImpl& filterMgr)
|
||||
: FilterWindow("Invert Color", ConfigSection, &filterMgr,
|
||||
WithChannelsSelector,
|
||||
WithoutTiledCheckBox)
|
||||
, m_filter(filter)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
InvertColorFilter& m_filter;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Invert Color command
|
||||
|
||||
class InvertColorCommand : public Command
|
||||
{
|
||||
public:
|
||||
InvertColorCommand();
|
||||
Command* clone() const { return new InvertColorCommand(*this); }
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* context);
|
||||
void onExecute(Context* context);
|
||||
};
|
||||
|
||||
InvertColorCommand::InvertColorCommand()
|
||||
: Command("InvertColor",
|
||||
"Invert Color",
|
||||
CmdRecordableFlag)
|
||||
{
|
||||
}
|
||||
|
||||
bool InvertColorCommand::onEnabled(Context* context)
|
||||
{
|
||||
const CurrentSpriteReader sprite(context);
|
||||
return sprite != NULL;
|
||||
}
|
||||
|
||||
void InvertColorCommand::onExecute(Context* context)
|
||||
{
|
||||
InvertColorFilter filter;
|
||||
FilterManagerImpl filterMgr(context->getCurrentSprite(), &filter);
|
||||
filterMgr.setTarget(TARGET_RED_CHANNEL |
|
||||
TARGET_GREEN_CHANNEL |
|
||||
TARGET_BLUE_CHANNEL |
|
||||
TARGET_GRAY_CHANNEL);
|
||||
|
||||
InvertColorWindow window(filter, filterMgr);
|
||||
window.doModal();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CommandFactory
|
||||
|
||||
Command* CommandFactory::createInvertColorCommand()
|
||||
{
|
||||
return new InvertColorCommand;
|
||||
}
|
182
src/commands/filters/cmd_replace_color.cpp
Normal file
182
src/commands/filters/cmd_replace_color.cpp
Normal file
@ -0,0 +1,182 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "app.h"
|
||||
#include "app/color.h"
|
||||
#include "app/color_utils.h"
|
||||
#include "base/bind.h"
|
||||
#include "commands/command.h"
|
||||
#include "commands/filters/filter_window.h"
|
||||
#include "commands/filters/filter_manager_impl.h"
|
||||
#include "core/cfg.h"
|
||||
#include "filters/replace_color_filter.h"
|
||||
#include "gui/gui.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "sprite_wrappers.h"
|
||||
#include "widgets/color_bar.h"
|
||||
#include "widgets/color_button.h"
|
||||
|
||||
static const char* ConfigSection = "ReplaceColor";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Wrapper for ReplaceColorFilter to handle colors in an easy way
|
||||
|
||||
class ReplaceColorFilterWrapper : public ReplaceColorFilter
|
||||
{
|
||||
public:
|
||||
ReplaceColorFilterWrapper(Layer* layer) : m_layer(layer) { }
|
||||
|
||||
void setFrom(const Color& from) {
|
||||
m_from = from;
|
||||
ReplaceColorFilter::setFrom(color_utils::color_for_layer(from, m_layer));
|
||||
}
|
||||
void setTo(const Color& to) {
|
||||
m_to = to;
|
||||
ReplaceColorFilter::setTo(color_utils::color_for_layer(to, m_layer));
|
||||
}
|
||||
|
||||
Color getFrom() const { return m_from; }
|
||||
Color getTo() const { return m_to; }
|
||||
|
||||
private:
|
||||
Layer* m_layer;
|
||||
Color m_from;
|
||||
Color m_to;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Replace Color window
|
||||
|
||||
class ReplaceColorWindow : public FilterWindow
|
||||
{
|
||||
public:
|
||||
ReplaceColorWindow(ReplaceColorFilterWrapper& filter, FilterManagerImpl& filterMgr)
|
||||
: FilterWindow("Replace Color", ConfigSection, &filterMgr,
|
||||
WithChannelsSelector,
|
||||
WithoutTiledCheckBox)
|
||||
, m_filter(filter)
|
||||
, m_controlsWidget(load_widget("replace_color.xml", "controls"))
|
||||
{
|
||||
get_widgets(m_controlsWidget,
|
||||
"from", &m_fromButton,
|
||||
"to", &m_toButton,
|
||||
"tolerance", &m_toleranceSlider, NULL);
|
||||
|
||||
jwidget_add_child(getContainer(), m_controlsWidget);
|
||||
|
||||
m_fromButton->setColor(m_filter.getFrom());
|
||||
m_toButton->setColor(m_filter.getTo());
|
||||
m_toleranceSlider->setValue(m_filter.getTolerance());
|
||||
|
||||
m_fromButton->Change.connect(&ReplaceColorWindow::onFromChange, this);
|
||||
m_toButton->Change.connect(&ReplaceColorWindow::onToChange, this);
|
||||
m_toleranceSlider->Change.connect(&ReplaceColorWindow::onToleranceChange, this);
|
||||
}
|
||||
|
||||
protected:
|
||||
void onFromChange(const Color& color)
|
||||
{
|
||||
m_filter.setFrom(color);
|
||||
restartPreview();
|
||||
}
|
||||
|
||||
void onToChange(const Color& color)
|
||||
{
|
||||
m_filter.setTo(color);
|
||||
restartPreview();
|
||||
}
|
||||
|
||||
void onToleranceChange()
|
||||
{
|
||||
m_filter.setTolerance(m_toleranceSlider->getValue());
|
||||
restartPreview();
|
||||
}
|
||||
|
||||
private:
|
||||
ReplaceColorFilterWrapper& m_filter;
|
||||
WidgetPtr m_controlsWidget;
|
||||
ColorButton* m_fromButton;
|
||||
ColorButton* m_toButton;
|
||||
Slider* m_toleranceSlider;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Replace Color command
|
||||
|
||||
class ReplaceColorCommand : public Command
|
||||
{
|
||||
public:
|
||||
ReplaceColorCommand();
|
||||
Command* clone() const { return new ReplaceColorCommand(*this); }
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* context);
|
||||
void onExecute(Context* context);
|
||||
};
|
||||
|
||||
ReplaceColorCommand::ReplaceColorCommand()
|
||||
: Command("ReplaceColor",
|
||||
"Replace Color",
|
||||
CmdRecordableFlag)
|
||||
{
|
||||
}
|
||||
|
||||
bool ReplaceColorCommand::onEnabled(Context* context)
|
||||
{
|
||||
const CurrentSpriteReader sprite(context);
|
||||
return sprite != NULL;
|
||||
}
|
||||
|
||||
void ReplaceColorCommand::onExecute(Context* context)
|
||||
{
|
||||
Sprite* sprite = context->getCurrentSprite();
|
||||
|
||||
ReplaceColorFilterWrapper filter(sprite->getCurrentLayer());
|
||||
filter.setFrom(get_config_color(ConfigSection, "Color1", app_get_colorbar()->getFgColor()));
|
||||
filter.setTo(get_config_color(ConfigSection, "Color2", app_get_colorbar()->getBgColor()));
|
||||
filter.setTolerance(get_config_int(ConfigSection, "Tolerance", 0));
|
||||
|
||||
FilterManagerImpl filterMgr(sprite, &filter);
|
||||
filterMgr.setTarget(TARGET_RED_CHANNEL |
|
||||
TARGET_GREEN_CHANNEL |
|
||||
TARGET_BLUE_CHANNEL |
|
||||
TARGET_GRAY_CHANNEL |
|
||||
TARGET_ALPHA_CHANNEL);
|
||||
|
||||
ReplaceColorWindow window(filter, filterMgr);
|
||||
if (window.doModal()) {
|
||||
set_config_color(ConfigSection, "From", filter.getFrom());
|
||||
set_config_color(ConfigSection, "To", filter.getTo());
|
||||
set_config_int(ConfigSection, "Tolerance", filter.getTolerance());
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CommandFactory
|
||||
|
||||
Command* CommandFactory::createReplaceColorCommand()
|
||||
{
|
||||
return new ReplaceColorCommand;
|
||||
}
|
381
src/commands/filters/color_curve_editor.cpp
Normal file
381
src/commands/filters/color_curve_editor.cpp
Normal file
@ -0,0 +1,381 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <allegro.h>
|
||||
#include <cmath>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
|
||||
#include "commands/filters/color_curve_editor.h"
|
||||
#include "filters/color_curve.h"
|
||||
#include "gui/alert.h"
|
||||
#include "gui/entry.h"
|
||||
#include "gui/frame.h"
|
||||
#include "gui/manager.h"
|
||||
#include "gui/message.h"
|
||||
#include "gui/rect.h"
|
||||
#include "gui/system.h"
|
||||
#include "gui/view.h"
|
||||
#include "gui/widget.h"
|
||||
#include "modules/gui.h"
|
||||
|
||||
#define SCR2EDIT_X(xpos) \
|
||||
(m_x1 + \
|
||||
((m_x2 - m_x1 + 1) \
|
||||
* ((xpos) - rc->x1 - border_width.l) \
|
||||
/ (jrect_w(rc) - border_width.l - border_width.r)))
|
||||
|
||||
#define SCR2EDIT_Y(ypos) \
|
||||
(m_y1 + \
|
||||
((m_y2 - m_y1 + 1) \
|
||||
* ((jrect_h(rc) - border_width.t - border_width.b) \
|
||||
- ((ypos) - rc->y1 - border_width.t)) \
|
||||
/ (jrect_h(rc) - border_width.t - border_width.b)))
|
||||
|
||||
#define EDIT2SCR_X(xpos) \
|
||||
(rc->x1 + border_width.l \
|
||||
+ ((jrect_w(rc) - border_width.l - border_width.r) \
|
||||
* ((xpos) - m_x1) \
|
||||
/ (m_x2 - m_x1 + 1)))
|
||||
|
||||
#define EDIT2SCR_Y(ypos) \
|
||||
(rc->y1 \
|
||||
+ (jrect_h(rc) - border_width.t - border_width.b) \
|
||||
- ((jrect_h(rc) - border_width.t - border_width.b) \
|
||||
* ((ypos) - m_y1) \
|
||||
/ (m_y2 - m_y1 + 1)))
|
||||
|
||||
enum {
|
||||
STATUS_STANDBY,
|
||||
STATUS_MOVING_POINT,
|
||||
STATUS_SCROLLING,
|
||||
STATUS_SCALING,
|
||||
};
|
||||
|
||||
ColorCurveEditor::ColorCurveEditor(ColorCurve* curve, int x1, int y1, int x2, int y2)
|
||||
: Widget(JI_WIDGET)
|
||||
, m_curve(curve)
|
||||
{
|
||||
jwidget_focusrest(this, true);
|
||||
|
||||
border_width.l = border_width.r = 1;
|
||||
border_width.t = border_width.b = 1;
|
||||
child_spacing = 0;
|
||||
|
||||
m_curve = curve;
|
||||
m_x1 = x1;
|
||||
m_y1 = y1;
|
||||
m_x2 = x2;
|
||||
m_y2 = y2;
|
||||
m_status = STATUS_STANDBY;
|
||||
m_editPoint = NULL;
|
||||
|
||||
/* TODO */
|
||||
/* m_curve->type = CURVE_SPLINE; */
|
||||
}
|
||||
|
||||
bool ColorCurveEditor::onProcessMessage(JMessage msg)
|
||||
{
|
||||
switch (msg->type) {
|
||||
|
||||
case JM_REQSIZE: {
|
||||
#if 0
|
||||
msg->reqsize.w =
|
||||
+ border_width.l
|
||||
+ ((m_x2 - m_x1 + 1))
|
||||
+ border_width.r;
|
||||
|
||||
msg->reqsize.h =
|
||||
+ border_width.t
|
||||
+ ((m_y2 - m_y1 + 1))
|
||||
+ border_width.b;
|
||||
#else
|
||||
msg->reqsize.w = border_width.l + 1 + border_width.r;
|
||||
msg->reqsize.h = border_width.t + 1 + border_width.b;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
case JM_KEYPRESSED: {
|
||||
switch (msg->key.scancode) {
|
||||
|
||||
case KEY_INSERT: {
|
||||
int x = SCR2EDIT_X(jmouse_x(0));
|
||||
int y = SCR2EDIT_Y(jmouse_y(0));
|
||||
|
||||
// TODO undo?
|
||||
m_curve->addPoint(gfx::Point(x, y));
|
||||
|
||||
invalidate();
|
||||
CurveEditorChange();
|
||||
break;
|
||||
}
|
||||
|
||||
case KEY_DEL: {
|
||||
gfx::Point* point = getClosestPoint(SCR2EDIT_X(jmouse_x(0)),
|
||||
SCR2EDIT_Y(jmouse_y(0)),
|
||||
NULL, NULL);
|
||||
|
||||
// TODO undo?
|
||||
if (point) {
|
||||
m_curve->removePoint(*point);
|
||||
m_editPoint = NULL;
|
||||
|
||||
invalidate();
|
||||
CurveEditorChange();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case JM_DRAW: {
|
||||
BITMAP *bmp;
|
||||
int x, y, u;
|
||||
|
||||
bmp = create_bitmap(jrect_w(rc), jrect_h(rc));
|
||||
clear_to_color(bmp, makecol (0, 0, 0));
|
||||
|
||||
// Draw border
|
||||
rect(bmp, 0, 0, bmp->w-1, bmp->h-1, makecol (255, 255, 0));
|
||||
|
||||
// Draw guides
|
||||
for (x=1; x<=3; x++)
|
||||
vline(bmp, x*bmp->w/4, 1, bmp->h-2, makecol (128, 128, 0));
|
||||
|
||||
for (y=1; y<=3; y++)
|
||||
hline(bmp, 1, y*bmp->h/4, bmp->w-2, makecol (128, 128, 0));
|
||||
|
||||
// Get curve values
|
||||
std::vector<int> values(m_x2-m_x1+1);
|
||||
m_curve->getValues(m_x1, m_x2, values);
|
||||
|
||||
// Draw curve
|
||||
for (x=border_width.l;
|
||||
x<jrect_w(rc)-border_width.r; x++) {
|
||||
u = SCR2EDIT_X(rc->x1+x);
|
||||
u = MID(m_x1, u, m_x2);
|
||||
|
||||
y = values[u - m_x1];
|
||||
y = MID(m_y1, y, m_y2);
|
||||
|
||||
putpixel(bmp, x, EDIT2SCR_Y(y)-rc->y1,
|
||||
makecol(255, 255, 255));
|
||||
}
|
||||
|
||||
// Draw nodes
|
||||
for (ColorCurve::iterator it = m_curve->begin(), end = m_curve->end(); it != end; ++it) {
|
||||
const gfx::Point& point = *it;
|
||||
|
||||
x = EDIT2SCR_X(point.x) - rc->x1;
|
||||
y = EDIT2SCR_Y(point.y) - rc->y1;
|
||||
|
||||
rect(bmp, x-2, y-2, x+2, y+2,
|
||||
m_editPoint == &point ? makecol(255, 255, 0):
|
||||
makecol(0, 0, 255));
|
||||
}
|
||||
|
||||
// Blit to screen
|
||||
blit(bmp, ji_screen, 0, 0, rc->x1, rc->y1, bmp->w, bmp->h);
|
||||
destroy_bitmap(bmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
case JM_BUTTONPRESSED:
|
||||
// Change scroll
|
||||
if (msg->any.shifts & KB_SHIFT_FLAG) {
|
||||
m_status = STATUS_SCROLLING;
|
||||
jmouse_set_cursor(JI_CURSOR_SCROLL);
|
||||
}
|
||||
/* scaling */
|
||||
/* else if (msg->shifts & KB_CTRL_FLAG) { */
|
||||
/* m_status = STATUS_SCALING; */
|
||||
/* jmouse_set_cursor(JI_CURSOR_SCROLL); */
|
||||
/* } */
|
||||
// Show manual-entry dialog
|
||||
else if (msg->mouse.right) {
|
||||
m_editPoint = getClosestPoint(SCR2EDIT_X(msg->mouse.x),
|
||||
SCR2EDIT_Y(msg->mouse.y),
|
||||
NULL, NULL);
|
||||
if (m_editPoint) {
|
||||
invalidate();
|
||||
jwidget_flush_redraw(this);
|
||||
|
||||
if (editNodeManually(*m_editPoint))
|
||||
CurveEditorChange();
|
||||
|
||||
m_editPoint = NULL;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
// Edit node
|
||||
else {
|
||||
m_editPoint = getClosestPoint(SCR2EDIT_X(msg->mouse.x),
|
||||
SCR2EDIT_Y(msg->mouse.y),
|
||||
&m_editX,
|
||||
&m_editY);
|
||||
|
||||
m_status = STATUS_MOVING_POINT;
|
||||
jmouse_set_cursor(JI_CURSOR_HAND);
|
||||
}
|
||||
|
||||
captureMouse();
|
||||
// continue in motion message...
|
||||
|
||||
case JM_MOTION:
|
||||
if (hasCapture()) {
|
||||
switch (m_status) {
|
||||
|
||||
case STATUS_SCROLLING: {
|
||||
View* view = View::getView(this);
|
||||
gfx::Rect vp = view->getViewportBounds();
|
||||
gfx::Point scroll = view->getViewScroll();
|
||||
|
||||
scroll.x += jmouse_x(1)-jmouse_x(0);
|
||||
scroll.y += jmouse_y(1)-jmouse_y(0);
|
||||
|
||||
view->setViewScroll(scroll);
|
||||
|
||||
jmouse_control_infinite_scroll(vp);
|
||||
break;
|
||||
}
|
||||
|
||||
case STATUS_MOVING_POINT:
|
||||
if (m_editPoint) {
|
||||
*m_editX = SCR2EDIT_X(msg->mouse.x);
|
||||
*m_editY = SCR2EDIT_Y(msg->mouse.y);
|
||||
*m_editX = MID(m_x1, *m_editX, m_x2);
|
||||
*m_editY = MID(m_y1, *m_editY, m_y2);
|
||||
|
||||
// TODO this should be optional
|
||||
CurveEditorChange();
|
||||
|
||||
invalidate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#if 0 // TODO
|
||||
// If the mouse move above a curve_editor, the focus change to
|
||||
// this widget immediately
|
||||
else if (!jwidget_has_focus(this)) {
|
||||
jmanager_set_focus(this);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case JM_BUTTONRELEASED:
|
||||
if (hasCapture()) {
|
||||
releaseMouse();
|
||||
|
||||
switch (m_status) {
|
||||
|
||||
case STATUS_SCROLLING:
|
||||
jmouse_set_cursor(JI_CURSOR_NORMAL);
|
||||
break;
|
||||
|
||||
/* case STATUS_SCALING: */
|
||||
/* jmouse_set_cursor(JI_CURSOR_NORMAL); */
|
||||
/* break; */
|
||||
|
||||
case STATUS_MOVING_POINT:
|
||||
jmouse_set_cursor(JI_CURSOR_NORMAL);
|
||||
CurveEditorChange();
|
||||
|
||||
m_editPoint = NULL;
|
||||
invalidate();
|
||||
break;
|
||||
}
|
||||
|
||||
m_status = STATUS_STANDBY;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return Widget::onProcessMessage(msg);
|
||||
}
|
||||
|
||||
gfx::Point* ColorCurveEditor::getClosestPoint(int x, int y, int** edit_x, int** edit_y)
|
||||
{
|
||||
#define CALCDIST(xx, yy) \
|
||||
dx = point->xx-x; \
|
||||
dy = point->yy-y; \
|
||||
dist = std::sqrt(static_cast<double>(dx*dx + dy*dy)); \
|
||||
\
|
||||
if (!point_found || dist <= dist_min) { \
|
||||
point_found = point; \
|
||||
dist_min = dist; \
|
||||
\
|
||||
if (edit_x) *edit_x = &point->xx; \
|
||||
if (edit_y) *edit_y = &point->yy; \
|
||||
}
|
||||
|
||||
gfx::Point* point;
|
||||
gfx::Point* point_found = NULL;
|
||||
int dx, dy;
|
||||
double dist, dist_min = 0;
|
||||
|
||||
for (ColorCurve::iterator it = m_curve->begin(), end = m_curve->end(); it != end; ++it) {
|
||||
point = &(*it);
|
||||
CALCDIST(x, y);
|
||||
}
|
||||
|
||||
return point_found;
|
||||
}
|
||||
|
||||
int ColorCurveEditor::editNodeManually(gfx::Point& point)
|
||||
{
|
||||
JWidget entry_x, entry_y, button_ok;
|
||||
gfx::Point point_copy = point;
|
||||
int res;
|
||||
|
||||
FramePtr window(load_widget("color_curve.xml", "point_properties"));
|
||||
|
||||
entry_x = jwidget_find_name(window, "x");
|
||||
entry_y = jwidget_find_name(window, "y");
|
||||
button_ok = jwidget_find_name(window, "button_ok");
|
||||
|
||||
entry_x->setTextf("%d", point.x);
|
||||
entry_y->setTextf("%d", point.y);
|
||||
|
||||
window->open_window_fg();
|
||||
|
||||
if (window->get_killer() == button_ok) {
|
||||
point.x = entry_x->getTextDouble();
|
||||
point.y = entry_y->getTextDouble();
|
||||
res = true;
|
||||
}
|
||||
else {
|
||||
point = point_copy;
|
||||
res = false;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
53
src/commands/filters/color_curve_editor.h
Normal file
53
src/commands/filters/color_curve_editor.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 COMMANDS_FILTERS_COLOR_CURVE_EDITOR_H_INCLUDED
|
||||
#define COMMANDS_FILTERS_COLOR_CURVE_EDITOR_H_INCLUDED
|
||||
|
||||
#include "base/signal.h"
|
||||
#include "gfx/point.h"
|
||||
#include "gui/widget.h"
|
||||
|
||||
class ColorCurve;
|
||||
|
||||
class ColorCurveEditor : public Widget
|
||||
{
|
||||
public:
|
||||
ColorCurveEditor(ColorCurve* curve, int x1, int y1, int x2, int y2);
|
||||
|
||||
ColorCurve* getCurve() const { return m_curve; }
|
||||
|
||||
Signal0<void> CurveEditorChange;
|
||||
|
||||
protected:
|
||||
bool onProcessMessage(JMessage msg);
|
||||
|
||||
private:
|
||||
gfx::Point* getClosestPoint(int x, int y, int** edit_x, int** edit_y);
|
||||
int editNodeManually(gfx::Point& point);
|
||||
|
||||
ColorCurve* m_curve;
|
||||
int m_x1, m_y1;
|
||||
int m_x2, m_y2;
|
||||
int m_status;
|
||||
gfx::Point* m_editPoint;
|
||||
int* m_editX;
|
||||
int* m_editY;
|
||||
};
|
||||
|
||||
#endif
|
197
src/commands/filters/convolution_matrix_stock.cpp
Normal file
197
src/commands/filters/convolution_matrix_stock.cpp
Normal file
@ -0,0 +1,197 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "commands/filters/convolution_matrix_stock.h"
|
||||
|
||||
#include "filters/convolution_matrix.h"
|
||||
#include "resource_finder.h"
|
||||
#include "util/filetoks.h"
|
||||
|
||||
ConvolutionMatrixStock::ConvolutionMatrixStock()
|
||||
{
|
||||
reloadStock();
|
||||
}
|
||||
|
||||
ConvolutionMatrixStock::~ConvolutionMatrixStock()
|
||||
{
|
||||
cleanStock();
|
||||
}
|
||||
|
||||
SharedPtr<ConvolutionMatrix> ConvolutionMatrixStock::getByName(const char* name)
|
||||
{
|
||||
for (const_iterator it = begin(), end = this->end(); it != end; ++it) {
|
||||
if (strcmp((*it)->getName(), name) == 0)
|
||||
return *it;
|
||||
}
|
||||
return SharedPtr<ConvolutionMatrix>(0);
|
||||
}
|
||||
|
||||
namespace {
|
||||
class FileDestroyer {
|
||||
public:
|
||||
static void destroy(FILE* ptr) { fclose(ptr); }
|
||||
};
|
||||
}
|
||||
|
||||
void ConvolutionMatrixStock::reloadStock()
|
||||
{
|
||||
#define READ_TOK() { \
|
||||
if (!tok_read(f, buf, leavings, sizeof (leavings))) \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define READ_INT(var) { \
|
||||
READ_TOK(); \
|
||||
var = strtol(buf, NULL, 10); \
|
||||
}
|
||||
|
||||
const char *names[] = { "convmatr.usr",
|
||||
"convmatr.gen",
|
||||
"convmatr.def", NULL };
|
||||
char *s, buf[256], leavings[4096];
|
||||
int i, c, x, y, w, h, div, bias;
|
||||
SharedPtr<ConvolutionMatrix> matrix;
|
||||
SharedPtr<FILE, FileDestroyer> f;
|
||||
std::string name;
|
||||
|
||||
cleanStock();
|
||||
|
||||
for (i=0; names[i]; i++) {
|
||||
ResourceFinder rf;
|
||||
rf.findInDataDir(names[i]);
|
||||
|
||||
while (const char* path = rf.next()) {
|
||||
// Open matrices stock file
|
||||
f.reset(fopen(path, "r"));
|
||||
if (!f)
|
||||
continue;
|
||||
|
||||
tok_reset_line_num();
|
||||
|
||||
strcpy(leavings, "");
|
||||
|
||||
// Read the matrix name
|
||||
while (tok_read(f, buf, leavings, sizeof(leavings))) {
|
||||
// Name of the matrix
|
||||
name = buf;
|
||||
|
||||
// Width and height
|
||||
READ_INT(w);
|
||||
READ_INT(h);
|
||||
|
||||
if ((w <= 0) || (w > 32) ||
|
||||
(h <= 0) || (h > 32))
|
||||
break;
|
||||
|
||||
// Create the matrix data
|
||||
matrix.reset(new ConvolutionMatrix(w, h));
|
||||
matrix->setName(name.c_str());
|
||||
|
||||
// Centre
|
||||
READ_INT(x);
|
||||
READ_INT(y);
|
||||
|
||||
if ((x < 0) || (x >= w) ||
|
||||
(y < 0) || (y >= h))
|
||||
break;
|
||||
|
||||
matrix->setCenterX(x);
|
||||
matrix->setCenterY(y);
|
||||
|
||||
// Data
|
||||
READ_TOK(); // Jump the `{' char
|
||||
if (*buf != '{')
|
||||
break;
|
||||
|
||||
c = 0;
|
||||
div = 0;
|
||||
for (y=0; y<h; ++y) {
|
||||
for (x=0; x<w; ++x) {
|
||||
READ_TOK();
|
||||
int value = strtod(buf, NULL) * ConvolutionMatrix::Precision;
|
||||
div += value;
|
||||
|
||||
matrix->value(x, y) = value;
|
||||
}
|
||||
}
|
||||
|
||||
READ_TOK(); // Jump the `}' char
|
||||
if (*buf != '}')
|
||||
break;
|
||||
|
||||
if (div > 0)
|
||||
bias = 0;
|
||||
else if (div == 0) {
|
||||
div = ConvolutionMatrix::Precision;
|
||||
bias = 128;
|
||||
}
|
||||
else {
|
||||
div = ABS(div);
|
||||
bias = 255;
|
||||
}
|
||||
|
||||
// Div
|
||||
READ_TOK();
|
||||
if (strcmp(buf, "auto") != 0)
|
||||
div = strtod(buf, NULL) * ConvolutionMatrix::Precision;
|
||||
|
||||
matrix->setDiv(div);
|
||||
|
||||
// Bias
|
||||
READ_TOK();
|
||||
if (strcmp(buf, "auto") != 0)
|
||||
bias = strtod(buf, NULL);
|
||||
|
||||
matrix->setBias(bias);
|
||||
|
||||
// Target
|
||||
READ_TOK();
|
||||
|
||||
Target target = 0;
|
||||
for (s=buf; *s; s++) {
|
||||
switch (*s) {
|
||||
case 'r': target |= TARGET_RED_CHANNEL; break;
|
||||
case 'g': target |= TARGET_GREEN_CHANNEL; break;
|
||||
case 'b': target |= TARGET_BLUE_CHANNEL; break;
|
||||
case 'a': target |= TARGET_ALPHA_CHANNEL; break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((target & (TARGET_RED_CHANNEL |
|
||||
TARGET_GREEN_CHANNEL |
|
||||
TARGET_BLUE_CHANNEL)) != 0) {
|
||||
target |= TARGET_GRAY_CHANNEL;
|
||||
}
|
||||
|
||||
matrix->setDefaultTarget(target);
|
||||
|
||||
// Insert the new matrix in the list
|
||||
m_matrices.push_back(matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConvolutionMatrixStock::cleanStock()
|
||||
{
|
||||
m_matrices.clear();
|
||||
}
|
52
src/commands/filters/convolution_matrix_stock.h
Normal file
52
src/commands/filters/convolution_matrix_stock.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 COMMANDS_FILTERS_CONVOLUTION_MATRIX_STOCK_H_INCLUDED
|
||||
#define COMMANDS_FILTERS_CONVOLUTION_MATRIX_STOCK_H_INCLUDED
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/shared_ptr.h"
|
||||
|
||||
class ConvolutionMatrix;
|
||||
|
||||
// A container of all convolution matrices in the convmatr.def file.
|
||||
class ConvolutionMatrixStock
|
||||
{
|
||||
public:
|
||||
typedef std::vector<SharedPtr<ConvolutionMatrix> >::iterator iterator;
|
||||
typedef std::vector<SharedPtr<ConvolutionMatrix> >::const_iterator const_iterator;
|
||||
|
||||
ConvolutionMatrixStock();
|
||||
virtual ~ConvolutionMatrixStock();
|
||||
|
||||
iterator begin() { return m_matrices.begin(); }
|
||||
iterator end() { return m_matrices.end(); }
|
||||
const_iterator begin() const { return m_matrices.begin(); }
|
||||
const_iterator end() const { return m_matrices.end(); }
|
||||
|
||||
SharedPtr<ConvolutionMatrix> getByName(const char* name);
|
||||
|
||||
void reloadStock();
|
||||
void cleanStock();
|
||||
|
||||
private:
|
||||
std::vector<SharedPtr<ConvolutionMatrix> > m_matrices;
|
||||
};
|
||||
|
||||
#endif
|
414
src/commands/filters/filter_manager_impl.cpp
Normal file
414
src/commands/filters/filter_manager_impl.cpp
Normal file
@ -0,0 +1,414 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "commands/filters/filter_manager_impl.h"
|
||||
|
||||
#include "core/cfg.h"
|
||||
#include "filters/filter.h"
|
||||
#include "gui/manager.h"
|
||||
#include "gui/rect.h"
|
||||
#include "gui/region.h"
|
||||
#include "gui/view.h"
|
||||
#include "gui/widget.h"
|
||||
#include "modules/editors.h"
|
||||
#include "raster/cel.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/images_collector.h"
|
||||
#include "raster/layer.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "raster/stock.h"
|
||||
#include "raster/undo.h"
|
||||
#include "widgets/editor.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
using namespace std;
|
||||
|
||||
FilterManagerImpl::FilterManagerImpl(Sprite* sprite, Filter* filter)
|
||||
: m_sprite(sprite)
|
||||
, m_filter(filter)
|
||||
, m_progressDelegate(NULL)
|
||||
{
|
||||
int offset_x, offset_y;
|
||||
|
||||
m_src = NULL;
|
||||
m_dst = NULL;
|
||||
m_row = 0;
|
||||
m_offset_x = 0;
|
||||
m_offset_y = 0;
|
||||
m_mask = NULL;
|
||||
m_preview_mask = NULL;
|
||||
m_mask_address = NULL;
|
||||
m_targetOrig = TARGET_ALL_CHANNELS;
|
||||
m_target = TARGET_ALL_CHANNELS;
|
||||
|
||||
Image* image = m_sprite->getCurrentImage(&offset_x, &offset_y);
|
||||
if (image == NULL)
|
||||
throw NoImageException();
|
||||
|
||||
init(sprite->getCurrentLayer(), image, offset_x, offset_y);
|
||||
}
|
||||
|
||||
FilterManagerImpl::~FilterManagerImpl()
|
||||
{
|
||||
if (m_preview_mask)
|
||||
mask_free(m_preview_mask);
|
||||
|
||||
if (m_dst)
|
||||
image_free(m_dst);
|
||||
}
|
||||
|
||||
void FilterManagerImpl::setProgressDelegate(IProgressDelegate* progressDelegate)
|
||||
{
|
||||
m_progressDelegate = progressDelegate;
|
||||
}
|
||||
|
||||
void FilterManagerImpl::setTarget(int target)
|
||||
{
|
||||
m_targetOrig = target;
|
||||
m_target = target;
|
||||
|
||||
/* the alpha channel of the background layer can't be modified */
|
||||
if (m_sprite->getCurrentLayer() &&
|
||||
m_sprite->getCurrentLayer()->is_background())
|
||||
m_target &= ~TARGET_ALPHA_CHANNEL;
|
||||
}
|
||||
|
||||
void FilterManagerImpl::begin()
|
||||
{
|
||||
m_row = 0;
|
||||
m_mask = m_sprite->getMask();
|
||||
|
||||
updateMask(m_mask, m_src);
|
||||
}
|
||||
|
||||
void FilterManagerImpl::beginForPreview()
|
||||
{
|
||||
if (m_preview_mask) {
|
||||
mask_free(m_preview_mask);
|
||||
m_preview_mask = NULL;
|
||||
}
|
||||
|
||||
if ((m_sprite->getMask()) && (m_sprite->getMask()->bitmap))
|
||||
m_preview_mask = mask_new_copy(m_sprite->getMask());
|
||||
else {
|
||||
m_preview_mask = mask_new();
|
||||
mask_replace(m_preview_mask,
|
||||
m_offset_x, m_offset_y,
|
||||
m_src->w, m_src->h);
|
||||
}
|
||||
|
||||
m_row = 0;
|
||||
m_mask = m_preview_mask;
|
||||
|
||||
{
|
||||
Editor* editor = current_editor;
|
||||
gfx::Rect vp = View::getView(editor)->getViewportBounds();
|
||||
int x1, y1, x2, y2;
|
||||
int x, y, w, h;
|
||||
|
||||
editor->screen_to_editor(vp.x, vp.y, &x1, &y1);
|
||||
editor->screen_to_editor(vp.x+vp.w-1, vp.y+vp.h-1, &x2, &y2);
|
||||
|
||||
if (x1 < 0) x1 = 0;
|
||||
if (y1 < 0) y1 = 0;
|
||||
if (x2 >= m_sprite->getWidth()) x2 = m_sprite->getWidth()-1;
|
||||
if (y2 >= m_sprite->getHeight()) y2 = m_sprite->getHeight()-1;
|
||||
|
||||
x = x1;
|
||||
y = y1;
|
||||
w = x2 - x1 + 1;
|
||||
h = y2 - y1 + 1;
|
||||
|
||||
if ((w < 1) || (h < 1)) {
|
||||
mask_free(m_preview_mask);
|
||||
m_preview_mask = NULL;
|
||||
m_row = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
mask_intersect(m_preview_mask, x, y, w, h);
|
||||
}
|
||||
|
||||
if (!updateMask(m_mask, m_src)) {
|
||||
mask_free(m_preview_mask);
|
||||
m_preview_mask = NULL;
|
||||
m_row = -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool FilterManagerImpl::applyStep()
|
||||
{
|
||||
if ((m_row >= 0) && (m_row < m_h)) {
|
||||
if ((m_mask) && (m_mask->bitmap)) {
|
||||
m_d = div(m_x-m_mask->x+m_offset_x, 8);
|
||||
m_mask_address = ((ase_uint8 **)m_mask->bitmap->line)[m_row+m_y-m_mask->y+m_offset_y]+m_d.quot;
|
||||
}
|
||||
else
|
||||
m_mask_address = NULL;
|
||||
|
||||
switch (m_sprite->getImgType()) {
|
||||
case IMAGE_RGB: m_filter->applyToRgba(this); break;
|
||||
case IMAGE_GRAYSCALE: m_filter->applyToGrayscale(this); break;
|
||||
case IMAGE_INDEXED: m_filter->applyToIndexed(this); break;
|
||||
}
|
||||
++m_row;
|
||||
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void FilterManagerImpl::apply()
|
||||
{
|
||||
bool cancelled = false;
|
||||
|
||||
begin();
|
||||
while (!cancelled && applyStep()) {
|
||||
if (m_progressDelegate) {
|
||||
// Report progress.
|
||||
m_progressDelegate->reportProgress(m_progressBase + m_progressWidth * (m_row+1) / m_h);
|
||||
|
||||
// Does the user cancelled the whole process?
|
||||
cancelled = m_progressDelegate->isCancelled();
|
||||
}
|
||||
}
|
||||
|
||||
if (!cancelled) {
|
||||
// Undo stuff
|
||||
if (m_sprite->getUndo()->isEnabled()) {
|
||||
m_sprite->getUndo()->setLabel(m_filter->getName());
|
||||
m_sprite->getUndo()->undo_image(m_src, m_x, m_y, m_w, m_h);
|
||||
}
|
||||
|
||||
// Copy "dst" to "src"
|
||||
image_copy(m_src, m_dst, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void FilterManagerImpl::applyToTarget()
|
||||
{
|
||||
bool cancelled = false;
|
||||
|
||||
ImagesCollector images(m_sprite,
|
||||
(m_target & TARGET_ALL_LAYERS) == TARGET_ALL_LAYERS,
|
||||
(m_target & TARGET_ALL_FRAMES) == TARGET_ALL_FRAMES,
|
||||
true); // we will write in each image
|
||||
if (images.empty())
|
||||
return;
|
||||
|
||||
// Initialize writting operation
|
||||
SpriteReader reader(m_sprite);
|
||||
SpriteWriter writer(reader);
|
||||
|
||||
// Open group of undo operations
|
||||
if (images.size() > 1) {
|
||||
if (m_sprite->getUndo()->isEnabled())
|
||||
m_sprite->getUndo()->undo_open();
|
||||
}
|
||||
|
||||
m_progressBase = 0.0f;
|
||||
m_progressWidth = 1.0f / images.size();
|
||||
|
||||
// For each target image
|
||||
for (ImagesCollector::ItemsIterator it = images.begin();
|
||||
it != images.end() && !cancelled;
|
||||
++it) {
|
||||
applyToImage(it->layer(), it->image(), it->cel()->x, it->cel()->y);
|
||||
|
||||
// Is there a delegate to know if the process was cancelled by the user?
|
||||
if (m_progressDelegate)
|
||||
cancelled = m_progressDelegate->isCancelled();
|
||||
|
||||
// Make progress
|
||||
m_progressBase += m_progressWidth;
|
||||
}
|
||||
|
||||
// Close group of undo operations
|
||||
if (images.size() > 1) {
|
||||
if (m_sprite->getUndo()->isEnabled())
|
||||
m_sprite->getUndo()->undo_close();
|
||||
}
|
||||
}
|
||||
|
||||
void FilterManagerImpl::flush()
|
||||
{
|
||||
if (m_row >= 0) {
|
||||
JRegion reg1, reg2;
|
||||
struct jrect rect;
|
||||
Editor* editor = current_editor;
|
||||
|
||||
reg1 = jregion_new(NULL, 0);
|
||||
|
||||
editor->editor_to_screen(m_x+m_offset_x,
|
||||
m_y+m_offset_y+m_row-1,
|
||||
&rect.x1, &rect.y1);
|
||||
rect.x2 = rect.x1 + (m_w << editor->editor_get_zoom());
|
||||
rect.y2 = rect.y1 + (1 << editor->editor_get_zoom());
|
||||
|
||||
reg2 = jregion_new(&rect, 1);
|
||||
jregion_union(reg1, reg1, reg2);
|
||||
jregion_free(reg2);
|
||||
|
||||
reg2 = jwidget_get_drawable_region(editor, JI_GDR_CUTTOPWINDOWS);
|
||||
jregion_intersect(reg1, reg1, reg2);
|
||||
jregion_free(reg2);
|
||||
|
||||
editor->invalidateRegion(reg1);
|
||||
jregion_free(reg1);
|
||||
}
|
||||
}
|
||||
|
||||
const void* FilterManagerImpl::getSourceAddress()
|
||||
{
|
||||
switch (m_sprite->getImgType()) {
|
||||
case IMAGE_RGB: return ((ase_uint32**)m_src->line)[m_row+m_y]+m_x;
|
||||
case IMAGE_GRAYSCALE: return ((ase_uint16**)m_src->line)[m_row+m_y]+m_x;
|
||||
case IMAGE_INDEXED: return ((ase_uint8**)m_src->line)[m_row+m_y]+m_x;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* FilterManagerImpl::getDestinationAddress()
|
||||
{
|
||||
switch (m_sprite->getImgType()) {
|
||||
case IMAGE_RGB: return ((ase_uint32**)m_dst->line)[m_row+m_y]+m_x;
|
||||
case IMAGE_GRAYSCALE: return ((ase_uint16**)m_dst->line)[m_row+m_y]+m_x;
|
||||
case IMAGE_INDEXED: return ((ase_uint8**)m_dst->line)[m_row+m_y]+m_x;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool FilterManagerImpl::skipPixel()
|
||||
{
|
||||
bool skip = false;
|
||||
|
||||
if (m_mask_address) {
|
||||
if (!((*m_mask_address) & (1<<m_d.rem)))
|
||||
skip = true;
|
||||
|
||||
// Move to the next pixel in the mask.
|
||||
_image_bitmap_next_bit(m_d, m_mask_address);
|
||||
}
|
||||
|
||||
return skip;
|
||||
}
|
||||
|
||||
Palette* FilterManagerImpl::getPalette()
|
||||
{
|
||||
return m_sprite->getCurrentPalette();
|
||||
}
|
||||
|
||||
RgbMap* FilterManagerImpl::getRgbMap()
|
||||
{
|
||||
return m_sprite->getRgbMap();
|
||||
}
|
||||
|
||||
void FilterManagerImpl::init(const Layer* layer, Image* image, int offset_x, int offset_y)
|
||||
{
|
||||
m_offset_x = offset_x;
|
||||
m_offset_y = offset_y;
|
||||
|
||||
if (!updateMask(m_sprite->getMask(), image))
|
||||
throw InvalidAreaException();
|
||||
|
||||
if (m_preview_mask) {
|
||||
mask_free(m_preview_mask);
|
||||
m_preview_mask = NULL;
|
||||
}
|
||||
|
||||
if (m_dst) {
|
||||
image_free(m_dst);
|
||||
m_dst = NULL;
|
||||
}
|
||||
|
||||
m_src = image;
|
||||
m_dst = image_crop(image, 0, 0, image->w, image->h, 0);
|
||||
m_row = -1;
|
||||
m_mask = NULL;
|
||||
m_preview_mask = NULL;
|
||||
m_mask_address = NULL;
|
||||
|
||||
m_target = m_targetOrig;
|
||||
|
||||
/* the alpha channel of the background layer can't be modified */
|
||||
if (layer->is_background())
|
||||
m_target &= ~TARGET_ALPHA_CHANNEL;
|
||||
}
|
||||
|
||||
void FilterManagerImpl::applyToImage(Layer* layer, Image* image, int x, int y)
|
||||
{
|
||||
init(layer, image, x, y);
|
||||
apply();
|
||||
}
|
||||
|
||||
bool FilterManagerImpl::updateMask(Mask* mask, const Image* image)
|
||||
{
|
||||
int x, y, w, h;
|
||||
|
||||
if ((mask) && (mask->bitmap)) {
|
||||
x = mask->x - m_offset_x;
|
||||
y = mask->y - m_offset_y;
|
||||
w = mask->w;
|
||||
h = mask->h;
|
||||
|
||||
if (x < 0) {
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if (y < 0) {
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if (x+w-1 >= image->w-1)
|
||||
w = image->w-x;
|
||||
|
||||
if (y+h-1 >= image->h-1)
|
||||
h = image->h-y;
|
||||
}
|
||||
else {
|
||||
x = 0;
|
||||
y = 0;
|
||||
w = image->w;
|
||||
h = image->h;
|
||||
}
|
||||
|
||||
if ((w < 1) || (h < 1)) {
|
||||
m_x = 0;
|
||||
m_y = 0;
|
||||
m_w = 0;
|
||||
m_h = 0;
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
m_x = x;
|
||||
m_y = y;
|
||||
m_w = w;
|
||||
m_h = h;
|
||||
return true;
|
||||
}
|
||||
}
|
129
src/commands/filters/filter_manager_impl.h
Normal file
129
src/commands/filters/filter_manager_impl.h
Normal file
@ -0,0 +1,129 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 COMMANDS_FILTERS_FILTER_MANAGER_IMPL_H_INCLUDED
|
||||
#define COMMANDS_FILTERS_FILTER_MANAGER_IMPL_H_INCLUDED
|
||||
|
||||
#include <cstring>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "base/exception.h"
|
||||
#include "filters/filter_indexed_data.h"
|
||||
#include "filters/filter_manager.h"
|
||||
#include "sprite_wrappers.h"
|
||||
|
||||
class Filter;
|
||||
class Image;
|
||||
class Layer;
|
||||
class Mask;
|
||||
class Sprite;
|
||||
|
||||
class InvalidAreaException : public base::Exception
|
||||
{
|
||||
public:
|
||||
InvalidAreaException() throw()
|
||||
: base::Exception("The current mask/area to apply the effect is completelly invalid.") { }
|
||||
};
|
||||
|
||||
class NoImageException : public base::Exception
|
||||
{
|
||||
public:
|
||||
NoImageException() throw()
|
||||
: base::Exception("There are not an active image to apply the effect.\n"
|
||||
"Please select a layer/cel with an image and try again.") { }
|
||||
};
|
||||
|
||||
class FilterManagerImpl : public FilterManager
|
||||
, public FilterIndexedData
|
||||
{
|
||||
public:
|
||||
// Interface to report progress to the user and take input from him
|
||||
// to cancel the whole process.
|
||||
class IProgressDelegate {
|
||||
public:
|
||||
virtual ~IProgressDelegate() { }
|
||||
|
||||
// Called to report the progress of the filter (with progress from 0.0 to 1.0).
|
||||
virtual void reportProgress(float progress) = 0;
|
||||
|
||||
// Should return true if the user wants to cancel the filter.
|
||||
virtual bool isCancelled() = 0;
|
||||
};
|
||||
|
||||
FilterManagerImpl(Sprite* sprite, Filter* filter);
|
||||
~FilterManagerImpl();
|
||||
|
||||
void setProgressDelegate(IProgressDelegate* progressDelegate);
|
||||
|
||||
int getImgType() const { return m_sprite->getImgType(); };
|
||||
|
||||
void setTarget(Target target);
|
||||
|
||||
void begin();
|
||||
void beginForPreview();
|
||||
bool applyStep();
|
||||
void apply();
|
||||
void applyToTarget();
|
||||
|
||||
Sprite* getSprite() const { return m_sprite; }
|
||||
Image* getDestinationImage() const { return m_dst; }
|
||||
|
||||
// Updates the current editor to show the progress of the preview.
|
||||
void flush();
|
||||
|
||||
// FilterManager implementation
|
||||
const void* getSourceAddress();
|
||||
void* getDestinationAddress();
|
||||
int getWidth() { return m_w; }
|
||||
Target getTarget() { return m_target; }
|
||||
FilterIndexedData* getIndexedData() { return this; }
|
||||
bool skipPixel();
|
||||
const Image* getSourceImage() { return m_src; }
|
||||
int getX() { return m_x; }
|
||||
int getY() { return m_y+m_row; }
|
||||
|
||||
// FilterIndexedData implementation
|
||||
Palette* getPalette();
|
||||
RgbMap* getRgbMap();
|
||||
|
||||
private:
|
||||
void init(const Layer* layer, Image* image, int offset_x, int offset_y);
|
||||
void applyToImage(Layer* layer, Image* image, int x, int y);
|
||||
bool updateMask(Mask* mask, const Image* image);
|
||||
|
||||
Sprite* m_sprite;
|
||||
Filter* m_filter;
|
||||
Image* m_src;
|
||||
Image* m_dst;
|
||||
int m_row;
|
||||
int m_x, m_y, m_w, m_h;
|
||||
int m_offset_x, m_offset_y;
|
||||
Mask* m_mask;
|
||||
Mask* m_preview_mask;
|
||||
unsigned char* m_mask_address;
|
||||
div_t m_d;
|
||||
Target m_targetOrig; // Original targets
|
||||
Target m_target; // Filtered targets
|
||||
|
||||
// Hooks
|
||||
float m_progressBase;
|
||||
float m_progressWidth;
|
||||
IProgressDelegate* m_progressDelegate;
|
||||
};
|
||||
|
||||
#endif
|
94
src/commands/filters/filter_preview.cpp
Normal file
94
src/commands/filters/filter_preview.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "commands/filters/filter_preview.h"
|
||||
|
||||
#include "commands/filters/filter_manager_impl.h"
|
||||
#include "gui/manager.h"
|
||||
#include "gui/message.h"
|
||||
#include "gui/widget.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "util/render.h"
|
||||
|
||||
FilterPreview::FilterPreview(FilterManagerImpl* filterMgr)
|
||||
: Widget(JI_WIDGET)
|
||||
, m_filterMgr(filterMgr)
|
||||
, m_timerId(-1)
|
||||
{
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
FilterPreview::~FilterPreview()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
void FilterPreview::stop()
|
||||
{
|
||||
m_filterMgr = NULL;
|
||||
if (m_timerId >= 0) {
|
||||
jmanager_remove_timer(m_timerId);
|
||||
m_timerId = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void FilterPreview::restartPreview()
|
||||
{
|
||||
m_filterMgr->beginForPreview();
|
||||
|
||||
if (m_timerId < 0)
|
||||
m_timerId = jmanager_add_timer(this, 1);
|
||||
|
||||
jmanager_start_timer(m_timerId);
|
||||
}
|
||||
|
||||
FilterManagerImpl* FilterPreview::getFilterManager() const
|
||||
{
|
||||
return m_filterMgr;
|
||||
}
|
||||
|
||||
bool FilterPreview::onProcessMessage(JMessage msg)
|
||||
{
|
||||
switch (msg->type) {
|
||||
|
||||
case JM_OPEN:
|
||||
RenderEngine::setPreviewImage(m_filterMgr->getSprite()->getCurrentLayer(),
|
||||
m_filterMgr->getDestinationImage());
|
||||
break;
|
||||
|
||||
case JM_CLOSE:
|
||||
RenderEngine::setPreviewImage(NULL, NULL);
|
||||
|
||||
// Stop the preview timer.
|
||||
jmanager_stop_timer(m_timerId);
|
||||
break;
|
||||
|
||||
case JM_TIMER:
|
||||
if (m_filterMgr) {
|
||||
if (m_filterMgr->applyStep())
|
||||
m_filterMgr->flush();
|
||||
else
|
||||
jmanager_stop_timer(m_timerId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return Widget::onProcessMessage(msg);
|
||||
}
|
@ -16,19 +16,30 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef WIDGETS_CURVEDIT_H_INCLUDED
|
||||
#define WIDGETS_CURVEDIT_H_INCLUDED
|
||||
#ifndef COMMANDS_FILTERS_FILTER_PREVIEW_H_INCLUDED
|
||||
#define COMMANDS_FILTERS_FILTER_PREVIEW_H_INCLUDED
|
||||
|
||||
#include "gui/base.h"
|
||||
#include "gui/widget.h"
|
||||
|
||||
// TODO use some JI_SIGNAL_USER
|
||||
#define SIGNAL_CURVE_EDITOR_CHANGE 0x10004
|
||||
class FilterManagerImpl;
|
||||
|
||||
struct Curve;
|
||||
// Invisible widget to control a effect-preview in the current editor.
|
||||
class FilterPreview : public Widget
|
||||
{
|
||||
public:
|
||||
FilterPreview(FilterManagerImpl* filterMgr);
|
||||
~FilterPreview();
|
||||
|
||||
JWidget curve_editor_new(Curve* curve, int x1, int y1, int x2, int y2);
|
||||
int curve_editor_type();
|
||||
void stop();
|
||||
void restartPreview();
|
||||
FilterManagerImpl* getFilterManager() const;
|
||||
|
||||
Curve* curve_editor_get_curve(JWidget curve_editor);
|
||||
protected:
|
||||
bool onProcessMessage(JMessage msg);
|
||||
|
||||
private:
|
||||
FilterManagerImpl* m_filterMgr;
|
||||
int m_timerId;
|
||||
};
|
||||
|
||||
#endif
|
212
src/commands/filters/filter_target_buttons.cpp
Normal file
212
src/commands/filters/filter_target_buttons.cpp
Normal file
@ -0,0 +1,212 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "commands/filters/filter_target_buttons.h"
|
||||
|
||||
#include <allegro.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "gui/box.h"
|
||||
#include "gui/button.h"
|
||||
#include "gui/theme.h"
|
||||
#include "gui/widget.h"
|
||||
#include "modules/gfx.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/image.h"
|
||||
#include "skin/skin_parts.h"
|
||||
|
||||
FilterTargetButtons::FilterTargetButtons(int imgtype, bool withChannels)
|
||||
: Box(JI_VERTICAL)
|
||||
, m_target(0)
|
||||
{
|
||||
#define ADD(box, widget, hook) \
|
||||
if (widget) { \
|
||||
jwidget_set_border(widget, 2 * jguiscale()); \
|
||||
jwidget_add_child(box, widget); \
|
||||
widget->Click.connect(Bind<void>(&FilterTargetButtons::hook, this, widget)); \
|
||||
}
|
||||
|
||||
Box* hbox;
|
||||
CheckBox* r = NULL;
|
||||
CheckBox* g = NULL;
|
||||
CheckBox* b = NULL;
|
||||
CheckBox* k = NULL;
|
||||
CheckBox* a = NULL;
|
||||
CheckBox* index = NULL;
|
||||
Button* images = NULL;
|
||||
|
||||
hbox = new Box(JI_HORIZONTAL | JI_HOMOGENEOUS);
|
||||
|
||||
jwidget_noborders(this);
|
||||
jwidget_noborders(hbox);
|
||||
|
||||
if (withChannels) {
|
||||
switch (imgtype) {
|
||||
|
||||
case IMAGE_RGB:
|
||||
case IMAGE_INDEXED:
|
||||
r = check_button_new("R", 2, 0, 0, 0);
|
||||
g = check_button_new("G", 0, 0, 0, 0);
|
||||
b = check_button_new("B", 0, (imgtype == IMAGE_RGB) ? 0: 2, 0, 0);
|
||||
|
||||
r->setName("r");
|
||||
g->setName("g");
|
||||
b->setName("b");
|
||||
|
||||
if (imgtype == IMAGE_RGB) {
|
||||
a = check_button_new("A", 0, 2, 0, 0);
|
||||
a->setName("a");
|
||||
}
|
||||
else {
|
||||
index = check_button_new("Index", 0, 0, 0, 0);
|
||||
index->setName("i");
|
||||
}
|
||||
break;
|
||||
|
||||
case IMAGE_GRAYSCALE:
|
||||
k = check_button_new("K", 2, 0, 0, 0);
|
||||
a = check_button_new("A", 0, 2, 0, 0);
|
||||
|
||||
k->setName("k");
|
||||
a->setName("a");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the button to select "image" target
|
||||
images = new Button(NULL);
|
||||
setup_bevels(images,
|
||||
withChannels ? 0: 2,
|
||||
withChannels ? 0: 2, 2, 2);
|
||||
setup_mini_look(images);
|
||||
set_gfxicon_to_button(images,
|
||||
getTargetNormalIcon(),
|
||||
getTargetSelectedIcon(), -1,
|
||||
JI_CENTER | JI_MIDDLE);
|
||||
|
||||
// Make hierarchy
|
||||
ADD(hbox, r, onChannelChange);
|
||||
ADD(hbox, g, onChannelChange);
|
||||
ADD(hbox, b, onChannelChange);
|
||||
ADD(hbox, k, onChannelChange);
|
||||
ADD(hbox, a, onChannelChange);
|
||||
|
||||
if (withChannels)
|
||||
jwidget_add_child(this, hbox);
|
||||
else
|
||||
jwidget_free(hbox);
|
||||
|
||||
ADD(this, index, onChannelChange);
|
||||
ADD(this, images, onImagesChange);
|
||||
}
|
||||
|
||||
void FilterTargetButtons::setTarget(int target)
|
||||
{
|
||||
m_target = target;
|
||||
|
||||
selectTargetButton("r", TARGET_RED_CHANNEL);
|
||||
selectTargetButton("g", TARGET_GREEN_CHANNEL);
|
||||
selectTargetButton("b", TARGET_BLUE_CHANNEL);
|
||||
selectTargetButton("a", TARGET_ALPHA_CHANNEL);
|
||||
selectTargetButton("k", TARGET_GRAY_CHANNEL);
|
||||
selectTargetButton("i", TARGET_INDEX_CHANNEL);
|
||||
}
|
||||
|
||||
void FilterTargetButtons::selectTargetButton(const char* name, int specificTarget)
|
||||
{
|
||||
Widget* wgt = findChild(name);
|
||||
if (wgt != NULL)
|
||||
wgt->setSelected((m_target & specificTarget) == specificTarget);
|
||||
}
|
||||
|
||||
void FilterTargetButtons::onChannelChange(ButtonBase* button)
|
||||
{
|
||||
int flag = 0;
|
||||
|
||||
switch (button->name[0]) {
|
||||
case 'r': flag = TARGET_RED_CHANNEL; break;
|
||||
case 'g': flag = TARGET_GREEN_CHANNEL; break;
|
||||
case 'b': flag = TARGET_BLUE_CHANNEL; break;
|
||||
case 'k': flag = TARGET_GRAY_CHANNEL; break;
|
||||
case 'a': flag = TARGET_ALPHA_CHANNEL; break;
|
||||
case 'i': flag = TARGET_INDEX_CHANNEL; break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (button->isSelected())
|
||||
m_target |= flag;
|
||||
else
|
||||
m_target &= ~flag;
|
||||
|
||||
TargetChange();
|
||||
}
|
||||
|
||||
void FilterTargetButtons::onImagesChange(ButtonBase* button)
|
||||
{
|
||||
// Rotate target
|
||||
if (m_target & TARGET_ALL_FRAMES) {
|
||||
m_target &= ~TARGET_ALL_FRAMES;
|
||||
|
||||
if (m_target & TARGET_ALL_LAYERS)
|
||||
m_target &= ~TARGET_ALL_LAYERS;
|
||||
else
|
||||
m_target |= TARGET_ALL_LAYERS;
|
||||
}
|
||||
else {
|
||||
m_target |= TARGET_ALL_FRAMES;
|
||||
}
|
||||
|
||||
set_gfxicon_to_button(button,
|
||||
getTargetNormalIcon(),
|
||||
getTargetSelectedIcon(), -1,
|
||||
JI_CENTER | JI_MIDDLE);
|
||||
|
||||
TargetChange();
|
||||
}
|
||||
|
||||
int FilterTargetButtons::getTargetNormalIcon() const
|
||||
{
|
||||
if (m_target & TARGET_ALL_FRAMES) {
|
||||
return (m_target & TARGET_ALL_LAYERS) ?
|
||||
PART_TARGET_FRAMES_LAYERS:
|
||||
PART_TARGET_FRAMES;
|
||||
}
|
||||
else {
|
||||
return (m_target & TARGET_ALL_LAYERS) ?
|
||||
PART_TARGET_LAYERS:
|
||||
PART_TARGET_ONE;
|
||||
}
|
||||
}
|
||||
|
||||
int FilterTargetButtons::getTargetSelectedIcon() const
|
||||
{
|
||||
if (m_target & TARGET_ALL_FRAMES) {
|
||||
return (m_target & TARGET_ALL_LAYERS) ?
|
||||
PART_TARGET_FRAMES_LAYERS_SELECTED:
|
||||
PART_TARGET_FRAMES_SELECTED;
|
||||
}
|
||||
else {
|
||||
return (m_target & TARGET_ALL_LAYERS) ?
|
||||
PART_TARGET_LAYERS_SELECTED:
|
||||
PART_TARGET_ONE_SELECTED;
|
||||
}
|
||||
}
|
@ -16,42 +16,37 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef EFFECT_COLCURVE_H_INCLUDED
|
||||
#define EFFECT_COLCURVE_H_INCLUDED
|
||||
#ifndef COMMANDS_FILTERS_FILTER_TARGET_BUTTONS_H_INCLUDED
|
||||
#define COMMANDS_FILTERS_FILTER_TARGET_BUTTONS_H_INCLUDED
|
||||
|
||||
#include "gui/base.h"
|
||||
#include "base/signal.h"
|
||||
#include "filters/target.h"
|
||||
#include "gui/box.h"
|
||||
|
||||
struct Effect;
|
||||
class ButtonBase;
|
||||
|
||||
enum {
|
||||
CURVE_LINEAR,
|
||||
CURVE_SPLINE,
|
||||
class FilterTargetButtons : public Box
|
||||
{
|
||||
public:
|
||||
// Creates a new button to handle "targets" to apply some filter in
|
||||
// the a sprite.
|
||||
FilterTargetButtons(int imgtype, bool withChannels);
|
||||
|
||||
Target getTarget() const { return m_target; }
|
||||
void setTarget(Target target);
|
||||
|
||||
Signal0<void> TargetChange;
|
||||
|
||||
protected:
|
||||
void onChannelChange(ButtonBase* button);
|
||||
void onImagesChange(ButtonBase* button);
|
||||
|
||||
private:
|
||||
void selectTargetButton(const char* name, Target specificTarget);
|
||||
int getTargetNormalIcon() const;
|
||||
int getTargetSelectedIcon() const;
|
||||
|
||||
Target m_target;
|
||||
};
|
||||
|
||||
typedef struct CurvePoint
|
||||
{
|
||||
int x, y;
|
||||
} CurvePoint;
|
||||
|
||||
typedef struct Curve
|
||||
{
|
||||
int type;
|
||||
JList points;
|
||||
} Curve;
|
||||
|
||||
CurvePoint *curve_point_new(int x, int y);
|
||||
void curve_point_free(CurvePoint *point);
|
||||
|
||||
Curve *curve_new(int type);
|
||||
void curve_free(Curve *curve);
|
||||
void curve_add_point(Curve *curve, CurvePoint *point);
|
||||
void curve_remove_point(Curve *curve, CurvePoint *point);
|
||||
void curve_get_values(Curve *curve, int x1, int x2, int *values);
|
||||
|
||||
void set_color_curve(Curve *curve);
|
||||
|
||||
void apply_color_curve4(struct Effect *effect);
|
||||
void apply_color_curve2(struct Effect *effect);
|
||||
void apply_color_curve1(struct Effect *effect);
|
||||
|
||||
#endif
|
166
src/commands/filters/filter_window.cpp
Normal file
166
src/commands/filters/filter_window.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "commands/filters/filter_window.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "commands/filters/filter_manager_impl.h"
|
||||
#include "commands/filters/filter_worker.h"
|
||||
#include "core/cfg.h"
|
||||
#include "modules/gui.h"
|
||||
|
||||
FilterWindow::FilterWindow(const char* title, const char* cfgSection,
|
||||
FilterManagerImpl* filterMgr,
|
||||
WithChannels withChannels,
|
||||
WithTiled withTiled,
|
||||
TiledMode tiledMode)
|
||||
: Frame(false, title)
|
||||
, m_cfgSection(cfgSection)
|
||||
, m_filterMgr(filterMgr)
|
||||
, m_hbox(JI_HORIZONTAL)
|
||||
, m_container(JI_VERTICAL)
|
||||
, m_vbox(JI_VERTICAL)
|
||||
, m_okButton("&OK")
|
||||
, m_cancelButton("&Cancel")
|
||||
, m_preview(filterMgr)
|
||||
, m_targetButton(filterMgr->getImgType(), (withChannels == WithChannelsSelector))
|
||||
, m_showPreview("&Preview")
|
||||
, m_tiledCheck(withTiled == WithTiledCheckBox ? new CheckBox("&Tiled") : NULL)
|
||||
{
|
||||
m_targetButton.setTarget(filterMgr->getTarget());
|
||||
m_targetButton.TargetChange.connect(&FilterWindow::onTargetButtonChange, this);
|
||||
m_okButton.Click.connect(&FilterWindow::onOk, this);
|
||||
m_cancelButton.Click.connect(&FilterWindow::onCancel, this);
|
||||
m_showPreview.Click.connect(&FilterWindow::onShowPreview, this);
|
||||
|
||||
jwidget_expansive(&m_container, true);
|
||||
|
||||
jwidget_add_child(&m_hbox, &m_container);
|
||||
jwidget_add_child(&m_hbox, &m_vbox);
|
||||
|
||||
jwidget_add_child(&m_vbox, &m_okButton);
|
||||
jwidget_add_child(&m_vbox, &m_cancelButton);
|
||||
jwidget_add_child(&m_vbox, &m_targetButton);
|
||||
jwidget_add_child(&m_vbox, &m_showPreview);
|
||||
|
||||
jwidget_add_child(this, &m_preview);
|
||||
jwidget_add_child(this, &m_hbox);
|
||||
|
||||
if (m_tiledCheck) {
|
||||
m_tiledCheck->setSelected(tiledMode != TILED_NONE);
|
||||
m_tiledCheck->Click.connect(Bind<void>(&FilterWindow::onTiledChange, this));
|
||||
|
||||
jwidget_add_child(&m_vbox, m_tiledCheck);
|
||||
}
|
||||
|
||||
// Load "Preview" check status.
|
||||
m_showPreview.setSelected(get_config_bool(m_cfgSection, "Preview", true));
|
||||
|
||||
// OK is magnetic (the default button)
|
||||
jwidget_magnetic(&m_okButton, true);
|
||||
}
|
||||
|
||||
FilterWindow::~FilterWindow()
|
||||
{
|
||||
// Save window configuration
|
||||
save_window_pos(this, m_cfgSection);
|
||||
|
||||
// Save "Preview" check status.
|
||||
set_config_bool(m_cfgSection, "Preview", m_showPreview.isSelected());
|
||||
}
|
||||
|
||||
bool FilterWindow::doModal()
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
// Default position
|
||||
remap_window();
|
||||
center_window();
|
||||
|
||||
// Load window configuration
|
||||
load_window_pos(this, m_cfgSection);
|
||||
|
||||
// Start first preview
|
||||
restartPreview();
|
||||
|
||||
// Open in foreground
|
||||
open_window_fg();
|
||||
|
||||
// Did the user press OK?
|
||||
if (get_killer() == &m_okButton) {
|
||||
m_preview.stop();
|
||||
|
||||
// Apply the filter in background
|
||||
start_filter_worker(m_filterMgr);
|
||||
result = true;
|
||||
}
|
||||
|
||||
// Always update editors
|
||||
update_screen_for_sprite(m_filterMgr->getSprite());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void FilterWindow::restartPreview()
|
||||
{
|
||||
if (m_showPreview.isSelected())
|
||||
m_preview.restartPreview();
|
||||
}
|
||||
|
||||
void FilterWindow::setNewTarget(Target target)
|
||||
{
|
||||
m_filterMgr->setTarget(target);
|
||||
m_targetButton.setTarget(target);
|
||||
}
|
||||
|
||||
void FilterWindow::onOk(Event& ev)
|
||||
{
|
||||
m_okButton.closeWindow();
|
||||
}
|
||||
|
||||
void FilterWindow::onCancel(Event& ev)
|
||||
{
|
||||
m_cancelButton.closeWindow();
|
||||
}
|
||||
|
||||
void FilterWindow::onShowPreview(Event& ev)
|
||||
{
|
||||
restartPreview();
|
||||
}
|
||||
|
||||
// Called when the user changes the target-buttons.
|
||||
void FilterWindow::onTargetButtonChange()
|
||||
{
|
||||
// Change the targets in the filter manager and restart the filter preview.
|
||||
m_filterMgr->setTarget(m_targetButton.getTarget());
|
||||
restartPreview();
|
||||
}
|
||||
|
||||
void FilterWindow::onTiledChange()
|
||||
{
|
||||
ASSERT(m_tiledCheck != NULL);
|
||||
|
||||
// Call derived class implementation of setupTiledMode() so the
|
||||
// filter is modified.
|
||||
setupTiledMode(m_tiledCheck->isSelected() ? TILED_BOTH: TILED_NONE);
|
||||
|
||||
// Restart the preview.
|
||||
restartPreview();
|
||||
}
|
87
src/commands/filters/filter_window.h
Normal file
87
src/commands/filters/filter_window.h
Normal file
@ -0,0 +1,87 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 COMMANDS_FILTERS_FILTER_WINDOW_H_INCLUDED
|
||||
#define COMMANDS_FILTERS_FILTER_WINDOW_H_INCLUDED
|
||||
|
||||
#include "gui/box.h"
|
||||
#include "gui/button.h"
|
||||
#include "gui/frame.h"
|
||||
#include "commands/filters/filter_preview.h"
|
||||
#include "commands/filters/filter_target_buttons.h"
|
||||
#include "filters/tiled_mode.h"
|
||||
|
||||
class FilterManagerImpl;
|
||||
|
||||
// A generic window to show parameters for a Filter with integrated
|
||||
// preview in the current editor.
|
||||
class FilterWindow : public Frame
|
||||
{
|
||||
public:
|
||||
enum WithChannels { WithChannelsSelector, WithoutChannelsSelector };
|
||||
enum WithTiled { WithTiledCheckBox, WithoutTiledCheckBox };
|
||||
|
||||
FilterWindow(const char* title, const char* cfgSection,
|
||||
FilterManagerImpl* filterMgr,
|
||||
WithChannels withChannels,
|
||||
WithTiled withTiled,
|
||||
TiledMode tiledMode = TILED_NONE);
|
||||
~FilterWindow();
|
||||
|
||||
// Shows the window as modal (blocking interface), and returns true
|
||||
// if the user pressed "OK" button (i.e. wants to apply the filter
|
||||
// with the current settings).
|
||||
bool doModal();
|
||||
|
||||
// Starts (or restart) the preview procedure. You should call this
|
||||
// method each time the user modifies parameters of the Filter.
|
||||
void restartPreview();
|
||||
|
||||
protected:
|
||||
// Changes the target buttons. Used by convolution matrix filter
|
||||
// which specified different targets for each matrix.
|
||||
void setNewTarget(Target target);
|
||||
|
||||
// Returns the container where derived classes should put controls.
|
||||
Widget* getContainer() { return &m_container; }
|
||||
|
||||
void onOk(Event& ev);
|
||||
void onCancel(Event& ev);
|
||||
void onShowPreview(Event& ev);
|
||||
void onTargetButtonChange();
|
||||
void onTiledChange();
|
||||
|
||||
// Derived classes WithTiledCheckBox should set its filter's tiled
|
||||
// mode overriding this method.
|
||||
virtual void setupTiledMode(TiledMode tiledMode) { }
|
||||
|
||||
private:
|
||||
const char* m_cfgSection;
|
||||
FilterManagerImpl* m_filterMgr;
|
||||
Box m_hbox;
|
||||
Box m_vbox;
|
||||
Box m_container;
|
||||
Button m_okButton;
|
||||
Button m_cancelButton;
|
||||
FilterPreview m_preview;
|
||||
FilterTargetButtons m_targetButton;
|
||||
CheckBox m_showPreview;
|
||||
CheckBox* m_tiledCheck;
|
||||
};
|
||||
|
||||
#endif
|
186
src/commands/filters/filter_worker.cpp
Normal file
186
src/commands/filters/filter_worker.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "app.h"
|
||||
#include "base/mutex.h"
|
||||
#include "base/scoped_lock.h"
|
||||
#include "base/thread.h"
|
||||
#include "commands/filters/filter_manager_impl.h"
|
||||
#include "core/cfg.h"
|
||||
#include "gui/gui.h"
|
||||
#include "modules/editors.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "widgets/editor.h"
|
||||
#include "widgets/statebar.h"
|
||||
|
||||
// Applies filters in two threads: a background worker thread to
|
||||
// modify the sprite, and the main thread to monitoring the progress
|
||||
// (and given to the user the possibility to cancel the process).
|
||||
|
||||
class FilterWorker : public FilterManagerImpl::IProgressDelegate
|
||||
{
|
||||
public:
|
||||
FilterWorker(FilterManagerImpl* filterMgr);
|
||||
~FilterWorker();
|
||||
|
||||
void run();
|
||||
|
||||
// IProgressDelegate implementation
|
||||
void reportProgress(float progress);
|
||||
bool isCancelled();
|
||||
|
||||
private:
|
||||
void applyFilterInBackground();
|
||||
void monitor();
|
||||
|
||||
static void thread_proxy(void* data) {
|
||||
FilterWorker* filterWorker = (FilterWorker*)data;
|
||||
filterWorker->applyFilterInBackground();
|
||||
}
|
||||
|
||||
static void monitor_proxy(void* data) {
|
||||
FilterWorker* filterWorker = (FilterWorker*)data;
|
||||
filterWorker->monitor();
|
||||
}
|
||||
|
||||
FilterManagerImpl* m_filterMgr; // Effect to be applied.
|
||||
Mutex m_mutex; // Mutex to access to 'pos', 'done' and 'cancelled' fields in different threads.
|
||||
float m_pos; // Current progress position
|
||||
bool m_done : 1; // Was the effect completelly applied?
|
||||
bool m_cancelled : 1; // Was the effect cancelled by the user?
|
||||
Monitor* m_monitor; // Monitor to update the progress-bar
|
||||
Progress* m_progressBar; // The progress-bar.
|
||||
AlertPtr m_alertWindow; // Alert for the user to cancel the filter-progress if he wants.
|
||||
};
|
||||
|
||||
FilterWorker::FilterWorker(FilterManagerImpl* filterMgr)
|
||||
: m_filterMgr(filterMgr)
|
||||
{
|
||||
m_filterMgr->setProgressDelegate(this);
|
||||
|
||||
m_pos = 0.0;
|
||||
m_done = false;
|
||||
m_cancelled = false;
|
||||
|
||||
m_progressBar = app_get_statusbar()->addProgress();
|
||||
|
||||
m_alertWindow = Alert::create(PACKAGE
|
||||
"<<Applying effect...||&Cancel");
|
||||
|
||||
m_monitor = add_gui_monitor(FilterWorker::monitor_proxy, NULL, this);
|
||||
}
|
||||
|
||||
FilterWorker::~FilterWorker()
|
||||
{
|
||||
if (m_alertWindow != NULL)
|
||||
m_alertWindow->closeWindow(NULL);
|
||||
|
||||
delete m_progressBar;
|
||||
}
|
||||
|
||||
void FilterWorker::run()
|
||||
{
|
||||
// Launch the thread to apply the effect in background
|
||||
base::thread thread(&FilterWorker::thread_proxy, this);
|
||||
|
||||
// Open the alert window in foreground (this is modal, locks the main thread)
|
||||
m_alertWindow->open_window_fg();
|
||||
|
||||
// Remove the monitor
|
||||
remove_gui_monitor(m_monitor);
|
||||
|
||||
{
|
||||
ScopedLock lock(m_mutex);
|
||||
if (!m_done)
|
||||
m_cancelled = true;
|
||||
}
|
||||
|
||||
// Wait the `effect_bg' thread
|
||||
thread.join();
|
||||
}
|
||||
|
||||
// Called by FilterManagerImpl to informate the progress of the filter.
|
||||
//
|
||||
// [effect thread]
|
||||
//
|
||||
void FilterWorker::reportProgress(float progress)
|
||||
{
|
||||
ScopedLock lock(m_mutex);
|
||||
m_pos = progress;
|
||||
}
|
||||
|
||||
// Called by effect_apply to know if the user cancelled the operation.
|
||||
//
|
||||
// [effect thread]
|
||||
//
|
||||
bool FilterWorker::isCancelled()
|
||||
{
|
||||
bool cancelled;
|
||||
|
||||
ScopedLock lock(m_mutex);
|
||||
cancelled = m_cancelled;
|
||||
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
// Applies the effect to the sprite in a background thread.
|
||||
//
|
||||
// [effect thread]
|
||||
//
|
||||
void FilterWorker::applyFilterInBackground()
|
||||
{
|
||||
// Apply the filter
|
||||
m_filterMgr->applyToTarget();
|
||||
|
||||
// Mark the work as 'done'.
|
||||
ScopedLock lock(m_mutex);
|
||||
m_done = true;
|
||||
}
|
||||
|
||||
// Called by the GUI monitor (a timer in the gui module that is called
|
||||
// every 100 milliseconds).
|
||||
//
|
||||
// [main thread]
|
||||
//
|
||||
void FilterWorker::monitor()
|
||||
{
|
||||
ScopedLock lock(m_mutex);
|
||||
|
||||
if (m_progressBar)
|
||||
m_progressBar->setPos(m_pos);
|
||||
|
||||
if (m_done)
|
||||
m_alertWindow->closeWindow(NULL);
|
||||
}
|
||||
|
||||
// Applies the filter in a background thread meanwhile a progress bar
|
||||
// is shown to the user.
|
||||
//
|
||||
// [main thread]
|
||||
//
|
||||
void start_filter_worker(FilterManagerImpl* filterMgr)
|
||||
{
|
||||
FilterWorker filterWorker(filterMgr);
|
||||
filterWorker.run();
|
||||
}
|
@ -16,11 +16,11 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef COMMANDS_FX_EFFECTBG_H_INCLUDED
|
||||
#define COMMANDS_FX_EFFECTBG_H_INCLUDED
|
||||
#ifndef COMMANDS_FILTERS_FILTER_BG_H_INCLUDED
|
||||
#define COMMANDS_FILTERS_FILTER_BG_H_INCLUDED
|
||||
|
||||
struct Effect;
|
||||
class FilterManagerImpl;
|
||||
|
||||
void effect_apply_to_target_with_progressbar(struct Effect* effect);
|
||||
void start_filter_worker(FilterManagerImpl* filterMgr);
|
||||
|
||||
#endif
|
@ -1,193 +0,0 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "gui/gui.h"
|
||||
|
||||
#include "app.h"
|
||||
#include "app/color.h"
|
||||
#include "commands/command.h"
|
||||
#include "commands/fx/effectbg.h"
|
||||
#include "console.h"
|
||||
#include "core/cfg.h"
|
||||
#include "effect/colcurve.h"
|
||||
#include "effect/effect.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "util/misc.h"
|
||||
#include "widgets/color_button.h"
|
||||
#include "widgets/curvedit.h"
|
||||
#include "widgets/preview.h"
|
||||
#include "widgets/target.h"
|
||||
|
||||
static Curve* the_curve = NULL;
|
||||
static JWidget preview;
|
||||
static CheckBox* check_preview;
|
||||
|
||||
static bool window_msg_proc(JWidget widget, JMessage msg);
|
||||
static void preview_change_hook(Widget* widget);
|
||||
static void make_preview();
|
||||
|
||||
// Slot for App::Exit signal
|
||||
static void on_exit_delete_curve()
|
||||
{
|
||||
curve_free(the_curve);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// ColorCurveCommand
|
||||
|
||||
class ColorCurveCommand : public Command
|
||||
{
|
||||
public:
|
||||
ColorCurveCommand();
|
||||
Command* clone() const { return new ColorCurveCommand(*this); }
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* context);
|
||||
void onExecute(Context* context);
|
||||
};
|
||||
|
||||
ColorCurveCommand::ColorCurveCommand()
|
||||
: Command("ColorCurve",
|
||||
"Color Curve",
|
||||
CmdRecordableFlag)
|
||||
{
|
||||
}
|
||||
|
||||
bool ColorCurveCommand::onEnabled(Context* context)
|
||||
{
|
||||
const CurrentSpriteReader sprite(context);
|
||||
return
|
||||
sprite != NULL;
|
||||
}
|
||||
|
||||
void ColorCurveCommand::onExecute(Context* context)
|
||||
{
|
||||
const CurrentSpriteReader sprite(context);
|
||||
Widget* button_ok;
|
||||
Widget* curve_editor;
|
||||
Widget* box_target;
|
||||
Widget* target_button;
|
||||
View* view_curve;
|
||||
|
||||
if (!the_curve) {
|
||||
/* default curve */
|
||||
the_curve = curve_new(CURVE_LINEAR);
|
||||
curve_add_point(the_curve, curve_point_new(0, 0));
|
||||
curve_add_point(the_curve, curve_point_new(255, 255));
|
||||
|
||||
App::instance()->Exit.connect(&on_exit_delete_curve);
|
||||
}
|
||||
|
||||
FramePtr window(load_widget("color_curve.xml", "color_curve"));
|
||||
get_widgets(window,
|
||||
"preview", &check_preview,
|
||||
"button_ok", &button_ok,
|
||||
"curve", &view_curve,
|
||||
"target", &box_target, NULL);
|
||||
|
||||
Effect effect(sprite, "color_curve");
|
||||
effect_set_target(&effect, TARGET_RED_CHANNEL | TARGET_GREEN_CHANNEL |
|
||||
TARGET_BLUE_CHANNEL | TARGET_ALPHA_CHANNEL);
|
||||
|
||||
preview = preview_new(&effect);
|
||||
|
||||
set_color_curve(the_curve);
|
||||
|
||||
curve_editor = curve_editor_new(the_curve, 0, 0, 255, 255);
|
||||
target_button = target_button_new(sprite->getImgType(), true);
|
||||
target_button_set_target(target_button, effect.target);
|
||||
|
||||
if (get_config_bool("ColorCurve", "Preview", true))
|
||||
check_preview->setSelected(true);
|
||||
|
||||
view_curve->attachToView(curve_editor);
|
||||
jwidget_set_min_size(view_curve, 128, 64);
|
||||
|
||||
jwidget_add_child(box_target, target_button);
|
||||
jwidget_add_child(window, preview);
|
||||
|
||||
check_preview->Click.connect(Bind<void>(&preview_change_hook, check_preview));
|
||||
jwidget_add_hook(window, -1, window_msg_proc, NULL);
|
||||
|
||||
/* default position */
|
||||
window->remap_window();
|
||||
window->center_window();
|
||||
|
||||
/* first preview */
|
||||
make_preview();
|
||||
|
||||
/* load window configuration */
|
||||
load_window_pos(window, "ColorCurve");
|
||||
|
||||
/* open the window */
|
||||
window->open_window_fg();
|
||||
|
||||
if (window->get_killer() == button_ok)
|
||||
effect_apply_to_target_with_progressbar(&effect);
|
||||
|
||||
/* update editors */
|
||||
update_screen_for_sprite(sprite);
|
||||
|
||||
/* save window configuration */
|
||||
save_window_pos(window, "ColorCurve");
|
||||
}
|
||||
|
||||
static bool window_msg_proc(JWidget widget, JMessage msg)
|
||||
{
|
||||
if (msg->type == JM_SIGNAL) {
|
||||
switch (msg->signal.num) {
|
||||
|
||||
case SIGNAL_CURVE_EDITOR_CHANGE:
|
||||
set_color_curve(curve_editor_get_curve(msg->signal.from));
|
||||
make_preview();
|
||||
break;
|
||||
|
||||
case SIGNAL_TARGET_BUTTON_CHANGE:
|
||||
effect_set_target(preview_get_effect(preview),
|
||||
target_button_get_target(msg->signal.from));
|
||||
make_preview();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void preview_change_hook(Widget* widget)
|
||||
{
|
||||
set_config_bool("ColorCurve", "Preview", widget->isSelected());
|
||||
make_preview();
|
||||
}
|
||||
|
||||
static void make_preview()
|
||||
{
|
||||
if (check_preview->isSelected())
|
||||
preview_restart(preview);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CommandFactory
|
||||
|
||||
Command* CommandFactory::createColorCurveCommand()
|
||||
{
|
||||
return new ColorCurveCommand;
|
||||
}
|
@ -1,346 +0,0 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "gui/button.h"
|
||||
#include "gui/frame.h"
|
||||
#include "gui/hook.h"
|
||||
#include "gui/list.h"
|
||||
#include "gui/listbox.h"
|
||||
#include "gui/label.h"
|
||||
#include "gui/slider.h"
|
||||
#include "gui/view.h"
|
||||
#include "gui/widget.h"
|
||||
|
||||
#include "app/color.h"
|
||||
#include "commands/command.h"
|
||||
#include "commands/fx/effectbg.h"
|
||||
#include "console.h"
|
||||
#include "core/cfg.h"
|
||||
#include "effect/colcurve.h"
|
||||
#include "effect/convmatr.h"
|
||||
#include "effect/effect.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "ui_context.h"
|
||||
#include "util/misc.h"
|
||||
#include "widgets/color_button.h"
|
||||
#include "widgets/curvedit.h"
|
||||
#include "widgets/preview.h"
|
||||
#include "widgets/target.h"
|
||||
|
||||
static CheckBox* check_preview, *check_tiled;
|
||||
static JWidget preview;
|
||||
static JWidget target_button;
|
||||
|
||||
static void listbox_fill_convmatg(JWidget listbox);
|
||||
static void listbox_select_current_convmatr(JWidget listbox);
|
||||
|
||||
static bool reload_select_hook(Widget* listbox);
|
||||
static bool generate_select_hook();
|
||||
|
||||
static bool list_change_hook(JWidget widget, void *data);
|
||||
static bool target_change_hook(JWidget widget, void *data);
|
||||
static void preview_change_hook(Widget* widget);
|
||||
static void tiled_change_hook(Widget* widget);
|
||||
static void make_preview();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// convolution_matrix
|
||||
|
||||
class ConvolutionMatrixCommand : public Command
|
||||
{
|
||||
public:
|
||||
ConvolutionMatrixCommand();
|
||||
Command* clone() const { return new ConvolutionMatrixCommand(*this); }
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* context);
|
||||
void onExecute(Context* context);
|
||||
};
|
||||
|
||||
ConvolutionMatrixCommand::ConvolutionMatrixCommand()
|
||||
: Command("ConvolutionMatrix",
|
||||
"Convolution Matrix",
|
||||
CmdRecordableFlag)
|
||||
{
|
||||
}
|
||||
|
||||
bool ConvolutionMatrixCommand::onEnabled(Context* context)
|
||||
{
|
||||
const CurrentSpriteReader sprite(context);
|
||||
return
|
||||
sprite != NULL;
|
||||
}
|
||||
|
||||
void ConvolutionMatrixCommand::onExecute(Context* context)
|
||||
{
|
||||
const CurrentSpriteReader sprite(context);
|
||||
Widget* button_ok;
|
||||
View* view_convmatr;
|
||||
Widget *list_convmatr;
|
||||
Widget* box_target;
|
||||
Button* reload, *generate;
|
||||
|
||||
FramePtr window(load_widget("convolution_matrix.xml", "convolution_matrix"));
|
||||
get_widgets(window,
|
||||
"preview", &check_preview,
|
||||
"tiled", &check_tiled,
|
||||
"button_ok", &button_ok,
|
||||
"view", &view_convmatr,
|
||||
"target", &box_target,
|
||||
"reload", &reload,
|
||||
"generate", &generate, NULL);
|
||||
|
||||
Effect effect(sprite, "convolution_matrix");
|
||||
preview = preview_new(&effect);
|
||||
|
||||
list_convmatr = jlistbox_new();
|
||||
listbox_fill_convmatg(list_convmatr);
|
||||
|
||||
target_button = target_button_new(sprite->getImgType(), true);
|
||||
target_button_set_target(target_button, effect.target);
|
||||
|
||||
if (get_config_bool("ConvolutionMatrix", "Preview", true))
|
||||
check_preview->setSelected(true);
|
||||
|
||||
if (context->getSettings()->getTiledMode() != TILED_NONE)
|
||||
check_tiled->setSelected(true);
|
||||
|
||||
view_convmatr->attachToView(list_convmatr);
|
||||
jwidget_set_min_size(view_convmatr, 128, 64);
|
||||
|
||||
jwidget_add_child(box_target, target_button);
|
||||
jwidget_add_child(window, preview);
|
||||
|
||||
HOOK(list_convmatr, JI_SIGNAL_LISTBOX_CHANGE, list_change_hook, 0);
|
||||
HOOK(target_button, SIGNAL_TARGET_BUTTON_CHANGE, target_change_hook, 0);
|
||||
check_preview->Click.connect(Bind<void>(&preview_change_hook, check_preview));
|
||||
check_tiled->Click.connect(Bind<void>(&tiled_change_hook, check_tiled));
|
||||
reload->Click.connect(Bind<bool>(&reload_select_hook, list_convmatr));
|
||||
generate->Click.connect(Bind<void>(&generate_select_hook));
|
||||
|
||||
// TODO enable this someday
|
||||
generate->setEnabled(false);
|
||||
|
||||
/* default position */
|
||||
window->remap_window();
|
||||
window->center_window();
|
||||
|
||||
/* load window configuration */
|
||||
load_window_pos(window, "ConvolutionMatrix");
|
||||
|
||||
/* select default convmatr */
|
||||
listbox_select_current_convmatr(list_convmatr);
|
||||
|
||||
/* open the window */
|
||||
window->open_window_fg();
|
||||
|
||||
if (window->get_killer() == button_ok)
|
||||
effect_apply_to_target_with_progressbar(&effect);
|
||||
|
||||
/* update editors */
|
||||
update_screen_for_sprite(sprite);
|
||||
|
||||
/* save window configuration */
|
||||
save_window_pos(window, "ConvolutionMatrix");
|
||||
}
|
||||
|
||||
static void listbox_fill_convmatg(JWidget listbox)
|
||||
{
|
||||
ConvMatr *convmatr;
|
||||
JWidget listitem;
|
||||
JLink link;
|
||||
|
||||
JI_LIST_FOR_EACH(get_convmatr_stock(), link) {
|
||||
convmatr = reinterpret_cast<ConvMatr *>(link->data);
|
||||
listitem = jlistitem_new(convmatr->name);
|
||||
listitem->user_data[0] = convmatr;
|
||||
jwidget_add_child(listbox, listitem);
|
||||
}
|
||||
}
|
||||
|
||||
static void listbox_select_current_convmatr(JWidget listbox)
|
||||
{
|
||||
const char *selected = get_config_string("ConvolutionMatrix",
|
||||
"Selected", "");
|
||||
JWidget select_this = reinterpret_cast<JWidget>(jlist_first_data(listbox->children));
|
||||
JWidget child = NULL;
|
||||
JLink link;
|
||||
|
||||
if (selected && *selected) {
|
||||
JI_LIST_FOR_EACH(listbox->children, link) {
|
||||
child = reinterpret_cast<JWidget>(link->data);
|
||||
|
||||
if (strcmp(child->getText(), selected) == 0) {
|
||||
select_this = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (select_this) {
|
||||
select_this->setSelected(true);
|
||||
list_change_hook(listbox, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static bool reload_select_hook(Widget* listbox)
|
||||
{
|
||||
JWidget listitem;
|
||||
JLink link, next;
|
||||
|
||||
/* clean the list */
|
||||
JI_LIST_FOR_EACH_SAFE(listbox->children, link, next) {
|
||||
listitem = reinterpret_cast<JWidget>(link->data);
|
||||
jwidget_remove_child(listbox, listitem);
|
||||
jwidget_free(listitem);
|
||||
}
|
||||
|
||||
/* re-load the convolution matrix stock */
|
||||
reload_matrices_stock();
|
||||
|
||||
/* re-fill the list */
|
||||
listbox_fill_convmatg(listbox);
|
||||
listbox_select_current_convmatr(listbox);
|
||||
View::getView(listbox)->updateView();
|
||||
|
||||
return true; /* do not close */
|
||||
}
|
||||
|
||||
static bool generate_select_hook()
|
||||
{
|
||||
#if 0
|
||||
JWidget view_x;
|
||||
JWidget view_y;
|
||||
JWidget curvedit_x;
|
||||
JWidget curvedit_y;
|
||||
Curve *curve_x;
|
||||
Curve *curve_y;
|
||||
JWidget div, div_auto;
|
||||
JWidget bias, bias_auto;
|
||||
|
||||
JWidgetPtr window(load_widget("convolution_matrix.xml", "generate_convolution_matrix"));
|
||||
get_widgets(window,
|
||||
"view_x", &view_x,
|
||||
"view_y", &view_y,
|
||||
"div", &div,
|
||||
"bias", &bias,
|
||||
"div_auto", &div_auto,
|
||||
"bias_auto", &bias_auto, NULL);
|
||||
|
||||
/* curve_x = curve_new(CURVE_SPLINE); */
|
||||
/* curve_y = curve_new(CURVE_SPLINE); */
|
||||
curve_x = curve_new(CURVE_LINEAR);
|
||||
curve_y = curve_new(CURVE_LINEAR);
|
||||
curve_add_point(curve_x, curve_point_new(-100, 0));
|
||||
curve_add_point(curve_x, curve_point_new(0, +100));
|
||||
curve_add_point(curve_x, curve_point_new(+100, 0));
|
||||
curve_add_point(curve_y, curve_point_new(-100, 0));
|
||||
curve_add_point(curve_y, curve_point_new(0, +100));
|
||||
curve_add_point(curve_y, curve_point_new(+100, 0));
|
||||
|
||||
curvedit_x = curve_editor_new(curve_x, -200, -200, 200, 200);
|
||||
curvedit_y = curve_editor_new(curve_y, -200, -200, 200, 200);
|
||||
|
||||
view_x->attachToView(curvedit_x);
|
||||
view_y->attachToView(curvedit_y);
|
||||
|
||||
jwidget_set_min_size(view_x, 64, 64);
|
||||
jwidget_set_min_size(view_y, 64, 64);
|
||||
|
||||
/* TODO fix this */
|
||||
/* jwidget_get_vtable(div)->request_size = NULL; */
|
||||
/* jwidget_get_vtable(bias)->request_size = NULL; */
|
||||
|
||||
jwidget_set_min_size(div, 1, 1);
|
||||
jwidget_set_min_size(bias, 1, 1);
|
||||
|
||||
window->open_window_fg();
|
||||
|
||||
/* TODO do something */
|
||||
|
||||
curve_free(curve_x);
|
||||
curve_free(curve_y);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool list_change_hook(JWidget widget, void *data)
|
||||
{
|
||||
JWidget selected = jlistbox_get_selected_child(widget);
|
||||
ConvMatr *convmatr = reinterpret_cast<ConvMatr*>(selected->user_data[0]);
|
||||
int new_target = convmatr->default_target;
|
||||
|
||||
set_config_string("ConvolutionMatrix", "Selected", convmatr->name);
|
||||
|
||||
// TODO avoid UIContext::instance, hold the context in some place
|
||||
TiledMode tiled = UIContext::instance()->getSettings()->getTiledMode();
|
||||
set_convmatr(convmatr, tiled);
|
||||
|
||||
target_button_set_target(target_button, new_target);
|
||||
effect_set_target(preview_get_effect(preview), new_target);
|
||||
|
||||
make_preview();
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool target_change_hook(JWidget widget, void *data)
|
||||
{
|
||||
effect_set_target(preview_get_effect(preview),
|
||||
target_button_get_target(widget));
|
||||
make_preview();
|
||||
return false;
|
||||
}
|
||||
|
||||
static void preview_change_hook(Widget* widget)
|
||||
{
|
||||
set_config_bool("ConvolutionMatrix", "Preview", widget->isSelected());
|
||||
make_preview();
|
||||
}
|
||||
|
||||
static void tiled_change_hook(Widget* widget)
|
||||
{
|
||||
TiledMode tiled = widget->isSelected() ? TILED_BOTH:
|
||||
TILED_NONE;
|
||||
|
||||
// TODO avoid UIContext::instance, hold the context in some place
|
||||
UIContext::instance()->getSettings()->setTiledMode(tiled);
|
||||
|
||||
make_preview();
|
||||
}
|
||||
|
||||
static void make_preview()
|
||||
{
|
||||
if (check_preview->isSelected())
|
||||
preview_restart(preview);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CommandFactory
|
||||
|
||||
Command* CommandFactory::createConvolutionMatrixCommand()
|
||||
{
|
||||
return new ConvolutionMatrixCommand;
|
||||
}
|
||||
|
@ -1,211 +0,0 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "gui/button.h"
|
||||
#include "gui/entry.h"
|
||||
#include "gui/frame.h"
|
||||
#include "gui/hook.h"
|
||||
#include "gui/widget.h"
|
||||
|
||||
#include "commands/command.h"
|
||||
#include "commands/fx/effectbg.h"
|
||||
#include "console.h"
|
||||
#include "core/cfg.h"
|
||||
#include "effect/effect.h"
|
||||
#include "effect/median.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "settings/settings.h"
|
||||
#include "ui_context.h"
|
||||
#include "util/misc.h"
|
||||
#include "widgets/preview.h"
|
||||
#include "widgets/target.h"
|
||||
|
||||
static JWidget entry_width, entry_height;
|
||||
static JWidget preview;
|
||||
static CheckBox* check_preview;
|
||||
static CheckBox* check_tiled;
|
||||
|
||||
static bool width_change_hook(JWidget widget, void *data);
|
||||
static bool height_change_hook(JWidget widget, void *data);
|
||||
static bool target_change_hook(JWidget widget, void *data);
|
||||
static void preview_change_hook(JWidget widget);
|
||||
static bool tiled_change_hook(JWidget widget, void *data);
|
||||
static void make_preview();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// despeckle
|
||||
|
||||
class DespeckleCommand : public Command
|
||||
{
|
||||
public:
|
||||
DespeckleCommand();
|
||||
Command* clone() const { return new DespeckleCommand(*this); }
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* context);
|
||||
void onExecute(Context* context);
|
||||
};
|
||||
|
||||
DespeckleCommand::DespeckleCommand()
|
||||
: Command("Despeckle",
|
||||
"Despeckle",
|
||||
CmdRecordableFlag)
|
||||
{
|
||||
}
|
||||
|
||||
bool DespeckleCommand::onEnabled(Context* context)
|
||||
{
|
||||
const CurrentSpriteReader sprite(context);
|
||||
return
|
||||
sprite != NULL;
|
||||
}
|
||||
|
||||
void DespeckleCommand::onExecute(Context* context)
|
||||
{
|
||||
const CurrentSpriteReader sprite(context);
|
||||
JWidget box_target, target_button, button_ok;
|
||||
|
||||
FramePtr window(load_widget("median_blur.xml", "median"));
|
||||
get_widgets(window,
|
||||
"width", &entry_width,
|
||||
"height", &entry_height,
|
||||
"preview", &check_preview,
|
||||
"tiled", &check_tiled,
|
||||
"target", &box_target,
|
||||
"button_ok", &button_ok, NULL);
|
||||
|
||||
Effect effect(sprite, "median");
|
||||
effect_set_target(&effect, TARGET_RED_CHANNEL |
|
||||
TARGET_GREEN_CHANNEL |
|
||||
TARGET_BLUE_CHANNEL);
|
||||
|
||||
preview = preview_new(&effect);
|
||||
|
||||
target_button = target_button_new(sprite->getImgType(), true);
|
||||
target_button_set_target(target_button, effect.target);
|
||||
|
||||
entry_width->setTextf("%d", get_config_int("Median", "Width", 3));
|
||||
entry_height->setTextf("%d", get_config_int("Median", "Height", 3));
|
||||
|
||||
if (get_config_bool("Median", "Preview", true))
|
||||
check_preview->setSelected(true);
|
||||
|
||||
if (context->getSettings()->getTiledMode() != TILED_NONE)
|
||||
check_tiled->setSelected(true);
|
||||
|
||||
jwidget_add_child(box_target, target_button);
|
||||
jwidget_add_child(window, preview);
|
||||
|
||||
HOOK(entry_width, JI_SIGNAL_ENTRY_CHANGE, width_change_hook, 0);
|
||||
HOOK(entry_height, JI_SIGNAL_ENTRY_CHANGE, height_change_hook, 0);
|
||||
HOOK(target_button, SIGNAL_TARGET_BUTTON_CHANGE, target_change_hook, 0);
|
||||
HOOK(check_tiled, JI_SIGNAL_CHECK_CHANGE, tiled_change_hook, 0);
|
||||
|
||||
check_preview->Click.connect(Bind<void>(&preview_change_hook, check_preview));
|
||||
|
||||
/* default position */
|
||||
window->remap_window();
|
||||
window->center_window();
|
||||
|
||||
/* first preview */
|
||||
make_preview();
|
||||
|
||||
/* load window configuration */
|
||||
load_window_pos(window, "Median");
|
||||
|
||||
/* open the window */
|
||||
window->open_window_fg();
|
||||
|
||||
if (window->get_killer() == button_ok)
|
||||
effect_apply_to_target_with_progressbar(&effect);
|
||||
|
||||
/* update editors */
|
||||
update_screen_for_sprite(sprite);
|
||||
|
||||
/* save window configuration */
|
||||
save_window_pos(window, "Median");
|
||||
}
|
||||
|
||||
static bool width_change_hook(JWidget widget, void *data)
|
||||
{
|
||||
set_config_int("Median", "Width", widget->getTextInt());
|
||||
make_preview();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool height_change_hook(JWidget widget, void *data)
|
||||
{
|
||||
set_config_int("Median", "Height", widget->getTextInt());
|
||||
make_preview();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool target_change_hook(JWidget widget, void *data)
|
||||
{
|
||||
effect_set_target(preview_get_effect(preview),
|
||||
target_button_get_target(widget));
|
||||
make_preview();
|
||||
return false;
|
||||
}
|
||||
|
||||
static void preview_change_hook(JWidget widget)
|
||||
{
|
||||
set_config_bool("Median", "Preview", widget->isSelected());
|
||||
make_preview();
|
||||
}
|
||||
|
||||
static bool tiled_change_hook(JWidget widget, void *data)
|
||||
{
|
||||
TiledMode tiled = widget->isSelected() ? TILED_BOTH:
|
||||
TILED_NONE;
|
||||
|
||||
// TODO save context in some place, don't use UIContext directly
|
||||
UIContext::instance()->getSettings()->setTiledMode(tiled);
|
||||
make_preview();
|
||||
return false;
|
||||
}
|
||||
|
||||
static void make_preview()
|
||||
{
|
||||
int w, h;
|
||||
|
||||
w = get_config_int("Median", "Width", 3);
|
||||
h = get_config_int("Median", "Height", 3);
|
||||
|
||||
// TODO do not use UIContext::instance
|
||||
set_median_size(UIContext::instance()->getSettings()->getTiledMode(),
|
||||
MID(1, w, 32), MID(1, h, 32));
|
||||
|
||||
if (check_preview->isSelected())
|
||||
preview_restart(preview);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CommandFactory
|
||||
|
||||
Command* CommandFactory::createDespeckleCommand()
|
||||
{
|
||||
return new DespeckleCommand;
|
||||
}
|
@ -1,157 +0,0 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "gui/button.h"
|
||||
#include "gui/frame.h"
|
||||
#include "gui/hook.h"
|
||||
#include "gui/label.h"
|
||||
#include "gui/slider.h"
|
||||
#include "gui/widget.h"
|
||||
|
||||
#include "app/color.h"
|
||||
#include "commands/command.h"
|
||||
#include "commands/fx/effectbg.h"
|
||||
#include "console.h"
|
||||
#include "core/cfg.h"
|
||||
#include "effect/effect.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "util/misc.h"
|
||||
#include "widgets/color_button.h"
|
||||
#include "widgets/preview.h"
|
||||
#include "widgets/target.h"
|
||||
|
||||
static CheckBox* check_preview;
|
||||
static JWidget preview;
|
||||
|
||||
static bool target_change_hook(JWidget widget, void *data);
|
||||
static void preview_change_hook(Widget* widget);
|
||||
static void make_preview();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// invert_color
|
||||
|
||||
class InvertColorCommand : public Command
|
||||
{
|
||||
public:
|
||||
InvertColorCommand();
|
||||
Command* clone() const { return new InvertColorCommand(*this); }
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* context);
|
||||
void onExecute(Context* context);
|
||||
};
|
||||
|
||||
InvertColorCommand::InvertColorCommand()
|
||||
: Command("InvertColor",
|
||||
"Invert Color",
|
||||
CmdRecordableFlag)
|
||||
{
|
||||
}
|
||||
|
||||
bool InvertColorCommand::onEnabled(Context* context)
|
||||
{
|
||||
const CurrentSpriteReader sprite(context);
|
||||
return
|
||||
sprite != NULL;
|
||||
}
|
||||
|
||||
void InvertColorCommand::onExecute(Context* context)
|
||||
{
|
||||
const CurrentSpriteReader sprite(context);
|
||||
JWidget box_target, target_button, button_ok;
|
||||
|
||||
FramePtr window(load_widget("invert_color.xml", "invert_color"));
|
||||
get_widgets(window,
|
||||
"target", &box_target,
|
||||
"preview", &check_preview,
|
||||
"button_ok", &button_ok, NULL);
|
||||
|
||||
Effect effect(sprite, "invert_color");
|
||||
effect_set_target(&effect, TARGET_RED_CHANNEL |
|
||||
TARGET_GREEN_CHANNEL |
|
||||
TARGET_BLUE_CHANNEL);
|
||||
|
||||
preview = preview_new(&effect);
|
||||
target_button = target_button_new(sprite->getImgType(), true);
|
||||
target_button_set_target(target_button, effect.target);
|
||||
|
||||
if (get_config_bool("InvertColor", "Preview", true))
|
||||
check_preview->setSelected(true);
|
||||
|
||||
jwidget_add_child(box_target, target_button);
|
||||
jwidget_add_child(window, preview);
|
||||
|
||||
HOOK(target_button, SIGNAL_TARGET_BUTTON_CHANGE, target_change_hook, 0);
|
||||
check_preview->Click.connect(Bind<void>(&preview_change_hook, check_preview));
|
||||
|
||||
/* default position */
|
||||
window->remap_window();
|
||||
window->center_window();
|
||||
|
||||
/* first preview */
|
||||
make_preview();
|
||||
|
||||
/* load window configuration */
|
||||
load_window_pos(window, "InvertColor");
|
||||
|
||||
/* open the window */
|
||||
window->open_window_fg();
|
||||
|
||||
if (window->get_killer() == button_ok)
|
||||
effect_apply_to_target_with_progressbar(&effect);
|
||||
|
||||
/* update editors */
|
||||
update_screen_for_sprite(sprite);
|
||||
|
||||
/* save window configuration */
|
||||
save_window_pos(window, "InvertColor");
|
||||
}
|
||||
|
||||
static bool target_change_hook(JWidget widget, void *data)
|
||||
{
|
||||
effect_set_target(preview_get_effect(preview),
|
||||
target_button_get_target(widget));
|
||||
make_preview();
|
||||
return false;
|
||||
}
|
||||
|
||||
static void preview_change_hook(Widget* widget)
|
||||
{
|
||||
set_config_bool("InvertColor", "Preview", widget->isSelected());
|
||||
make_preview();
|
||||
}
|
||||
|
||||
static void make_preview()
|
||||
{
|
||||
if (check_preview->isSelected())
|
||||
preview_restart(preview);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CommandFactory
|
||||
|
||||
Command* CommandFactory::createInvertColorCommand()
|
||||
{
|
||||
return new InvertColorCommand;
|
||||
}
|
@ -1,211 +0,0 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "gui/gui.h"
|
||||
|
||||
#include "app.h"
|
||||
#include "app/color.h"
|
||||
#include "app/color_utils.h"
|
||||
#include "commands/command.h"
|
||||
#include "commands/fx/effectbg.h"
|
||||
#include "console.h"
|
||||
#include "core/cfg.h"
|
||||
#include "effect/effect.h"
|
||||
#include "effect/replcol.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "util/misc.h"
|
||||
#include "widgets/color_bar.h"
|
||||
#include "widgets/color_button.h"
|
||||
#include "widgets/preview.h"
|
||||
#include "widgets/target.h"
|
||||
|
||||
static ColorButton* button_color1;
|
||||
static ColorButton* button_color2;
|
||||
static Slider* slider_tolerance;
|
||||
static JWidget preview;
|
||||
static CheckBox* check_preview;
|
||||
|
||||
static void color_change_hook(Widget* widget, int num);
|
||||
static bool target_change_hook(Widget* widget, void *data);
|
||||
static void slider_change_hook(Slider* tolerance_slider);
|
||||
static void preview_change_hook(Widget* widget);
|
||||
static void make_preview();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// replace_color
|
||||
|
||||
class ReplaceColorCommand : public Command
|
||||
{
|
||||
public:
|
||||
ReplaceColorCommand();
|
||||
Command* clone() const { return new ReplaceColorCommand(*this); }
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* context);
|
||||
void onExecute(Context* context);
|
||||
};
|
||||
|
||||
ReplaceColorCommand::ReplaceColorCommand()
|
||||
: Command("ReplaceColor",
|
||||
"Replace Color",
|
||||
CmdRecordableFlag)
|
||||
{
|
||||
}
|
||||
|
||||
bool ReplaceColorCommand::onEnabled(Context* context)
|
||||
{
|
||||
const CurrentSpriteReader sprite(context);
|
||||
return
|
||||
sprite != NULL;
|
||||
}
|
||||
|
||||
void ReplaceColorCommand::onExecute(Context* context)
|
||||
{
|
||||
const CurrentSpriteReader sprite(context);
|
||||
JWidget color_buttons_box;
|
||||
JWidget box_target, target_button;
|
||||
JWidget button_ok;
|
||||
|
||||
FramePtr window(load_widget("replace_color.xml", "replace_color"));
|
||||
get_widgets(window,
|
||||
"color_buttons_box", &color_buttons_box,
|
||||
"preview", &check_preview,
|
||||
"tolerance", &slider_tolerance,
|
||||
"target", &box_target,
|
||||
"button_ok", &button_ok, NULL);
|
||||
|
||||
Effect effect(sprite, "replace_color");
|
||||
effect_set_target(&effect, TARGET_RED_CHANNEL |
|
||||
TARGET_GREEN_CHANNEL |
|
||||
TARGET_BLUE_CHANNEL |
|
||||
TARGET_ALPHA_CHANNEL);
|
||||
preview = preview_new(&effect);
|
||||
|
||||
button_color1 = new ColorButton
|
||||
(get_config_color("ReplaceColor", "Color1",
|
||||
app_get_colorbar()->getFgColor()),
|
||||
sprite->getImgType());
|
||||
|
||||
button_color2 = new ColorButton
|
||||
(get_config_color("ReplaceColor", "Color2",
|
||||
app_get_colorbar()->getBgColor()),
|
||||
sprite->getImgType());
|
||||
|
||||
target_button = target_button_new(sprite->getImgType(), false);
|
||||
target_button_set_target(target_button, effect.target);
|
||||
|
||||
slider_tolerance->setValue(get_config_int("ReplaceColor", "Tolerance", 0));
|
||||
if (get_config_bool("ReplaceColor", "Preview", true))
|
||||
check_preview->setSelected(true);
|
||||
|
||||
jwidget_add_child(color_buttons_box, button_color1);
|
||||
jwidget_add_child(color_buttons_box, button_color2);
|
||||
jwidget_add_child(box_target, target_button);
|
||||
jwidget_add_child(window, preview);
|
||||
|
||||
button_color1->Change.connect(Bind<void>(&color_change_hook, button_color1, 1));
|
||||
button_color2->Change.connect(Bind<void>(&color_change_hook, button_color2, 2));
|
||||
HOOK(target_button, SIGNAL_TARGET_BUTTON_CHANGE, target_change_hook, 0);
|
||||
slider_tolerance->Change.connect(Bind<void>(&slider_change_hook, slider_tolerance));
|
||||
check_preview->Click.connect(Bind<void>(&preview_change_hook, check_preview));
|
||||
|
||||
/* default position */
|
||||
window->remap_window();
|
||||
window->center_window();
|
||||
|
||||
/* first preview */
|
||||
make_preview();
|
||||
|
||||
/* load window configuration */
|
||||
load_window_pos(window, "ReplaceColor");
|
||||
|
||||
/* open the window */
|
||||
window->open_window_fg();
|
||||
|
||||
if (window->get_killer() == button_ok)
|
||||
effect_apply_to_target_with_progressbar(&effect);
|
||||
|
||||
/* update editors */
|
||||
update_screen_for_sprite(sprite);
|
||||
|
||||
/* save window configuration */
|
||||
save_window_pos(window, "ReplaceColor");
|
||||
}
|
||||
|
||||
static void color_change_hook(Widget* widget, int num)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
sprintf(buf, "Color%u", num);
|
||||
set_config_color("ReplaceColor", buf, static_cast<ColorButton*>(widget)->getColor());
|
||||
|
||||
make_preview();
|
||||
}
|
||||
|
||||
static bool target_change_hook(JWidget widget, void *data)
|
||||
{
|
||||
effect_set_target(preview_get_effect(preview),
|
||||
target_button_get_target(widget));
|
||||
make_preview();
|
||||
return false;
|
||||
}
|
||||
|
||||
static void slider_change_hook(Slider* tolerance_slider)
|
||||
{
|
||||
set_config_int("ReplaceColor", "Tolerance", tolerance_slider->getValue());
|
||||
make_preview();
|
||||
}
|
||||
|
||||
static void preview_change_hook(Widget* widget)
|
||||
{
|
||||
set_config_bool("ReplaceColor", "Preview", widget->isSelected());
|
||||
make_preview();
|
||||
}
|
||||
|
||||
static void make_preview()
|
||||
{
|
||||
Sprite* sprite = preview_get_effect(preview)->sprite;
|
||||
int tolerance;
|
||||
|
||||
Color from = get_config_color("ReplaceColor", "Color1", Color::fromMask());
|
||||
Color to = get_config_color("ReplaceColor", "Color2", Color::fromMask());
|
||||
tolerance = get_config_int("ReplaceColor", "Tolerance", 0);
|
||||
|
||||
set_replace_colors(color_utils::color_for_layer(from, sprite->getCurrentLayer()),
|
||||
color_utils::color_for_layer(to, sprite->getCurrentLayer()),
|
||||
MID(0, tolerance, 255));
|
||||
|
||||
if (check_preview->isSelected())
|
||||
preview_restart(preview);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// CommandFactory
|
||||
|
||||
Command* CommandFactory::createReplaceColorCommand()
|
||||
{
|
||||
return new ReplaceColorCommand;
|
||||
}
|
@ -1,184 +0,0 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "app.h"
|
||||
#include "base/mutex.h"
|
||||
#include "base/scoped_lock.h"
|
||||
#include "base/thread.h"
|
||||
#include "core/cfg.h"
|
||||
#include "effect/effect.h"
|
||||
#include "gui/gui.h"
|
||||
#include "modules/editors.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "widgets/editor.h"
|
||||
#include "widgets/statebar.h"
|
||||
|
||||
/**********************************************************************
|
||||
Apply effect in two threads: bg-thread to modify the sprite, and the
|
||||
main thread to monitoring the progress.
|
||||
**********************************************************************/
|
||||
|
||||
struct ThreadData
|
||||
{
|
||||
Effect* effect; /* effect to be applied */
|
||||
Mutex mutex; /* mutex to access to 'pos', 'done'
|
||||
and 'cancelled' fields in different
|
||||
threads */
|
||||
float pos; /* current progress position */
|
||||
bool done : 1; /* was the effect completelly applied? */
|
||||
bool cancelled : 1; /* was the effect cancelled by the user? */
|
||||
Monitor* monitor; /* monitor to update the progress-bar */
|
||||
Progress* progress; /* the progress-bar */
|
||||
AlertPtr alert_window; /* alert for the user to cancel the
|
||||
effect-progress if he wants */
|
||||
};
|
||||
|
||||
/**
|
||||
* Called by @ref effect_apply to informate the progress of the
|
||||
* effect.
|
||||
*
|
||||
* [effect thread]
|
||||
*/
|
||||
static void effect_progress_hook(void *_data, float progress)
|
||||
{
|
||||
ThreadData *data = (ThreadData *)_data;
|
||||
|
||||
ScopedLock lock(data->mutex);
|
||||
data->pos = progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by @ref effect_apply to know if the user cancelled the
|
||||
* operation.
|
||||
*
|
||||
* [effect thread]
|
||||
*/
|
||||
static bool effect_is_cancelled_hook(void *_data)
|
||||
{
|
||||
ThreadData *data = (ThreadData *)_data;
|
||||
bool cancelled;
|
||||
|
||||
ScopedLock lock(data->mutex);
|
||||
cancelled = data->cancelled;
|
||||
|
||||
return cancelled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the effect to the sprite in a background thread.
|
||||
*
|
||||
* [effect thread]
|
||||
*/
|
||||
static void effect_bg(ThreadData* data)
|
||||
{
|
||||
/* apply the effect */
|
||||
effect_apply_to_target(data->effect);
|
||||
|
||||
/* mark the work as 'done' */
|
||||
ScopedLock lock(data->mutex);
|
||||
data->done = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the gui-monitor (a timer in the gui module that is called
|
||||
* every 100 milliseconds).
|
||||
*
|
||||
* [main thread]
|
||||
*/
|
||||
static void monitor_effect_bg(void *_data)
|
||||
{
|
||||
ThreadData *data = (ThreadData *)_data;
|
||||
float pos;
|
||||
bool done;
|
||||
|
||||
{
|
||||
ScopedLock lock(data->mutex);
|
||||
pos = data->pos;
|
||||
done = data->done;
|
||||
}
|
||||
|
||||
if (data->progress)
|
||||
data->progress->setPos(pos);
|
||||
|
||||
if (data->done)
|
||||
remove_gui_monitor(data->monitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to destroy the data of the monitor.
|
||||
*
|
||||
* [main thread]
|
||||
*/
|
||||
static void monitor_free(void *_data)
|
||||
{
|
||||
ThreadData *data = (ThreadData *)_data;
|
||||
|
||||
if (data->alert_window != NULL)
|
||||
data->alert_window->closeWindow(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the effect in a background thread meanwhile the progress
|
||||
* bar is shown to the user.
|
||||
*
|
||||
* [main thread]
|
||||
*/
|
||||
void effect_apply_to_target_with_progressbar(Effect* effect)
|
||||
{
|
||||
ThreadData* data = new ThreadData;
|
||||
|
||||
effect->progress_data = data;
|
||||
effect->progress = effect_progress_hook;
|
||||
effect->is_cancelled = effect_is_cancelled_hook;
|
||||
|
||||
data->effect = effect;
|
||||
data->pos = 0.0;
|
||||
data->done = false;
|
||||
data->cancelled = false;
|
||||
data->progress = app_get_statusbar()->addProgress();
|
||||
data->alert_window = Alert::create(PACKAGE
|
||||
"<<Applying effect...||&Cancel");
|
||||
data->monitor = add_gui_monitor(monitor_effect_bg,
|
||||
monitor_free, data);
|
||||
|
||||
// Launch the thread to apply the effect in background
|
||||
base::thread thread(&effect_bg, data);
|
||||
|
||||
// Open the alert window in foreground (this is modal, locks the main thread)
|
||||
data->alert_window->open_window_fg();
|
||||
|
||||
{
|
||||
ScopedLock lock(data->mutex);
|
||||
if (!data->done) {
|
||||
remove_gui_monitor(data->monitor);
|
||||
data->cancelled = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait the `effect_bg' thread
|
||||
thread.join();
|
||||
|
||||
delete data->progress;
|
||||
delete data;
|
||||
}
|
@ -19,7 +19,6 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "core/modules.h"
|
||||
#include "effect/effect.h"
|
||||
#include "modules/editors.h"
|
||||
#include "modules/gui.h"
|
||||
#include "modules/palettes.h"
|
||||
@ -43,7 +42,6 @@ static Module module[] =
|
||||
first ones. */
|
||||
|
||||
DEF_MODULE(palette, 0),
|
||||
DEF_MODULE(effect, 0),
|
||||
DEF_MODULE(gui, REQUIRE_INTERFACE),
|
||||
DEF_MODULE(rootmenu, REQUIRE_INTERFACE),
|
||||
DEF_MODULE(editors, REQUIRE_INTERFACE),
|
||||
|
@ -1,362 +0,0 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "effect/colcurve.h"
|
||||
#include "effect/effect.h"
|
||||
#include "gui/list.h"
|
||||
#include "modules/palettes.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/rgbmap.h"
|
||||
|
||||
static struct {
|
||||
Curve *curve;
|
||||
int cmap[256];
|
||||
} data;
|
||||
|
||||
CurvePoint *curve_point_new(int x, int y)
|
||||
{
|
||||
CurvePoint* point = new CurvePoint;
|
||||
|
||||
point->x = x;
|
||||
point->y = y;
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
void curve_point_free(CurvePoint *point)
|
||||
{
|
||||
delete point;
|
||||
}
|
||||
|
||||
Curve *curve_new(int type)
|
||||
{
|
||||
Curve* curve = new Curve;
|
||||
|
||||
curve->type = type;
|
||||
curve->points = jlist_new();
|
||||
|
||||
return curve;
|
||||
}
|
||||
|
||||
void curve_free(Curve *curve)
|
||||
{
|
||||
JLink link;
|
||||
|
||||
JI_LIST_FOR_EACH(curve->points, link)
|
||||
curve_point_free(reinterpret_cast<CurvePoint*>(link->data));
|
||||
|
||||
jlist_free(curve->points);
|
||||
delete curve;
|
||||
}
|
||||
|
||||
void curve_add_point(Curve* curve, CurvePoint* point)
|
||||
{
|
||||
JLink link;
|
||||
|
||||
JI_LIST_FOR_EACH(curve->points, link)
|
||||
if (((CurvePoint*)link->data)->x >= point->x)
|
||||
break;
|
||||
|
||||
jlist_insert_before(curve->points, link, point);
|
||||
}
|
||||
|
||||
void curve_remove_point(Curve *curve, CurvePoint *point)
|
||||
{
|
||||
jlist_remove(curve->points, point);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/* dacap: directly from GTK+ 2.2.2 source code */
|
||||
/**********************************************************************/
|
||||
|
||||
/* Solve the tridiagonal equation system that determines the second
|
||||
derivatives for the interpolation points. (Based on Numerical
|
||||
Recipies 2nd Edition.) */
|
||||
static void
|
||||
spline_solve(int n, float x[], float y[], float y2[])
|
||||
{
|
||||
float p, sig;
|
||||
int i, k;
|
||||
std::vector<float> u(n - 1);
|
||||
|
||||
y2[0] = u[0] = 0.0; /* set lower boundary condition to "natural" */
|
||||
|
||||
for (i = 1; i < n - 1; ++i)
|
||||
{
|
||||
sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]);
|
||||
p = sig * y2[i - 1] + 2.0;
|
||||
y2[i] = (sig - 1.0) / p;
|
||||
u[i] = ((y[i + 1] - y[i])
|
||||
/ (x[i + 1] - x[i]) - (y[i] - y[i - 1]) / (x[i] - x[i - 1]));
|
||||
u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p;
|
||||
}
|
||||
|
||||
y2[n - 1] = 0.0;
|
||||
for (k = n - 2; k >= 0; --k)
|
||||
y2[k] = y2[k] * y2[k + 1] + u[k];
|
||||
}
|
||||
|
||||
static float
|
||||
spline_eval(int n, float x[], float y[], float y2[], float val)
|
||||
{
|
||||
int k_lo, k_hi, k;
|
||||
float h, b, a;
|
||||
|
||||
/* do a binary search for the right interval: */
|
||||
k_lo = 0; k_hi = n - 1;
|
||||
while (k_hi - k_lo > 1)
|
||||
{
|
||||
k = (k_hi + k_lo) / 2;
|
||||
if (x[k] > val)
|
||||
k_hi = k;
|
||||
else
|
||||
k_lo = k;
|
||||
}
|
||||
|
||||
h = x[k_hi] - x[k_lo];
|
||||
/* TODO */
|
||||
/* ASSERT(h > 0.0); */
|
||||
|
||||
a = (x[k_hi] - val) / h;
|
||||
b = (val - x[k_lo]) / h;
|
||||
return a*y[k_lo] + b*y[k_hi] +
|
||||
((a*a*a - a)*y2[k_lo] + (b*b*b - b)*y2[k_hi]) * (h*h)/6.0;
|
||||
}
|
||||
|
||||
void curve_get_values(Curve *curve, int x1, int x2, int *values)
|
||||
{
|
||||
int x, num_points = jlist_length(curve->points);
|
||||
|
||||
if (num_points == 0) {
|
||||
for (x=x1; x<=x2; x++)
|
||||
values[x-x1] = 0;
|
||||
}
|
||||
else if (num_points == 1) {
|
||||
for (x=x1; x<=x2; x++)
|
||||
values[x-x1] = ((CurvePoint *)jlist_first_data(curve->points))->y;
|
||||
}
|
||||
else {
|
||||
switch (curve->type) {
|
||||
|
||||
case CURVE_LINEAR: {
|
||||
JLink link, last = jlist_last(curve->points);
|
||||
CurvePoint *p, *n;
|
||||
|
||||
JI_LIST_FOR_EACH(curve->points, link)
|
||||
if (((CurvePoint *)link->data)->x >= x1)
|
||||
break;
|
||||
|
||||
for (x=x1; x<=x2; x++) {
|
||||
while ((link != curve->points->end) &&
|
||||
(x > ((CurvePoint *)link->data)->x))
|
||||
link = link->next;
|
||||
|
||||
if (link != curve->points->end) {
|
||||
if (link->prev != curve->points->end) {
|
||||
p = reinterpret_cast<CurvePoint*>(link->prev->data);
|
||||
n = reinterpret_cast<CurvePoint*>(link->data);
|
||||
|
||||
values[x-x1] = p->y + (n->y-p->y) * (x-p->x) / (n->x-p->x);
|
||||
}
|
||||
else {
|
||||
values[x-x1] = ((CurvePoint *)link->data)->y;
|
||||
}
|
||||
}
|
||||
else {
|
||||
values[x-x1] = ((CurvePoint *)last->data)->y;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CURVE_SPLINE: {
|
||||
/* dacap: almost all code from GTK+ 2.2.2 source code */
|
||||
float rx, ry, dx, min_x, *xv, *yv, *y2v, prev;
|
||||
int dst, veclen = x2-x1+1;
|
||||
JLink link;
|
||||
|
||||
min_x = 0;
|
||||
|
||||
std::vector<float> mem(3 * num_points);
|
||||
xv = &mem[0];
|
||||
yv = &mem[num_points];
|
||||
y2v = &mem[2*num_points];
|
||||
|
||||
prev = min_x - 1.0;
|
||||
dst = 0;
|
||||
JI_LIST_FOR_EACH(curve->points, link) {
|
||||
if (((CurvePoint *)link->data)->x > prev) {
|
||||
prev = ((CurvePoint*)link->data)->x;
|
||||
xv[dst] = ((CurvePoint*)link->data)->x;
|
||||
yv[dst] = ((CurvePoint*)link->data)->y;
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
|
||||
spline_solve(dst, xv, yv, y2v);
|
||||
|
||||
rx = min_x;
|
||||
dx = (x2 - x1) / (veclen-1);
|
||||
for (x=0; x<veclen; ++x, rx+=dx) {
|
||||
ry = spline_eval(dst, xv, yv, y2v, rx);
|
||||
#if 0
|
||||
/* if (ry < curve->min_y) ry = curve->min_y; */
|
||||
/* if (ry > curve->max_y) ry = curve->max_y; */
|
||||
#else
|
||||
/* if (ry < 0) ry = 0; */
|
||||
/* else if (ry > 255) ry = 255; */
|
||||
#endif
|
||||
values[x] = ry;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set_color_curve(Curve *curve)
|
||||
{
|
||||
int c;
|
||||
|
||||
data.curve = curve;
|
||||
|
||||
/* generate the color convertion map */
|
||||
curve_get_values(data.curve, 0, 255, data.cmap);
|
||||
|
||||
for (c=0; c<256; c++)
|
||||
data.cmap[c] = MID(0, data.cmap[c], 255);
|
||||
}
|
||||
|
||||
void apply_color_curve4(Effect *effect)
|
||||
{
|
||||
ase_uint32 *src_address;
|
||||
ase_uint32 *dst_address;
|
||||
int x, c, r, g, b, a;
|
||||
|
||||
src_address = ((ase_uint32 **)effect->src->line)[effect->row+effect->y]+effect->x;
|
||||
dst_address = ((ase_uint32 **)effect->dst->line)[effect->row+effect->y]+effect->x;
|
||||
|
||||
for (x=0; x<effect->w; x++) {
|
||||
if (effect->mask_address) {
|
||||
if (!((*effect->mask_address) & (1<<effect->d.rem))) {
|
||||
src_address++;
|
||||
dst_address++;
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
r = _rgba_getr(c);
|
||||
g = _rgba_getg(c);
|
||||
b = _rgba_getb(c);
|
||||
a = _rgba_geta(c);
|
||||
|
||||
if (effect->target & TARGET_RED_CHANNEL) r = data.cmap[r];
|
||||
if (effect->target & TARGET_GREEN_CHANNEL) g = data.cmap[g];
|
||||
if (effect->target & TARGET_BLUE_CHANNEL) b = data.cmap[b];
|
||||
if (effect->target & TARGET_ALPHA_CHANNEL) a = data.cmap[a];
|
||||
|
||||
*(dst_address++) = _rgba(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
void apply_color_curve2(Effect *effect)
|
||||
{
|
||||
ase_uint16 *src_address;
|
||||
ase_uint16 *dst_address;
|
||||
int x, c, k, a;
|
||||
|
||||
src_address = ((ase_uint16 **)effect->src->line)[effect->row+effect->y]+effect->x;
|
||||
dst_address = ((ase_uint16 **)effect->dst->line)[effect->row+effect->y]+effect->x;
|
||||
|
||||
for (x=0; x<effect->w; x++) {
|
||||
if (effect->mask_address) {
|
||||
if (!((*effect->mask_address) & (1<<effect->d.rem))) {
|
||||
src_address++;
|
||||
dst_address++;
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
k = _graya_getv(c);
|
||||
a = _graya_geta(c);
|
||||
|
||||
if (effect->target & TARGET_GRAY_CHANNEL) k = data.cmap[k];
|
||||
if (effect->target & TARGET_ALPHA_CHANNEL) a = data.cmap[a];
|
||||
|
||||
*(dst_address++) = _graya(k, a);
|
||||
}
|
||||
}
|
||||
|
||||
void apply_color_curve1(Effect *effect)
|
||||
{
|
||||
Palette *pal = get_current_palette();
|
||||
RgbMap* rgbmap = effect->sprite->getRgbMap();
|
||||
ase_uint8* src_address;
|
||||
ase_uint8* dst_address;
|
||||
int x, c, r, g, b;
|
||||
|
||||
src_address = ((ase_uint8**)effect->src->line)[effect->row+effect->y]+effect->x;
|
||||
dst_address = ((ase_uint8**)effect->dst->line)[effect->row+effect->y]+effect->x;
|
||||
|
||||
for (x=0; x<effect->w; x++) {
|
||||
if (effect->mask_address) {
|
||||
if (!((*effect->mask_address) & (1<<effect->d.rem))) {
|
||||
src_address++;
|
||||
dst_address++;
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
if (effect->target & TARGET_INDEX_CHANNEL) {
|
||||
c = data.cmap[c];
|
||||
}
|
||||
else {
|
||||
r = _rgba_getr(pal->getEntry(c));
|
||||
g = _rgba_getg(pal->getEntry(c));
|
||||
b = _rgba_getb(pal->getEntry(c));
|
||||
|
||||
if (effect->target & TARGET_RED_CHANNEL) r = data.cmap[r];
|
||||
if (effect->target & TARGET_GREEN_CHANNEL) g = data.cmap[g];
|
||||
if (effect->target & TARGET_BLUE_CHANNEL) b = data.cmap[b];
|
||||
|
||||
c = rgbmap->mapColor(r, g, b);
|
||||
}
|
||||
|
||||
*(dst_address++) = MID(0, c, pal->size()-1);
|
||||
}
|
||||
}
|
@ -1,539 +0,0 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <allegro.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "base/memory.h"
|
||||
#include "core/cfg.h"
|
||||
#include "effect/convmatr.h"
|
||||
#include "effect/effect.h"
|
||||
#include "gui/list.h"
|
||||
#include "modules/palettes.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/rgbmap.h"
|
||||
#include "resource_finder.h"
|
||||
#include "util/filetoks.h"
|
||||
|
||||
/* TODO warning: this number could be dangerous for big filters */
|
||||
#define PRECISION (256)
|
||||
|
||||
static struct { /* TODO warning: not thread safe */
|
||||
JList matrices;
|
||||
ConvMatr* convmatr;
|
||||
TiledMode tiled;
|
||||
unsigned char **lines;
|
||||
} data;
|
||||
|
||||
void init_convolution_matrix()
|
||||
{
|
||||
data.matrices = jlist_new();
|
||||
data.convmatr = NULL;
|
||||
data.tiled = TILED_NONE;
|
||||
data.lines = NULL;
|
||||
|
||||
reload_matrices_stock();
|
||||
}
|
||||
|
||||
void exit_convolution_matrix()
|
||||
{
|
||||
clean_matrices_stock();
|
||||
jlist_free(data.matrices);
|
||||
|
||||
if (data.lines != NULL)
|
||||
base_free(data.lines);
|
||||
}
|
||||
|
||||
ConvMatr* convmatr_new(int w, int h)
|
||||
{
|
||||
ConvMatr* convmatr = new ConvMatr;
|
||||
|
||||
convmatr->name = NULL;
|
||||
convmatr->w = w;
|
||||
convmatr->h = h;
|
||||
convmatr->cx = convmatr->w/2;
|
||||
convmatr->cy = convmatr->h/2;
|
||||
|
||||
int size = convmatr->w * convmatr->h;
|
||||
|
||||
convmatr->data = (int*)base_malloc(sizeof(int) * size);
|
||||
if (!convmatr->data) {
|
||||
convmatr_free(convmatr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int c=0; c<size; c++)
|
||||
convmatr->data[c] = 0;
|
||||
|
||||
convmatr->div = PRECISION;
|
||||
convmatr->bias = 0;
|
||||
|
||||
return convmatr;
|
||||
}
|
||||
|
||||
ConvMatr *convmatr_new_string(const char *format)
|
||||
{
|
||||
/* TODO */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void convmatr_free(ConvMatr *convmatr)
|
||||
{
|
||||
if (convmatr->name)
|
||||
base_free(convmatr->name);
|
||||
|
||||
if (convmatr->data)
|
||||
base_free(convmatr->data);
|
||||
|
||||
delete convmatr;
|
||||
}
|
||||
|
||||
void set_convmatr(ConvMatr *convmatr, TiledMode tiled)
|
||||
{
|
||||
data.convmatr = convmatr;
|
||||
data.tiled = tiled;
|
||||
|
||||
if (data.lines != NULL)
|
||||
base_free(data.lines);
|
||||
|
||||
data.lines = (unsigned char**)base_malloc(sizeof(unsigned char*) * convmatr->h);
|
||||
}
|
||||
|
||||
ConvMatr* get_convmatr()
|
||||
{
|
||||
return data.convmatr;
|
||||
}
|
||||
|
||||
ConvMatr* get_convmatr_by_name(const char *name)
|
||||
{
|
||||
ConvMatr* convmatr;
|
||||
JLink link;
|
||||
|
||||
JI_LIST_FOR_EACH(data.matrices, link) {
|
||||
convmatr = reinterpret_cast<ConvMatr*>(link->data);
|
||||
if (strcmp(convmatr->name, name) == 0)
|
||||
return convmatr;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void reload_matrices_stock()
|
||||
{
|
||||
#define READ_TOK() { \
|
||||
if (!tok_read(f, buf, leavings, sizeof (leavings))) \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define READ_INT(var) { \
|
||||
READ_TOK(); \
|
||||
var = ustrtol(buf, NULL, 10); \
|
||||
}
|
||||
|
||||
const char *names[] = { "convmatr.usr",
|
||||
"convmatr.gen",
|
||||
"convmatr.def", NULL };
|
||||
char *s, buf[256], leavings[4096];
|
||||
int i, c, w, h, div, bias;
|
||||
ConvMatr *convmatr;
|
||||
FILE *f;
|
||||
char *name;
|
||||
|
||||
clean_matrices_stock();
|
||||
|
||||
for (i=0; names[i]; i++) {
|
||||
ResourceFinder rf;
|
||||
rf.findInDataDir(names[i]);
|
||||
|
||||
while (const char* path = rf.next()) {
|
||||
// Open matrices stock file
|
||||
f = fopen(path, "r");
|
||||
if (!f)
|
||||
continue;
|
||||
|
||||
tok_reset_line_num();
|
||||
|
||||
name = NULL;
|
||||
convmatr = NULL;
|
||||
strcpy(leavings, "");
|
||||
|
||||
/* read the matrix name */
|
||||
while (tok_read(f, buf, leavings, sizeof(leavings))) {
|
||||
/* name of the matrix */
|
||||
name = base_strdup(buf);
|
||||
|
||||
/* width and height */
|
||||
READ_INT(w);
|
||||
READ_INT(h);
|
||||
|
||||
if ((w <= 0) || (w > 32) ||
|
||||
(h <= 0) || (h > 32))
|
||||
break;
|
||||
|
||||
/* create the matrix data */
|
||||
convmatr = convmatr_new(w, h);
|
||||
if (!convmatr)
|
||||
break;
|
||||
|
||||
/* centre */
|
||||
READ_INT(convmatr->cx);
|
||||
READ_INT(convmatr->cy);
|
||||
|
||||
if ((convmatr->cx < 0) || (convmatr->cx >= w) ||
|
||||
(convmatr->cy < 0) || (convmatr->cy >= h))
|
||||
break;
|
||||
|
||||
/* data */
|
||||
READ_TOK(); /* jump the `{' char */
|
||||
if (*buf != '{')
|
||||
break;
|
||||
|
||||
c = 0;
|
||||
div = 0;
|
||||
for (c=0; c<w*h; c++) {
|
||||
READ_TOK();
|
||||
convmatr->data[c] = ustrtod(buf, NULL) * PRECISION;
|
||||
div += convmatr->data[c];
|
||||
}
|
||||
|
||||
READ_TOK(); /* jump the `}' char */
|
||||
if (*buf != '}')
|
||||
break;
|
||||
|
||||
if (div > 0)
|
||||
bias = 0;
|
||||
else if (div == 0) {
|
||||
div = PRECISION;
|
||||
bias = 128;
|
||||
}
|
||||
else {
|
||||
div = ABS(div);
|
||||
bias = 255;
|
||||
}
|
||||
|
||||
/* div */
|
||||
READ_TOK();
|
||||
if (ustricmp (buf, "auto") != 0)
|
||||
div = ustrtod(buf, NULL) * PRECISION;
|
||||
|
||||
convmatr->div = div;
|
||||
|
||||
/* bias */
|
||||
READ_TOK();
|
||||
if (ustricmp (buf, "auto") != 0)
|
||||
bias = ustrtod(buf, NULL);
|
||||
|
||||
convmatr->bias = bias;
|
||||
|
||||
/* target */
|
||||
READ_TOK();
|
||||
|
||||
convmatr->default_target = 0;
|
||||
for (s=buf; *s; s++) {
|
||||
switch (*s) {
|
||||
case 'r': convmatr->default_target |= TARGET_RED_CHANNEL; break;
|
||||
case 'g': convmatr->default_target |= TARGET_GREEN_CHANNEL; break;
|
||||
case 'b': convmatr->default_target |= TARGET_BLUE_CHANNEL; break;
|
||||
case 'a': convmatr->default_target |= TARGET_ALPHA_CHANNEL; break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((convmatr->default_target & (TARGET_RED_CHANNEL |
|
||||
TARGET_GREEN_CHANNEL |
|
||||
TARGET_BLUE_CHANNEL)) != 0) {
|
||||
convmatr->default_target |= TARGET_GRAY_CHANNEL;
|
||||
}
|
||||
|
||||
/* name */
|
||||
convmatr->name = name;
|
||||
|
||||
/* insert the new matrix in the list */
|
||||
jlist_append(data.matrices, convmatr);
|
||||
|
||||
name = NULL;
|
||||
convmatr = NULL;
|
||||
}
|
||||
|
||||
/* destroy the last invalid matrix in case of error */
|
||||
if (name)
|
||||
base_free(name);
|
||||
|
||||
if (convmatr)
|
||||
convmatr_free(convmatr);
|
||||
|
||||
// Close the file
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clean_matrices_stock()
|
||||
{
|
||||
JLink link;
|
||||
|
||||
JI_LIST_FOR_EACH(data.matrices, link)
|
||||
convmatr_free(reinterpret_cast<ConvMatr*>(link->data));
|
||||
|
||||
jlist_clear(data.matrices);
|
||||
}
|
||||
|
||||
JList get_convmatr_stock()
|
||||
{
|
||||
return data.matrices;
|
||||
}
|
||||
|
||||
#define GET_CONVMATR_DATA(Traits, do_job) \
|
||||
div = matrix->div; \
|
||||
mdata = matrix->data; \
|
||||
\
|
||||
GET_MATRIX_DATA \
|
||||
(Traits::pixel_t, \
|
||||
src, src_address, \
|
||||
matrix->w, matrix->h, \
|
||||
matrix->cx, matrix->cy, \
|
||||
data.tiled, \
|
||||
if (*mdata) { \
|
||||
color = *src_address; \
|
||||
do_job; \
|
||||
} \
|
||||
mdata++; \
|
||||
); \
|
||||
\
|
||||
color = image_getpixel_fast<Traits>(src, x, y); \
|
||||
if (div == 0) { \
|
||||
*(dst_address++) = color; \
|
||||
continue; \
|
||||
}
|
||||
|
||||
void apply_convolution_matrix4(Effect *effect)
|
||||
{
|
||||
ConvMatr* matrix = data.convmatr;
|
||||
const Image* src = effect->src;
|
||||
Image* dst = effect->dst;
|
||||
ase_uint32* src_address;
|
||||
ase_uint32* dst_address;
|
||||
int x, y, dx, dy, color;
|
||||
int getx, gety, addx, addy;
|
||||
int r, g, b, a;
|
||||
int *mdata;
|
||||
int w, div;
|
||||
|
||||
if (matrix) {
|
||||
w = effect->x+effect->w;
|
||||
y = effect->y+effect->row;
|
||||
dst_address = ((ase_uint32 **)dst->line)[y]+effect->x;
|
||||
|
||||
for (x=effect->x; x<w; x++) {
|
||||
/* avoid the unmask region */
|
||||
if (effect->mask_address) {
|
||||
if (!((*effect->mask_address) & (1<<effect->d.rem))) {
|
||||
dst_address++;
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
}
|
||||
|
||||
r = g = b = a = 0;
|
||||
|
||||
GET_CONVMATR_DATA
|
||||
(RgbTraits,
|
||||
if (_rgba_geta(color) == 0)
|
||||
div -= *mdata;
|
||||
else {
|
||||
r += _rgba_getr(color) * (*mdata);
|
||||
g += _rgba_getg(color) * (*mdata);
|
||||
b += _rgba_getb(color) * (*mdata);
|
||||
a += _rgba_geta(color) * (*mdata);
|
||||
}
|
||||
);
|
||||
|
||||
if (effect->target & TARGET_RED_CHANNEL) {
|
||||
r = r / div + matrix->bias;
|
||||
r = MID(0, r, 255);
|
||||
}
|
||||
else
|
||||
r = _rgba_getr(color);
|
||||
|
||||
if (effect->target & TARGET_GREEN_CHANNEL) {
|
||||
g = g / div + matrix->bias;
|
||||
g = MID(0, g, 255);
|
||||
}
|
||||
else
|
||||
g = _rgba_getg(color);
|
||||
|
||||
if (effect->target & TARGET_BLUE_CHANNEL) {
|
||||
b = b / div + matrix->bias;
|
||||
b = MID(0, b, 255);
|
||||
}
|
||||
else
|
||||
b = _rgba_getb(color);
|
||||
|
||||
if (effect->target & TARGET_ALPHA_CHANNEL) {
|
||||
a = a / matrix->div + matrix->bias;
|
||||
a = MID(0, a, 255);
|
||||
}
|
||||
else
|
||||
a = _rgba_geta(color);
|
||||
|
||||
*(dst_address++) = _rgba(r, g, b, a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void apply_convolution_matrix2(Effect *effect)
|
||||
{
|
||||
ConvMatr* matrix = data.convmatr;
|
||||
const Image* src = effect->src;
|
||||
Image* dst = effect->dst;
|
||||
ase_uint16* src_address;
|
||||
ase_uint16* dst_address;
|
||||
int x, y, dx, dy, color;
|
||||
int getx, gety, addx, addy;
|
||||
int k, a;
|
||||
int *mdata;
|
||||
int w, div;
|
||||
|
||||
if (matrix) {
|
||||
w = effect->x+effect->w;
|
||||
y = effect->y+effect->row;
|
||||
dst_address = ((ase_uint16 **)dst->line)[y]+effect->x;
|
||||
|
||||
for (x=effect->x; x<w; x++) {
|
||||
/* avoid the unmask region */
|
||||
if (effect->mask_address) {
|
||||
if (!((*effect->mask_address) & (1<<effect->d.rem))) {
|
||||
dst_address++;
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
}
|
||||
|
||||
k = a = 0;
|
||||
|
||||
GET_CONVMATR_DATA
|
||||
(GrayscaleTraits,
|
||||
if (_graya_geta(color) == 0)
|
||||
div -= *mdata;
|
||||
else {
|
||||
k += _graya_getv(color) * (*mdata);
|
||||
a += _graya_geta(color) * (*mdata);
|
||||
}
|
||||
);
|
||||
|
||||
if (effect->target & TARGET_GRAY_CHANNEL) {
|
||||
k = k / div + matrix->bias;
|
||||
k = MID(0, k, 255);
|
||||
}
|
||||
else
|
||||
k = _graya_getv(color);
|
||||
|
||||
if (effect->target & TARGET_ALPHA_CHANNEL) {
|
||||
a = a / matrix->div + matrix->bias;
|
||||
a = MID(0, a, 255);
|
||||
}
|
||||
else
|
||||
a = _graya_geta(color);
|
||||
|
||||
*(dst_address++) = _graya(k, a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void apply_convolution_matrix1(Effect *effect)
|
||||
{
|
||||
const Palette* pal = get_current_palette();
|
||||
const RgbMap* rgbmap = effect->sprite->getRgbMap();
|
||||
const ConvMatr* matrix = data.convmatr;
|
||||
const Image* src = effect->src;
|
||||
Image* dst = effect->dst;
|
||||
ase_uint8* src_address;
|
||||
ase_uint8* dst_address;
|
||||
int x, y, dx, dy, color;
|
||||
int getx, gety, addx, addy;
|
||||
int r, g, b, index;
|
||||
int *mdata;
|
||||
int w, div;
|
||||
|
||||
if (matrix) {
|
||||
w = effect->x+effect->w;
|
||||
y = effect->y+effect->row;
|
||||
dst_address = ((ase_uint8 **)dst->line)[y]+effect->x;
|
||||
|
||||
for (x=effect->x; x<w; x++) {
|
||||
/* avoid the unmask region */
|
||||
if (effect->mask_address) {
|
||||
if (!((*effect->mask_address) & (1<<effect->d.rem))) {
|
||||
dst_address++;
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
}
|
||||
|
||||
r = g = b = index = 0;
|
||||
|
||||
GET_CONVMATR_DATA
|
||||
(IndexedTraits,
|
||||
r += _rgba_getr(pal->getEntry(color)) * (*mdata);
|
||||
g += _rgba_getg(pal->getEntry(color)) * (*mdata);
|
||||
b += _rgba_getb(pal->getEntry(color)) * (*mdata);
|
||||
index += color * (*mdata);
|
||||
);
|
||||
|
||||
if (effect->target & TARGET_INDEX_CHANNEL) {
|
||||
index = index / matrix->div + matrix->bias;
|
||||
index = MID(0, index, 255);
|
||||
|
||||
*(dst_address++) = index;
|
||||
}
|
||||
else {
|
||||
if (effect->target & TARGET_RED_CHANNEL) {
|
||||
r = r / div + matrix->bias;
|
||||
r = MID(0, r, 255);
|
||||
}
|
||||
else
|
||||
r = _rgba_getr(pal->getEntry(color));
|
||||
|
||||
if (effect->target & TARGET_GREEN_CHANNEL) {
|
||||
g = g / div + matrix->bias;
|
||||
g = MID(0, g, 255);
|
||||
}
|
||||
else
|
||||
g = _rgba_getg(pal->getEntry(color));
|
||||
|
||||
if (effect->target & TARGET_BLUE_CHANNEL) {
|
||||
b = b / div + matrix->bias;
|
||||
b = MID(0, b, 255);
|
||||
}
|
||||
else
|
||||
b = _rgba_getb(pal->getEntry(color));
|
||||
|
||||
*(dst_address++) = rgbmap->mapColor(r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 EFFECT_CONVMATR_H_INCLUDED
|
||||
#define EFFECT_CONVMATR_H_INCLUDED
|
||||
|
||||
#include "gui/base.h"
|
||||
#include "tiled_mode.h"
|
||||
|
||||
struct Effect;
|
||||
|
||||
typedef struct ConvMatr /* a convolution matrix */
|
||||
{
|
||||
char *name; /* name */
|
||||
int w, h; /* size of the matrix */
|
||||
int cx, cy; /* centre of the filter */
|
||||
int *data; /* the matrix with the multiplication factors */
|
||||
int div; /* division factor */
|
||||
int bias; /* addition factor (for offset) */
|
||||
int default_target; /* targets by default (look at
|
||||
TARGET_RED_CHANNEL, etc. constants) */
|
||||
} ConvMatr;
|
||||
|
||||
ConvMatr *convmatr_new(int w, int h);
|
||||
ConvMatr *convmatr_new_string(const char *format);
|
||||
void convmatr_free(ConvMatr *convmatr);
|
||||
|
||||
void set_convmatr(ConvMatr *convmatr, TiledMode tiled);
|
||||
ConvMatr *get_convmatr();
|
||||
ConvMatr *get_convmatr_by_name(const char *name);
|
||||
|
||||
void reload_matrices_stock();
|
||||
void clean_matrices_stock();
|
||||
JList get_convmatr_stock();
|
||||
|
||||
void init_convolution_matrix();
|
||||
void exit_convolution_matrix();
|
||||
|
||||
void apply_convolution_matrix4(struct Effect *effect);
|
||||
void apply_convolution_matrix2(struct Effect *effect);
|
||||
void apply_convolution_matrix1(struct Effect *effect);
|
||||
|
||||
#endif
|
@ -1,432 +0,0 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gui/manager.h"
|
||||
#include "gui/rect.h"
|
||||
#include "gui/region.h"
|
||||
#include "gui/view.h"
|
||||
#include "gui/widget.h"
|
||||
|
||||
#include "console.h"
|
||||
#include "core/cfg.h"
|
||||
#include "effect/colcurve.h"
|
||||
#include "effect/convmatr.h"
|
||||
#include "effect/effect.h"
|
||||
#include "effect/invrtcol.h"
|
||||
#include "effect/median.h"
|
||||
#include "effect/replcol.h"
|
||||
#include "modules/editors.h"
|
||||
#include "raster/cel.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/images_collector.h"
|
||||
#include "raster/layer.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "raster/stock.h"
|
||||
#include "raster/undo.h"
|
||||
#include "util/misc.h"
|
||||
#include "widgets/editor.h"
|
||||
|
||||
typedef struct EffectData
|
||||
{
|
||||
const char *name;
|
||||
const char *label;
|
||||
void (*apply_4)(Effect *effect);
|
||||
void (*apply_2)(Effect *effect);
|
||||
void (*apply_1)(Effect *effect);
|
||||
} EffectData;
|
||||
|
||||
#define FXDATA(name, label) \
|
||||
{ #name, label, apply_##name##4, apply_##name##2, apply_##name##1 }
|
||||
|
||||
static EffectData effects_data[] = {
|
||||
FXDATA(color_curve, "Color Curve"),
|
||||
FXDATA(convolution_matrix, "Convolution Matrix"),
|
||||
FXDATA(invert_color, "Invert Color"),
|
||||
FXDATA(median, "Median"),
|
||||
FXDATA(replace_color, "Replace Color"),
|
||||
{ NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static EffectData *get_effect_data(const char *name);
|
||||
static void effect_init(Effect* effect, const Layer* layer, Image* image, int offset_x, int offset_y);
|
||||
static void effect_apply_to_image(Effect* effect, Layer* layer, Image* image, int x, int y);
|
||||
static bool effect_update_mask(Effect* effect, Mask* mask, const Image* image);
|
||||
|
||||
int init_module_effect()
|
||||
{
|
||||
init_convolution_matrix();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void exit_module_effect()
|
||||
{
|
||||
exit_convolution_matrix();
|
||||
}
|
||||
|
||||
Effect::Effect(const SpriteReader& sprite, const char* name)
|
||||
{
|
||||
int offset_x, offset_y;
|
||||
EffectData* effect_data;
|
||||
void (*apply)(Effect*);
|
||||
|
||||
effect_data = get_effect_data(name);
|
||||
|
||||
apply = NULL;
|
||||
switch (sprite->getImgType()) {
|
||||
case IMAGE_RGB: apply = effect_data->apply_4; break;
|
||||
case IMAGE_GRAYSCALE: apply = effect_data->apply_2; break;
|
||||
case IMAGE_INDEXED: apply = effect_data->apply_1; break;
|
||||
default:
|
||||
throw invalid_imgtype_exception();
|
||||
}
|
||||
|
||||
this->sprite = sprite;
|
||||
this->src = NULL;
|
||||
this->dst = NULL;
|
||||
this->row = 0;
|
||||
this->offset_x = 0;
|
||||
this->offset_y = 0;
|
||||
this->mask = NULL;
|
||||
this->preview_mask = NULL;
|
||||
this->mask_address = NULL;
|
||||
this->effect_data = effect_data;
|
||||
this->apply = apply;
|
||||
this->_target = TARGET_ALL_CHANNELS;
|
||||
this->target = TARGET_ALL_CHANNELS;
|
||||
this->progress_data = NULL;
|
||||
this->progress = NULL;
|
||||
this->is_cancelled = NULL;
|
||||
|
||||
Image* image = this->sprite->getCurrentImage(&offset_x, &offset_y);
|
||||
if (image == NULL)
|
||||
throw no_image_exception();
|
||||
|
||||
effect_init(this, sprite->getCurrentLayer(), image, offset_x, offset_y);
|
||||
}
|
||||
|
||||
Effect::~Effect()
|
||||
{
|
||||
if (this->preview_mask)
|
||||
mask_free(this->preview_mask);
|
||||
|
||||
if (this->dst)
|
||||
image_free(this->dst);
|
||||
}
|
||||
|
||||
void effect_set_target(Effect *effect, int target)
|
||||
{
|
||||
effect->_target = target;
|
||||
effect->target = target;
|
||||
|
||||
/* the alpha channel of the background layer can't be modified */
|
||||
if (effect->sprite->getCurrentLayer() &&
|
||||
effect->sprite->getCurrentLayer()->is_background())
|
||||
effect->target &= ~TARGET_ALPHA_CHANNEL;
|
||||
}
|
||||
|
||||
void effect_begin(Effect *effect)
|
||||
{
|
||||
effect->row = 0;
|
||||
effect->mask = effect->sprite->getMask();
|
||||
|
||||
effect_update_mask(effect, effect->mask, effect->src);
|
||||
}
|
||||
|
||||
void effect_begin_for_preview(Effect *effect)
|
||||
{
|
||||
if (effect->preview_mask) {
|
||||
mask_free(effect->preview_mask);
|
||||
effect->preview_mask = NULL;
|
||||
}
|
||||
|
||||
if ((effect->sprite->getMask()) && (effect->sprite->getMask()->bitmap))
|
||||
effect->preview_mask = mask_new_copy(effect->sprite->getMask());
|
||||
else {
|
||||
effect->preview_mask = mask_new();
|
||||
mask_replace(effect->preview_mask,
|
||||
effect->offset_x, effect->offset_y,
|
||||
effect->src->w, effect->src->h);
|
||||
}
|
||||
|
||||
effect->row = 0;
|
||||
effect->mask = effect->preview_mask;
|
||||
|
||||
{
|
||||
Editor* editor = current_editor;
|
||||
gfx::Rect vp = View::getView(editor)->getViewportBounds();
|
||||
int x1, y1, x2, y2;
|
||||
int x, y, w, h;
|
||||
|
||||
editor->screen_to_editor(vp.x, vp.y, &x1, &y1);
|
||||
editor->screen_to_editor(vp.x+vp.w-1, vp.y+vp.h-1, &x2, &y2);
|
||||
|
||||
if (x1 < 0) x1 = 0;
|
||||
if (y1 < 0) y1 = 0;
|
||||
if (x2 >= effect->sprite->getWidth()) x2 = effect->sprite->getWidth()-1;
|
||||
if (y2 >= effect->sprite->getHeight()) y2 = effect->sprite->getHeight()-1;
|
||||
|
||||
x = x1;
|
||||
y = y1;
|
||||
w = x2 - x1 + 1;
|
||||
h = y2 - y1 + 1;
|
||||
|
||||
if ((w < 1) || (h < 1)) {
|
||||
mask_free(effect->preview_mask);
|
||||
effect->preview_mask = NULL;
|
||||
effect->row = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
mask_intersect(effect->preview_mask, x, y, w, h);
|
||||
}
|
||||
|
||||
if (!effect_update_mask(effect, effect->mask, effect->src)) {
|
||||
mask_free(effect->preview_mask);
|
||||
effect->preview_mask = NULL;
|
||||
effect->row = -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool effect_apply_step(Effect *effect)
|
||||
{
|
||||
if ((effect->row >= 0) && (effect->row < effect->h)) {
|
||||
if ((effect->mask) && (effect->mask->bitmap)) {
|
||||
effect->d = div(effect->x-effect->mask->x+effect->offset_x, 8);
|
||||
effect->mask_address =
|
||||
((ase_uint8 **)effect->mask->bitmap->line)
|
||||
[effect->row+effect->y-effect->mask->y+effect->offset_y]+effect->d.quot;
|
||||
}
|
||||
else
|
||||
effect->mask_address = NULL;
|
||||
|
||||
(*effect->apply)(effect);
|
||||
effect->row++;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void effect_apply(Effect* effect)
|
||||
{
|
||||
bool cancelled = false;
|
||||
|
||||
effect_begin(effect);
|
||||
while (!cancelled && effect_apply_step(effect)) {
|
||||
if (effect->progress != NULL)
|
||||
(effect->progress)(effect->progress_data,
|
||||
effect->progress_base
|
||||
+ effect->progress_width * (effect->row+1) / effect->h);
|
||||
|
||||
if (effect->is_cancelled != NULL)
|
||||
cancelled = (effect->is_cancelled)(effect->progress_data);
|
||||
}
|
||||
|
||||
if (!cancelled) {
|
||||
// Undo stuff
|
||||
if (effect->sprite->getUndo()->isEnabled()) {
|
||||
effect->sprite->getUndo()->setLabel(effect->effect_data->label);
|
||||
effect->sprite->getUndo()
|
||||
->undo_image(effect->src, effect->x, effect->y, effect->w, effect->h);
|
||||
}
|
||||
|
||||
// Copy "dst" to "src"
|
||||
image_copy(effect->src, effect->dst, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates the current editor to show the progress of the preview.
|
||||
*/
|
||||
void effect_flush(Effect *effect)
|
||||
{
|
||||
if (effect->row >= 0) {
|
||||
JRegion reg1, reg2;
|
||||
struct jrect rect;
|
||||
Editor* editor = current_editor;
|
||||
|
||||
reg1 = jregion_new(NULL, 0);
|
||||
|
||||
editor->editor_to_screen(effect->x+effect->offset_x,
|
||||
effect->y+effect->offset_y+effect->row-1,
|
||||
&rect.x1, &rect.y1);
|
||||
rect.x2 = rect.x1 + (effect->w << editor->editor_get_zoom());
|
||||
rect.y2 = rect.y1 + (1 << editor->editor_get_zoom());
|
||||
|
||||
reg2 = jregion_new(&rect, 1);
|
||||
jregion_union(reg1, reg1, reg2);
|
||||
jregion_free(reg2);
|
||||
|
||||
reg2 = jwidget_get_drawable_region(editor, JI_GDR_CUTTOPWINDOWS);
|
||||
jregion_intersect(reg1, reg1, reg2);
|
||||
jregion_free(reg2);
|
||||
|
||||
editor->invalidateRegion(reg1);
|
||||
jregion_free(reg1);
|
||||
}
|
||||
}
|
||||
|
||||
void effect_apply_to_target(Effect *effect)
|
||||
{
|
||||
bool cancelled = false;
|
||||
|
||||
ImagesCollector images(effect->sprite,
|
||||
(effect->target & TARGET_ALL_LAYERS) == TARGET_ALL_LAYERS,
|
||||
(effect->target & TARGET_ALL_FRAMES) == TARGET_ALL_FRAMES,
|
||||
true); // we will write in each image
|
||||
if (images.empty())
|
||||
return;
|
||||
|
||||
// Open group of undo operations
|
||||
if (images.size() > 1) {
|
||||
if (effect->sprite->getUndo()->isEnabled())
|
||||
effect->sprite->getUndo()->undo_open();
|
||||
}
|
||||
|
||||
effect->progress_base = 0.0f;
|
||||
effect->progress_width = 1.0f / images.size();
|
||||
|
||||
// For each target image
|
||||
for (ImagesCollector::ItemsIterator it = images.begin();
|
||||
it != images.end() && !cancelled;
|
||||
++it) {
|
||||
effect_apply_to_image(effect, it->layer(), it->image(), it->cel()->x, it->cel()->y);
|
||||
|
||||
// There is a 'is_cancelled' hook?
|
||||
if (effect->is_cancelled != NULL)
|
||||
cancelled = (effect->is_cancelled)(effect->progress_data);
|
||||
|
||||
// Make progress
|
||||
effect->progress_base += effect->progress_width;
|
||||
}
|
||||
|
||||
// Close group of undo operations
|
||||
if (images.size() > 1) {
|
||||
if (effect->sprite->getUndo()->isEnabled())
|
||||
effect->sprite->getUndo()->undo_close();
|
||||
}
|
||||
}
|
||||
|
||||
static EffectData *get_effect_data(const char *name)
|
||||
{
|
||||
int c;
|
||||
|
||||
for (c=0; effects_data[c].name; c++) {
|
||||
if (strcmp(effects_data[c].name, name) == 0)
|
||||
return effects_data+c;
|
||||
}
|
||||
|
||||
throw invalid_effect_exception(name);
|
||||
}
|
||||
|
||||
static void effect_init(Effect* effect, const Layer* layer, Image* image,
|
||||
int offset_x, int offset_y)
|
||||
{
|
||||
effect->offset_x = offset_x;
|
||||
effect->offset_y = offset_y;
|
||||
|
||||
if (!effect_update_mask(effect, effect->sprite->getMask(), image))
|
||||
throw invalid_area_exception();
|
||||
|
||||
if (effect->preview_mask) {
|
||||
mask_free(effect->preview_mask);
|
||||
effect->preview_mask = NULL;
|
||||
}
|
||||
|
||||
if (effect->dst) {
|
||||
image_free(effect->dst);
|
||||
effect->dst = NULL;
|
||||
}
|
||||
|
||||
effect->src = image;
|
||||
effect->dst = image_crop(image, 0, 0, image->w, image->h, 0);
|
||||
effect->row = -1;
|
||||
effect->mask = NULL;
|
||||
effect->preview_mask = NULL;
|
||||
effect->mask_address = NULL;
|
||||
|
||||
effect->target = effect->_target;
|
||||
|
||||
/* the alpha channel of the background layer can't be modified */
|
||||
if (layer->is_background())
|
||||
effect->target &= ~TARGET_ALPHA_CHANNEL;
|
||||
}
|
||||
|
||||
static void effect_apply_to_image(Effect* effect, Layer* layer, Image* image, int x, int y)
|
||||
{
|
||||
effect_init(effect, layer, image, x, y);
|
||||
effect_apply(effect);
|
||||
}
|
||||
|
||||
static bool effect_update_mask(Effect* effect, Mask* mask, const Image* image)
|
||||
{
|
||||
int x, y, w, h;
|
||||
|
||||
if ((mask) && (mask->bitmap)) {
|
||||
x = mask->x - effect->offset_x;
|
||||
y = mask->y - effect->offset_y;
|
||||
w = mask->w;
|
||||
h = mask->h;
|
||||
|
||||
if (x < 0) {
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if (y < 0) {
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
if (x+w-1 >= image->w-1)
|
||||
w = image->w-x;
|
||||
|
||||
if (y+h-1 >= image->h-1)
|
||||
h = image->h-y;
|
||||
}
|
||||
else {
|
||||
x = 0;
|
||||
y = 0;
|
||||
w = image->w;
|
||||
h = image->h;
|
||||
}
|
||||
|
||||
if ((w < 1) || (h < 1)) {
|
||||
effect->x = 0;
|
||||
effect->y = 0;
|
||||
effect->w = 0;
|
||||
effect->h = 0;
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
effect->x = x;
|
||||
effect->y = y;
|
||||
effect->w = w;
|
||||
effect->h = h;
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,197 +0,0 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 EFFECT_EFFECT_H_INCLUDED
|
||||
#define EFFECT_EFFECT_H_INCLUDED
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <cstring>
|
||||
#include "sprite_wrappers.h"
|
||||
#include "gui/base.h"
|
||||
#include "tiled_mode.h"
|
||||
|
||||
class Image;
|
||||
class Mask;
|
||||
class Sprite;
|
||||
|
||||
#define TARGET_RED_CHANNEL 1
|
||||
#define TARGET_GREEN_CHANNEL 2
|
||||
#define TARGET_BLUE_CHANNEL 4
|
||||
#define TARGET_ALPHA_CHANNEL 8
|
||||
#define TARGET_GRAY_CHANNEL 16
|
||||
#define TARGET_INDEX_CHANNEL 32
|
||||
#define TARGET_ALL_FRAMES 64
|
||||
#define TARGET_ALL_LAYERS 128
|
||||
|
||||
#define TARGET_ALL_CHANNELS \
|
||||
(TARGET_RED_CHANNEL | \
|
||||
TARGET_GREEN_CHANNEL | \
|
||||
TARGET_BLUE_CHANNEL | \
|
||||
TARGET_ALPHA_CHANNEL | \
|
||||
TARGET_GRAY_CHANNEL )
|
||||
|
||||
|
||||
class invalid_effect_exception : public base::Exception
|
||||
{
|
||||
public:
|
||||
invalid_effect_exception(const char* effect_name) throw()
|
||||
: base::Exception("Invalid effect specified: %s", effect_name) { }
|
||||
};
|
||||
|
||||
class invalid_imgtype_exception : public base::Exception
|
||||
{
|
||||
public:
|
||||
invalid_imgtype_exception() throw()
|
||||
: base::Exception("Invalid image type specified.") { }
|
||||
};
|
||||
|
||||
class invalid_area_exception : public base::Exception
|
||||
{
|
||||
public:
|
||||
invalid_area_exception() throw()
|
||||
: base::Exception("The current mask/area to apply the effect is completelly invalid.") { }
|
||||
};
|
||||
|
||||
class no_image_exception : public base::Exception
|
||||
{
|
||||
public:
|
||||
no_image_exception() throw()
|
||||
: base::Exception("There are not an active image to apply the effect.\n"
|
||||
"Please select a layer/cel with an image and try again.") { }
|
||||
};
|
||||
|
||||
struct EffectData;
|
||||
|
||||
struct Effect
|
||||
{
|
||||
SpriteWriter sprite;
|
||||
Image* src;
|
||||
Image* dst;
|
||||
int row;
|
||||
int x, y, w, h;
|
||||
int offset_x, offset_y;
|
||||
Mask* mask;
|
||||
Mask* preview_mask;
|
||||
unsigned char *mask_address;
|
||||
div_t d;
|
||||
struct EffectData *effect_data;
|
||||
void (*apply)(struct Effect* effect);
|
||||
int _target; /* original targets */
|
||||
int target; /* filtered targets */
|
||||
/* hooks */
|
||||
float progress_base, progress_width;
|
||||
void *progress_data;
|
||||
void (*progress)(void *data, float progress);
|
||||
bool (*is_cancelled)(void *data);
|
||||
|
||||
Effect(const SpriteReader& sprite, const char* name);
|
||||
~Effect();
|
||||
};
|
||||
|
||||
int init_module_effect();
|
||||
void exit_module_effect();
|
||||
|
||||
void effect_set_target(Effect* effect, int target);
|
||||
|
||||
void effect_begin(Effect* effect);
|
||||
void effect_begin_for_preview(Effect* effect);
|
||||
bool effect_apply_step(Effect* effect);
|
||||
|
||||
void effect_apply(Effect* effect);
|
||||
void effect_flush(Effect* effect);
|
||||
|
||||
void effect_apply_to_target(Effect* effect);
|
||||
|
||||
/**
|
||||
* Macro to get contiguos pixels from an image. It's useful to fill a
|
||||
* matrix of pixels of "width x height" dimension.
|
||||
*
|
||||
* It needs some variables to be defined before to use this routines:
|
||||
* x, y = pixel position
|
||||
* getx, gety, addx, addy, dx, dy = auxiliars
|
||||
*/
|
||||
#define GET_MATRIX_DATA(ptr_type, src, src_address, \
|
||||
width, height, cx, cy, tiled, do_job) \
|
||||
/* Y position to get pixel */ \
|
||||
gety = y-(cy); \
|
||||
addy = 0; \
|
||||
if (gety < 0) { \
|
||||
if (tiled & TILED_Y_AXIS) \
|
||||
gety = src->h - (-(gety+1) % src->h) - 1; \
|
||||
else { \
|
||||
addy = -gety; \
|
||||
gety = 0; \
|
||||
} \
|
||||
} \
|
||||
else if (gety >= src->h) { \
|
||||
if (tiled & TILED_Y_AXIS) \
|
||||
gety = gety % src->h; \
|
||||
else \
|
||||
gety = src->h-1; \
|
||||
} \
|
||||
\
|
||||
for (dy=0; dy<(height); dy++) { \
|
||||
/* X position to get pixel */ \
|
||||
getx = x-(cx); \
|
||||
addx = 0; \
|
||||
if (getx < 0) { \
|
||||
if (tiled & TILED_X_AXIS) \
|
||||
getx = src->w - (-(getx+1) % src->w) - 1; \
|
||||
else { \
|
||||
addx = -getx; \
|
||||
getx = 0; \
|
||||
} \
|
||||
} \
|
||||
else if (getx >= src->w) { \
|
||||
if (tiled & TILED_X_AXIS) \
|
||||
getx = getx % src->w; \
|
||||
else \
|
||||
getx = src->w-1; \
|
||||
} \
|
||||
\
|
||||
src_address = ((ptr_type **)src->line)[gety]+getx; \
|
||||
\
|
||||
for (dx=0; dx<width; dx++) { \
|
||||
do_job \
|
||||
\
|
||||
/* update X position to get pixel */ \
|
||||
if (getx < src->w-1) { \
|
||||
getx++; \
|
||||
if (addx == 0) \
|
||||
src_address++; \
|
||||
else \
|
||||
addx--; \
|
||||
} \
|
||||
else if (tiled & TILED_X_AXIS) { \
|
||||
getx = 0; \
|
||||
src_address = ((ptr_type **)src->line)[gety]+getx; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
/* update Y position to get pixel */ \
|
||||
if (gety < src->h-1) { \
|
||||
if (addy == 0) \
|
||||
gety++; \
|
||||
else \
|
||||
addy--; \
|
||||
} \
|
||||
else if (tiled & TILED_Y_AXIS) \
|
||||
gety = 0; \
|
||||
}
|
||||
|
||||
#endif
|
@ -1,138 +0,0 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "effect/effect.h"
|
||||
#include "modules/palettes.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/rgbmap.h"
|
||||
|
||||
void apply_invert_color4(Effect *effect)
|
||||
{
|
||||
ase_uint32 *src_address;
|
||||
ase_uint32 *dst_address;
|
||||
int x, c, r, g, b, a;
|
||||
|
||||
src_address = ((ase_uint32 **)effect->src->line)[effect->row+effect->y]+effect->x;
|
||||
dst_address = ((ase_uint32 **)effect->dst->line)[effect->row+effect->y]+effect->x;
|
||||
|
||||
for (x=0; x<effect->w; x++) {
|
||||
if (effect->mask_address) {
|
||||
if (!((*effect->mask_address) & (1<<effect->d.rem))) {
|
||||
src_address++;
|
||||
dst_address++;
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
r = _rgba_getr(c);
|
||||
g = _rgba_getg(c);
|
||||
b = _rgba_getb(c);
|
||||
a = _rgba_geta(c);
|
||||
|
||||
if (effect->target & TARGET_RED_CHANNEL) r ^= 0xff;
|
||||
if (effect->target & TARGET_GREEN_CHANNEL) g ^= 0xff;
|
||||
if (effect->target & TARGET_BLUE_CHANNEL) b ^= 0xff;
|
||||
if (effect->target & TARGET_ALPHA_CHANNEL) a ^= 0xff;
|
||||
|
||||
*(dst_address++) = _rgba(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
void apply_invert_color2(Effect *effect)
|
||||
{
|
||||
ase_uint16 *src_address;
|
||||
ase_uint16 *dst_address;
|
||||
int x, c, k, a;
|
||||
|
||||
src_address = ((ase_uint16 **)effect->src->line)[effect->row+effect->y]+effect->x;
|
||||
dst_address = ((ase_uint16 **)effect->dst->line)[effect->row+effect->y]+effect->x;
|
||||
|
||||
for (x=0; x<effect->w; x++) {
|
||||
if (effect->mask_address) {
|
||||
if (!((*effect->mask_address) & (1<<effect->d.rem))) {
|
||||
src_address++;
|
||||
dst_address++;
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
k = _graya_getv(c);
|
||||
a = _graya_geta(c);
|
||||
|
||||
if (effect->target & TARGET_GRAY_CHANNEL) k ^= 0xff;
|
||||
if (effect->target & TARGET_ALPHA_CHANNEL) a ^= 0xff;
|
||||
|
||||
*(dst_address++) = _graya(k, a);
|
||||
}
|
||||
}
|
||||
|
||||
void apply_invert_color1(Effect *effect)
|
||||
{
|
||||
Palette *pal = get_current_palette();
|
||||
RgbMap* rgbmap = effect->sprite->getRgbMap();
|
||||
ase_uint8 *src_address;
|
||||
ase_uint8 *dst_address;
|
||||
int x, c, r, g, b;
|
||||
|
||||
src_address = ((ase_uint8 **)effect->src->line)[effect->row+effect->y]+effect->x;
|
||||
dst_address = ((ase_uint8 **)effect->dst->line)[effect->row+effect->y]+effect->x;
|
||||
|
||||
for (x=0; x<effect->w; x++) {
|
||||
if (effect->mask_address) {
|
||||
if (!((*effect->mask_address) & (1<<effect->d.rem))) {
|
||||
src_address++;
|
||||
dst_address++;
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
if (effect->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));
|
||||
|
||||
if (effect->target & TARGET_RED_CHANNEL ) r ^= 0xff;
|
||||
if (effect->target & TARGET_GREEN_CHANNEL) g ^= 0xff;
|
||||
if (effect->target & TARGET_BLUE_CHANNEL ) b ^= 0xff;
|
||||
|
||||
c = rgbmap->mapColor(r, g, b);
|
||||
}
|
||||
|
||||
*(dst_address++) = c;
|
||||
}
|
||||
}
|
@ -1,260 +0,0 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <allegro.h>
|
||||
|
||||
#include "base/memory.h"
|
||||
#include "effect/effect.h"
|
||||
#include "modules/palettes.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/rgbmap.h"
|
||||
#include "tiled_mode.h"
|
||||
|
||||
static struct {
|
||||
TiledMode tiled;
|
||||
int w, h;
|
||||
int ncolors;
|
||||
unsigned char *channel[4];
|
||||
} data = { TILED_NONE, 0, 0, 0, { NULL, NULL, NULL, NULL } };
|
||||
|
||||
void set_median_size(TiledMode tiled, int w, int h)
|
||||
{
|
||||
int c;
|
||||
|
||||
data.tiled = tiled;
|
||||
data.w = w;
|
||||
data.h = h;
|
||||
data.ncolors = w*h;
|
||||
|
||||
for (c=0; c<4; c++) {
|
||||
if (data.channel[c])
|
||||
base_free(data.channel[c]);
|
||||
|
||||
data.channel[c] = (unsigned char*)base_malloc(sizeof(unsigned char) * data.ncolors);
|
||||
}
|
||||
}
|
||||
|
||||
static int cmp_channel(const void *p1, const void *p2)
|
||||
{
|
||||
return (*(unsigned char *)p2) -(*(unsigned char *)p1);
|
||||
}
|
||||
|
||||
void apply_median4(Effect *effect)
|
||||
{
|
||||
const Image *src = effect->src;
|
||||
Image *dst = effect->dst;
|
||||
const ase_uint32 *src_address;
|
||||
ase_uint32 *dst_address;
|
||||
int x, y, dx, dy, color;
|
||||
int c, w, r, g, b, a;
|
||||
int getx, gety, addx, addy;
|
||||
|
||||
w = effect->x+effect->w;
|
||||
y = effect->y+effect->row;
|
||||
dst_address = ((ase_uint32 **)dst->line)[y]+effect->x;
|
||||
|
||||
for (x=effect->x; x<w; x++) {
|
||||
/* avoid the unmask region */
|
||||
if (effect->mask_address) {
|
||||
if (!((*effect->mask_address) & (1<<effect->d.rem))) {
|
||||
dst_address++;
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
}
|
||||
|
||||
c = 0;
|
||||
|
||||
GET_MATRIX_DATA
|
||||
(ase_uint32, src, src_address,
|
||||
data.w, data.h, data.w/2, data.h/2, data.tiled,
|
||||
color = *src_address;
|
||||
data.channel[0][c] = _rgba_getr(color);
|
||||
data.channel[1][c] = _rgba_getg(color);
|
||||
data.channel[2][c] = _rgba_getb(color);
|
||||
data.channel[3][c] = _rgba_geta(color);
|
||||
c++;
|
||||
);
|
||||
|
||||
for (c=0; c<4; c++)
|
||||
qsort(data.channel[c], data.ncolors, sizeof(unsigned char), cmp_channel);
|
||||
|
||||
color = image_getpixel_fast<RgbTraits>(src, x, y);
|
||||
|
||||
if (effect->target & TARGET_RED_CHANNEL)
|
||||
r = data.channel[0][data.ncolors/2];
|
||||
else
|
||||
r = _rgba_getr(color);
|
||||
|
||||
if (effect->target & TARGET_GREEN_CHANNEL)
|
||||
g = data.channel[1][data.ncolors/2];
|
||||
else
|
||||
g = _rgba_getg(color);
|
||||
|
||||
if (effect->target & TARGET_BLUE_CHANNEL)
|
||||
b = data.channel[2][data.ncolors/2];
|
||||
else
|
||||
b = _rgba_getb(color);
|
||||
|
||||
if (effect->target & TARGET_ALPHA_CHANNEL)
|
||||
a = data.channel[3][data.ncolors/2];
|
||||
else
|
||||
a = _rgba_geta(color);
|
||||
|
||||
*(dst_address++) = _rgba(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
void apply_median2(Effect *effect)
|
||||
{
|
||||
const Image *src = effect->src;
|
||||
Image *dst = effect->dst;
|
||||
const ase_uint16 *src_address;
|
||||
ase_uint16 *dst_address;
|
||||
int x, y, dx, dy, color;
|
||||
int c, w, k, a;
|
||||
int getx, gety, addx, addy;
|
||||
|
||||
w = effect->x+effect->w;
|
||||
y = effect->y+effect->row;
|
||||
dst_address = ((ase_uint16 **)dst->line)[y]+effect->x;
|
||||
|
||||
for (x=effect->x; x<w; x++) {
|
||||
/* avoid the unmask region */
|
||||
if (effect->mask_address) {
|
||||
if (!((*effect->mask_address) & (1<<effect->d.rem))) {
|
||||
dst_address++;
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
}
|
||||
|
||||
c = 0;
|
||||
|
||||
GET_MATRIX_DATA
|
||||
(ase_uint16, src, src_address,
|
||||
data.w, data.h, data.w/2, data.h/2, data.tiled,
|
||||
color = *src_address;
|
||||
data.channel[0][c] = _graya_getv(color);
|
||||
data.channel[1][c] = _graya_geta(color);
|
||||
c++;
|
||||
);
|
||||
|
||||
for (c=0; c<2; c++)
|
||||
qsort(data.channel[c], data.ncolors, sizeof(unsigned char), cmp_channel);
|
||||
|
||||
color = image_getpixel_fast<GrayscaleTraits>(src, x, y);
|
||||
|
||||
if (effect->target & TARGET_GRAY_CHANNEL)
|
||||
k = data.channel[0][data.ncolors/2];
|
||||
else
|
||||
k = _graya_getv(color);
|
||||
|
||||
if (effect->target & TARGET_ALPHA_CHANNEL)
|
||||
a = data.channel[1][data.ncolors/2];
|
||||
else
|
||||
a = _graya_geta(color);
|
||||
|
||||
*(dst_address++) = _graya(k, a);
|
||||
}
|
||||
}
|
||||
|
||||
void apply_median1(Effect *effect)
|
||||
{
|
||||
const Palette* pal = get_current_palette();
|
||||
const RgbMap* rgbmap = effect->sprite->getRgbMap();
|
||||
const Image* src = effect->src;
|
||||
Image* dst = effect->dst;
|
||||
const ase_uint8* src_address;
|
||||
ase_uint8* dst_address;
|
||||
int x, y, dx, dy, color;
|
||||
int c, w, r, g, b;
|
||||
int getx, gety, addx, addy;
|
||||
|
||||
w = effect->x+effect->w;
|
||||
y = effect->y+effect->row;
|
||||
dst_address = ((ase_uint8 **)dst->line)[y]+effect->x;
|
||||
|
||||
for (x=effect->x; x<w; x++) {
|
||||
/* avoid the unmask region */
|
||||
if (effect->mask_address) {
|
||||
if (!((*effect->mask_address) & (1<<effect->d.rem))) {
|
||||
dst_address++;
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
}
|
||||
|
||||
c = 0;
|
||||
|
||||
GET_MATRIX_DATA
|
||||
(ase_uint8, src, src_address,
|
||||
data.w, data.h, data.w/2, data.h/2, data.tiled,
|
||||
color = *src_address;
|
||||
if (effect->target & TARGET_INDEX_CHANNEL) {
|
||||
data.channel[0][c] = color;
|
||||
}
|
||||
else {
|
||||
data.channel[0][c] = _rgba_getr(pal->getEntry(color));
|
||||
data.channel[1][c] = _rgba_getg(pal->getEntry(color));
|
||||
data.channel[2][c] = _rgba_getb(pal->getEntry(color));
|
||||
}
|
||||
c++;
|
||||
);
|
||||
|
||||
if (effect->target & TARGET_INDEX_CHANNEL)
|
||||
qsort(data.channel[0], data.ncolors, sizeof(unsigned char), cmp_channel);
|
||||
else {
|
||||
for (c=0; c<3; c++)
|
||||
qsort(data.channel[c], data.ncolors, sizeof(unsigned char), cmp_channel);
|
||||
}
|
||||
|
||||
if (effect->target & TARGET_INDEX_CHANNEL) {
|
||||
*(dst_address++) = data.channel[0][data.ncolors/2];
|
||||
}
|
||||
else {
|
||||
color = image_getpixel_fast<IndexedTraits>(src, x, y);
|
||||
|
||||
if (effect->target & TARGET_RED_CHANNEL)
|
||||
r = data.channel[0][data.ncolors/2];
|
||||
else
|
||||
r = _rgba_getr(pal->getEntry(color));
|
||||
|
||||
if (effect->target & TARGET_GREEN_CHANNEL)
|
||||
g = data.channel[1][data.ncolors/2];
|
||||
else
|
||||
g = _rgba_getg(pal->getEntry(color));
|
||||
|
||||
if (effect->target & TARGET_BLUE_CHANNEL)
|
||||
b = data.channel[2][data.ncolors/2];
|
||||
else
|
||||
b = _rgba_getb(pal->getEntry(color));
|
||||
|
||||
*(dst_address++) = rgbmap->mapColor(r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,149 +0,0 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "app/color.h"
|
||||
#include "effect/effect.h"
|
||||
#include "raster/image.h"
|
||||
|
||||
static struct {
|
||||
int from, to;
|
||||
int tolerance;
|
||||
} data;
|
||||
|
||||
void set_replace_colors(int from, int to, int tolerance)
|
||||
{
|
||||
data.from = from;
|
||||
data.to = to;
|
||||
data.tolerance = MID(0, tolerance, 255);
|
||||
}
|
||||
|
||||
void apply_replace_color4(Effect *effect)
|
||||
{
|
||||
ase_uint32 *src_address;
|
||||
ase_uint32 *dst_address;
|
||||
int src_r, src_g, src_b, src_a;
|
||||
int dst_r, dst_g, dst_b, dst_a;
|
||||
int x, c;
|
||||
|
||||
src_address = ((ase_uint32 **)effect->src->line)[effect->row+effect->y]+effect->x;
|
||||
dst_address = ((ase_uint32 **)effect->dst->line)[effect->row+effect->y]+effect->x;
|
||||
|
||||
dst_r = _rgba_getr(data.from);
|
||||
dst_g = _rgba_getg(data.from);
|
||||
dst_b = _rgba_getb(data.from);
|
||||
dst_a = _rgba_geta(data.from);
|
||||
|
||||
for (x=0; x<effect->w; x++) {
|
||||
if (effect->mask_address) {
|
||||
if (!((*effect->mask_address) & (1<<effect->d.rem))) {
|
||||
src_address++;
|
||||
dst_address++;
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
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) <= data.tolerance) &&
|
||||
(ABS(src_g-dst_g) <= data.tolerance) &&
|
||||
(ABS(src_b-dst_b) <= data.tolerance) &&
|
||||
(ABS(src_a-dst_a) <= data.tolerance))
|
||||
*(dst_address++) = data.to;
|
||||
else
|
||||
*(dst_address++) = c;
|
||||
}
|
||||
}
|
||||
|
||||
void apply_replace_color2(Effect *effect)
|
||||
{
|
||||
ase_uint16 *src_address;
|
||||
ase_uint16 *dst_address;
|
||||
int src_k, src_a;
|
||||
int dst_k, dst_a;
|
||||
int x, c;
|
||||
|
||||
src_address = ((ase_uint16 **)effect->src->line)[effect->row+effect->y]+effect->x;
|
||||
dst_address = ((ase_uint16 **)effect->dst->line)[effect->row+effect->y]+effect->x;
|
||||
|
||||
dst_k = _graya_getv(data.from);
|
||||
dst_a = _graya_geta(data.from);
|
||||
|
||||
for (x=0; x<effect->w; x++) {
|
||||
if (effect->mask_address) {
|
||||
if (!((*effect->mask_address) & (1<<effect->d.rem))) {
|
||||
src_address++;
|
||||
dst_address++;
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
src_k = _graya_getv(c);
|
||||
src_a = _graya_geta(c);
|
||||
|
||||
if ((ABS(src_k-dst_k) <= data.tolerance) &&
|
||||
(ABS(src_a-dst_a) <= data.tolerance))
|
||||
*(dst_address++) = data.to;
|
||||
else
|
||||
*(dst_address++) = c;
|
||||
}
|
||||
}
|
||||
|
||||
void apply_replace_color1(Effect *effect)
|
||||
{
|
||||
ase_uint8 *src_address;
|
||||
ase_uint8 *dst_address;
|
||||
int x, c;
|
||||
|
||||
src_address = ((ase_uint8 **)effect->src->line)[effect->row+effect->y]+effect->x;
|
||||
dst_address = ((ase_uint8 **)effect->dst->line)[effect->row+effect->y]+effect->x;
|
||||
|
||||
for (x=0; x<effect->w; x++) {
|
||||
if (effect->mask_address) {
|
||||
if (!((*effect->mask_address) & (1<<effect->d.rem))) {
|
||||
src_address++;
|
||||
dst_address++;
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
_image_bitmap_next_bit(effect->d, effect->mask_address);
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
if (ABS(c-data.from) <= data.tolerance)
|
||||
*(dst_address++) = data.to;
|
||||
else
|
||||
*(dst_address++) = c;
|
||||
}
|
||||
}
|
12
src/filters/CMakeLists.txt
Normal file
12
src/filters/CMakeLists.txt
Normal file
@ -0,0 +1,12 @@
|
||||
# ASE - Allegro Sprite Editor
|
||||
# Copyright (C) 2001-2011 David Capello
|
||||
|
||||
add_library(filters-lib
|
||||
color_curve.cpp
|
||||
color_curve_filter.cpp
|
||||
convolution_matrix.cpp
|
||||
convolution_matrix_filter.cpp
|
||||
invert_color_filter.cpp
|
||||
median_filter.cpp
|
||||
replace_color_filter.cpp)
|
||||
|
95
src/filters/color_curve.cpp
Normal file
95
src/filters/color_curve.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "filters/color_curve.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
ColorCurve::ColorCurve(Type type)
|
||||
: m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
void ColorCurve::addPoint(const gfx::Point& point)
|
||||
{
|
||||
for (iterator it = begin(), end = this->end(); it != end; ++it) {
|
||||
if (it->x >= point.x) {
|
||||
m_points.insert(it, point);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_points.push_back(point);
|
||||
}
|
||||
|
||||
void ColorCurve::removePoint(const gfx::Point& point)
|
||||
{
|
||||
iterator it = std::find(begin(), end(), point);
|
||||
if (it != end())
|
||||
m_points.erase(it);
|
||||
}
|
||||
|
||||
void ColorCurve::getValues(int x1, int x2, std::vector<int>& values)
|
||||
{
|
||||
int x, num_points = (int)m_points.size();
|
||||
|
||||
if (num_points == 0) {
|
||||
for (x=x1; x<=x2; x++)
|
||||
values[x-x1] = 0;
|
||||
}
|
||||
else if (num_points == 1) {
|
||||
for (x=x1; x<=x2; x++)
|
||||
values[x-x1] = m_points[0].y;
|
||||
}
|
||||
else {
|
||||
switch (m_type) {
|
||||
|
||||
case Linear: {
|
||||
iterator it, begin = this->begin(), end = this->end();
|
||||
|
||||
for (it = begin; it != end; ++it)
|
||||
if (it->x >= x1)
|
||||
break;
|
||||
|
||||
for (x=x1; x<=x2; x++) {
|
||||
while ((it != end) && (x > it->x))
|
||||
++it;
|
||||
|
||||
if (it != end) {
|
||||
if (it != begin) {
|
||||
const gfx::Point& p = *(it-1);
|
||||
const gfx::Point& n = *it;
|
||||
|
||||
values[x-x1] = p.y + (n.y-p.y) * (x-p.x) / (n.x-p.x);
|
||||
}
|
||||
else {
|
||||
values[x-x1] = it->y;
|
||||
}
|
||||
}
|
||||
else {
|
||||
values[x-x1] = (end-1)->y;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
51
src/filters/color_curve.h
Normal file
51
src/filters/color_curve.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 FILTERS_COLOR_CURVE_H_INCLUDED
|
||||
#define FILTERS_COLOR_CURVE_H_INCLUDED
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "gfx/point.h"
|
||||
|
||||
class ColorCurve
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
Linear,
|
||||
//Spline, // TODO for the future
|
||||
};
|
||||
|
||||
typedef std::vector<gfx::Point>::iterator iterator;
|
||||
|
||||
ColorCurve(Type type);
|
||||
|
||||
iterator begin() { return m_points.begin(); }
|
||||
iterator end() { return m_points.end(); }
|
||||
|
||||
void addPoint(const gfx::Point& point);
|
||||
void removePoint(const gfx::Point& point);
|
||||
|
||||
void getValues(int x1, int x2, std::vector<int>& values);
|
||||
|
||||
private:
|
||||
Type m_type;
|
||||
std::vector<gfx::Point> m_points;
|
||||
};
|
||||
|
||||
#endif
|
150
src/filters/color_curve_filter.cpp
Normal file
150
src/filters/color_curve_filter.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "filters/color_curve_filter.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "filters/color_curve.h"
|
||||
#include "filters/filter_indexed_data.h"
|
||||
#include "filters/filter_manager.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/rgbmap.h"
|
||||
#include "raster/sprite.h"
|
||||
|
||||
ColorCurveFilter::ColorCurveFilter()
|
||||
: m_curve(NULL)
|
||||
, m_cmap(256)
|
||||
{
|
||||
}
|
||||
|
||||
void ColorCurveFilter::setCurve(ColorCurve* curve)
|
||||
{
|
||||
ASSERT(curve != NULL);
|
||||
|
||||
m_curve = curve;
|
||||
|
||||
// Generate the color convertion map
|
||||
m_curve->getValues(0, 255, m_cmap);
|
||||
for (int c=0; c<256; c++)
|
||||
m_cmap[c] = MID(0, m_cmap[c], 255);
|
||||
}
|
||||
|
||||
const char* ColorCurveFilter::getName()
|
||||
{
|
||||
return "Color Curve";
|
||||
}
|
||||
|
||||
void ColorCurveFilter::applyToRgba(FilterManager* filterMgr)
|
||||
{
|
||||
const ase_uint32* src_address = (ase_uint32*)filterMgr->getSourceAddress();
|
||||
ase_uint32* dst_address = (ase_uint32*)filterMgr->getDestinationAddress();
|
||||
int w = filterMgr->getWidth();
|
||||
Target target = filterMgr->getTarget();
|
||||
int x, c, r, g, b, a;
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void ColorCurveFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
{
|
||||
const ase_uint16* src_address = (ase_uint16*)filterMgr->getSourceAddress();
|
||||
ase_uint16* dst_address = (ase_uint16*)filterMgr->getDestinationAddress();
|
||||
int w = filterMgr->getWidth();
|
||||
Target target = filterMgr->getTarget();
|
||||
int x, c, k, a;
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void ColorCurveFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
{
|
||||
const ase_uint8* src_address = (ase_uint8*)filterMgr->getSourceAddress();
|
||||
ase_uint8* dst_address = (ase_uint8*)filterMgr->getDestinationAddress();
|
||||
int w = filterMgr->getWidth();
|
||||
Target target = filterMgr->getTarget();
|
||||
const Palette* pal = filterMgr->getIndexedData()->getPalette();
|
||||
const RgbMap* rgbmap = filterMgr->getIndexedData()->getRgbMap();
|
||||
int x, c, r, g, b;
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
if (target & TARGET_INDEX_CHANNEL) {
|
||||
c = m_cmap[c];
|
||||
}
|
||||
else {
|
||||
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];
|
||||
if (target & TARGET_BLUE_CHANNEL) b = m_cmap[b];
|
||||
|
||||
c = rgbmap->mapColor(r, g, b);
|
||||
}
|
||||
|
||||
*(dst_address++) = MID(0, c, pal->size()-1);
|
||||
}
|
||||
}
|
@ -16,17 +16,32 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef WIDGETS_PREVIEW_H_INCLUDED
|
||||
#define WIDGETS_PREVIEW_H_INCLUDED
|
||||
#ifndef FILTERS_COLOR_CURVE_FILTER_H_INCLUDED
|
||||
#define FILTERS_COLOR_CURVE_FILTER_H_INCLUDED
|
||||
|
||||
#include "gui/base.h"
|
||||
#include <vector>
|
||||
|
||||
struct Effect;
|
||||
#include "filters/filter.h"
|
||||
|
||||
JWidget preview_new(struct Effect *effect);
|
||||
int preview_type();
|
||||
class ColorCurve;
|
||||
|
||||
void preview_restart(JWidget preview);
|
||||
struct Effect *preview_get_effect(JWidget preview);
|
||||
class ColorCurveFilter : public Filter
|
||||
{
|
||||
public:
|
||||
ColorCurveFilter();
|
||||
|
||||
void setCurve(ColorCurve* curve);
|
||||
ColorCurve* getCurve() const { return m_curve; }
|
||||
|
||||
// Filter implementation
|
||||
const char* getName();
|
||||
void applyToRgba(FilterManager* filterMgr);
|
||||
void applyToGrayscale(FilterManager* filterMgr);
|
||||
void applyToIndexed(FilterManager* filterMgr);
|
||||
|
||||
private:
|
||||
ColorCurve* m_curve;
|
||||
std::vector<int> m_cmap;
|
||||
};
|
||||
|
||||
#endif
|
@ -16,15 +16,18 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef EFFECT_REPLCOL_H_INCLUDED
|
||||
#define EFFECT_REPLCOL_H_INCLUDED
|
||||
#include "config.h"
|
||||
|
||||
struct Effect;
|
||||
#include "filters/convolution_matrix.h"
|
||||
|
||||
void set_replace_colors(int from, int to, int tolerance);
|
||||
|
||||
void apply_replace_color4(struct Effect *effect);
|
||||
void apply_replace_color2(struct Effect *effect);
|
||||
void apply_replace_color1(struct Effect *effect);
|
||||
|
||||
#endif
|
||||
ConvolutionMatrix::ConvolutionMatrix(int width, int height)
|
||||
: m_data(width*height, 0)
|
||||
, m_width(width)
|
||||
, m_height(height)
|
||||
, m_cx(width/2)
|
||||
, m_cy(height/2)
|
||||
, m_div(ConvolutionMatrix::Precision)
|
||||
, m_bias(0)
|
||||
, m_defaultTarget(0)
|
||||
{
|
||||
}
|
77
src/filters/convolution_matrix.h
Normal file
77
src/filters/convolution_matrix.h
Normal file
@ -0,0 +1,77 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 FILTERS_CONVOLUTION_MATRIX_H_INCLUDED
|
||||
#define FILTERS_CONVOLUTION_MATRIX_H_INCLUDED
|
||||
|
||||
#include "filters/target.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
// A convolution matrix which is used by ConvolutionMatrixFilter.
|
||||
class ConvolutionMatrix
|
||||
{
|
||||
public:
|
||||
// TODO warning: this number could be dangerous for big filters
|
||||
static const int Precision = 256;
|
||||
|
||||
ConvolutionMatrix(int width, int height);
|
||||
|
||||
const char* getName() const { return m_name.c_str(); }
|
||||
int getWidth() const { return m_width; }
|
||||
int getHeight() const { return m_height; }
|
||||
int getCenterX() const { return m_cx; }
|
||||
int getCenterY() const { return m_cy; }
|
||||
int getDiv() const { return m_div; }
|
||||
int getBias() const { return m_bias; }
|
||||
Target getDefaultTarget() const { return m_defaultTarget; }
|
||||
|
||||
void setName(const char* name) { m_name = name; }
|
||||
void setWidth(int width) { m_width = width; }
|
||||
void setHeight(int height) { m_height = height; }
|
||||
void setCenterX(int cx) { m_cx = cx; }
|
||||
void setCenterY(int cy) { m_cy = cy; }
|
||||
void setDiv(int div) { m_div = div; }
|
||||
void setBias(int bias) { m_bias = bias; }
|
||||
void setDefaultTarget(Target target) { m_defaultTarget = target; }
|
||||
|
||||
// Returns a reference to a value in the matrix. It is very
|
||||
// important that values of this matrix are sortered in the
|
||||
// following way (e.g. m_width=4, m_height=3):
|
||||
//
|
||||
// x0 x1 x2 x3
|
||||
// x4 x5 x6 x7
|
||||
// x8 x9 x10 x11
|
||||
//
|
||||
// The ConvolutionMatrixFilter expects that memory layout.
|
||||
//
|
||||
int& value(int x, int y) { return m_data[y*m_width+x]; }
|
||||
const int& value(int x, int y) const { return m_data[y*m_width+x]; }
|
||||
|
||||
private:
|
||||
std::string m_name; // Name
|
||||
int m_width, m_height; // Size of the matrix
|
||||
int m_cx, m_cy; // Center of the filter
|
||||
int m_div; // Division factor
|
||||
int m_bias; // Addition factor (for offset)
|
||||
Target m_defaultTarget; // Targets by default (look at TARGET_RED_CHANNEL, etc. constants)
|
||||
std::vector<int> m_data; // The matrix with the multiplication factors
|
||||
};
|
||||
|
||||
#endif
|
333
src/filters/convolution_matrix_filter.cpp
Normal file
333
src/filters/convolution_matrix_filter.cpp
Normal file
@ -0,0 +1,333 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "filters/convolution_matrix_filter.h"
|
||||
|
||||
#include "filters/convolution_matrix.h"
|
||||
#include "filters/filter_indexed_data.h"
|
||||
#include "filters/filter_manager.h"
|
||||
#include "filters/neighboring_pixels.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/rgbmap.h"
|
||||
|
||||
ConvolutionMatrixFilter::ConvolutionMatrixFilter()
|
||||
: m_matrix(NULL)
|
||||
, m_tiledMode(TILED_NONE)
|
||||
{
|
||||
}
|
||||
|
||||
void ConvolutionMatrixFilter::setMatrix(const SharedPtr<ConvolutionMatrix>& matrix)
|
||||
{
|
||||
m_matrix = matrix;
|
||||
m_lines.resize(matrix->getHeight());
|
||||
}
|
||||
|
||||
void ConvolutionMatrixFilter::setTiledMode(TiledMode tiledMode)
|
||||
{
|
||||
m_tiledMode = tiledMode;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct GetPixelsDelegate
|
||||
{
|
||||
ase_uint32 color;
|
||||
int div;
|
||||
const int* matrixData;
|
||||
|
||||
void reset(const ConvolutionMatrix* matrix) {
|
||||
div = matrix->getDiv();
|
||||
matrixData = &matrix->value(0, 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct GetPixelsDelegateRgba : public GetPixelsDelegate
|
||||
{
|
||||
int r, g, b, a;
|
||||
|
||||
void reset(const ConvolutionMatrix* matrix) {
|
||||
GetPixelsDelegate::reset(matrix);
|
||||
r = g = b = a = 0;
|
||||
}
|
||||
|
||||
void operator()(RgbTraits::pixel_t color)
|
||||
{
|
||||
if (*matrixData) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
matrixData++;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct GetPixelsDelegateGrayscale : public GetPixelsDelegate
|
||||
{
|
||||
int v, a;
|
||||
|
||||
void reset(const ConvolutionMatrix* matrix) {
|
||||
GetPixelsDelegate::reset(matrix);
|
||||
v = a = 0;
|
||||
}
|
||||
|
||||
void operator()(GrayscaleTraits::pixel_t color)
|
||||
{
|
||||
if (*matrixData) {
|
||||
if (_graya_geta(color) == 0)
|
||||
div -= *matrixData;
|
||||
else {
|
||||
v += _graya_getv(color) * (*matrixData);
|
||||
a += _graya_geta(color) * (*matrixData);
|
||||
}
|
||||
}
|
||||
matrixData++;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct GetPixelsDelegateIndexed : public GetPixelsDelegate
|
||||
{
|
||||
const Palette* pal;
|
||||
int r, g, b, index;
|
||||
|
||||
GetPixelsDelegateIndexed(const Palette* pal) : pal(pal) { }
|
||||
|
||||
void reset(const ConvolutionMatrix* matrix) {
|
||||
GetPixelsDelegate::reset(matrix);
|
||||
r = g = b = index = 0;
|
||||
}
|
||||
|
||||
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);
|
||||
index += color * (*matrixData);
|
||||
}
|
||||
matrixData++;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
const char* ConvolutionMatrixFilter::getName()
|
||||
{
|
||||
return "Convolution Matrix";
|
||||
}
|
||||
|
||||
void ConvolutionMatrixFilter::applyToRgba(FilterManager* filterMgr)
|
||||
{
|
||||
if (!m_matrix)
|
||||
return;
|
||||
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
ase_uint32* dst_address = (ase_uint32*)filterMgr->getDestinationAddress();
|
||||
Target target = filterMgr->getTarget();
|
||||
ase_uint32 color;
|
||||
GetPixelsDelegateRgba delegate;
|
||||
int x = filterMgr->getX();
|
||||
int x2 = x+filterMgr->getWidth();
|
||||
int y = filterMgr->getY();
|
||||
|
||||
for (; x<x2; ++x) {
|
||||
// Avoid the non-selected region
|
||||
if (filterMgr->skipPixel()) {
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
delegate.reset(m_matrix);
|
||||
get_neighboring_pixels<RgbTraits>(src, x, y,
|
||||
m_matrix->getWidth(),
|
||||
m_matrix->getHeight(),
|
||||
m_matrix->getCenterX(),
|
||||
m_matrix->getCenterY(),
|
||||
m_tiledMode, delegate);
|
||||
|
||||
color = image_getpixel_fast<RgbTraits>(src, x, y);
|
||||
if (delegate.div == 0) {
|
||||
*(dst_address++) = color;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (target & TARGET_RED_CHANNEL) {
|
||||
delegate.r = delegate.r / delegate.div + m_matrix->getBias();
|
||||
delegate.r = MID(0, delegate.r, 255);
|
||||
}
|
||||
else
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
*(dst_address++) = _rgba(delegate.r, delegate.g, delegate.b, delegate.a);
|
||||
}
|
||||
}
|
||||
|
||||
void ConvolutionMatrixFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
{
|
||||
if (!m_matrix)
|
||||
return;
|
||||
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
ase_uint16* dst_address = (ase_uint16*)filterMgr->getDestinationAddress();
|
||||
Target target = filterMgr->getTarget();
|
||||
ase_uint16 color;
|
||||
GetPixelsDelegateGrayscale delegate;
|
||||
int x = filterMgr->getX();
|
||||
int x2 = x+filterMgr->getWidth();
|
||||
int y = filterMgr->getY();
|
||||
|
||||
for (; x<x2; ++x) {
|
||||
// Avoid the non-selected region
|
||||
if (filterMgr->skipPixel()) {
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
delegate.reset(m_matrix);
|
||||
get_neighboring_pixels<GrayscaleTraits>(src, x, y,
|
||||
m_matrix->getWidth(),
|
||||
m_matrix->getHeight(),
|
||||
m_matrix->getCenterX(),
|
||||
m_matrix->getCenterY(),
|
||||
m_tiledMode, delegate);
|
||||
|
||||
color = image_getpixel_fast<GrayscaleTraits>(src, x, y);
|
||||
if (delegate.div == 0) {
|
||||
*(dst_address++) = color;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (target & TARGET_GRAY_CHANNEL) {
|
||||
delegate.v = delegate.v / delegate.div + m_matrix->getBias();
|
||||
delegate.v = MID(0, delegate.v, 255);
|
||||
}
|
||||
else
|
||||
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);
|
||||
|
||||
*(dst_address++) = _graya(delegate.v, delegate.a);
|
||||
}
|
||||
}
|
||||
|
||||
void ConvolutionMatrixFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
{
|
||||
if (!m_matrix)
|
||||
return;
|
||||
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
ase_uint8* dst_address = (ase_uint8*)filterMgr->getDestinationAddress();
|
||||
const Palette* pal = filterMgr->getIndexedData()->getPalette();
|
||||
const RgbMap* rgbmap = filterMgr->getIndexedData()->getRgbMap();
|
||||
Target target = filterMgr->getTarget();
|
||||
ase_uint8 color;
|
||||
GetPixelsDelegateIndexed delegate(pal);
|
||||
int x = filterMgr->getX();
|
||||
int x2 = x+filterMgr->getWidth();
|
||||
int y = filterMgr->getY();
|
||||
|
||||
for (; x<x2; ++x) {
|
||||
// Avoid the non-selected region
|
||||
if (filterMgr->skipPixel()) {
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
delegate.reset(m_matrix);
|
||||
get_neighboring_pixels<IndexedTraits>(src, x, y,
|
||||
m_matrix->getWidth(),
|
||||
m_matrix->getHeight(),
|
||||
m_matrix->getCenterX(),
|
||||
m_matrix->getCenterY(),
|
||||
m_tiledMode, delegate);
|
||||
|
||||
color = image_getpixel_fast<IndexedTraits>(src, x, y);
|
||||
if (delegate.div == 0) {
|
||||
*(dst_address++) = color;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (target & TARGET_INDEX_CHANNEL) {
|
||||
delegate.index = delegate.index / m_matrix->getDiv() + m_matrix->getBias();
|
||||
delegate.index = MID(0, delegate.index, 255);
|
||||
|
||||
*(dst_address++) = delegate.index;
|
||||
}
|
||||
else {
|
||||
if (target & TARGET_RED_CHANNEL) {
|
||||
delegate.r = delegate.r / delegate.div + m_matrix->getBias();
|
||||
delegate.r = MID(0, delegate.r, 255);
|
||||
}
|
||||
else
|
||||
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));
|
||||
|
||||
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));
|
||||
|
||||
*(dst_address++) = rgbmap->mapColor(delegate.r, delegate.g, delegate.b);
|
||||
}
|
||||
}
|
||||
}
|
53
src/filters/convolution_matrix_filter.h
Normal file
53
src/filters/convolution_matrix_filter.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 FILTERS_CONVOLUTION_MATRIX_FILTER_H_INCLUDED
|
||||
#define FILTERS_CONVOLUTION_MATRIX_FILTER_H_INCLUDED
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/shared_ptr.h"
|
||||
#include "filters/filter.h"
|
||||
#include "filters/tiled_mode.h"
|
||||
|
||||
class ConvolutionMatrix;
|
||||
|
||||
class ConvolutionMatrixFilter : public Filter
|
||||
{
|
||||
public:
|
||||
ConvolutionMatrixFilter();
|
||||
|
||||
void setMatrix(const SharedPtr<ConvolutionMatrix>& matrix);
|
||||
void setTiledMode(TiledMode tiledMode);
|
||||
|
||||
SharedPtr<ConvolutionMatrix> getMatrix() { return m_matrix; }
|
||||
TiledMode getTiledMode() const { return m_tiledMode; }
|
||||
|
||||
// Filter implementation
|
||||
const char* getName();
|
||||
void applyToRgba(FilterManager* filterMgr);
|
||||
void applyToGrayscale(FilterManager* filterMgr);
|
||||
void applyToIndexed(FilterManager* filterMgr);
|
||||
|
||||
private:
|
||||
SharedPtr<ConvolutionMatrix> m_matrix;
|
||||
TiledMode m_tiledMode;
|
||||
std::vector<ase_uint8*> m_lines;
|
||||
};
|
||||
|
||||
#endif
|
52
src/filters/filter.h
Normal file
52
src/filters/filter.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 FILTERS_FILTER_H_INCLUDED
|
||||
#define FILTERS_FILTER_H_INCLUDED
|
||||
|
||||
class FilterManager;
|
||||
|
||||
// Interface which applies a filter to a sprite given a FilterManager
|
||||
// which indicates where we have to apply the filter.
|
||||
class Filter
|
||||
{
|
||||
public:
|
||||
virtual ~Filter() { }
|
||||
|
||||
// Returns a proper name for the filter. It is used to show a label
|
||||
// with the Undo action.
|
||||
virtual const char* getName() = 0;
|
||||
|
||||
// Applies the filter to one RGBA row. You must use
|
||||
// FilterManager::getSourceAddress() and advance 32 bits to modify
|
||||
// each pixel.
|
||||
virtual void applyToRgba(FilterManager* filterMgr) = 0;
|
||||
|
||||
// Applies the filter to one grayscale row. You must use
|
||||
// FilterManager::getSourceAddress() and advance 16 bits to modify
|
||||
// each pixel.
|
||||
virtual void applyToGrayscale(FilterManager* filterMgr) = 0;
|
||||
|
||||
// Applies the filter to one indexed row. You must use
|
||||
// FilterManager::getSourceAddress() and advance 8 bits to modify
|
||||
// each pixel.
|
||||
virtual void applyToIndexed(FilterManager* filterMgr) = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -1,28 +1,35 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 EFFECT_INVRTCOL_H_INCLUDED
|
||||
#define EFFECT_INVRTCOL_H_INCLUDED
|
||||
|
||||
struct Effect;
|
||||
|
||||
void apply_invert_color4 (struct Effect *effect);
|
||||
void apply_invert_color2 (struct Effect *effect);
|
||||
void apply_invert_color1 (struct Effect *effect);
|
||||
|
||||
#endif
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 FILTERS_FILTER_INDEXED_DATA_H_INCLUDED
|
||||
#define FILTERS_FILTER_INDEXED_DATA_H_INCLUDED
|
||||
|
||||
class Palette;
|
||||
class RgbMap;
|
||||
|
||||
// Provides a Palette and a RgbMap to help a Filter which operate
|
||||
// over an indexed image.
|
||||
class FilterIndexedData
|
||||
{
|
||||
public:
|
||||
virtual ~FilterIndexedData() { }
|
||||
virtual Palette* getPalette() = 0;
|
||||
virtual RgbMap* getRgbMap() = 0;
|
||||
};
|
||||
|
||||
#endif
|
81
src/filters/filter_manager.h
Normal file
81
src/filters/filter_manager.h
Normal file
@ -0,0 +1,81 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 FILTERS_FILTER_MANAGER_H_INCLUDED
|
||||
#define FILTERS_FILTER_MANAGER_H_INCLUDED
|
||||
|
||||
#include "filters/target.h"
|
||||
|
||||
class FilterIndexedData;
|
||||
class Image;
|
||||
|
||||
// Information given to a filter (Filter interface) to apply it to a
|
||||
// single row. Basically an Filter implementation has to obtain
|
||||
// colors from getSourceAddress(), applies some kind of transformation
|
||||
// to that color, and save the result in getDestinationAddress().
|
||||
// This process must be repeated getWidth() times.
|
||||
class FilterManager
|
||||
{
|
||||
public:
|
||||
virtual ~FilterManager() { }
|
||||
|
||||
// Gets the address of the first pixel which has the original color
|
||||
// to apply the filter.
|
||||
virtual const void* getSourceAddress() = 0;
|
||||
|
||||
// Gets the address of the first pixel which is destination of the
|
||||
// filter.
|
||||
virtual void* getDestinationAddress() = 0;
|
||||
|
||||
// Returns the width of the row to apply the filter. You must apply
|
||||
// the Filter "getWidth()" times, in each pixel from getSourceAddress().
|
||||
virtual int getWidth() = 0;
|
||||
|
||||
// Returns the target of the Filter, i.e. what channels/components
|
||||
// (e.g. Red, Green, or Blue) will be modified by the filter.
|
||||
virtual Target getTarget() = 0;
|
||||
|
||||
// Returns a interface needed by filters which operate over indexed
|
||||
// images. FilterIndexedData interface provides a Palette and a
|
||||
// RgbMap to help the filter to make its job.
|
||||
virtual FilterIndexedData* getIndexedData() = 0;
|
||||
|
||||
// Returns true if you should skip the current pixel (do not apply
|
||||
// the filter). You must increment all your internal source and
|
||||
// destination address pointers one pixel without applying the
|
||||
// filter.
|
||||
//
|
||||
// This method is used to skip non-selected pixels (when the
|
||||
// selection is actived).
|
||||
virtual bool skipPixel() = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Special members for 2D filters like convolution matrices.
|
||||
|
||||
// Returns the source image.
|
||||
virtual const Image* getSourceImage() = 0;
|
||||
|
||||
// Returns the first X coordinate of the row to apply the filter.
|
||||
virtual int getX() = 0;
|
||||
|
||||
// Returns the Y coordinate of the row.
|
||||
virtual int getY() = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
127
src/filters/invert_color_filter.cpp
Normal file
127
src/filters/invert_color_filter.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "filters/invert_color_filter.h"
|
||||
|
||||
#include "filters/filter_indexed_data.h"
|
||||
#include "filters/filter_manager.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/rgbmap.h"
|
||||
|
||||
const char* InvertColorFilter::getName()
|
||||
{
|
||||
return "Invert Color";
|
||||
}
|
||||
|
||||
void InvertColorFilter::applyToRgba(FilterManager* filterMgr)
|
||||
{
|
||||
const ase_uint32* src_address = (ase_uint32*)filterMgr->getSourceAddress();
|
||||
ase_uint32* dst_address = (ase_uint32*)filterMgr->getDestinationAddress();
|
||||
int w = filterMgr->getWidth();
|
||||
Target target = filterMgr->getTarget();
|
||||
int x, c, r, g, b, a;
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void InvertColorFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
{
|
||||
const ase_uint16* src_address = (ase_uint16*)filterMgr->getSourceAddress();
|
||||
ase_uint16* dst_address = (ase_uint16*)filterMgr->getDestinationAddress();
|
||||
int w = filterMgr->getWidth();
|
||||
Target target = filterMgr->getTarget();
|
||||
int x, c, k, a;
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void InvertColorFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
{
|
||||
const ase_uint8* src_address = (ase_uint8*)filterMgr->getSourceAddress();
|
||||
ase_uint8* dst_address = (ase_uint8*)filterMgr->getDestinationAddress();
|
||||
const Palette* pal = filterMgr->getIndexedData()->getPalette();
|
||||
const RgbMap* rgbmap = filterMgr->getIndexedData()->getRgbMap();
|
||||
int w = filterMgr->getWidth();
|
||||
Target target = filterMgr->getTarget();
|
||||
int x, c, r, g, b;
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
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));
|
||||
|
||||
if (target & TARGET_RED_CHANNEL ) r ^= 0xff;
|
||||
if (target & TARGET_GREEN_CHANNEL) g ^= 0xff;
|
||||
if (target & TARGET_BLUE_CHANNEL ) b ^= 0xff;
|
||||
|
||||
c = rgbmap->mapColor(r, g, b);
|
||||
}
|
||||
|
||||
*(dst_address++) = c;
|
||||
}
|
||||
}
|
@ -16,17 +16,19 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef EFFECT_MEDIAN_H_INCLUDED
|
||||
#define EFFECT_MEDIAN_H_INCLUDED
|
||||
#ifndef FILTERS_INVERT_COLOR_FILTER_H_INCLUDED
|
||||
#define FILTERS_INVERT_COLOR_FILTER_H_INCLUDED
|
||||
|
||||
#include "tiled_mode.h"
|
||||
#include "filters/filter.h"
|
||||
|
||||
struct Effect;
|
||||
|
||||
void set_median_size(TiledMode tiled, int w, int h);
|
||||
|
||||
void apply_median4(Effect* effect);
|
||||
void apply_median2(Effect* effect);
|
||||
void apply_median1(Effect* effect);
|
||||
class InvertColorFilter : public Filter
|
||||
{
|
||||
public:
|
||||
// Filter implementation
|
||||
const char* getName();
|
||||
void applyToRgba(FilterManager* filterMgr);
|
||||
void applyToGrayscale(FilterManager* filterMgr);
|
||||
void applyToIndexed(FilterManager* filterMgr);
|
||||
};
|
||||
|
||||
#endif
|
281
src/filters/median_filter.cpp
Normal file
281
src/filters/median_filter.cpp
Normal file
@ -0,0 +1,281 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "filters/median_filter.h"
|
||||
|
||||
#include "base/memory.h"
|
||||
#include "filters/filter_indexed_data.h"
|
||||
#include "filters/filter_manager.h"
|
||||
#include "filters/neighboring_pixels.h"
|
||||
#include "filters/tiled_mode.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/rgbmap.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
MedianFilter::MedianFilter()
|
||||
: m_tiledMode(TILED_NONE)
|
||||
, m_width(0)
|
||||
, m_height(0)
|
||||
, m_ncolors(0)
|
||||
, m_channel(4)
|
||||
{
|
||||
}
|
||||
|
||||
void MedianFilter::setTiledMode(TiledMode tiled)
|
||||
{
|
||||
m_tiledMode = tiled;
|
||||
}
|
||||
|
||||
void MedianFilter::setSize(int width, int height)
|
||||
{
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_ncolors = width*height;
|
||||
|
||||
for (int c = 0; c < 4; ++c)
|
||||
m_channel[c].resize(m_ncolors);
|
||||
}
|
||||
|
||||
const char* MedianFilter::getName()
|
||||
{
|
||||
return "Median Blur";
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct GetPixelsDelegateRgba
|
||||
{
|
||||
std::vector<std::vector<ase_uint8> >& channel;
|
||||
int c;
|
||||
|
||||
GetPixelsDelegateRgba(std::vector<std::vector<ase_uint8> >& channel) : channel(channel) { }
|
||||
|
||||
void reset() { c = 0; }
|
||||
|
||||
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);
|
||||
c++;
|
||||
}
|
||||
};
|
||||
|
||||
struct GetPixelsDelegateGrayscale
|
||||
{
|
||||
std::vector<std::vector<ase_uint8> >& channel;
|
||||
int c;
|
||||
|
||||
GetPixelsDelegateGrayscale(std::vector<std::vector<ase_uint8> >& channel) : channel(channel) { }
|
||||
|
||||
void reset() { c = 0; }
|
||||
|
||||
void operator()(GrayscaleTraits::pixel_t color)
|
||||
{
|
||||
channel[0][c] = _graya_getv(color);
|
||||
channel[1][c] = _graya_geta(color);
|
||||
c++;
|
||||
}
|
||||
};
|
||||
|
||||
struct GetPixelsDelegateIndexed
|
||||
{
|
||||
const Palette* pal;
|
||||
std::vector<std::vector<ase_uint8> >& channel;
|
||||
Target target;
|
||||
int c;
|
||||
|
||||
GetPixelsDelegateIndexed(const Palette* pal, std::vector<std::vector<ase_uint8> >& channel, Target target)
|
||||
: pal(pal), channel(channel), target(target) { }
|
||||
|
||||
void reset() { c = 0; }
|
||||
|
||||
void operator()(IndexedTraits::pixel_t color)
|
||||
{
|
||||
if (target & TARGET_INDEX_CHANNEL) {
|
||||
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));
|
||||
}
|
||||
c++;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
void MedianFilter::applyToRgba(FilterManager* filterMgr)
|
||||
{
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
ase_uint32* dst_address = (ase_uint32*)filterMgr->getDestinationAddress();
|
||||
Target target = filterMgr->getTarget();
|
||||
int color;
|
||||
int r, g, b, a;
|
||||
GetPixelsDelegateRgba delegate(m_channel);
|
||||
int x = filterMgr->getX();
|
||||
int x2 = x+filterMgr->getWidth();
|
||||
int y = filterMgr->getY();
|
||||
|
||||
for (; x<x2; ++x) {
|
||||
// Avoid the non-selected region
|
||||
if (filterMgr->skipPixel()) {
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<RgbTraits>(src, x, y, m_width, m_height, m_width/2, m_height/2,
|
||||
m_tiledMode, delegate);
|
||||
|
||||
color = image_getpixel_fast<RgbTraits>(src, x, y);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
*(dst_address++) = _rgba(r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
void MedianFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
{
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
ase_uint16* dst_address = (ase_uint16*)filterMgr->getDestinationAddress();
|
||||
Target target = filterMgr->getTarget();
|
||||
int color, k, a;
|
||||
GetPixelsDelegateGrayscale delegate(m_channel);
|
||||
int x = filterMgr->getX();
|
||||
int x2 = x+filterMgr->getWidth();
|
||||
int y = filterMgr->getY();
|
||||
|
||||
for (; x<x2; ++x) {
|
||||
// Avoid the non-selected region
|
||||
if (filterMgr->skipPixel()) {
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<GrayscaleTraits>(src, x, y, m_width, m_height, m_width/2, m_height/2,
|
||||
m_tiledMode, delegate);
|
||||
|
||||
color = image_getpixel_fast<GrayscaleTraits>(src, x, y);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
*(dst_address++) = _graya(k, a);
|
||||
}
|
||||
}
|
||||
|
||||
void MedianFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
{
|
||||
const Image* src = filterMgr->getSourceImage();
|
||||
ase_uint8* dst_address = (ase_uint8*)filterMgr->getDestinationAddress();
|
||||
const Palette* pal = filterMgr->getIndexedData()->getPalette();
|
||||
const RgbMap* rgbmap = filterMgr->getIndexedData()->getRgbMap();
|
||||
Target target = filterMgr->getTarget();
|
||||
int color, r, g, b;
|
||||
GetPixelsDelegateIndexed delegate(pal, m_channel, target);
|
||||
int x = filterMgr->getX();
|
||||
int x2 = x+filterMgr->getWidth();
|
||||
int y = filterMgr->getY();
|
||||
|
||||
for (; x<x2; ++x) {
|
||||
// Avoid the non-selected region
|
||||
if (filterMgr->skipPixel()) {
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<IndexedTraits>(src, x, y, m_width, m_height, m_width/2, m_height/2,
|
||||
m_tiledMode, delegate);
|
||||
|
||||
if (target & TARGET_INDEX_CHANNEL) {
|
||||
std::sort(m_channel[0].begin(), m_channel[0].end());
|
||||
*(dst_address++) = m_channel[0][m_ncolors/2];
|
||||
}
|
||||
else {
|
||||
color = image_getpixel_fast<IndexedTraits>(src, x, y);
|
||||
|
||||
if (target & TARGET_RED_CHANNEL) {
|
||||
std::sort(m_channel[0].begin(), m_channel[0].end());
|
||||
r = m_channel[0][m_ncolors/2];
|
||||
}
|
||||
else
|
||||
r = _rgba_getr(pal->getEntry(color));
|
||||
|
||||
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));
|
||||
|
||||
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));
|
||||
|
||||
*(dst_address++) = rgbmap->mapColor(r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
53
src/filters/median_filter.h
Normal file
53
src/filters/median_filter.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 FILTERS_MEDIAN_FILTER_PROCESS_H_INCLUDED
|
||||
#define FILTERS_MEDIAN_FILTER_PROCESS_H_INCLUDED
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "filters/filter.h"
|
||||
#include "filters/tiled_mode.h"
|
||||
|
||||
class MedianFilter : public Filter
|
||||
{
|
||||
public:
|
||||
MedianFilter();
|
||||
|
||||
void setTiledMode(TiledMode tiled);
|
||||
void setSize(int width, int height);
|
||||
|
||||
TiledMode getTiledMode() const { return m_tiledMode; }
|
||||
int getWidth() const { return m_width; }
|
||||
int getHeight() const { return m_height; }
|
||||
|
||||
// Filter implementation
|
||||
const char* getName();
|
||||
void applyToRgba(FilterManager* filterMgr);
|
||||
void applyToGrayscale(FilterManager* filterMgr);
|
||||
void applyToIndexed(FilterManager* filterMgr);
|
||||
|
||||
private:
|
||||
TiledMode m_tiledMode;
|
||||
int m_width;
|
||||
int m_height;
|
||||
int m_ncolors;
|
||||
std::vector<std::vector<ase_uint8> > m_channel;
|
||||
};
|
||||
|
||||
#endif
|
110
src/filters/neighboring_pixels.h
Normal file
110
src/filters/neighboring_pixels.h
Normal file
@ -0,0 +1,110 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 FILTERS_NEIGHBORING_PIXELS_H_INCLUDED
|
||||
#define FILTERS_NEIGHBORING_PIXELS_H_INCLUDED
|
||||
|
||||
#include "filters/tiled_mode.h"
|
||||
#include "raster/image.h"
|
||||
#include "raster/image_traits.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
// Calls the specified "delegate" for all neighboring pixels in a 2D
|
||||
// (width*height) matrix located in (x,y) where its center is the
|
||||
// (centerX,centerY) element of the matrix.
|
||||
template<typename Traits, typename Delegate>
|
||||
inline void get_neighboring_pixels(const Image* sourceImage, int x, int y,
|
||||
int width, int height,
|
||||
int centerX, int centerY,
|
||||
TiledMode tiledMode,
|
||||
typename Delegate& delegate)
|
||||
{
|
||||
int dx, dy;
|
||||
|
||||
// Y position to get pixel.
|
||||
int getx, gety = y - centerY;
|
||||
int addx, addy = 0;
|
||||
if (gety < 0) {
|
||||
if (tiledMode & TILED_Y_AXIS)
|
||||
gety = sourceImage->h - (-(gety+1) % sourceImage->h) - 1;
|
||||
else {
|
||||
addy = -gety;
|
||||
gety = 0;
|
||||
}
|
||||
}
|
||||
else if (gety >= sourceImage->h) {
|
||||
if (tiledMode & TILED_Y_AXIS)
|
||||
gety = gety % sourceImage->h;
|
||||
else
|
||||
gety = sourceImage->h-1;
|
||||
}
|
||||
|
||||
for (dy=0; dy<height; ++dy) {
|
||||
// X position to get pixel.
|
||||
getx = x - centerX;
|
||||
addx = 0;
|
||||
if (getx < 0) {
|
||||
if (tiledMode & TILED_X_AXIS)
|
||||
getx = sourceImage->w - (-(getx+1) % sourceImage->w) - 1;
|
||||
else {
|
||||
addx = -getx;
|
||||
getx = 0;
|
||||
}
|
||||
}
|
||||
else if (getx >= sourceImage->w) {
|
||||
if (tiledMode & TILED_X_AXIS)
|
||||
getx = getx % sourceImage->w;
|
||||
else
|
||||
getx = sourceImage->w-1;
|
||||
}
|
||||
|
||||
typename Traits::const_address_t srcAddress =
|
||||
image_address_fast<Traits>(sourceImage, getx, gety);
|
||||
|
||||
for (dx=0; dx<width; dx++) {
|
||||
// Call the delegate for each pixel value.
|
||||
delegate(*srcAddress);
|
||||
|
||||
// Update X position to get pixel.
|
||||
if (getx < sourceImage->w-1) {
|
||||
++getx;
|
||||
if (addx == 0)
|
||||
++srcAddress;
|
||||
else
|
||||
--addx;
|
||||
}
|
||||
else if (tiledMode & TILED_X_AXIS) {
|
||||
getx = 0;
|
||||
srcAddress = image_address_fast<Traits>(sourceImage, getx, gety);
|
||||
}
|
||||
}
|
||||
|
||||
// Update Y position to get pixel
|
||||
if (gety < sourceImage->h-1) {
|
||||
if (addy == 0)
|
||||
++gety;
|
||||
else
|
||||
--addy;
|
||||
}
|
||||
else if (tiledMode & TILED_Y_AXIS)
|
||||
gety = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
142
src/filters/replace_color_filter.cpp
Normal file
142
src/filters/replace_color_filter.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "filters/replace_color_filter.h"
|
||||
|
||||
#include "filters/filter_manager.h"
|
||||
#include "raster/image.h"
|
||||
|
||||
ReplaceColorFilter::ReplaceColorFilter()
|
||||
{
|
||||
m_from = m_to = m_tolerance = 0;
|
||||
}
|
||||
|
||||
void ReplaceColorFilter::setFrom(int from)
|
||||
{
|
||||
m_from = from;
|
||||
}
|
||||
|
||||
void ReplaceColorFilter::setTo(int to)
|
||||
{
|
||||
m_to = to;
|
||||
}
|
||||
|
||||
void ReplaceColorFilter::setTolerance(int tolerance)
|
||||
{
|
||||
m_tolerance = MID(0, tolerance, 255);
|
||||
}
|
||||
|
||||
const char* ReplaceColorFilter::getName()
|
||||
{
|
||||
return "Replace Color";
|
||||
}
|
||||
|
||||
void ReplaceColorFilter::applyToRgba(FilterManager* filterMgr)
|
||||
{
|
||||
const ase_uint32* src_address = (ase_uint32*)filterMgr->getSourceAddress();
|
||||
ase_uint32* dst_address = (ase_uint32*)filterMgr->getDestinationAddress();
|
||||
int w = filterMgr->getWidth();
|
||||
int src_r, src_g, src_b, src_a;
|
||||
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);
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
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) &&
|
||||
(ABS(src_b-dst_b) <= m_tolerance) &&
|
||||
(ABS(src_a-dst_a) <= m_tolerance))
|
||||
*(dst_address++) = m_to;
|
||||
else
|
||||
*(dst_address++) = c;
|
||||
}
|
||||
}
|
||||
|
||||
void ReplaceColorFilter::applyToGrayscale(FilterManager* filterMgr)
|
||||
{
|
||||
const ase_uint16* src_address = (ase_uint16*)filterMgr->getSourceAddress();
|
||||
ase_uint16* dst_address = (ase_uint16*)filterMgr->getDestinationAddress();
|
||||
int w = filterMgr->getWidth();
|
||||
int src_k, src_a;
|
||||
int dst_k, dst_a;
|
||||
int x, c;
|
||||
|
||||
dst_k = _graya_getv(m_from);
|
||||
dst_a = _graya_geta(m_from);
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
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))
|
||||
*(dst_address++) = m_to;
|
||||
else
|
||||
*(dst_address++) = c;
|
||||
}
|
||||
}
|
||||
|
||||
void ReplaceColorFilter::applyToIndexed(FilterManager* filterMgr)
|
||||
{
|
||||
const ase_uint8* src_address = (ase_uint8*)filterMgr->getSourceAddress();
|
||||
ase_uint8* dst_address = (ase_uint8*)filterMgr->getDestinationAddress();
|
||||
int w = filterMgr->getWidth();
|
||||
int x, c;
|
||||
|
||||
for (x=0; x<w; x++) {
|
||||
if (filterMgr->skipPixel()) {
|
||||
++src_address;
|
||||
++dst_address;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *(src_address++);
|
||||
|
||||
if (ABS(c-m_from) <= m_tolerance)
|
||||
*(dst_address++) = m_to;
|
||||
else
|
||||
*(dst_address++) = c;
|
||||
}
|
||||
}
|
49
src/filters/replace_color_filter.h
Normal file
49
src/filters/replace_color_filter.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 FILTERS_REPLACE_COLOR_FILTER_H_INCLUDED
|
||||
#define FILTERS_REPLACE_COLOR_FILTER_H_INCLUDED
|
||||
|
||||
#include "filters/filter.h"
|
||||
|
||||
class ReplaceColorFilter : public Filter
|
||||
{
|
||||
public:
|
||||
ReplaceColorFilter();
|
||||
|
||||
void setFrom(int from);
|
||||
void setTo(int to);
|
||||
void setTolerance(int tolerance);
|
||||
|
||||
int getFrom() const { return m_from; }
|
||||
int getTo() const { return m_to; }
|
||||
int getTolerance() const { return m_tolerance; }
|
||||
|
||||
// Filter implementation
|
||||
const char* getName();
|
||||
void applyToRgba(FilterManager* filterMgr);
|
||||
void applyToGrayscale(FilterManager* filterMgr);
|
||||
void applyToIndexed(FilterManager* filterMgr);
|
||||
|
||||
private:
|
||||
int m_from;
|
||||
int m_to;
|
||||
int m_tolerance;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,32 +1,40 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 WIDGETS_TARGET_H_INCLUDED
|
||||
#define WIDGETS_TARGET_H_INCLUDED
|
||||
|
||||
#include "gui/base.h"
|
||||
|
||||
/* TODO use some JI_SIGNAL_USER */
|
||||
#define SIGNAL_TARGET_BUTTON_CHANGE 0x10003
|
||||
|
||||
JWidget target_button_new(int imgtype, bool with_channels);
|
||||
|
||||
int target_button_get_target(JWidget widget);
|
||||
void target_button_set_target(JWidget widget, int target);
|
||||
|
||||
#endif
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 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 FILTERS_TARGET_H_INCLUDED
|
||||
#define FILTERS_TARGET_H_INCLUDED
|
||||
|
||||
#define TARGET_RED_CHANNEL 1
|
||||
#define TARGET_GREEN_CHANNEL 2
|
||||
#define TARGET_BLUE_CHANNEL 4
|
||||
#define TARGET_ALPHA_CHANNEL 8
|
||||
#define TARGET_GRAY_CHANNEL 16
|
||||
#define TARGET_INDEX_CHANNEL 32
|
||||
#define TARGET_ALL_FRAMES 64
|
||||
#define TARGET_ALL_LAYERS 128
|
||||
|
||||
#define TARGET_ALL_CHANNELS \
|
||||
(TARGET_RED_CHANNEL | \
|
||||
TARGET_GREEN_CHANNEL | \
|
||||
TARGET_BLUE_CHANNEL | \
|
||||
TARGET_ALPHA_CHANNEL | \
|
||||
TARGET_GRAY_CHANNEL )
|
||||
|
||||
typedef int Target;
|
||||
|
||||
#endif
|
@ -16,8 +16,8 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef TILED_MODE_H_INCLUDED
|
||||
#define TILED_MODE_H_INCLUDED
|
||||
#ifndef FILTERS_TILED_MODE_H_INCLUDED
|
||||
#define FILTERS_TILED_MODE_H_INCLUDED
|
||||
|
||||
enum TiledMode {
|
||||
TILED_NONE = 0,
|
@ -19,9 +19,9 @@
|
||||
#ifndef SETTINGS_SETTINGS_H_INCLUDED
|
||||
#define SETTINGS_SETTINGS_H_INCLUDED
|
||||
|
||||
#include "gfx/rect.h"
|
||||
#include "app/color.h"
|
||||
#include "tiled_mode.h"
|
||||
#include "filters/tiled_mode.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "raster/pen_type.h"
|
||||
|
||||
class IToolSettings;
|
||||
|
@ -16,7 +16,7 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "effect/effect.h"
|
||||
#include "filters/neighboring_pixels.h"
|
||||
#include "modules/palettes.h"
|
||||
#include "raster/palette.h"
|
||||
#include "raster/rgbmap.h"
|
||||
@ -158,49 +158,89 @@ static void ink_hline8_transparent(int x1, int y, int x2, IToolLoop* loop)
|
||||
// Blur Ink
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace {
|
||||
struct BlurGetPixelsDelegateRgba
|
||||
{
|
||||
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);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct BlurGetPixelsDelegateGrayscale
|
||||
{
|
||||
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);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct BlurGetPixelsDelegateIndexed
|
||||
{
|
||||
const Palette* pal;
|
||||
int count, r, g, b, a;
|
||||
|
||||
BlurGetPixelsDelegateIndexed(const Palette* pal) : pal(pal) { }
|
||||
|
||||
void reset() { count = r = g = b = a = 0; }
|
||||
|
||||
void operator()(IndexedTraits::pixel_t color)
|
||||
{
|
||||
a += (color == 0 ? 0: 255);
|
||||
|
||||
color = pal->getEntry(color);
|
||||
r += _rgba_getr(color);
|
||||
g += _rgba_getg(color);
|
||||
b += _rgba_getb(color);
|
||||
count++;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
static void ink_hline32_blur(int x1, int y, int x2, IToolLoop* loop)
|
||||
{
|
||||
int c, r, g, b, a;
|
||||
int opacity = loop->getOpacity();
|
||||
TiledMode tiled = loop->getTiledMode();
|
||||
Image* src = loop->getSrcImage();
|
||||
int getx, gety;
|
||||
int addx, addy;
|
||||
int dx, dy, color;
|
||||
ase_uint32 *src_address2;
|
||||
TiledMode tiledMode = loop->getTiledMode();
|
||||
const Image* src = loop->getSrcImage();
|
||||
BlurGetPixelsDelegateRgba delegate;
|
||||
|
||||
DEFINE_INK_PROCESSING_SRCDST
|
||||
(RgbTraits,
|
||||
{
|
||||
c = 0;
|
||||
r = g = b = a = 0;
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<RgbTraits>(src, x, y, 3, 3, 1, 1, tiledMode, delegate);
|
||||
|
||||
GET_MATRIX_DATA
|
||||
(ase_uint32, src, src_address2,
|
||||
3, 3, 1, 1, tiled,
|
||||
color = *src_address2;
|
||||
if (_rgba_geta(color) != 0) {
|
||||
r += _rgba_getr(color);
|
||||
g += _rgba_getg(color);
|
||||
b += _rgba_getb(color);
|
||||
a += _rgba_geta(color);
|
||||
++c;
|
||||
}
|
||||
);
|
||||
if (delegate.count > 0) {
|
||||
delegate.r /= delegate.count;
|
||||
delegate.g /= delegate.count;
|
||||
delegate.b /= delegate.count;
|
||||
delegate.a /= 9;
|
||||
|
||||
if (c > 0) {
|
||||
r /= c;
|
||||
g /= c;
|
||||
b /= c;
|
||||
a /= 9;
|
||||
|
||||
c = *src_address;
|
||||
r = _rgba_getr(c) + (r-_rgba_getr(c)) * opacity / 255;
|
||||
g = _rgba_getg(c) + (g-_rgba_getg(c)) * opacity / 255;
|
||||
b = _rgba_getb(c) + (b-_rgba_getb(c)) * opacity / 255;
|
||||
a = _rgba_geta(c) + (a-_rgba_geta(c)) * opacity / 255;
|
||||
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(r, g, b, a);
|
||||
*dst_address = _rgba(delegate.r, delegate.g, delegate.b, delegate.a);
|
||||
}
|
||||
else {
|
||||
*dst_address = *src_address;
|
||||
@ -210,41 +250,26 @@ static void ink_hline32_blur(int x1, int y, int x2, IToolLoop* loop)
|
||||
|
||||
static void ink_hline16_blur(int x1, int y, int x2, IToolLoop* loop)
|
||||
{
|
||||
int c, v, a;
|
||||
int opacity = loop->getOpacity();
|
||||
TiledMode tiled = loop->getTiledMode();
|
||||
Image* src = loop->getSrcImage();
|
||||
int getx, gety;
|
||||
int addx, addy;
|
||||
int dx, dy, color;
|
||||
ase_uint16 *src_address2;
|
||||
TiledMode tiledMode = loop->getTiledMode();
|
||||
const Image* src = loop->getSrcImage();
|
||||
BlurGetPixelsDelegateGrayscale delegate;
|
||||
|
||||
DEFINE_INK_PROCESSING_SRCDST
|
||||
(GrayscaleTraits,
|
||||
{
|
||||
c = 0;
|
||||
v = a = 0;
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<GrayscaleTraits>(src, x, y, 3, 3, 1, 1, tiledMode, delegate);
|
||||
|
||||
GET_MATRIX_DATA
|
||||
(ase_uint16, src, src_address2,
|
||||
3, 3, 1, 1, tiled,
|
||||
color = *src_address2;
|
||||
if (_graya_geta(color) > 0) {
|
||||
v += _graya_getv(color);
|
||||
a += _graya_geta(color);
|
||||
}
|
||||
c++;
|
||||
);
|
||||
if (delegate.count > 0) {
|
||||
delegate.v /= delegate.count;
|
||||
delegate.a /= 9;
|
||||
|
||||
if (c > 0) {
|
||||
v /= c;
|
||||
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;
|
||||
|
||||
c = *src_address;
|
||||
v = _graya_getv(c) + (v-_graya_getv(c)) * opacity / 255;
|
||||
a = _graya_geta(c) + (a-_graya_geta(c)) * opacity / 255;
|
||||
|
||||
*dst_address = _graya(v, a);
|
||||
*dst_address = _graya(delegate.v, delegate.a);
|
||||
}
|
||||
else {
|
||||
*dst_address = *src_address;
|
||||
@ -254,48 +279,30 @@ static void ink_hline16_blur(int x1, int y, int x2, IToolLoop* loop)
|
||||
|
||||
static void ink_hline8_blur(int x1, int y, int x2, IToolLoop* loop)
|
||||
{
|
||||
Palette *pal = get_current_palette();
|
||||
const Palette *pal = get_current_palette();
|
||||
RgbMap* rgbmap = loop->getSprite()->getRgbMap();
|
||||
int c, r, g, b, a;
|
||||
int opacity = loop->getOpacity();
|
||||
TiledMode tiled = loop->getTiledMode();
|
||||
Image* src = loop->getSrcImage();
|
||||
int getx, gety;
|
||||
int addx, addy;
|
||||
int dx, dy, color;
|
||||
ase_uint8 *src_address2;
|
||||
TiledMode tiledMode = loop->getTiledMode();
|
||||
const Image* src = loop->getSrcImage();
|
||||
BlurGetPixelsDelegateIndexed delegate(pal);
|
||||
|
||||
DEFINE_INK_PROCESSING_SRCDST
|
||||
(IndexedTraits,
|
||||
{
|
||||
c = 0;
|
||||
r = g = b = a = 0;
|
||||
delegate.reset();
|
||||
get_neighboring_pixels<IndexedTraits>(src, x, y, 3, 3, 1, 1, tiledMode, delegate);
|
||||
|
||||
GET_MATRIX_DATA
|
||||
(ase_uint8, src, src_address2,
|
||||
3, 3, 1, 1, tiled,
|
||||
if (delegate.count > 0 && delegate.a/9 >= 128) {
|
||||
delegate.r /= delegate.count;
|
||||
delegate.g /= delegate.count;
|
||||
delegate.b /= delegate.count;
|
||||
|
||||
color = *src_address2;
|
||||
a += (color == 0 ? 0: 255);
|
||||
IndexedTraits::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;
|
||||
|
||||
color = pal->getEntry(color);
|
||||
r += _rgba_getr(color);
|
||||
g += _rgba_getg(color);
|
||||
b += _rgba_getb(color);
|
||||
c++;
|
||||
);
|
||||
|
||||
if (c > 0 && a/9 >= 128) {
|
||||
r /= c;
|
||||
g /= c;
|
||||
b /= c;
|
||||
|
||||
c = pal->getEntry(*src_address);
|
||||
r = _rgba_getr(c) + (r-_rgba_getr(c)) * opacity / 255;
|
||||
g = _rgba_getg(c) + (g-_rgba_getg(c)) * opacity / 255;
|
||||
b = _rgba_getb(c) + (b-_rgba_getb(c)) * opacity / 255;
|
||||
|
||||
*dst_address = rgbmap->mapColor(r, g, b);
|
||||
*dst_address = rgbmap->mapColor(delegate.r, delegate.g, delegate.b);
|
||||
}
|
||||
else {
|
||||
*dst_address = *src_address;
|
||||
@ -336,7 +343,7 @@ static void ink_hline16_replace(int x1, int y, int x2, IToolLoop* loop)
|
||||
static void ink_hline8_replace(int x1, int y, int x2, IToolLoop* loop)
|
||||
{
|
||||
int color1 = loop->getPrimaryColor();
|
||||
Palette *pal = get_current_palette();
|
||||
const Palette *pal = get_current_palette();
|
||||
RgbMap* rgbmap = loop->getSprite()->getRgbMap();
|
||||
ase_uint32 c;
|
||||
ase_uint32 tc = pal->getEntry(loop->getSecondaryColor());
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "raster/undo.h"
|
||||
|
||||
#include "tools/ink_processing.h"
|
||||
#include "context.h"
|
||||
|
||||
|
||||
// Ink used for tools which paint with primary/secondary
|
||||
@ -51,8 +52,8 @@ public:
|
||||
case WithBg:
|
||||
{
|
||||
int color = color_utils::color_for_layer(m_type == WithFg ?
|
||||
loop->getContext()->getSettings()->getFgColor():
|
||||
loop->getContext()->getSettings()->getBgColor(),
|
||||
loop->getContext()->getSettings()->getFgColor():
|
||||
loop->getContext()->getSettings()->getBgColor(),
|
||||
loop->getLayer());
|
||||
loop->setPrimaryColor(color);
|
||||
loop->setSecondaryColor(color);
|
||||
|
@ -19,17 +19,16 @@
|
||||
#ifndef TOOLS_TOOL_H_INCLUDED
|
||||
#define TOOLS_TOOL_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "filters/tiled_mode.h"
|
||||
#include "gfx/point.h"
|
||||
#include "gfx/rect.h"
|
||||
#include "gui/message.h"
|
||||
#include "gui/rect.h"
|
||||
|
||||
#include "tiled_mode.h"
|
||||
|
||||
class Context;
|
||||
class Sprite;
|
||||
class Image;
|
||||
|
@ -1,482 +0,0 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <allegro.h>
|
||||
#include <cmath>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
|
||||
#include "effect/colcurve.h"
|
||||
#include "gui/alert.h"
|
||||
#include "gui/entry.h"
|
||||
#include "gui/frame.h"
|
||||
#include "gui/list.h"
|
||||
#include "gui/manager.h"
|
||||
#include "gui/message.h"
|
||||
#include "gui/rect.h"
|
||||
#include "gui/system.h"
|
||||
#include "gui/view.h"
|
||||
#include "gui/widget.h"
|
||||
#include "modules/gui.h"
|
||||
#include "widgets/curvedit.h"
|
||||
|
||||
#define SCR2EDIT_X(xpos) \
|
||||
(curve_editor->x1 + \
|
||||
((curve_editor->x2 - curve_editor->x1 + 1) \
|
||||
* ((xpos) - widget->rc->x1 - widget->border_width.l) \
|
||||
/ (jrect_w(widget->rc) - widget->border_width.l - widget->border_width.r)))
|
||||
|
||||
#define SCR2EDIT_Y(ypos) \
|
||||
(curve_editor->y1 + \
|
||||
((curve_editor->y2 - curve_editor->y1 + 1) \
|
||||
* ((jrect_h(widget->rc) - widget->border_width.t - widget->border_width.b) \
|
||||
- ((ypos) - widget->rc->y1 - widget->border_width.t)) \
|
||||
/ (jrect_h(widget->rc) - widget->border_width.t - widget->border_width.b)))
|
||||
|
||||
#define EDIT2SCR_X(xpos) \
|
||||
(widget->rc->x1 + widget->border_width.l \
|
||||
+ ((jrect_w(widget->rc) - widget->border_width.l - widget->border_width.r) \
|
||||
* ((xpos) - curve_editor->x1) \
|
||||
/ (curve_editor->x2 - curve_editor->x1 + 1)))
|
||||
|
||||
#define EDIT2SCR_Y(ypos) \
|
||||
(widget->rc->y1 \
|
||||
+ (jrect_h(widget->rc) - widget->border_width.t - widget->border_width.b) \
|
||||
- ((jrect_h(widget->rc) - widget->border_width.t - widget->border_width.b) \
|
||||
* ((ypos) - curve_editor->y1) \
|
||||
/ (curve_editor->y2 - curve_editor->y1 + 1)))
|
||||
|
||||
enum {
|
||||
STATUS_STANDBY,
|
||||
STATUS_MOVING_POINT,
|
||||
STATUS_SCROLLING,
|
||||
STATUS_SCALING,
|
||||
};
|
||||
|
||||
struct CurveEditor
|
||||
{
|
||||
Curve *curve;
|
||||
int x1, y1;
|
||||
int x2, y2;
|
||||
int status;
|
||||
CurvePoint* edit_point;
|
||||
int *edit_x;
|
||||
int *edit_y;
|
||||
};
|
||||
|
||||
static CurveEditor* curve_editor_data(JWidget widget);
|
||||
static bool curve_editor_msg_proc(JWidget widget, JMessage msg);
|
||||
|
||||
static CurvePoint* curve_editor_get_more_close_point(JWidget widget, int x, int y, int **edit_x, int **edit_y);
|
||||
|
||||
static int edit_node_manual(CurvePoint* point);
|
||||
|
||||
JWidget curve_editor_new(Curve *curve, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
JWidget widget = new Widget(curve_editor_type());
|
||||
CurveEditor* curve_editor = new CurveEditor;
|
||||
|
||||
jwidget_add_hook(widget, curve_editor_type(),
|
||||
curve_editor_msg_proc, curve_editor);
|
||||
jwidget_focusrest(widget, true);
|
||||
|
||||
widget->border_width.l = widget->border_width.r = 1;
|
||||
widget->border_width.t = widget->border_width.b = 1;
|
||||
widget->child_spacing = 0;
|
||||
|
||||
curve_editor->curve = curve;
|
||||
curve_editor->x1 = x1;
|
||||
curve_editor->y1 = y1;
|
||||
curve_editor->x2 = x2;
|
||||
curve_editor->y2 = y2;
|
||||
curve_editor->status = STATUS_STANDBY;
|
||||
curve_editor->edit_point = NULL;
|
||||
|
||||
/* TODO */
|
||||
/* curve_editor->curve->type = CURVE_SPLINE; */
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
int curve_editor_type()
|
||||
{
|
||||
static int type = 0;
|
||||
if (!type)
|
||||
type = ji_register_widget_type();
|
||||
return type;
|
||||
}
|
||||
|
||||
Curve *curve_editor_get_curve(JWidget widget)
|
||||
{
|
||||
CurveEditor* curve_editor = curve_editor_data(widget);
|
||||
|
||||
return curve_editor->curve;
|
||||
}
|
||||
|
||||
static CurveEditor* curve_editor_data(JWidget widget)
|
||||
{
|
||||
return reinterpret_cast<CurveEditor*>
|
||||
(jwidget_get_data(widget, curve_editor_type()));
|
||||
}
|
||||
|
||||
static bool curve_editor_msg_proc(JWidget widget, JMessage msg)
|
||||
{
|
||||
CurveEditor* curve_editor = curve_editor_data(widget);
|
||||
|
||||
switch (msg->type) {
|
||||
|
||||
case JM_DESTROY:
|
||||
delete curve_editor;
|
||||
break;
|
||||
|
||||
case JM_REQSIZE: {
|
||||
#if 0
|
||||
msg->reqsize.w =
|
||||
+ widget->border_width.l
|
||||
+ ((curve_editor->x2 - curve_editor->x1 + 1))
|
||||
+ widget->border_width.r;
|
||||
|
||||
msg->reqsize.h =
|
||||
+ widget->border_width.t
|
||||
+ ((curve_editor->y2 - curve_editor->y1 + 1))
|
||||
+ widget->border_width.b;
|
||||
#else
|
||||
msg->reqsize.w = widget->border_width.l + 1 + widget->border_width.r;
|
||||
msg->reqsize.h = widget->border_width.t + 1 + widget->border_width.b;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
case JM_KEYPRESSED: {
|
||||
switch (msg->key.scancode) {
|
||||
|
||||
case KEY_INSERT: {
|
||||
int x = SCR2EDIT_X(jmouse_x(0));
|
||||
int y = SCR2EDIT_Y(jmouse_y(0));
|
||||
CurvePoint* point = curve_point_new(x, y);
|
||||
|
||||
/* TODO undo? */
|
||||
curve_add_point(curve_editor->curve, point);
|
||||
|
||||
widget->invalidate();
|
||||
jwidget_emit_signal(widget, SIGNAL_CURVE_EDITOR_CHANGE);
|
||||
break;
|
||||
}
|
||||
|
||||
case KEY_DEL: {
|
||||
CurvePoint* point = curve_editor_get_more_close_point
|
||||
(widget,
|
||||
SCR2EDIT_X(jmouse_x(0)),
|
||||
SCR2EDIT_Y(jmouse_y(0)),
|
||||
NULL, NULL);
|
||||
|
||||
/* TODO undo? */
|
||||
curve_remove_point(curve_editor->curve, point);
|
||||
|
||||
widget->invalidate();
|
||||
jwidget_emit_signal(widget, SIGNAL_CURVE_EDITOR_CHANGE);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case JM_DRAW: {
|
||||
BITMAP *bmp;
|
||||
JLink link;
|
||||
CurvePoint* point;
|
||||
int x, y, u;
|
||||
|
||||
bmp = create_bitmap(jrect_w(widget->rc), jrect_h(widget->rc));
|
||||
clear_to_color(bmp, makecol (0, 0, 0));
|
||||
|
||||
/* draw border */
|
||||
rect(bmp, 0, 0, bmp->w-1, bmp->h-1, makecol (255, 255, 0));
|
||||
|
||||
/* draw guides */
|
||||
for (x=1; x<=3; x++)
|
||||
vline(bmp, x*bmp->w/4, 1, bmp->h-2, makecol (128, 128, 0));
|
||||
|
||||
for (y=1; y<=3; y++)
|
||||
hline(bmp, 1, y*bmp->h/4, bmp->w-2, makecol (128, 128, 0));
|
||||
|
||||
/* get curve values */
|
||||
std::vector<int> values(curve_editor->x2-curve_editor->x1+1);
|
||||
curve_get_values(curve_editor->curve,
|
||||
curve_editor->x1,
|
||||
curve_editor->x2, &values[0]);
|
||||
|
||||
/* draw curve */
|
||||
for (x=widget->border_width.l;
|
||||
x<jrect_w(widget->rc)-widget->border_width.r; x++) {
|
||||
u = SCR2EDIT_X(widget->rc->x1+x);
|
||||
u = MID(curve_editor->x1, u, curve_editor->x2);
|
||||
|
||||
y = values[u - curve_editor->x1];
|
||||
y = MID(curve_editor->y1, y, curve_editor->y2);
|
||||
|
||||
putpixel(bmp, x, EDIT2SCR_Y(y)-widget->rc->y1,
|
||||
makecol(255, 255, 255));
|
||||
}
|
||||
|
||||
/* draw nodes */
|
||||
JI_LIST_FOR_EACH(curve_editor->curve->points, link) {
|
||||
point = reinterpret_cast<CurvePoint*>(link->data);
|
||||
|
||||
x = EDIT2SCR_X(point->x) - widget->rc->x1;
|
||||
y = EDIT2SCR_Y(point->y) - widget->rc->y1;
|
||||
|
||||
rect(bmp, x-2, y-2, x+2, y+2,
|
||||
curve_editor->edit_point == point ?
|
||||
makecol(255, 255, 0): makecol(0, 0, 255));
|
||||
}
|
||||
|
||||
/* blit to screen */
|
||||
blit(bmp, ji_screen,
|
||||
0, 0, widget->rc->x1, widget->rc->y1, bmp->w, bmp->h);
|
||||
destroy_bitmap(bmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
case JM_BUTTONPRESSED:
|
||||
/* change scroll */
|
||||
if (msg->any.shifts & KB_SHIFT_FLAG) {
|
||||
curve_editor->status = STATUS_SCROLLING;
|
||||
jmouse_set_cursor(JI_CURSOR_SCROLL);
|
||||
}
|
||||
/* scaling */
|
||||
/* else if (msg->shifts & KB_CTRL_FLAG) { */
|
||||
/* curve_editor->status = STATUS_SCALING; */
|
||||
/* jmouse_set_cursor(JI_CURSOR_SCROLL); */
|
||||
/* } */
|
||||
/* show manual-entry dialog */
|
||||
else if (msg->mouse.right) {
|
||||
curve_editor->edit_point =
|
||||
curve_editor_get_more_close_point(widget,
|
||||
SCR2EDIT_X(msg->mouse.x),
|
||||
SCR2EDIT_Y(msg->mouse.y),
|
||||
NULL, NULL);
|
||||
if (curve_editor->edit_point) {
|
||||
widget->invalidate();
|
||||
jwidget_flush_redraw(widget);
|
||||
|
||||
if (edit_node_manual(curve_editor->edit_point))
|
||||
jwidget_emit_signal(widget, SIGNAL_CURVE_EDITOR_CHANGE);
|
||||
|
||||
curve_editor->edit_point = NULL;
|
||||
widget->invalidate();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/* edit node */
|
||||
else {
|
||||
curve_editor->edit_point =
|
||||
curve_editor_get_more_close_point(widget,
|
||||
SCR2EDIT_X(msg->mouse.x),
|
||||
SCR2EDIT_Y(msg->mouse.y),
|
||||
&curve_editor->edit_x,
|
||||
&curve_editor->edit_y);
|
||||
|
||||
curve_editor->status = STATUS_MOVING_POINT;
|
||||
jmouse_set_cursor(JI_CURSOR_HAND);
|
||||
}
|
||||
|
||||
widget->captureMouse();
|
||||
/* continue in motion message... */
|
||||
|
||||
case JM_MOTION:
|
||||
if (widget->hasCapture()) {
|
||||
switch (curve_editor->status) {
|
||||
|
||||
case STATUS_SCROLLING: {
|
||||
View* view = View::getView(widget);
|
||||
gfx::Rect vp = view->getViewportBounds();
|
||||
gfx::Point scroll = view->getViewScroll();
|
||||
|
||||
scroll.x += jmouse_x(1)-jmouse_x(0);
|
||||
scroll.y += jmouse_y(1)-jmouse_y(0);
|
||||
|
||||
view->setViewScroll(scroll);
|
||||
|
||||
jmouse_control_infinite_scroll(vp);
|
||||
break;
|
||||
}
|
||||
|
||||
case STATUS_MOVING_POINT:
|
||||
if (curve_editor->edit_point) {
|
||||
/* int old_x = *curve_editor->edit_x; */
|
||||
/* int old_y = *curve_editor->edit_y; */
|
||||
/* int offset_x, offset_y; */
|
||||
|
||||
*curve_editor->edit_x = SCR2EDIT_X(msg->mouse.x);
|
||||
*curve_editor->edit_y = SCR2EDIT_Y(msg->mouse.y);
|
||||
|
||||
*curve_editor->edit_x = MID(curve_editor->x1,
|
||||
*curve_editor->edit_x,
|
||||
curve_editor->x2);
|
||||
|
||||
*curve_editor->edit_y = MID(curve_editor->y1,
|
||||
*curve_editor->edit_y,
|
||||
curve_editor->y2);
|
||||
|
||||
/* if (curve_editor->edit_x == &curve_editor->edit_key->x && */
|
||||
/* curve_editor->edit_y == &curve_editor->edit_key->y) { */
|
||||
/* offset_x = (*curve_editor->edit_x) - old_x; */
|
||||
/* offset_y = (*curve_editor->edit_y) - old_y; */
|
||||
|
||||
/* curve_editor->edit_key->px += offset_x; */
|
||||
/* curve_editor->edit_key->py += offset_y; */
|
||||
/* curve_editor->edit_key->nx += offset_x; */
|
||||
/* curve_editor->edit_key->ny += offset_y; */
|
||||
/* } */
|
||||
|
||||
/* TODO this should be optional */
|
||||
jwidget_emit_signal(widget, SIGNAL_CURVE_EDITOR_CHANGE);
|
||||
|
||||
widget->invalidate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#if 0 /* TODO */
|
||||
/* if the mouse move above a curve_editor, the focus change to
|
||||
this widget immediately */
|
||||
else if (!jwidget_has_focus(widget)) {
|
||||
jmanager_set_focus(widget);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case JM_BUTTONRELEASED:
|
||||
if (widget->hasCapture()) {
|
||||
widget->releaseMouse();
|
||||
|
||||
switch (curve_editor->status) {
|
||||
|
||||
case STATUS_SCROLLING:
|
||||
jmouse_set_cursor(JI_CURSOR_NORMAL);
|
||||
break;
|
||||
|
||||
/* case STATUS_SCALING: */
|
||||
/* jmouse_set_cursor(JI_CURSOR_NORMAL); */
|
||||
/* break; */
|
||||
|
||||
case STATUS_MOVING_POINT:
|
||||
jmouse_set_cursor(JI_CURSOR_NORMAL);
|
||||
jwidget_emit_signal(widget, SIGNAL_CURVE_EDITOR_CHANGE);
|
||||
|
||||
curve_editor->edit_point = NULL;
|
||||
widget->invalidate();
|
||||
break;
|
||||
}
|
||||
|
||||
curve_editor->status = STATUS_STANDBY;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static CurvePoint* curve_editor_get_more_close_point(JWidget widget,
|
||||
int x, int y,
|
||||
int **edit_x,
|
||||
int **edit_y)
|
||||
{
|
||||
#define CALCDIST(xx, yy) \
|
||||
dx = point->xx-x; \
|
||||
dy = point->yy-y; \
|
||||
dist = std::sqrt(static_cast<double>(dx*dx + dy*dy)); \
|
||||
\
|
||||
if (!point_found || dist <= dist_min) { \
|
||||
point_found = point; \
|
||||
dist_min = dist; \
|
||||
\
|
||||
if (edit_x) *edit_x = &point->xx; \
|
||||
if (edit_y) *edit_y = &point->yy; \
|
||||
}
|
||||
|
||||
CurveEditor* curve_editor = curve_editor_data(widget);
|
||||
CurvePoint* point;
|
||||
CurvePoint* point_found = NULL;
|
||||
JLink link;
|
||||
int dx, dy;
|
||||
double dist, dist_min = 0;
|
||||
|
||||
JI_LIST_FOR_EACH(curve_editor->curve->points, link) {
|
||||
point = reinterpret_cast<CurvePoint*>(link->data);
|
||||
CALCDIST(x, y);
|
||||
}
|
||||
|
||||
/* if (curve_editor->curve->union_type == PROP_SPLINE && edit_x && edit_y) { */
|
||||
/* for (it=curve_editor->curve->keys; it; it=it->next) { */
|
||||
/* key = it->data; */
|
||||
|
||||
/* if (it->prev) { */
|
||||
/* CALCDIST(px, py); */
|
||||
/* } */
|
||||
|
||||
/* if (it->next) { */
|
||||
/* CALCDIST(nx, ny); */
|
||||
/* } */
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
return point_found;
|
||||
}
|
||||
|
||||
static int edit_node_manual(CurvePoint* point)
|
||||
{
|
||||
JWidget entry_x, entry_y, button_ok;
|
||||
CurvePoint point_copy = *point;
|
||||
int res;
|
||||
|
||||
FramePtr window(load_widget("color_curve.xml", "point_properties"));
|
||||
|
||||
entry_x = jwidget_find_name(window, "x");
|
||||
entry_y = jwidget_find_name(window, "y");
|
||||
button_ok = jwidget_find_name(window, "button_ok");
|
||||
|
||||
entry_x->setTextf("%d", point->x);
|
||||
entry_y->setTextf("%d", point->y);
|
||||
|
||||
window->open_window_fg();
|
||||
|
||||
if (window->get_killer() == button_ok) {
|
||||
point->x = entry_x->getTextDouble();
|
||||
point->y = entry_y->getTextDouble();
|
||||
res = true;
|
||||
}
|
||||
else {
|
||||
point->x = point_copy.x;
|
||||
point->y = point_copy.y;
|
||||
res = false;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "effect/effect.h"
|
||||
#include "gui/manager.h"
|
||||
#include "gui/message.h"
|
||||
#include "gui/widget.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "util/render.h"
|
||||
#include "widgets/preview.h"
|
||||
|
||||
typedef struct Preview
|
||||
{
|
||||
Effect *effect;
|
||||
int timer_id;
|
||||
} Preview;
|
||||
|
||||
static bool preview_msg_proc(JWidget widget, JMessage msg);
|
||||
|
||||
/**
|
||||
* Invisible widget to control a effect-preview.
|
||||
*/
|
||||
JWidget preview_new(Effect* effect)
|
||||
{
|
||||
Widget* widget = new Widget(preview_type());
|
||||
Preview* preview = new Preview;
|
||||
|
||||
preview->effect = effect;
|
||||
preview->timer_id = -1;
|
||||
|
||||
jwidget_add_hook(widget, preview_type(), preview_msg_proc, preview);
|
||||
widget->setVisible(false);
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
int preview_type()
|
||||
{
|
||||
static int type = 0;
|
||||
if (!type)
|
||||
type = ji_register_widget_type();
|
||||
return type;
|
||||
}
|
||||
|
||||
void preview_restart(JWidget widget)
|
||||
{
|
||||
ASSERT_VALID_WIDGET(widget);
|
||||
|
||||
Preview* preview = reinterpret_cast<Preview*>(jwidget_get_data(widget, preview_type()));
|
||||
|
||||
effect_begin_for_preview(preview->effect);
|
||||
|
||||
if (preview->timer_id < 0)
|
||||
preview->timer_id = jmanager_add_timer(widget, 1);
|
||||
jmanager_start_timer(preview->timer_id);
|
||||
}
|
||||
|
||||
Effect *preview_get_effect(JWidget widget)
|
||||
{
|
||||
ASSERT_VALID_WIDGET(widget);
|
||||
|
||||
Preview* preview = reinterpret_cast<Preview*>(jwidget_get_data(widget, preview_type()));
|
||||
return preview->effect;
|
||||
}
|
||||
|
||||
static bool preview_msg_proc(JWidget widget, JMessage msg)
|
||||
{
|
||||
Preview* preview = reinterpret_cast<Preview*>(jwidget_get_data(widget, preview_type()));
|
||||
Effect* effect = preview_get_effect(widget);
|
||||
|
||||
switch (msg->type) {
|
||||
|
||||
case JM_DESTROY:
|
||||
if (preview->timer_id >= 0)
|
||||
jmanager_remove_timer(preview->timer_id);
|
||||
delete preview;
|
||||
break;
|
||||
|
||||
case JM_OPEN:
|
||||
RenderEngine::setPreviewImage(effect->sprite->getCurrentLayer(), effect->dst);
|
||||
break;
|
||||
|
||||
case JM_CLOSE:
|
||||
RenderEngine::setPreviewImage(NULL, NULL);
|
||||
/* stop the preview timer */
|
||||
jmanager_stop_timer(preview->timer_id);
|
||||
break;
|
||||
|
||||
case JM_TIMER:
|
||||
if (effect) {
|
||||
if (effect_apply_step(effect))
|
||||
effect_flush(effect);
|
||||
else
|
||||
jmanager_stop_timer(preview->timer_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -1,242 +0,0 @@
|
||||
/* ASE - Allegro Sprite Editor
|
||||
* Copyright (C) 2001-2011 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <allegro.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "core/cfg.h"
|
||||
#include "effect/effect.h"
|
||||
#include "gui/box.h"
|
||||
#include "gui/button.h"
|
||||
#include "gui/hook.h"
|
||||
#include "gui/theme.h"
|
||||
#include "gui/widget.h"
|
||||
#include "modules/gfx.h"
|
||||
#include "modules/gui.h"
|
||||
#include "raster/image.h"
|
||||
#include "skin/skin_parts.h"
|
||||
#include "widgets/target.h"
|
||||
|
||||
static bool channel_change_hook(ButtonBase* widget, Widget* data);
|
||||
static bool images_change_hook(ButtonBase* widget, Widget* data);
|
||||
static int get_target_normal_icon(int target);
|
||||
static int get_target_selected_icon(int target);
|
||||
|
||||
/**
|
||||
* Creates a new button to handle "targets" to apply some effect in
|
||||
* the sprite
|
||||
*
|
||||
* user_data[0] = target flags (TARGET_RED_CHANNEL, etc.)
|
||||
*/
|
||||
JWidget target_button_new(int imgtype, bool with_channels)
|
||||
{
|
||||
#define ADD(box, widget, hook) \
|
||||
if (widget) { \
|
||||
jwidget_set_border(widget, 2 * jguiscale()); \
|
||||
jwidget_add_child(box, widget); \
|
||||
widget->Click.connect(Bind<bool>(&hook, widget, vbox)); \
|
||||
}
|
||||
|
||||
int default_targets = 0;
|
||||
Box* vbox, *hbox;
|
||||
CheckBox* r = NULL;
|
||||
CheckBox* g = NULL;
|
||||
CheckBox* b = NULL;
|
||||
CheckBox* k = NULL;
|
||||
CheckBox* a = NULL;
|
||||
CheckBox* index = NULL;
|
||||
Button* images = NULL;
|
||||
|
||||
vbox = new Box(JI_VERTICAL);
|
||||
hbox = new Box(JI_HORIZONTAL | JI_HOMOGENEOUS);
|
||||
|
||||
jwidget_noborders(vbox);
|
||||
jwidget_noborders(hbox);
|
||||
|
||||
if (with_channels) {
|
||||
switch (imgtype) {
|
||||
|
||||
case IMAGE_RGB:
|
||||
case IMAGE_INDEXED:
|
||||
r = check_button_new("R", 2, 0, 0, 0);
|
||||
g = check_button_new("G", 0, 0, 0, 0);
|
||||
b = check_button_new("B", 0, (imgtype == IMAGE_RGB) ? 0: 2, 0, 0);
|
||||
|
||||
r->setName("r");
|
||||
g->setName("g");
|
||||
b->setName("b");
|
||||
|
||||
if (imgtype == IMAGE_RGB) {
|
||||
a = check_button_new("A", 0, 2, 0, 0);
|
||||
a->setName("a");
|
||||
}
|
||||
else {
|
||||
index = check_button_new("Index", 0, 0, 0, 0);
|
||||
index->setName("i");
|
||||
}
|
||||
break;
|
||||
|
||||
case IMAGE_GRAYSCALE:
|
||||
k = check_button_new("K", 2, 0, 0, 0);
|
||||
a = check_button_new("A", 0, 2, 0, 0);
|
||||
|
||||
k->setName("k");
|
||||
a->setName("a");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* create the button to select "image" target */
|
||||
images = new Button(NULL);
|
||||
setup_bevels(images,
|
||||
with_channels ? 0: 2,
|
||||
with_channels ? 0: 2, 2, 2);
|
||||
setup_mini_look(images);
|
||||
set_gfxicon_to_button(images,
|
||||
get_target_normal_icon(default_targets),
|
||||
get_target_selected_icon(default_targets), -1,
|
||||
JI_CENTER | JI_MIDDLE);
|
||||
|
||||
/* make hierarchy */
|
||||
ADD(hbox, r, channel_change_hook);
|
||||
ADD(hbox, g, channel_change_hook);
|
||||
ADD(hbox, b, channel_change_hook);
|
||||
ADD(hbox, k, channel_change_hook);
|
||||
ADD(hbox, a, channel_change_hook);
|
||||
|
||||
if (with_channels)
|
||||
jwidget_add_child(vbox, hbox);
|
||||
else
|
||||
jwidget_free(hbox);
|
||||
|
||||
ADD(vbox, index, channel_change_hook);
|
||||
ADD(vbox, images, images_change_hook);
|
||||
|
||||
vbox->user_data[0] = (void *)default_targets;
|
||||
return vbox;
|
||||
}
|
||||
|
||||
int target_button_get_target(JWidget widget)
|
||||
{
|
||||
return (size_t)widget->user_data[0];
|
||||
}
|
||||
|
||||
void target_button_set_target(JWidget widget, int target)
|
||||
{
|
||||
JWidget w;
|
||||
|
||||
#define ACTIVATE_TARGET(name, TARGET) \
|
||||
w = jwidget_find_name(widget, name); \
|
||||
if (w != NULL) { \
|
||||
w->setSelected((target & TARGET) == TARGET); \
|
||||
}
|
||||
|
||||
ACTIVATE_TARGET("r", TARGET_RED_CHANNEL);
|
||||
ACTIVATE_TARGET("g", TARGET_GREEN_CHANNEL);
|
||||
ACTIVATE_TARGET("b", TARGET_BLUE_CHANNEL);
|
||||
ACTIVATE_TARGET("a", TARGET_ALPHA_CHANNEL);
|
||||
ACTIVATE_TARGET("k", TARGET_GRAY_CHANNEL);
|
||||
ACTIVATE_TARGET("i", TARGET_INDEX_CHANNEL);
|
||||
|
||||
widget->user_data[0] = (void *)target;
|
||||
}
|
||||
|
||||
static bool channel_change_hook(ButtonBase* widget, Widget* target_button)
|
||||
{
|
||||
int target = (size_t)target_button->user_data[0];
|
||||
int flag = 0;
|
||||
|
||||
switch (*widget->name) {
|
||||
case 'r': flag = TARGET_RED_CHANNEL; break;
|
||||
case 'g': flag = TARGET_GREEN_CHANNEL; break;
|
||||
case 'b': flag = TARGET_BLUE_CHANNEL; break;
|
||||
case 'k': flag = TARGET_GRAY_CHANNEL; break;
|
||||
case 'a': flag = TARGET_ALPHA_CHANNEL; break;
|
||||
case 'i': flag = TARGET_INDEX_CHANNEL; break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
if (widget->isSelected())
|
||||
target |= flag;
|
||||
else
|
||||
target &= ~flag;
|
||||
|
||||
target_button->user_data[0] = (void *)target;
|
||||
|
||||
jwidget_emit_signal(target_button, SIGNAL_TARGET_BUTTON_CHANGE);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool images_change_hook(ButtonBase* widget, Widget* target_button)
|
||||
{
|
||||
int target = (size_t)target_button->user_data[0];
|
||||
|
||||
/* rotate target */
|
||||
if (target & TARGET_ALL_FRAMES) {
|
||||
target &= ~TARGET_ALL_FRAMES;
|
||||
|
||||
if (target & TARGET_ALL_LAYERS)
|
||||
target &= ~TARGET_ALL_LAYERS;
|
||||
else
|
||||
target |= TARGET_ALL_LAYERS;
|
||||
}
|
||||
else {
|
||||
target |= TARGET_ALL_FRAMES;
|
||||
}
|
||||
|
||||
set_gfxicon_to_button(widget,
|
||||
get_target_normal_icon(target),
|
||||
get_target_selected_icon(target), -1,
|
||||
JI_CENTER | JI_MIDDLE);
|
||||
|
||||
target_button->user_data[0] = (void *)target;
|
||||
jwidget_emit_signal(target_button, SIGNAL_TARGET_BUTTON_CHANGE);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int get_target_normal_icon(int target)
|
||||
{
|
||||
if (target & TARGET_ALL_FRAMES) {
|
||||
return (target & TARGET_ALL_LAYERS) ?
|
||||
PART_TARGET_FRAMES_LAYERS:
|
||||
PART_TARGET_FRAMES;
|
||||
}
|
||||
else {
|
||||
return (target & TARGET_ALL_LAYERS) ?
|
||||
PART_TARGET_LAYERS:
|
||||
PART_TARGET_ONE;
|
||||
}
|
||||
}
|
||||
|
||||
static int get_target_selected_icon(int target)
|
||||
{
|
||||
if (target & TARGET_ALL_FRAMES) {
|
||||
return (target & TARGET_ALL_LAYERS) ?
|
||||
PART_TARGET_FRAMES_LAYERS_SELECTED:
|
||||
PART_TARGET_FRAMES_SELECTED;
|
||||
}
|
||||
else {
|
||||
return (target & TARGET_ALL_LAYERS) ?
|
||||
PART_TARGET_LAYERS_SELECTED:
|
||||
PART_TARGET_ONE_SELECTED;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user