diff --git a/libs/image/CMakeLists.txt b/libs/image/CMakeLists.txt index f72d83badf..c38bd98be3 100644 --- a/libs/image/CMakeLists.txt +++ b/libs/image/CMakeLists.txt @@ -1,387 +1,388 @@ add_subdirectory( tests ) add_subdirectory( tiles3 ) include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/metadata ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty ${CMAKE_CURRENT_SOURCE_DIR}/brushengine ${CMAKE_CURRENT_SOURCE_DIR}/commands ${CMAKE_CURRENT_SOURCE_DIR}/commands_new ${CMAKE_CURRENT_SOURCE_DIR}/filter ${CMAKE_CURRENT_SOURCE_DIR}/floodfill ${CMAKE_CURRENT_SOURCE_DIR}/generator ${CMAKE_CURRENT_SOURCE_DIR}/layerstyles ${CMAKE_CURRENT_SOURCE_DIR}/processing ${CMAKE_SOURCE_DIR}/sdk/tests ) include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR} ) if(FFTW3_FOUND) include_directories(${FFTW3_INCLUDE_DIR}) endif() if(HAVE_VC) include_directories(SYSTEM ${Vc_INCLUDE_DIR} ${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS}) ko_compile_for_all_implementations(__per_arch_circle_mask_generator_objs kis_brush_mask_applicator_factories.cpp) else() set(__per_arch_circle_mask_generator_objs kis_brush_mask_applicator_factories.cpp) endif() set(kritaimage_LIB_SRCS tiles3/kis_tile.cc tiles3/kis_tile_data.cc tiles3/kis_tile_data_store.cc tiles3/kis_tile_data_pooler.cc tiles3/kis_tiled_data_manager.cc tiles3/KisTiledExtentManager.cpp tiles3/kis_memento_manager.cc tiles3/kis_hline_iterator.cpp tiles3/kis_vline_iterator.cpp tiles3/kis_random_accessor.cc tiles3/swap/kis_abstract_compression.cpp tiles3/swap/kis_lzf_compression.cpp tiles3/swap/kis_abstract_tile_compressor.cpp tiles3/swap/kis_legacy_tile_compressor.cpp tiles3/swap/kis_tile_compressor_2.cpp tiles3/swap/kis_chunk_allocator.cpp tiles3/swap/kis_memory_window.cpp tiles3/swap/kis_swapped_data_store.cpp tiles3/swap/kis_tile_data_swapper.cpp kis_distance_information.cpp kis_painter.cc kis_painter_blt_multi_fixed.cpp kis_marker_painter.cpp KisPrecisePaintDeviceWrapper.cpp kis_progress_updater.cpp brushengine/kis_paint_information.cc brushengine/kis_random_source.cpp brushengine/KisPerStrokeRandomSource.cpp brushengine/kis_stroke_random_source.cpp brushengine/kis_paintop.cc brushengine/kis_paintop_factory.cpp brushengine/kis_paintop_preset.cpp brushengine/kis_paintop_registry.cc brushengine/kis_paintop_settings.cpp brushengine/kis_paintop_settings_update_proxy.cpp brushengine/kis_paintop_utils.cpp brushengine/kis_no_size_paintop_settings.cpp brushengine/kis_locked_properties.cc brushengine/kis_locked_properties_proxy.cpp brushengine/kis_locked_properties_server.cpp brushengine/kis_paintop_config_widget.cpp brushengine/kis_uniform_paintop_property.cpp brushengine/kis_combo_based_paintop_property.cpp brushengine/kis_slider_based_paintop_property.cpp brushengine/kis_standard_uniform_properties_factory.cpp brushengine/KisStrokeSpeedMeasurer.cpp brushengine/KisPaintopSettingsIds.cpp commands/kis_deselect_global_selection_command.cpp commands/kis_image_change_layers_command.cpp commands/kis_image_change_visibility_command.cpp commands/kis_image_command.cpp commands/kis_image_set_projection_color_space_command.cpp commands/kis_image_layer_add_command.cpp commands/kis_image_layer_move_command.cpp commands/kis_image_layer_remove_command.cpp commands/kis_image_layer_remove_command_impl.cpp commands/kis_image_lock_command.cpp commands/kis_node_command.cpp commands/kis_node_compositeop_command.cpp commands/kis_node_opacity_command.cpp commands/kis_node_property_list_command.cpp commands/kis_reselect_global_selection_command.cpp commands/kis_set_global_selection_command.cpp commands_new/kis_saved_commands.cpp commands_new/kis_processing_command.cpp commands_new/kis_image_resize_command.cpp commands_new/kis_image_set_resolution_command.cpp commands_new/kis_node_move_command2.cpp commands_new/kis_set_layer_style_command.cpp commands_new/kis_selection_move_command2.cpp commands_new/kis_update_command.cpp commands_new/kis_switch_current_time_command.cpp commands_new/kis_change_projection_color_command.cpp commands_new/kis_activate_selection_mask_command.cpp processing/kis_do_nothing_processing_visitor.cpp processing/kis_simple_processing_visitor.cpp processing/kis_crop_processing_visitor.cpp processing/kis_crop_selections_processing_visitor.cpp processing/kis_transform_processing_visitor.cpp processing/kis_mirror_processing_visitor.cpp filter/kis_filter.cc + filter/kis_filter_category_ids.cpp filter/kis_filter_configuration.cc filter/kis_color_transformation_configuration.cc filter/kis_filter_registry.cc filter/kis_color_transformation_filter.cc generator/kis_generator.cpp generator/kis_generator_layer.cpp generator/kis_generator_registry.cpp floodfill/kis_fill_interval_map.cpp floodfill/kis_scanline_fill.cpp lazybrush/kis_min_cut_worker.cpp lazybrush/kis_lazy_fill_tools.cpp lazybrush/kis_multiway_cut.cpp lazybrush/KisWatershedWorker.cpp lazybrush/kis_colorize_mask.cpp lazybrush/kis_colorize_stroke_strategy.cpp KisDelayedUpdateNodeInterface.cpp kis_adjustment_layer.cc kis_selection_based_layer.cpp kis_node_filter_interface.cpp kis_base_accessor.cpp kis_base_node.cpp kis_base_processor.cpp kis_bookmarked_configuration_manager.cc kis_node_uuid_info.cpp kis_clone_layer.cpp kis_colorspace_convert_visitor.cpp kis_config_widget.cpp kis_convolution_kernel.cc kis_convolution_painter.cc kis_gaussian_kernel.cpp kis_edge_detection_kernel.cpp kis_cubic_curve.cpp kis_default_bounds.cpp kis_default_bounds_base.cpp kis_effect_mask.cc kis_fast_math.cpp kis_fill_painter.cc kis_filter_mask.cpp kis_filter_strategy.cc kis_transform_mask.cpp kis_transform_mask_params_interface.cpp kis_recalculate_transform_mask_job.cpp kis_recalculate_generator_layer_job.cpp kis_transform_mask_params_factory_registry.cpp kis_safe_transform.cpp kis_gradient_painter.cc kis_gradient_shape_strategy.cpp kis_cached_gradient_shape_strategy.cpp kis_polygonal_gradient_shape_strategy.cpp kis_iterator_ng.cpp kis_async_merger.cpp kis_merge_walker.cc kis_updater_context.cpp kis_update_job_item.cpp kis_stroke_strategy_undo_command_based.cpp kis_simple_stroke_strategy.cpp KisRunnableBasedStrokeStrategy.cpp KisRunnableStrokeJobData.cpp KisRunnableStrokeJobsInterface.cpp KisFakeRunnableStrokeJobsExecutor.cpp kis_stroke_job_strategy.cpp kis_stroke_strategy.cpp kis_stroke.cpp kis_strokes_queue.cpp KisStrokesQueueMutatedJobInterface.cpp kis_simple_update_queue.cpp kis_update_scheduler.cpp kis_queues_progress_updater.cpp kis_composite_progress_proxy.cpp kis_sync_lod_cache_stroke_strategy.cpp kis_lod_capable_layer_offset.cpp kis_update_time_monitor.cpp KisUpdateSchedulerConfigNotifier.cpp kis_group_layer.cc kis_count_visitor.cpp kis_histogram.cc kis_image_interfaces.cpp kis_image_animation_interface.cpp kis_time_range.cpp kis_node_graph_listener.cpp kis_image.cc kis_image_signal_router.cpp kis_image_config.cpp kis_projection_updates_filter.cpp kis_suspend_projection_updates_stroke_strategy.cpp kis_regenerate_frame_stroke_strategy.cpp kis_switch_time_stroke_strategy.cpp kis_crop_saved_extra_data.cpp kis_timed_signal_threshold.cpp kis_layer.cc kis_indirect_painting_support.cpp kis_abstract_projection_plane.cpp kis_layer_projection_plane.cpp kis_layer_utils.cpp kis_mask_projection_plane.cpp kis_projection_leaf.cpp kis_mask.cc kis_base_mask_generator.cpp kis_rect_mask_generator.cpp kis_circle_mask_generator.cpp kis_gauss_circle_mask_generator.cpp kis_gauss_rect_mask_generator.cpp ${__per_arch_circle_mask_generator_objs} kis_curve_circle_mask_generator.cpp kis_curve_rect_mask_generator.cpp kis_math_toolbox.cpp kis_memory_statistics_server.cpp kis_name_server.cpp kis_node.cpp kis_node_facade.cpp kis_node_progress_proxy.cpp kis_busy_progress_indicator.cpp kis_node_visitor.cpp kis_paint_device.cc kis_paint_device_debug_utils.cpp kis_fixed_paint_device.cpp KisOptimizedByteArray.cpp kis_paint_layer.cc kis_perspective_math.cpp kis_pixel_selection.cpp kis_processing_information.cpp kis_properties_configuration.cc kis_random_accessor_ng.cpp kis_random_generator.cc kis_random_sub_accessor.cpp kis_wrapped_random_accessor.cpp kis_selection.cc kis_selection_mask.cpp kis_update_outline_job.cpp kis_update_selection_job.cpp kis_serializable_configuration.cc kis_transaction_data.cpp kis_transform_worker.cc kis_perspectivetransform_worker.cpp bsplines/kis_bspline_1d.cpp bsplines/kis_bspline_2d.cpp bsplines/kis_nu_bspline_2d.cpp kis_warptransform_worker.cc kis_cage_transform_worker.cpp kis_liquify_transform_worker.cpp kis_green_coordinates_math.cpp kis_transparency_mask.cc kis_undo_adapter.cpp kis_macro_based_undo_store.cpp kis_surrogate_undo_adapter.cpp kis_legacy_undo_adapter.cpp kis_post_execution_undo_adapter.cpp kis_processing_visitor.cpp kis_processing_applicator.cpp krita_utils.cpp kis_outline_generator.cpp kis_layer_composition.cpp kis_selection_filters.cpp KisProofingConfiguration.h metadata/kis_meta_data_entry.cc metadata/kis_meta_data_filter.cc metadata/kis_meta_data_filter_p.cc metadata/kis_meta_data_filter_registry.cc metadata/kis_meta_data_filter_registry_model.cc metadata/kis_meta_data_io_backend.cc metadata/kis_meta_data_merge_strategy.cc metadata/kis_meta_data_merge_strategy_p.cc metadata/kis_meta_data_merge_strategy_registry.cc metadata/kis_meta_data_parser.cc metadata/kis_meta_data_schema.cc metadata/kis_meta_data_schema_registry.cc metadata/kis_meta_data_store.cc metadata/kis_meta_data_type_info.cc metadata/kis_meta_data_validator.cc metadata/kis_meta_data_value.cc kis_keyframe.cpp kis_keyframe_channel.cpp kis_keyframe_commands.cpp kis_scalar_keyframe_channel.cpp kis_raster_keyframe_channel.cpp kis_onion_skin_compositor.cpp kis_onion_skin_cache.cpp kis_idle_watcher.cpp kis_psd_layer_style.cpp kis_layer_properties_icons.cpp layerstyles/kis_multiple_projection.cpp layerstyles/kis_layer_style_filter.cpp layerstyles/kis_layer_style_filter_environment.cpp layerstyles/kis_layer_style_filter_projection_plane.cpp layerstyles/kis_layer_style_projection_plane.cpp layerstyles/kis_ls_drop_shadow_filter.cpp layerstyles/kis_ls_satin_filter.cpp layerstyles/kis_ls_stroke_filter.cpp layerstyles/kis_ls_bevel_emboss_filter.cpp layerstyles/kis_ls_overlay_filter.cpp layerstyles/kis_ls_utils.cpp layerstyles/gimp_bump_map.cpp KisProofingConfiguration.cpp kis_node_query_path.cc ) set(einspline_SRCS 3rdparty/einspline/bspline_create.cpp 3rdparty/einspline/bspline_data.cpp 3rdparty/einspline/multi_bspline_create.cpp 3rdparty/einspline/nubasis.cpp 3rdparty/einspline/nubspline_create.cpp 3rdparty/einspline/nugrid.cpp ) add_library(kritaimage SHARED ${kritaimage_LIB_SRCS} ${einspline_SRCS}) generate_export_header(kritaimage BASE_NAME kritaimage) target_link_libraries(kritaimage PUBLIC kritaversion kritawidgets kritaglobal kritapsd kritaodf kritapigment kritacommand kritawidgetutils Qt5::Concurrent ) target_link_libraries(kritaimage PUBLIC ${Boost_SYSTEM_LIBRARY}) if(OPENEXR_FOUND) target_link_libraries(kritaimage PUBLIC ${OPENEXR_LIBRARIES}) endif() if(FFTW3_FOUND) target_link_libraries(kritaimage PRIVATE ${FFTW3_LIBRARIES}) endif() if(HAVE_VC) target_link_libraries(kritaimage PUBLIC ${Vc_LIBRARIES}) endif() if (NOT GSL_FOUND) message (WARNING "KRITA WARNING! No GNU Scientific Library was found! Krita's Shaped Gradients might be non-normalized! Please install GSL library.") else () target_link_libraries(kritaimage PRIVATE ${GSL_LIBRARIES} ${GSL_CBLAS_LIBRARIES}) endif () target_include_directories(kritaimage PUBLIC $ $ $ $ $ $ ) set_target_properties(kritaimage PROPERTIES VERSION ${GENERIC_KRITA_LIB_VERSION} SOVERSION ${GENERIC_KRITA_LIB_SOVERSION} ) install(TARGETS kritaimage ${INSTALL_TARGETS_DEFAULT_ARGS}) ########### install schemas ############# install( FILES metadata/schemas/dc.schema metadata/schemas/exif.schema metadata/schemas/tiff.schema metadata/schemas/mkn.schema metadata/schemas/xmp.schema metadata/schemas/xmpmm.schema metadata/schemas/xmprights.schema DESTINATION ${DATA_INSTALL_DIR}/krita/metadata/schemas) diff --git a/libs/image/filter/kis_filter.cc b/libs/image/filter/kis_filter.cc index 08b26f456b..28d18d2c20 100644 --- a/libs/image/filter/kis_filter.cc +++ b/libs/image/filter/kis_filter.cc @@ -1,185 +1,133 @@ /* * Copyright (c) 2004,2006-2007 Cyrille Berger * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "filter/kis_filter.h" #include #include #include "kis_bookmarked_configuration_manager.h" #include "filter/kis_filter_configuration.h" #include "kis_processing_information.h" #include "kis_transaction.h" #include "kis_paint_device.h" #include "kis_selection.h" #include "kis_types.h" #include #include - -KoID KisFilter::categoryAdjust() -{ - return KoID("adjust_filters", i18n("Adjust")); -} - -KoID KisFilter::categoryArtistic() -{ - return KoID("artistic_filters", i18n("Artistic")); -} - -KoID KisFilter::categoryBlur() -{ - return KoID("blur_filters", i18n("Blur")); -} - -KoID KisFilter::categoryColors() -{ - return KoID("color_filters", i18n("Colors")); -} - -KoID KisFilter::categoryEdgeDetection() -{ - return KoID("edge_filters", i18n("Edge Detection")); -} - -KoID KisFilter::categoryEmboss() -{ - return KoID("emboss_filters", i18n("Emboss")); -} - -KoID KisFilter::categoryEnhance() -{ - return KoID("enhance_filters", i18n("Enhance")); -} - -KoID KisFilter::categoryMap() -{ - return KoID("map_filters", i18n("Map")); -} - -KoID KisFilter::categoryNonPhotorealistic() -{ - return KoID("nonphotorealistic_filters", i18n("Non-photorealistic")); -} - -KoID KisFilter::categoryOther() -{ - return KoID("other_filters", i18n("Other")); -} - - KisFilter::KisFilter(const KoID& _id, const KoID & category, const QString & entry) : KisBaseProcessor(_id, category, entry), m_supportsLevelOfDetail(false) { init(id() + "_filter_bookmarks"); } KisFilter::~KisFilter() { } void KisFilter::process(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater) const { process(device, device, KisSelectionSP(), applyRect, config, progressUpdater); } void KisFilter::process(const KisPaintDeviceSP src, KisPaintDeviceSP dst, KisSelectionSP selection, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { if (applyRect.isEmpty()) return; QRect needRect = neededRect(applyRect, config, src->defaultBounds()->currentLevelOfDetail()); KisPaintDeviceSP temporary; KisTransaction *transaction = 0; bool weirdDstColorSpace = dst->colorSpace() != dst->compositionSourceColorSpace() && *dst->colorSpace() != *dst->compositionSourceColorSpace(); if(src == dst && !selection && !weirdDstColorSpace) { temporary = src; } else { temporary = dst->createCompositionSourceDevice(src, needRect); transaction = new KisTransaction(temporary); } try { QScopedPointer fakeUpdater; if (!progressUpdater) { // TODO: remove dependency on KoUpdater, depend on KoProgressProxy, // it is more lightweight fakeUpdater.reset(new KoDummyUpdater()); progressUpdater = fakeUpdater.data(); } processImpl(temporary, applyRect, config, progressUpdater); } catch (std::bad_alloc) { warnKrita << "Filter" << name() << "failed to allocate enough memory to run."; } if(transaction) { delete transaction; KisPainter::copyAreaOptimized(applyRect.topLeft(), temporary, dst, applyRect, selection); } } QRect KisFilter::neededRect(const QRect & rect, const KisFilterConfigurationSP c, int lod) const { Q_UNUSED(c); Q_UNUSED(lod); return rect; } QRect KisFilter::changedRect(const QRect & rect, const KisFilterConfigurationSP c, int lod) const { Q_UNUSED(c); Q_UNUSED(lod); return rect; } bool KisFilter::supportsLevelOfDetail(const KisFilterConfigurationSP config, int lod) const { Q_UNUSED(config); Q_UNUSED(lod); return m_supportsLevelOfDetail; } void KisFilter::setSupportsLevelOfDetail(bool value) { m_supportsLevelOfDetail = value; } bool KisFilter::needsTransparentPixels(const KisFilterConfigurationSP config, const KoColorSpace *cs) const { Q_UNUSED(config); Q_UNUSED(cs); return false; } diff --git a/libs/image/filter/kis_filter.h b/libs/image/filter/kis_filter.h index ec9e787382..10a6964064 100644 --- a/libs/image/filter/kis_filter.h +++ b/libs/image/filter/kis_filter.h @@ -1,141 +1,126 @@ /* * Copyright (c) 2004,2006-2007 Cyrille Berger * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_FILTER_H_ #define _KIS_FILTER_H_ #include #include #include #include "KoID.h" #include "KoColorSpace.h" #include "kis_types.h" #include "kis_base_processor.h" #include "kritaimage_export.h" /** * Basic interface of a Krita filter. */ class KRITAIMAGE_EXPORT KisFilter : public KisBaseProcessor { - -public: - static KoID categoryAdjust(); - static KoID categoryArtistic(); - static KoID categoryBlur(); - static KoID categoryColors(); - static KoID categoryEdgeDetection(); - static KoID categoryEmboss(); - static KoID categoryEnhance(); - static KoID categoryMap(); - static KoID categoryNonPhotorealistic(); - static KoID categoryOther(); - public: /** * Construct a Krita filter */ KisFilter(const KoID& id, const KoID & category, const QString & entry); ~KisFilter() override; -public: - /** * Override this function with the implementation of your filter. * * This is a low level function that expects all the conditions * for the @param device be met. Use usual process() methods * instead. * * @param device the paint device to filter * @param applyRect the rectangle where the filter is applied * @param config the parameters of the filter * @param progressUpdater to pass on the progress the filter is making */ virtual void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater = 0 ) const = 0; /** * Filter \p src device and write the result into \p dst device. * If \p dst is an alpha color space device, it will get special * treatment. * * @param src the source paint device * @param dst the destination paint device * @param selection the selection * @param applyRect the rectangle where the filter is applied * @param config the parameters of the filter * @param progressUpdater to pass on the progress the filter is making */ void process(const KisPaintDeviceSP src, KisPaintDeviceSP dst, KisSelectionSP selection, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater = 0 ) const; /** * A convenience method for a two-device process() function */ void process(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater = 0 ) const; /** * Some filters need pixels outside the current processing rect to compute the new * value (for instance, convolution filters) */ virtual QRect neededRect(const QRect & rect, const KisFilterConfigurationSP config, int lod) const; /** * Similar to \ref neededRect: some filters will alter a lot of pixels that are * near to each other at the same time. So when you changed a single rectangle * in a device, the actual rectangle that will feel the influence of this change * might be bigger. Use this function to determine that rect. */ virtual QRect changedRect(const QRect & rect, const KisFilterConfigurationSP config, int lod) const; /** * Returns true if the filter is capable of handling LoD scaled planes * when generating preview. */ virtual bool supportsLevelOfDetail(const KisFilterConfigurationSP config, int lod) const; virtual bool needsTransparentPixels(const KisFilterConfigurationSP config, const KoColorSpace *cs) const; protected: QString configEntryGroup() const; void setSupportsLevelOfDetail(bool value); private: bool m_supportsLevelOfDetail; }; #endif diff --git a/libs/image/filter/kis_filter_category_ids.cpp b/libs/image/filter/kis_filter_category_ids.cpp new file mode 100644 index 0000000000..c17e3ed85c --- /dev/null +++ b/libs/image/filter/kis_filter_category_ids.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 Victor Wåhlström + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "kis_filter_category_ids.h" + +#include + +const KoID FiltersCategoryAdjustId("adjust_filters", i18n("Adjust")); +const KoID FiltersCategoryArtisticId("artistic_filters", i18n("Artistic")); +const KoID FiltersCategoryBlurId("blur_filters", i18n("Blur")); +const KoID FiltersCategoryColorId("color_filters", i18n("Colors")); +const KoID FiltersCategoryEdgeDetectionId("edge_filters", i18n("Edge Detection")); +const KoID FiltersCategoryEmbossId("emboss_filters", i18n("Emboss")); +const KoID FiltersCategoryEnhanceId("enhance_filters", i18n("Enhance")); +const KoID FiltersCategoryMapId("map_filters", i18n("Map")); +const KoID FiltersCategoryNonPhotorealisticId("nonphotorealistic_filters", i18n("Non-photorealistic")); +const KoID FiltersCategoryOtherId("other_filters", i18n("Other")); diff --git a/libs/image/filter/kis_filter_category_ids.h b/libs/image/filter/kis_filter_category_ids.h new file mode 100644 index 0000000000..94e367a9f5 --- /dev/null +++ b/libs/image/filter/kis_filter_category_ids.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 Victor Wåhlström + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _KIS_FILTER_CATEGORY_IDS_H_ +#define _KIS_FILTER_CATEGORY_IDS_H_ + +#include + +#include "kritaimage_export.h" + +extern const KoID KRITAIMAGE_EXPORT FiltersCategoryAdjustId; +extern const KoID KRITAIMAGE_EXPORT FiltersCategoryArtisticId; +extern const KoID KRITAIMAGE_EXPORT FiltersCategoryBlurId; +extern const KoID KRITAIMAGE_EXPORT FiltersCategoryColorId; +extern const KoID KRITAIMAGE_EXPORT FiltersCategoryEdgeDetectionId; +extern const KoID KRITAIMAGE_EXPORT FiltersCategoryEmbossId; +extern const KoID KRITAIMAGE_EXPORT FiltersCategoryEnhanceId; +extern const KoID KRITAIMAGE_EXPORT FiltersCategoryMapId; +extern const KoID KRITAIMAGE_EXPORT FiltersCategoryNonPhotorealisticId; +extern const KoID KRITAIMAGE_EXPORT FiltersCategoryOtherId; + +#endif // _KIS_FILTER_CATEGORY_IDS_H_ diff --git a/plugins/filters/asccdl/kis_asccdl_filter.cpp b/plugins/filters/asccdl/kis_asccdl_filter.cpp index 2278ca293d..12e0000b6c 100644 --- a/plugins/filters/asccdl/kis_asccdl_filter.cpp +++ b/plugins/filters/asccdl/kis_asccdl_filter.cpp @@ -1,129 +1,130 @@ /* * Copyright (c) 2017 Wolthera van Hövell tot Westerflier * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_asccdl_filter.h" #include "kis_wdg_asccdl.h" #include #include +#include #include #include #include K_PLUGIN_FACTORY_WITH_JSON(KritaASCCDLFactory, "kritaasccdl.json", registerPlugin();) KritaASCCDL::KritaASCCDL(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(KisFilterSP(new KisFilterASCCDL())); } KritaASCCDL::~KritaASCCDL() { } -KisFilterASCCDL::KisFilterASCCDL(): KisColorTransformationFilter(id(), categoryAdjust(), i18n("&Slope, Offset, Power...")) +KisFilterASCCDL::KisFilterASCCDL(): KisColorTransformationFilter(id(), FiltersCategoryAdjustId, i18n("&Slope, Offset, Power...")) { setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsLevelOfDetail(true); setSupportsThreading(true); setColorSpaceIndependence(FULLY_INDEPENDENT); setShowConfigurationWidget(true); } KoColorTransformation *KisFilterASCCDL::createTransformation(const KoColorSpace *cs, const KisFilterConfigurationSP config) const { KoColor black(Qt::black, cs); return new KisASCCDLTransformation(cs, config->getColor("slope", black), config->getColor("offset", black), config->getColor("power", black)); } KisConfigWidget *KisFilterASCCDL::createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev) const { return new KisASCCDLConfigWidget(parent, dev->colorSpace()); } bool KisFilterASCCDL::needsTransparentPixels(const KisFilterConfigurationSP config, const KoColorSpace *cs) const { KoColor black(Qt::black, cs); KoColor offset = config->getColor("offset", black); offset.convertTo(cs); if (cs->difference(black.data(), offset.data())>0) { return true; } return false; } KisFilterConfigurationSP KisFilterASCCDL::factoryConfiguration() const { KisColorTransformationConfigurationSP config = new KisColorTransformationConfiguration(id().id(), 0); QVariant colorVariant("KoColor"); KoColor black; black.fromQColor(QColor(Qt::black)); KoColor white; white.fromQColor(QColor(Qt::white)); colorVariant.setValue(white); config->setProperty( "slope", colorVariant); config->setProperty( "power", colorVariant); colorVariant.setValue(black); config->setProperty("offset", colorVariant); return config; } KisASCCDLTransformation::KisASCCDLTransformation(const KoColorSpace *cs, KoColor slope, KoColor offset, KoColor power) { QVector slopeN(cs->channelCount()); slope.convertTo(cs); slope.colorSpace()->normalisedChannelsValue(slope.data(), slopeN); m_slope = slopeN; offset.convertTo(cs); QVector offsetN(cs->channelCount()); offset.colorSpace()->normalisedChannelsValue(offset.data(), offsetN); m_offset = offsetN; power.convertTo(cs); QVector powerN(cs->channelCount()); power.colorSpace()->normalisedChannelsValue(power.data(), powerN); m_power = powerN; m_cs = cs; } void KisASCCDLTransformation::transform(const quint8 *src, quint8 *dst, qint32 nPixels) const { QVector normalised(m_cs->channelCount()); const int pixelSize = m_cs->pixelSize(); while (nPixels--) { m_cs->normalisedChannelsValue(src, normalised); for (uint c=0; cchannelCount(); c++){ if (m_cs->channels().at(c)->channelType()!=KoChannelInfo::ALPHA) { normalised[c] = qPow( (normalised.at(c)*m_slope.at(c))+m_offset.at(c), m_power.at(c)); } } m_cs->fromNormalisedChannelsValue(dst, normalised); src += pixelSize; dst += pixelSize; } } #include "kis_asccdl_filter.moc" diff --git a/plugins/filters/blur/kis_blur_filter.cpp b/plugins/filters/blur/kis_blur_filter.cpp index 46b62dbe0d..553a134070 100644 --- a/plugins/filters/blur/kis_blur_filter.cpp +++ b/plugins/filters/blur/kis_blur_filter.cpp @@ -1,138 +1,139 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include //MSVC requires that Vc come first #include "kis_blur_filter.h" #include #include #include #include "kis_wdg_blur.h" #include "ui_wdgblur.h" +#include #include #include #include #include #include "kis_mask_generator.h" #include "kis_lod_transform.h" -KisBlurFilter::KisBlurFilter() : KisFilter(id(), categoryBlur(), i18n("&Blur...")) +KisBlurFilter::KisBlurFilter() : KisFilter(id(), FiltersCategoryBlurId, i18n("&Blur...")) { setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsLevelOfDetail(true); setColorSpaceIndependence(FULLY_INDEPENDENT); } KisConfigWidget * KisBlurFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { return new KisWdgBlur(parent); } KisFilterConfigurationSP KisBlurFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 1); config->setProperty("halfWidth", 5); config->setProperty("halfHeight", 5); config->setProperty("rotate", 0); config->setProperty("strength", 0); config->setProperty("shape", 0); return config; } void KisBlurFilter::processImpl(KisPaintDeviceSP device, const QRect& rect, const KisFilterConfigurationSP _config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = rect.topLeft(); Q_ASSERT(device != 0); KisFilterConfigurationSP config = _config ? _config : new KisFilterConfiguration(id().id(), 1); KisLodTransformScalar t(device); QVariant value; const uint halfWidth = t.scale((config->getProperty("halfWidth", value)) ? value.toUInt() : 5); const uint halfHeight = t.scale((config->getProperty("halfHeight", value)) ? value.toUInt() : 5); int shape = (config->getProperty("shape", value)) ? value.toInt() : 0; uint width = 2 * halfWidth + 1; uint height = 2 * halfHeight + 1; float aspectRatio = (float) width / height; int rotate = (config->getProperty("rotate", value)) ? value.toInt() : 0; int strength = 100 - (config->getProperty("strength", value) ? value.toUInt() : 0); int hFade = (halfWidth * strength) / 100; int vFade = (halfHeight * strength) / 100; KisMaskGenerator* kas; dbgKrita << width << "" << height << "" << hFade << "" << vFade; switch (shape) { case 1: kas = new KisRectangleMaskGenerator(width, aspectRatio, hFade, vFade, 2, true); break; case 0: default: kas = new KisCircleMaskGenerator(width, aspectRatio, hFade, vFade, 2, true); break; } QBitArray channelFlags; if (config) { channelFlags = config->channelFlags(); } if (channelFlags.isEmpty() || !config) { channelFlags = QBitArray(device->colorSpace()->channelCount(), true); } KisConvolutionKernelSP kernel = KisConvolutionKernel::fromMaskGenerator(kas, rotate * M_PI / 180.0); delete kas; KisConvolutionPainter painter(device); painter.setChannelFlags(channelFlags); painter.setProgress(progressUpdater); painter.applyMatrix(kernel, device, srcTopLeft, srcTopLeft, rect.size(), BORDER_REPEAT); } QRect KisBlurFilter::neededRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; const int halfWidth = t.scale(_config->getProperty("halfWidth", value) ? value.toUInt() : 5); const int halfHeight = t.scale(_config->getProperty("halfHeight", value) ? value.toUInt() : 5); return rect.adjusted(-halfWidth * 2, -halfHeight * 2, halfWidth * 2, halfHeight * 2); } QRect KisBlurFilter::changedRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; const int halfWidth = t.scale(_config->getProperty("halfWidth", value) ? value.toUInt() : 5); const int halfHeight = t.scale(_config->getProperty("halfHeight", value) ? value.toUInt() : 5); return rect.adjusted(-halfWidth, -halfHeight, halfWidth, halfHeight); } diff --git a/plugins/filters/blur/kis_gaussian_blur_filter.cpp b/plugins/filters/blur/kis_gaussian_blur_filter.cpp index 40450579d5..c4943be755 100644 --- a/plugins/filters/blur/kis_gaussian_blur_filter.cpp +++ b/plugins/filters/blur/kis_gaussian_blur_filter.cpp @@ -1,122 +1,123 @@ /* * This file is part of Krita * * Copyright (c) 2009 Edward Apap * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_gaussian_blur_filter.h" #include "kis_wdg_gaussian_blur.h" #include #include #include #include #include "ui_wdg_gaussian_blur.h" +#include #include #include #include #include #include "kis_lod_transform.h" #include -KisGaussianBlurFilter::KisGaussianBlurFilter() : KisFilter(id(), categoryBlur(), i18n("&Gaussian Blur...")) +KisGaussianBlurFilter::KisGaussianBlurFilter() : KisFilter(id(), FiltersCategoryBlurId, i18n("&Gaussian Blur...")) { setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsLevelOfDetail(true); setColorSpaceIndependence(FULLY_INDEPENDENT); } KisConfigWidget * KisGaussianBlurFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { return new KisWdgGaussianBlur(parent); } KisFilterConfigurationSP KisGaussianBlurFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 1); config->setProperty("horizRadius", 5); config->setProperty("vertRadius", 5); config->setProperty("lockAspect", true); return config; } void KisGaussianBlurFilter::processImpl(KisPaintDeviceSP device, const QRect& rect, const KisFilterConfigurationSP _config, KoUpdater* progressUpdater ) const { Q_ASSERT(device != 0); KisFilterConfigurationSP config = _config ? _config : new KisFilterConfiguration(id().id(), 1); KisLodTransformScalar t(device); QVariant value; config->getProperty("horizRadius", value); float horizontalRadius = t.scale(value.toFloat()); config->getProperty("vertRadius", value); float verticalRadius = t.scale(value.toFloat()); QBitArray channelFlags; if (config) { channelFlags = config->channelFlags(); } if (channelFlags.isEmpty() || !config) { channelFlags = QBitArray(device->colorSpace()->channelCount(), true); } KisGaussianKernel::applyGaussian(device, rect, horizontalRadius, verticalRadius, channelFlags, progressUpdater); } QRect KisGaussianBlurFilter::neededRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; /** * NOTE: integer devision by two is done on purpose, * because the kernel size is always odd */ const int halfWidth = _config->getProperty("horizRadius", value) ? KisGaussianKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; const int halfHeight = _config->getProperty("vertRadius", value) ? KisGaussianKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; return rect.adjusted(-halfWidth * 2, -halfHeight * 2, halfWidth * 2, halfHeight * 2); } QRect KisGaussianBlurFilter::changedRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; const int halfWidth = _config->getProperty("horizRadius", value) ? KisGaussianKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; const int halfHeight = _config->getProperty("vertRadius", value) ? KisGaussianKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; return rect.adjusted( -halfWidth, -halfHeight, halfWidth, halfHeight); } diff --git a/plugins/filters/blur/kis_lens_blur_filter.cpp b/plugins/filters/blur/kis_lens_blur_filter.cpp index 01c42c5f01..b7d7e6c4cf 100644 --- a/plugins/filters/blur/kis_lens_blur_filter.cpp +++ b/plugins/filters/blur/kis_lens_blur_filter.cpp @@ -1,204 +1,205 @@ /* * This file is part of Krita * * Copyright (c) 2010 Edward Apap * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_lens_blur_filter.h" #include "kis_wdg_lens_blur.h" #include #include #include #include "ui_wdg_lens_blur.h" +#include #include #include #include #include #include "kis_lod_transform.h" #include #include -KisLensBlurFilter::KisLensBlurFilter() : KisFilter(id(), categoryBlur(), i18n("&Lens Blur...")) +KisLensBlurFilter::KisLensBlurFilter() : KisFilter(id(), FiltersCategoryBlurId, i18n("&Lens Blur...")) { setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsLevelOfDetail(true); setColorSpaceIndependence(FULLY_INDEPENDENT); } KisConfigWidget * KisLensBlurFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { return new KisWdgLensBlur(parent); } QSize KisLensBlurFilter::getKernelHalfSize(const KisFilterConfigurationSP config, int lod) { QPolygonF iris = getIrisPolygon(config, lod); QRect rect = iris.boundingRect().toAlignedRect(); int w = std::ceil(qreal(rect.width()) / 2.0); int h = std::ceil(qreal(rect.height()) / 2.0); return QSize(w, h); } KisFilterConfigurationSP KisLensBlurFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 1); config->setProperty("irisShape", "Pentagon (5)"); config->setProperty("irisRadius", 5); config->setProperty("irisRotation", 0); QSize halfSize = getKernelHalfSize(config, 0); config->setProperty("halfWidth", halfSize.width()); config->setProperty("halfHeight", halfSize.height()); return config; } QPolygonF KisLensBlurFilter::getIrisPolygon(const KisFilterConfigurationSP config, int lod) { KIS_ASSERT_RECOVER(config) { return QPolygonF(); } KisLodTransformScalar t(lod); QVariant value; config->getProperty("irisShape", value); QString irisShape = value.toString(); config->getProperty("irisRadius", value); uint irisRadius = t.scale(value.toUInt()); config->getProperty("irisRotation", value); uint irisRotation = value.toUInt(); if (irisRadius < 1) return QPolygon(); QPolygonF irisShapePoly; int sides = 1; qreal angle = 0; if (irisShape == "Triangle") sides = 3; else if (irisShape == "Quadrilateral (4)") sides = 4; else if (irisShape == "Pentagon (5)") sides = 5; else if (irisShape == "Hexagon (6)") sides = 6; else if (irisShape == "Heptagon (7)") sides = 7; else if (irisShape == "Octagon (8)") sides = 8; else return QPolygonF(); for (int i = 0; i < sides; ++i) { irisShapePoly << QPointF(0.5 * cos(angle), 0.5 * sin(angle)); angle += 2 * M_PI / sides; } QTransform transform; transform.rotate(irisRotation); transform.scale(irisRadius * 2, irisRadius * 2); QPolygonF transformedIris = transform.map(irisShapePoly); return transformedIris; } void KisLensBlurFilter::processImpl(KisPaintDeviceSP device, const QRect& rect, const KisFilterConfigurationSP _config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = rect.topLeft(); Q_ASSERT(device != 0); KisFilterConfigurationSP config = _config ? _config : new KisFilterConfiguration(id().id(), 1); QBitArray channelFlags; if (config) { channelFlags = config->channelFlags(); } if (channelFlags.isEmpty() || !config) { channelFlags = QBitArray(device->colorSpace()->channelCount(), true); } const int lod = device->defaultBounds()->currentLevelOfDetail(); QPolygonF transformedIris = getIrisPolygon(config, lod); if (transformedIris.isEmpty()) return; QRectF boundingRect = transformedIris.boundingRect(); int kernelWidth = boundingRect.toAlignedRect().width(); int kernelHeight = boundingRect.toAlignedRect().height(); QImage kernelRepresentation(kernelWidth, kernelHeight, QImage::Format_RGB32); kernelRepresentation.fill(0); QPainter imagePainter(&kernelRepresentation); imagePainter.setRenderHint(QPainter::Antialiasing); imagePainter.setBrush(QColor::fromRgb(255, 255, 255)); QTransform offsetTransform; offsetTransform.translate(-boundingRect.x(), -boundingRect.y()); imagePainter.setTransform(offsetTransform); imagePainter.drawPolygon(transformedIris, Qt::WindingFill); // construct kernel from image Eigen::Matrix irisKernel(kernelHeight, kernelWidth); for (int j = 0; j < kernelHeight; ++j) { for (int i = 0; i < kernelWidth; ++i) { irisKernel(j, i) = qRed(kernelRepresentation.pixel(i, j)); } } // apply convolution KisConvolutionPainter painter(device); painter.setChannelFlags(channelFlags); painter.setProgress(progressUpdater); KisConvolutionKernelSP kernel = KisConvolutionKernel::fromMatrix(irisKernel, 0, irisKernel.sum()); painter.applyMatrix(kernel, device, srcTopLeft, srcTopLeft, rect.size(), BORDER_REPEAT); } QRect KisLensBlurFilter::neededRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; const int halfWidth = t.scale(_config->getProperty("halfWidth", value) ? value.toUInt() : 5); const int halfHeight = t.scale(_config->getProperty("halfHeight", value) ? value.toUInt() : 5); return rect.adjusted(-halfWidth * 2, -halfHeight * 2, halfWidth * 2, halfHeight * 2); } QRect KisLensBlurFilter::changedRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; const int halfWidth = t.scale(_config->getProperty("halfWidth", value) ? value.toUInt() : 5); const int halfHeight = t.scale(_config->getProperty("halfHeight", value) ? value.toUInt() : 5); return rect.adjusted(-halfWidth, -halfHeight, halfWidth, halfHeight); } diff --git a/plugins/filters/blur/kis_motion_blur_filter.cpp b/plugins/filters/blur/kis_motion_blur_filter.cpp index 690d5495f2..fa09173036 100644 --- a/plugins/filters/blur/kis_motion_blur_filter.cpp +++ b/plugins/filters/blur/kis_motion_blur_filter.cpp @@ -1,166 +1,167 @@ /* * This file is part of Krita * * Copyright (c) 2010 Edward Apap * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_motion_blur_filter.h" #include "kis_wdg_motion_blur.h" #include #include #include #include "ui_wdg_motion_blur.h" +#include #include #include #include #include #include "kis_lod_transform.h" #include #include -KisMotionBlurFilter::KisMotionBlurFilter() : KisFilter(id(), categoryBlur(), i18n("&Motion Blur...")) +KisMotionBlurFilter::KisMotionBlurFilter() : KisFilter(id(), FiltersCategoryBlurId, i18n("&Motion Blur...")) { setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsLevelOfDetail(true); setColorSpaceIndependence(FULLY_INDEPENDENT); } KisConfigWidget * KisMotionBlurFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { return new KisWdgMotionBlur(parent); } KisFilterConfigurationSP KisMotionBlurFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 1); config->setProperty("blurAngle", 0); config->setProperty("blurLength", 5); return config; } void KisMotionBlurFilter::processImpl(KisPaintDeviceSP device, const QRect& rect, const KisFilterConfigurationSP _config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = rect.topLeft(); Q_ASSERT(device != 0); KisFilterConfigurationSP config = _config ? _config : new KisFilterConfiguration(id().id(), 1); QVariant value; config->getProperty("blurAngle", value); uint blurAngle = value.toUInt(); KisLodTransformScalar t(device); config->getProperty("blurLength", value); uint blurLength = t.scale(value.toUInt()); if (blurLength == 0) return; QBitArray channelFlags; if (config) { channelFlags = config->channelFlags(); } if (channelFlags.isEmpty() || !config) { channelFlags = QBitArray(device->colorSpace()->channelCount(), true); } // convert angle to radians qreal angleRadians = blurAngle / 360.0 * 2 * M_PI; // construct image qreal halfWidth = blurLength / 2.0 * cos(angleRadians); qreal halfHeight = blurLength / 2.0 * sin(angleRadians); int kernelWidth = ceil(fabs(halfWidth)) * 2; int kernelHeight = ceil(fabs(halfHeight)) * 2; // check for zero dimensions (vertical/horizontal motion vectors) kernelWidth = (kernelWidth == 0) ? 1 : kernelWidth; kernelHeight = (kernelHeight == 0) ? 1 : kernelHeight; QImage kernelRepresentation(kernelWidth, kernelHeight, QImage::Format_RGB32); kernelRepresentation.fill(0); QPainter imagePainter(&kernelRepresentation); imagePainter.setRenderHint(QPainter::Antialiasing); imagePainter.setPen(QPen(QColor::fromRgb(255, 255, 255), 1.0)); imagePainter.drawLine(QPointF(kernelWidth / 2 - halfWidth, kernelHeight / 2 + halfHeight), QPointF(kernelWidth / 2 + halfWidth, kernelHeight / 2 - halfHeight)); // construct kernel from image Eigen::Matrix motionBlurKernel(kernelHeight, kernelWidth); for (int j = 0; j < kernelHeight; ++j) { for (int i = 0; i < kernelWidth; ++i) { motionBlurKernel(j, i) = qRed(kernelRepresentation.pixel(i, j)); } } // apply convolution KisConvolutionPainter painter(device); painter.setChannelFlags(channelFlags); painter.setProgress(progressUpdater); KisConvolutionKernelSP kernel = KisConvolutionKernel::fromMatrix(motionBlurKernel, 0, motionBlurKernel.sum()); painter.applyMatrix(kernel, device, srcTopLeft, srcTopLeft, rect.size(), BORDER_REPEAT); } QRect KisMotionBlurFilter::neededRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; uint blurAngle = _config->getProperty("blurAngle", value) ? value.toUInt() : 0; uint blurLength = t.scale(_config->getProperty("blurLength", value) ? value.toUInt() : 5); qreal angleRadians = blurAngle / 360.0 * 2 * M_PI; const int halfWidth = ceil(fabs(blurLength / 2.0 * cos(angleRadians))); const int halfHeight = ceil(fabs(blurLength / 2.0 * cos(angleRadians))); return rect.adjusted(-halfWidth * 2, -halfHeight * 2, halfWidth * 2, halfHeight * 2); } QRect KisMotionBlurFilter::changedRect(const QRect & rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; uint blurAngle = _config->getProperty("blurAngle", value) ? value.toUInt() : 0; uint blurLength = t.scale(_config->getProperty("blurLength", value) ? value.toUInt() : 5); qreal angleRadians = blurAngle / 360.0 * 2 * M_PI; const int halfWidth = ceil(fabs(blurLength * cos(angleRadians))); const int halfHeight = ceil(fabs(blurLength * cos(angleRadians))); return rect.adjusted(-halfWidth * 2, -halfHeight * 2, halfWidth * 2, halfHeight * 2); } diff --git a/plugins/filters/colors/kis_color_to_alpha.cpp b/plugins/filters/colors/kis_color_to_alpha.cpp index fa4178bc2c..8f1794b05f 100644 --- a/plugins/filters/colors/kis_color_to_alpha.cpp +++ b/plugins/filters/colors/kis_color_to_alpha.cpp @@ -1,188 +1,189 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_color_to_alpha.h" #include #include #include #include #include "kis_progress_update_helper.h" #include #include +#include #include #include #include "ui_wdgcolortoalphabase.h" #include "kis_wdg_color_to_alpha.h" #include #include KisFilterColorToAlpha::KisFilterColorToAlpha() - : KisFilter(id(), categoryColors(), i18n("&Color to Alpha...")) + : KisFilter(id(), FiltersCategoryColorId, i18n("&Color to Alpha...")) { setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsLevelOfDetail(true); setColorSpaceIndependence(FULLY_INDEPENDENT); } KisConfigWidget * KisFilterColorToAlpha::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { return new KisWdgColorToAlpha(parent); } KisFilterConfigurationSP KisFilterColorToAlpha::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("colortoalpha", 1); config->setProperty("targetcolor", QColor(255, 255, 255)); config->setProperty("threshold", 100); return config; } template inline void inverseOver(const int numChannels, const int *channelIndex, channel_type *dst, const channel_type *baseColor, qreal dstOpacity) { for (int i = 0; i < numChannels; i++) { const int idx = channelIndex[i]; dst[idx] = KoColorSpaceMaths::clamp( (static_cast(dst[idx]) - baseColor[idx]) / dstOpacity + baseColor[idx]); } } template void applyToIterator(const int numChannels, const int *channelIndex, KisSequentialIteratorProgress &it, KoColor baseColor, int threshold, const KoColorSpace *cs) { qreal thresholdF = threshold; quint8 *baseColorData_uint8 = baseColor.data(); channel_type *baseColorData = reinterpret_cast(baseColorData_uint8); while (it.nextPixel()) { channel_type *dst = reinterpret_cast(it.rawData()); quint8 *dst_uint8 = it.rawData(); quint8 diff = cs->difference(baseColorData_uint8, dst_uint8); qreal newOpacity = diff >= threshold ? 1.0 : diff / thresholdF; if(newOpacity < cs->opacityF(dst_uint8)) { cs->setOpacity(dst_uint8, newOpacity, 1); } inverseOver(numChannels, channelIndex, dst, baseColorData, newOpacity); } } void KisFilterColorToAlpha::processImpl(KisPaintDeviceSP device, const QRect& rect, const KisFilterConfigurationSP _config, KoUpdater* progressUpdater ) const { Q_ASSERT(device != 0); KisFilterConfigurationSP config = _config ? _config : new KisFilterConfiguration("colortoalpha", 1); QVariant value; QColor cTA = (config->getProperty("targetcolor", value)) ? value.value() : QColor(255, 255, 255); int threshold = (config->getProperty("threshold", value)) ? value.toInt() : 1; const KoColorSpace * cs = device->colorSpace(); KisSequentialIteratorProgress it(device, rect, progressUpdater); KoColor baseColor(cTA, cs); QVector channelIndex; KoChannelInfo::enumChannelValueType valueType = KoChannelInfo::OTHER; QList channels = cs->channels(); for (int i = 0; i < channels.size(); i++) { const KoChannelInfo *info = channels[i]; if (info->channelType() != KoChannelInfo::COLOR) continue; KoChannelInfo::enumChannelValueType currentValueType = info->channelValueType(); if (valueType != KoChannelInfo::OTHER && valueType != currentValueType) { warnKrita << "Cannot apply a Color-to-Alpha filter to a heterogeneous colorspace"; return; } else { valueType = currentValueType; } channelIndex.append(i); } switch (valueType) { case KoChannelInfo::UINT8: applyToIterator(channelIndex.size(), channelIndex.data(), it, baseColor, threshold, cs); break; case KoChannelInfo::UINT16: applyToIterator(channelIndex.size(), channelIndex.data(), it, baseColor, threshold, cs); break; case KoChannelInfo::UINT32: applyToIterator(channelIndex.size(), channelIndex.data(), it, baseColor, threshold, cs); break; case KoChannelInfo::FLOAT32: applyToIterator(channelIndex.size(), channelIndex.data(), it, baseColor, threshold, cs); break; case KoChannelInfo::FLOAT64: applyToIterator(channelIndex.size(), channelIndex.data(), it, baseColor, threshold, cs); break; case KoChannelInfo::FLOAT16: #include #ifdef HAVE_OPENEXR #include applyToIterator(channelIndex.size(), channelIndex.data(), it, baseColor, threshold, cs); break; #endif case KoChannelInfo::INT8: /* !UNSUPPORTED! */ case KoChannelInfo::INT16: /* !UNSUPPORTED! */ case KoChannelInfo::OTHER: warnKrita << "Color To Alpha: Unsupported channel type:" << valueType; } } diff --git a/plugins/filters/colors/kis_minmax_filters.cpp b/plugins/filters/colors/kis_minmax_filters.cpp index e4d418da82..56b65359c4 100644 --- a/plugins/filters/colors/kis_minmax_filters.cpp +++ b/plugins/filters/colors/kis_minmax_filters.cpp @@ -1,143 +1,144 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_minmax_filters.h" #include #include +#include #include #include #include #include #include typedef void (*funcMaxMin)(const quint8* , quint8* , uint); template void maximize(const quint8* s, quint8* d, uint nbpixels) { const _TYPE* sT = (_TYPE*)(s); _TYPE* dT = (_TYPE*)(d); _TYPE vmax = *sT; for (uint i = 1; i < nbpixels; i ++) { if (sT[i] > vmax) { vmax = sT[i]; } } for (uint i = 0; i < nbpixels; i ++) { if (dT[i] != vmax) { dT[i] = 0; } } } template void minimize(const quint8* s, quint8* d, uint nbpixels) { const _TYPE* sT = (_TYPE*)(s); _TYPE* dT = (_TYPE*)(d); _TYPE vmin = *sT; for (uint i = 1; i < nbpixels; i ++) { if (sT[i] < vmin) { vmin = sT[i]; } } for (uint i = 0; i < nbpixels; i ++) { if (dT[i] != vmin) { dT[i] = 0; } } } -KisFilterMax::KisFilterMax() : KisFilter(id(), categoryColors(), i18n("M&aximize Channel")) +KisFilterMax::KisFilterMax() : KisFilter(id(), FiltersCategoryColorId, i18n("M&aximize Channel")) { setSupportsPainting(true); setSupportsLevelOfDetail(true); setColorSpaceIndependence(FULLY_INDEPENDENT); setShowConfigurationWidget(false); } void KisFilterMax::processImpl(KisPaintDeviceSP device, const QRect& rect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { Q_UNUSED(config); Q_ASSERT(device != 0); const KoColorSpace * cs = device->colorSpace(); qint32 nC = cs->colorChannelCount(); funcMaxMin F; KoChannelInfo::enumChannelValueType cT = cs->channels()[0]->channelValueType(); if (cT == KoChannelInfo::UINT8 || cT == KoChannelInfo::INT8) { F = & maximize; } else if (cT == KoChannelInfo::UINT16 || cT == KoChannelInfo::INT16) { F = & maximize; } else if (cT == KoChannelInfo::FLOAT32) { F = & maximize; } else { return; } KisSequentialIteratorProgress it(device, rect, progressUpdater); while (it.nextPixel()) { F(it.oldRawData(), it.rawData(), nC); } } -KisFilterMin::KisFilterMin() : KisFilter(id(), categoryColors(), i18n("M&inimize Channel")) +KisFilterMin::KisFilterMin() : KisFilter(id(), FiltersCategoryColorId, i18n("M&inimize Channel")) { setSupportsPainting(true); setColorSpaceIndependence(FULLY_INDEPENDENT); setShowConfigurationWidget(false); } void KisFilterMin::processImpl(KisPaintDeviceSP device, const QRect& rect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { Q_UNUSED(config); Q_ASSERT(device != 0); const KoColorSpace * cs = device->colorSpace(); qint32 nC = cs->colorChannelCount(); funcMaxMin F; KoChannelInfo::enumChannelValueType cT = cs->channels()[0]->channelValueType(); if (cT == KoChannelInfo::UINT8 || cT == KoChannelInfo::INT8) { F = & minimize; } else if (cT == KoChannelInfo::UINT16 || cT == KoChannelInfo::INT16) { F = & minimize; } else if (cT == KoChannelInfo::FLOAT32) { F = & minimize; } else { return; } KisSequentialIteratorProgress it(device, rect, progressUpdater); while (it.nextPixel()) { F(it.oldRawData(), it.rawData(), nC); } } diff --git a/plugins/filters/colorsfilters/colorsfilters.cpp b/plugins/filters/colorsfilters/colorsfilters.cpp index 51635d0ed3..d45ac29bf4 100644 --- a/plugins/filters/colorsfilters/colorsfilters.cpp +++ b/plugins/filters/colorsfilters/colorsfilters.cpp @@ -1,175 +1,176 @@ /* * This file is part of Krita * * Copyright (c) 2004 Cyrille Berger * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "colorsfilters.h" #include #include #include #include #include #include #include #include #include #include "KoBasicHistogramProducers.h" #include #include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_hsv_adjustment_filter.h" #include "kis_perchannel_filter.h" #include "kis_cross_channel_filter.h" #include "kis_color_balance_filter.h" #include "kis_desaturate_filter.h" K_PLUGIN_FACTORY_WITH_JSON(ColorsFiltersFactory, "kritacolorsfilter.json", registerPlugin();) ColorsFilters::ColorsFilters(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry * manager = KisFilterRegistry::instance(); manager->add(new KisAutoContrast()); manager->add(new KisPerChannelFilter()); manager->add(new KisCrossChannelFilter()); manager->add(new KisDesaturateFilter()); manager->add(new KisHSVAdjustmentFilter()); manager->add(new KisColorBalanceFilter()); } ColorsFilters::~ColorsFilters() { } //================================================================== -KisAutoContrast::KisAutoContrast() : KisFilter(id(), categoryAdjust(), i18n("&Auto Contrast")) +KisAutoContrast::KisAutoContrast() : KisFilter(id(), FiltersCategoryAdjustId, i18n("&Auto Contrast")) { setSupportsPainting(false); setSupportsThreading(false); setSupportsAdjustmentLayers(false); setColorSpaceIndependence(TO_LAB16); setShowConfigurationWidget(false); } void KisAutoContrast::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater) const { Q_ASSERT(device != 0); Q_UNUSED(config); // initialize KoHistogramProducer *producer = new KoGenericLabHistogramProducer(); KisHistogram histogram(device, applyRect, producer, LINEAR); int minvalue = int(255 * histogram.calculations().getMin() + 0.5); int maxvalue = int(255 * histogram.calculations().getMax() + 0.5); if (maxvalue > 255) maxvalue = 255; histogram.setChannel(0); int twoPercent = int(0.005 * histogram.calculations().getCount()); int pixCount = 0; int binnum = 0; while (binnum < histogram.producer()->numberOfBins()) { pixCount += histogram.getValue(binnum); if (pixCount > twoPercent) { minvalue = binnum; break; } binnum++; } pixCount = 0; binnum = histogram.producer()->numberOfBins() - 1; while (binnum > 0) { pixCount += histogram.getValue(binnum); if (pixCount > twoPercent) { maxvalue = binnum; break; } binnum--; } // build the transferfunction int diff = maxvalue - minvalue; quint16* transfer = new quint16[256]; for (int i = 0; i < 255; i++) transfer[i] = 0xFFFF; if (diff != 0) { for (int i = 0; i < minvalue; i++) transfer[i] = 0x0; for (int i = minvalue; i < maxvalue; i++) { qint32 val = int((0xFFFF * (i - minvalue)) / diff); if (val > 0xFFFF) val = 0xFFFF; if (val < 0) val = 0; transfer[i] = val; } for (int i = maxvalue; i < 256; i++) transfer[i] = 0xFFFF; } // apply KoColorTransformation *adj = device->colorSpace()->createBrightnessContrastAdjustment(transfer); KisSequentialIteratorProgress it(device, applyRect, progressUpdater); quint32 npix = it.nConseqPixels(); while(it.nextPixels(npix)) { // adjust npix = it.nConseqPixels(); adj->transform(it.oldRawData(), it.rawData(), npix); } delete[] transfer; delete adj; } #include "colorsfilters.moc" diff --git a/plugins/filters/colorsfilters/kis_color_balance_filter.cpp b/plugins/filters/colorsfilters/kis_color_balance_filter.cpp index c4e856eb7d..e8ec5bbb3d 100644 --- a/plugins/filters/colorsfilters/kis_color_balance_filter.cpp +++ b/plugins/filters/colorsfilters/kis_color_balance_filter.cpp @@ -1,205 +1,206 @@ /* * Copyright (c) 2013 Sahil Nagpal * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_color_balance_filter.h" +#include #include "filter/kis_color_transformation_configuration.h" #include "kis_selection.h" #include "kis_paint_device.h" #include "kis_processing_information.h" KisColorBalanceFilter::KisColorBalanceFilter() - : KisColorTransformationFilter(id(), categoryAdjust(), i18n("&Color Balance...")) + : KisColorTransformationFilter(id(), FiltersCategoryAdjustId, i18n("&Color Balance...")) { setShortcut(QKeySequence(Qt::CTRL + Qt::Key_B)); setSupportsPainting(true); } KisConfigWidget * KisColorBalanceFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); return new KisColorBalanceConfigWidget(parent); } KoColorTransformation * KisColorBalanceFilter::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const { QHash params; if (config) { params["cyan_red_midtones"] = config->getInt("cyan_red_midtones", 0) * 0.01; params["magenta_green_midtones"] = config->getInt("magenta_green_midtones", 0) * 0.01; params["yellow_blue_midtones"] = config->getInt("yellow_blue_midtones", 0) * 0.01; params["cyan_red_shadows"] = config->getInt("cyan_red_shadows", 0) * 0.01; params["magenta_green_shadows"] = config->getInt("magenta_green_shadows", 0) * 0.01; params["yellow_blue_shadows"] = config->getInt("yellow_blue_shadows", 0) * 0.01; params["cyan_red_highlights"] = config->getInt("cyan_red_highlights", 0) * 0.01; params["magenta_green_highlights"] = config->getInt("magenta_green_highlights", 0) * 0.01; params["yellow_blue_highlights"] = config->getInt("yellow_blue_highlights", 0) * 0.01; params["preserve_luminosity"] = config->getBool("preserve_luminosity", true); } return cs->createColorTransformation("ColorBalance" , params); } KisFilterConfigurationSP KisColorBalanceFilter::factoryConfiguration() const { KisColorTransformationConfigurationSP config = new KisColorTransformationConfiguration(id().id(), 0); config->setProperty("cyan_red_midtones", 0); config->setProperty("yellow_green_midtones", 0); config->setProperty("magenta_blue_midtones", 0); config->setProperty("cyan_red_shadows", 0); config->setProperty("yellow_green_shadows", 0); config->setProperty("magenta_blue_shadows", 0); config->setProperty("cyan_red_highlights", 0); config->setProperty("yellow_green_highlights", 0); config->setProperty("magenta_blue_highlights", 0); config->setProperty("preserve_luminosity", true); return config; } KisColorBalanceConfigWidget::KisColorBalanceConfigWidget(QWidget* parent) : KisConfigWidget(parent) { m_page = new Ui_Form(); m_page->setupUi(this); m_page->cyanRedShadowsSlider->setMaximum(100); m_page->cyanRedShadowsSlider->setMinimum(-100); m_page->yellowBlueShadowsSlider->setMaximum(100); m_page->yellowBlueShadowsSlider->setMinimum(-100); m_page->magentaGreenShadowsSlider->setMaximum(100); m_page->magentaGreenShadowsSlider->setMinimum(-100); m_page->cyanRedMidtonesSlider->setMaximum(100); m_page->cyanRedMidtonesSlider->setMinimum(-100); m_page->yellowBlueMidtonesSlider->setMaximum(100); m_page->yellowBlueMidtonesSlider->setMinimum(-100); m_page->magentaGreenMidtonesSlider->setMaximum(100); m_page->magentaGreenMidtonesSlider->setMinimum(-100); m_page->cyanRedHighlightsSlider->setMaximum(100); m_page->cyanRedHighlightsSlider->setMinimum(-100); m_page->yellowBlueHighlightsSlider->setMaximum(100); m_page->yellowBlueHighlightsSlider->setMinimum(-100); m_page->magentaGreenHighlightsSlider->setMaximum(100); m_page->magentaGreenHighlightsSlider->setMinimum(-100); connect(m_page->cyanRedShadowsSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->magentaGreenShadowsSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->yellowBlueShadowsSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->cyanRedMidtonesSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->magentaGreenMidtonesSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->yellowBlueMidtonesSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->cyanRedHighlightsSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->magentaGreenHighlightsSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->yellowBlueHighlightsSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->chkPreserveLuminosity, SIGNAL(toggled(bool)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->pushResetShadows, SIGNAL(clicked()), SLOT(slotShadowsClear())); connect(m_page->pushResetMidtones, SIGNAL(clicked()), SLOT(slotMidtonesClear())); connect(m_page->pushResetHighlights, SIGNAL(clicked()), SLOT(slotHighlightsClear())); m_page->cyanRedShadowsSpinbox->setMaximum(100); m_page->cyanRedShadowsSpinbox->setMinimum(-100); m_page->yellowBlueShadowsSpinbox->setMaximum(100); m_page->yellowBlueShadowsSpinbox->setMinimum(-100); m_page->magentaGreenShadowsSpinbox->setMaximum(100); m_page->magentaGreenShadowsSpinbox->setMinimum(-100); m_page->cyanRedMidtonesSpinbox->setMaximum(100); m_page->cyanRedMidtonesSpinbox->setMinimum(-100); m_page->yellowBlueMidtonesSpinbox->setMaximum(100); m_page->yellowBlueMidtonesSpinbox->setMinimum(-100); m_page->magentaGreenMidtonesSpinbox->setMaximum(100); m_page->magentaGreenMidtonesSpinbox->setMinimum(-100); m_page->cyanRedHighlightsSpinbox->setMaximum(100); m_page->cyanRedHighlightsSpinbox->setMinimum(-100); m_page->yellowBlueHighlightsSpinbox->setMaximum(100); m_page->yellowBlueHighlightsSpinbox->setMinimum(-100); m_page->magentaGreenHighlightsSpinbox->setMaximum(100); m_page->magentaGreenHighlightsSpinbox->setMinimum(-100); } KisColorBalanceConfigWidget::~KisColorBalanceConfigWidget() { delete m_page; } KisPropertiesConfigurationSP KisColorBalanceConfigWidget::configuration() const { KisColorTransformationConfigurationSP c = new KisColorTransformationConfiguration(KisColorBalanceFilter::id().id(), 0); c->setProperty("cyan_red_shadows", m_page->cyanRedShadowsSlider->value()); c->setProperty("magenta_green_shadows", m_page->magentaGreenShadowsSlider->value()); c->setProperty("yellow_blue_shadows", m_page->yellowBlueShadowsSlider->value()); c->setProperty("cyan_red_midtones", m_page->cyanRedMidtonesSlider->value()); c->setProperty("magenta_green_midtones", m_page->magentaGreenMidtonesSlider->value()); c->setProperty("yellow_blue_midtones", m_page->yellowBlueMidtonesSlider->value()); c->setProperty("cyan_red_highlights", m_page->cyanRedHighlightsSlider->value()); c->setProperty("magenta_green_highlights", m_page->magentaGreenHighlightsSlider->value()); c->setProperty("yellow_blue_highlights", m_page->yellowBlueHighlightsSlider->value()); c->setProperty("preserve_luminosity", m_page->chkPreserveLuminosity->isChecked()); return c; } void KisColorBalanceConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config) { m_page->cyanRedMidtonesSlider->setValue( config->getDouble("cyan_red_midtones", 0)); m_page->magentaGreenMidtonesSlider->setValue( config->getDouble("magenta_green_midtones", 0)); m_page->yellowBlueMidtonesSlider->setValue( config->getDouble("yellow_blue_midtones", 0)); m_page->cyanRedShadowsSlider->setValue( config->getDouble("cyan_red_shadows", 0)); m_page->magentaGreenShadowsSlider->setValue( config->getDouble("magenta_green_shadows", 0)); m_page->yellowBlueShadowsSlider->setValue( config->getDouble("yellow_blue_shadows", 0)); m_page->cyanRedHighlightsSlider->setValue( config->getDouble("cyan_red_highlights", 0)); m_page->magentaGreenHighlightsSlider->setValue( config->getDouble("magenta_green_highlights", 0)); m_page->yellowBlueHighlightsSlider->setValue( config->getDouble("yellow_blue_highlights", 0)); m_page->chkPreserveLuminosity->setChecked(config->getBool("preserve_luminosity", true)); } void KisColorBalanceConfigWidget::slotMidtonesClear() { m_page->cyanRedMidtonesSlider->setValue(0); m_page->magentaGreenMidtonesSlider->setValue(0); m_page->yellowBlueMidtonesSlider->setValue(0); } void KisColorBalanceConfigWidget::slotHighlightsClear() { m_page->cyanRedHighlightsSlider->setValue(0); m_page->magentaGreenHighlightsSlider->setValue(0); m_page->yellowBlueHighlightsSlider->setValue(0); } void KisColorBalanceConfigWidget::slotShadowsClear() { m_page->cyanRedShadowsSlider->setValue(0); m_page->magentaGreenShadowsSlider->setValue(0); m_page->yellowBlueShadowsSlider->setValue(0); } diff --git a/plugins/filters/colorsfilters/kis_desaturate_filter.cpp b/plugins/filters/colorsfilters/kis_desaturate_filter.cpp index 80f57320c9..b72f1e5179 100644 --- a/plugins/filters/colorsfilters/kis_desaturate_filter.cpp +++ b/plugins/filters/colorsfilters/kis_desaturate_filter.cpp @@ -1,122 +1,123 @@ /* * This file is part of Krita * * Copyright (c) 2004 Cyrille Berger * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_desaturate_filter.h" #include #include #include #include #include #include #include #include #include #include #include "KoBasicHistogramProducers.h" #include #include +#include #include #include #include #include #include #include #include #include #include #include "filter/kis_filter_registry.h" #include #include #include #include KisDesaturateFilter::KisDesaturateFilter() - : KisColorTransformationFilter(id(), categoryAdjust(), i18n("&Desaturate...")) + : KisColorTransformationFilter(id(), FiltersCategoryAdjustId, i18n("&Desaturate...")) { setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_U)); setSupportsPainting(true); } KisDesaturateFilter::~KisDesaturateFilter() { } KisConfigWidget *KisDesaturateFilter::createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); return new KisDesaturateConfigWidget(parent); } KoColorTransformation* KisDesaturateFilter::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const { QHash params; if (config) { params["type"] = config->getInt("type", 0); } return cs->createColorTransformation("desaturate_adjustment", params); } KisFilterConfigurationSP KisDesaturateFilter::factoryConfiguration() const { KisColorTransformationConfigurationSP config = new KisColorTransformationConfiguration(id().id(), 1); config->setProperty("type", 0); return config; } KisDesaturateConfigWidget::KisDesaturateConfigWidget(QWidget * parent, Qt::WindowFlags f) : KisConfigWidget(parent, f) { m_page = new Ui_WdgDesaturate(); m_page->setupUi(this); m_group = new QButtonGroup(this); m_group->addButton(m_page->radioLightness, 0); m_group->addButton(m_page->radioLuminosityBT709, 1); m_group->addButton(m_page->radioLuminosityBT601, 2); m_group->addButton(m_page->radioAverage, 3); m_group->addButton(m_page->radioMin, 4); m_group->addButton(m_page->radioMax, 5); m_group->setExclusive(true); connect(m_group, SIGNAL(buttonClicked(int)), SIGNAL(sigConfigurationItemChanged())); } KisDesaturateConfigWidget::~KisDesaturateConfigWidget() { delete m_page; } KisPropertiesConfigurationSP KisDesaturateConfigWidget::configuration() const { KisColorTransformationConfigurationSP c = new KisColorTransformationConfiguration(KisDesaturateFilter::id().id(), 0); c->setProperty("type", m_group->checkedId()); return c; } void KisDesaturateConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config) { m_group->button(config->getInt("type", 0))->setChecked(true); emit sigConfigurationItemChanged(); } diff --git a/plugins/filters/colorsfilters/kis_hsv_adjustment_filter.cpp b/plugins/filters/colorsfilters/kis_hsv_adjustment_filter.cpp index 44277ed32c..a9ae138370 100644 --- a/plugins/filters/colorsfilters/kis_hsv_adjustment_filter.cpp +++ b/plugins/filters/colorsfilters/kis_hsv_adjustment_filter.cpp @@ -1,207 +1,208 @@ /* * Copyright (c) 2007 Cyrille Berger * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; version 2 * of the License. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_hsv_adjustment_filter.h" +#include #include #include #include #include #include namespace { struct SliderConfig { QString m_text; int m_minimum; int m_maximum; inline void apply(QSpinBox* spinBox, QSlider* slider, QLabel* label) const { label->setText(m_text); slider->setMinimum(m_minimum); slider->setMaximum(m_maximum); spinBox->setMinimum(m_minimum); spinBox->setMaximum(m_maximum); int sliderValue = slider->value(); if (sliderValue < m_minimum || sliderValue > m_maximum) { slider->setValue((m_minimum + m_maximum) / 2); } } inline double normalize(int value) const { return (double)value / (double)m_maximum; } inline void resetSlider( QSlider* slider) const { slider->setValue(0); } }; struct WidgetSlidersConfig { SliderConfig m_sliders[3]; }; #define PERCENT_FIELD_REL(x) {x, -100, 100} #define PERCENT_FIELD_ABS(x) {x, 0, 100} #define DEGREES_FIELD_REL(x) {x, -180, 180} #define DEGREES_FIELD_ABS(x) {x, 0, 360} #define HSX_CONFIGS(x) { \ { {DEGREES_FIELD_REL(i18n("Hue:")), PERCENT_FIELD_REL(i18n("Saturation:")), PERCENT_FIELD_REL(x)} }, \ { {DEGREES_FIELD_ABS(i18n("Hue:")), PERCENT_FIELD_ABS(i18n("Saturation:")), PERCENT_FIELD_REL(x)} } \ } const WidgetSlidersConfig WIDGET_CONFIGS[][2] = { // Hue/Saturation/Value HSX_CONFIGS(i18n("Value:")), // Hue/Saturation/Lightness HSX_CONFIGS(i18n("Lightness:")), // Hue/Saturation/Intensity HSX_CONFIGS(i18n("Intensity:")), // Hue/Saturation/Luminosity HSX_CONFIGS(i18n("Luma:")), // Blue Chroma/Red Chroma/Luma {{ {PERCENT_FIELD_REL(i18n("Yellow-Blue:")), PERCENT_FIELD_REL(i18n("Green-Red:")), PERCENT_FIELD_REL(i18n("Luma:"))} }, { {PERCENT_FIELD_ABS(i18n("Yellow-Blue:")), PERCENT_FIELD_ABS(i18n("Green-Red:")), PERCENT_FIELD_REL(i18n("Luma:"))} }} }; inline const WidgetSlidersConfig& getCurrentWidgetConfig(int type, bool colorize) { return WIDGET_CONFIGS[type][colorize ? 1 : 0]; } } KisHSVAdjustmentFilter::KisHSVAdjustmentFilter() - : KisColorTransformationFilter(id(), categoryAdjust(), i18n("&HSV Adjustment...")) + : KisColorTransformationFilter(id(), FiltersCategoryAdjustId, i18n("&HSV Adjustment...")) { setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U)); setSupportsPainting(true); } KisConfigWidget * KisHSVAdjustmentFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); return new KisHSVConfigWidget(parent); } KoColorTransformation* KisHSVAdjustmentFilter::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const { QHash params; if (config) { int type = config->getInt("type", 1); bool colorize = config->getBool("colorize", false); const WidgetSlidersConfig& widgetConfig = getCurrentWidgetConfig(type, colorize); params["h"] = widgetConfig.m_sliders[0].normalize(config->getInt("h", 0)); params["s"] = widgetConfig.m_sliders[1].normalize(config->getInt("s", 0)); params["v"] = widgetConfig.m_sliders[2].normalize(config->getInt("v", 0)); params["type"] = type; params["colorize"] = colorize; params["lumaRed"] = cs->lumaCoefficients()[0]; params["lumaGreen"] = cs->lumaCoefficients()[1]; params["lumaBlue"] = cs->lumaCoefficients()[2]; } return cs->createColorTransformation("hsv_adjustment", params); } KisFilterConfigurationSP KisHSVAdjustmentFilter::factoryConfiguration() const { KisColorTransformationConfigurationSP config = new KisColorTransformationConfiguration(id().id(), 1); config->setProperty("h", 0); config->setProperty("s", 0); config->setProperty("v", 0); config->setProperty("type", 1); config->setProperty("colorize", false); return config; } KisHSVConfigWidget::KisHSVConfigWidget(QWidget * parent, Qt::WindowFlags f) : KisConfigWidget(parent, f) { m_page = new Ui_WdgHSVAdjustment(); m_page->setupUi(this); connect(m_page->cmbType, SIGNAL(activated(int)), this, SLOT(configureSliderLimitsAndLabels())); connect(m_page->chkColorize, SIGNAL(toggled(bool)), this, SLOT(configureSliderLimitsAndLabels())); connect(m_page->reset,SIGNAL(clicked(bool)),this,SLOT(resetFilter())); // connect horizontal sliders connect(m_page->hueSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->saturationSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->valueSlider, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->hueSpinBox, SIGNAL(valueChanged(int)), m_page->hueSlider, SLOT(setValue(int))); connect(m_page->saturationSpinBox, SIGNAL(valueChanged(int)), m_page->saturationSlider, SLOT(setValue(int))); connect(m_page->valueSpinBox, SIGNAL(valueChanged(int)), m_page->valueSlider, SLOT(setValue(int))); connect(m_page->hueSlider, SIGNAL(valueChanged(int)), m_page->hueSpinBox, SLOT(setValue(int))); connect(m_page->saturationSlider, SIGNAL(valueChanged(int)), m_page->saturationSpinBox, SLOT(setValue(int))); connect(m_page->valueSlider, SIGNAL(valueChanged(int)), m_page->valueSpinBox, SLOT(setValue(int))); } KisHSVConfigWidget::~KisHSVConfigWidget() { delete m_page; } KisPropertiesConfigurationSP KisHSVConfigWidget::configuration() const { KisColorTransformationConfigurationSP c = new KisColorTransformationConfiguration(KisHSVAdjustmentFilter::id().id(), 0); c->setProperty("h", m_page->hueSlider->value()); c->setProperty("s", m_page->saturationSlider->value()); c->setProperty("v", m_page->valueSlider->value()); c->setProperty("type", m_page->cmbType->currentIndex()); c->setProperty("colorize", m_page->chkColorize->isChecked()); return c; } void KisHSVConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config) { m_page->cmbType->setCurrentIndex(config->getInt("type", 1)); m_page->chkColorize->setChecked(config->getBool("colorize", false)); m_page->hueSlider->setValue(config->getInt("h", 0)); m_page->saturationSlider->setValue(config->getInt("s", 0)); m_page->valueSlider->setValue(config->getInt("v", 0)); configureSliderLimitsAndLabels(); } void KisHSVConfigWidget::configureSliderLimitsAndLabels() { const WidgetSlidersConfig& widget = getCurrentWidgetConfig(m_page->cmbType->currentIndex(), m_page->chkColorize->isChecked()); widget.m_sliders[0].apply(m_page->hueSpinBox, m_page->hueSlider, m_page->label); widget.m_sliders[1].apply(m_page->saturationSpinBox, m_page->saturationSlider, m_page->label_2); widget.m_sliders[2].apply(m_page->valueSpinBox, m_page->valueSlider, m_page->label_3); emit sigConfigurationItemChanged(); } void KisHSVConfigWidget::resetFilter() { const WidgetSlidersConfig& widget = getCurrentWidgetConfig(m_page->cmbType->currentIndex(), m_page->chkColorize->isChecked()); widget.m_sliders[0].resetSlider(m_page->hueSlider); widget.m_sliders[1].resetSlider(m_page->saturationSlider); widget.m_sliders[2].resetSlider(m_page->valueSlider); } diff --git a/plugins/filters/colorsfilters/kis_multichannel_filter_base.cpp b/plugins/filters/colorsfilters/kis_multichannel_filter_base.cpp index 9ab392d467..6d0933935e 100644 --- a/plugins/filters/colorsfilters/kis_multichannel_filter_base.cpp +++ b/plugins/filters/colorsfilters/kis_multichannel_filter_base.cpp @@ -1,507 +1,508 @@ /* * This file is part of Krita * * Copyright (c) 2018 Jouni Pentikainen * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_multichannel_filter_base.h" #include #include #include #include #include #include #include #include #include "KoChannelInfo.h" #include "KoBasicHistogramProducers.h" #include "KoColorModelStandardIds.h" #include "KoColorSpace.h" #include "KoColorTransformation.h" #include "KoCompositeColorTransformation.h" #include "KoCompositeOp.h" #include "KoID.h" #include "kis_signals_blocker.h" #include "kis_bookmarked_configuration_manager.h" #include "kis_config_widget.h" +#include #include #include #include #include #include "kis_histogram.h" #include "kis_painter.h" #include "widgets/kis_curve_widget.h" KisMultiChannelFilter::KisMultiChannelFilter(const KoID& id, const QString &entry) - : KisColorTransformationFilter(id, categoryAdjust(), entry) + : KisColorTransformationFilter(id, FiltersCategoryAdjustId, entry) { setSupportsPainting(true); setColorSpaceIndependence(TO_LAB16); } bool KisMultiChannelFilter::needsTransparentPixels(const KisFilterConfigurationSP config, const KoColorSpace *cs) const { Q_UNUSED(config); return cs->colorModelId() == AlphaColorModelID; } QVector KisMultiChannelFilter::getVirtualChannels(const KoColorSpace *cs) { const bool supportsLightness = cs->colorModelId() != LABAColorModelID && cs->colorModelId() != GrayAColorModelID && cs->colorModelId() != GrayColorModelID && cs->colorModelId() != AlphaColorModelID; const bool supportsHue = supportsLightness; const bool supportSaturation = supportsLightness; QVector vchannels; QList sortedChannels = KoChannelInfo::displayOrderSorted(cs->channels()); if (supportsLightness) { vchannels << VirtualChannelInfo(VirtualChannelInfo::ALL_COLORS, -1, 0, cs); } Q_FOREACH (KoChannelInfo *channel, sortedChannels) { int pixelIndex = KoChannelInfo::displayPositionToChannelIndex(channel->displayPosition(), sortedChannels); vchannels << VirtualChannelInfo(VirtualChannelInfo::REAL, pixelIndex, channel, cs); } if (supportsHue) { vchannels << VirtualChannelInfo(VirtualChannelInfo::HUE, -1, 0, cs); } if (supportSaturation) { vchannels << VirtualChannelInfo(VirtualChannelInfo::SATURATION, -1, 0, cs); } if (supportsLightness) { vchannels << VirtualChannelInfo(VirtualChannelInfo::LIGHTNESS, -1, 0, cs); } return vchannels; } int KisMultiChannelFilter::findChannel(const QVector &virtualChannels, const VirtualChannelInfo::Type &channelType) { for (int i = 0; i < virtualChannels.size(); i++) { if (virtualChannels[i].type() == channelType) { return i; } } return -1; } KisMultiChannelFilterConfiguration::KisMultiChannelFilterConfiguration(int channelCount, const QString & name, qint32 version) : KisColorTransformationConfiguration(name, version) , m_channelCount(channelCount) { m_transfers.resize(m_channelCount); } KisMultiChannelFilterConfiguration::~KisMultiChannelFilterConfiguration() {} void KisMultiChannelFilterConfiguration::init() { m_curves.clear(); for (int i = 0; i < m_channelCount; ++i) { m_curves.append(getDefaultCurve()); } updateTransfers(); } bool KisMultiChannelFilterConfiguration::isCompatible(const KisPaintDeviceSP dev) const { return (int)dev->compositionSourceColorSpace()->channelCount() == m_channelCount; } void KisMultiChannelFilterConfiguration::setCurves(QList &curves) { m_curves.clear(); m_curves = curves; m_channelCount = curves.size(); updateTransfers(); } void KisMultiChannelFilterConfiguration::updateTransfers() { m_transfers.resize(m_channelCount); for (int i = 0; i < m_channelCount; i++) { m_transfers[i] = m_curves[i].uint16Transfer(); } } const QVector >& KisMultiChannelFilterConfiguration::transfers() const { return m_transfers; } const QList& KisMultiChannelFilterConfiguration::curves() const { return m_curves; } void KisMultiChannelFilterConfiguration::fromLegacyXML(const QDomElement& root) { fromXML(root); } void KisMultiChannelFilterConfiguration::fromXML(const QDomElement& root) { QList curves; quint16 numTransfers = 0; int version; version = root.attribute("version").toInt(); QDomElement e = root.firstChild().toElement(); QString attributeName; KisCubicCurve curve; quint16 index; while (!e.isNull()) { if ((attributeName = e.attribute("name")) == "nTransfers") { numTransfers = e.text().toUShort(); } else { QRegExp rx("curve(\\d+)"); if (rx.indexIn(attributeName, 0) != -1) { index = rx.cap(1).toUShort(); index = qMin(index, quint16(curves.count())); if (!e.text().isEmpty()) { curve.fromString(e.text()); } curves.insert(index, curve); } } e = e.nextSiblingElement(); } //prepend empty curves for the brightness contrast filter. if(getString("legacy") == "brightnesscontrast") { if (getString("colorModel") == LABAColorModelID.id()) { curves.append(KisCubicCurve()); curves.append(KisCubicCurve()); curves.append(KisCubicCurve()); } else { int extraChannels = 5; if (getString("colorModel") == CMYKAColorModelID.id()) { extraChannels = 6; } else if (getString("colorModel") == GrayAColorModelID.id()) { extraChannels = 0; } for(int c = 0; c < extraChannels; c ++) { curves.insert(0, KisCubicCurve()); } } } if (!numTransfers) return; setVersion(version); setCurves(curves); } /** * Inherited from KisPropertiesConfiguration */ //void KisMultiChannelFilterConfiguration::fromXML(const QString& s) void addParamNode(QDomDocument& doc, QDomElement& root, const QString &name, const QString &value) { QDomText text = doc.createTextNode(value); QDomElement t = doc.createElement("param"); t.setAttribute("name", name); t.appendChild(text); root.appendChild(t); } void KisMultiChannelFilterConfiguration::toXML(QDomDocument& doc, QDomElement& root) const { /** * * 3 * 0,0;0.5,0.5;1,1; * 0,0;1,1; * 0,0;1,1; * */ root.setAttribute("version", version()); QDomText text; QDomElement t; addParamNode(doc, root, "nTransfers", QString::number(m_channelCount)); KisCubicCurve curve; QString paramName; for (int i = 0; i < m_curves.size(); ++i) { QString name = QLatin1String("curve") + QString::number(i); QString value = m_curves[i].toString(); addParamNode(doc, root, name, value); } } KisMultiChannelConfigWidget::KisMultiChannelConfigWidget(QWidget * parent, KisPaintDeviceSP dev, Qt::WindowFlags f) : KisConfigWidget(parent, f) , m_dev(dev) , m_page(new WdgPerChannel(this)) { Q_ASSERT(m_dev); const KoColorSpace *targetColorSpace = dev->compositionSourceColorSpace(); m_virtualChannels = KisMultiChannelFilter::getVirtualChannels(targetColorSpace); } /** * Initialize the dialog. * Note: m_virtualChannels must be populated before calling this */ void KisMultiChannelConfigWidget::init() { QHBoxLayout * layout = new QHBoxLayout(this); Q_CHECK_PTR(layout); layout->setContentsMargins(0,0,0,0); layout->addWidget(m_page); resetCurves(); const int virtualChannelCount = m_virtualChannels.size(); for (int i = 0; i < virtualChannelCount; i++) { const VirtualChannelInfo &info = m_virtualChannels[i]; m_page->cmbChannel->addItem(info.name(), i); } connect(m_page->cmbChannel, SIGNAL(activated(int)), this, SLOT(slotChannelSelected(int))); connect((QObject*)(m_page->chkLogarithmic), SIGNAL(toggled(bool)), this, SLOT(logHistView())); connect((QObject*)(m_page->resetButton), SIGNAL(clicked()), this, SLOT(resetCurve())); // create the horizontal and vertical gradient labels m_page->hgradient->setPixmap(createGradient(Qt::Horizontal)); m_page->vgradient->setPixmap(createGradient(Qt::Vertical)); // init histogram calculator const KoColorSpace *targetColorSpace = m_dev->compositionSourceColorSpace(); QList keys = KoHistogramProducerFactoryRegistry::instance()->keysCompatibleWith(targetColorSpace); if (keys.size() > 0) { KoHistogramProducerFactory *hpf; hpf = KoHistogramProducerFactoryRegistry::instance()->get(keys.at(0)); m_histogram = new KisHistogram(m_dev, m_dev->exactBounds(), hpf->generate(), LINEAR); } connect(m_page->curveWidget, SIGNAL(modified()), this, SIGNAL(sigConfigurationItemChanged())); { KisSignalsBlocker b(m_page->curveWidget); m_page->curveWidget->setCurve(m_curves[0]); setActiveChannel(0); } } KisMultiChannelConfigWidget::~KisMultiChannelConfigWidget() { delete m_histogram; } void KisMultiChannelConfigWidget::resetCurves() { const KisPropertiesConfigurationSP &defaultConfiguration = getDefaultConfiguration(); const auto *defaults = dynamic_cast(defaultConfiguration.data()); KIS_SAFE_ASSERT_RECOVER_RETURN(defaults); m_curves = defaults->curves(); const int virtualChannelCount = m_virtualChannels.size(); for (int i = 0; i < virtualChannelCount; i++) { const VirtualChannelInfo &info = m_virtualChannels[i]; m_curves[i].setName(info.name()); } } void KisMultiChannelConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config) { const KisMultiChannelFilterConfiguration * cfg = dynamic_cast(config.data()); if (!cfg) { return; } if (cfg->curves().empty()) { /** * HACK ALERT: our configuration factory generates * default configuration with nTransfers==0. * Catching it here. Just set everything to defaults instead. */ const KisPropertiesConfigurationSP &defaultConfiguration = getDefaultConfiguration(); const auto *defaults = dynamic_cast(defaultConfiguration.data()); KIS_SAFE_ASSERT_RECOVER_RETURN(defaults); if (!defaults->curves().isEmpty()) { setConfiguration(defaultConfiguration); return; } } else if (cfg->curves().size() != int(m_virtualChannels.size())) { warnKrita << "WARNING: trying to load a curve with incorrect number of channels!"; warnKrita << "WARNING: expected:" << m_virtualChannels.size(); warnKrita << "WARNING: got:" << cfg->curves().size(); return; } else { for (int ch = 0; ch < cfg->curves().size(); ch++) { m_curves[ch] = cfg->curves()[ch]; } } // HACK: we save the previous curve in setActiveChannel, so just copy it m_page->curveWidget->setCurve(m_curves[m_activeVChannel]); setActiveChannel(0); } inline QPixmap KisMultiChannelConfigWidget::createGradient(Qt::Orientation orient /*, int invert (not used yet) */) { int width; int height; int *i, inc, col; int x = 0, y = 0; if (orient == Qt::Horizontal) { i = &x; inc = 1; col = 0; width = 256; height = 1; } else { i = &y; inc = -1; col = 255; width = 1; height = 256; } QPixmap gradientpix(width, height); QPainter p(&gradientpix); p.setPen(QPen(QColor(0, 0, 0), 1, Qt::SolidLine)); for (; *i < 256; (*i)++, col += inc) { p.setPen(QColor(col, col, col)); p.drawPoint(x, y); } return gradientpix; } inline QPixmap KisMultiChannelConfigWidget::getHistogram() { int i; int height = 256; QPixmap pix(256, height); KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(m_histogram, pix); bool logarithmic = m_page->chkLogarithmic->isChecked(); if (logarithmic) m_histogram->setHistogramType(LOGARITHMIC); else m_histogram->setHistogramType(LINEAR); QPalette appPalette = QApplication::palette(); pix.fill(QColor(appPalette.color(QPalette::Base))); QPainter p(&pix); p.setPen(QColor(appPalette.color(QPalette::Text))); p.save(); p.setOpacity(0.2); const VirtualChannelInfo &info = m_virtualChannels[m_activeVChannel]; if (info.type() == VirtualChannelInfo::REAL) { m_histogram->setChannel(info.pixelIndex()); double highest = (double)m_histogram->calculations().getHighest(); qint32 bins = m_histogram->producer()->numberOfBins(); if (m_histogram->getHistogramType() == LINEAR) { double factor = (double)height / highest; for (i = 0; i < bins; ++i) { p.drawLine(i, height, i, height - int(m_histogram->getValue(i) * factor)); } } else { double factor = (double)height / (double)log(highest); for (i = 0; i < bins; ++i) { p.drawLine(i, height, i, height - int(log((double)m_histogram->getValue(i)) * factor)); } } } p.restore(); return pix; } void KisMultiChannelConfigWidget::slotChannelSelected(int index) { const int virtualChannel = m_page->cmbChannel->itemData(index).toInt(); setActiveChannel(virtualChannel); } void KisMultiChannelConfigWidget::setActiveChannel(int ch) { m_curves[m_activeVChannel] = m_page->curveWidget->curve(); m_activeVChannel = ch; m_page->curveWidget->setCurve(m_curves[m_activeVChannel]); m_page->curveWidget->setPixmap(getHistogram()); const int index = m_page->cmbChannel->findData(m_activeVChannel); m_page->cmbChannel->setCurrentIndex(index); updateChannelControls(); } void KisMultiChannelConfigWidget::logHistView() { m_page->curveWidget->setPixmap(getHistogram()); } void KisMultiChannelConfigWidget::resetCurve() { const KisPropertiesConfigurationSP &defaultConfiguration = getDefaultConfiguration(); const auto *defaults = dynamic_cast(defaultConfiguration.data()); KIS_SAFE_ASSERT_RECOVER_RETURN(defaults); auto defaultCurves = defaults->curves(); KIS_SAFE_ASSERT_RECOVER_RETURN(defaultCurves.size() > m_activeVChannel); m_page->curveWidget->setCurve(defaultCurves[m_activeVChannel]); } diff --git a/plugins/filters/convertheightnormalmap/kis_convert_height_to_normal_map_filter.cpp b/plugins/filters/convertheightnormalmap/kis_convert_height_to_normal_map_filter.cpp index 8ee397a572..2e6b466e19 100644 --- a/plugins/filters/convertheightnormalmap/kis_convert_height_to_normal_map_filter.cpp +++ b/plugins/filters/convertheightnormalmap/kis_convert_height_to_normal_map_filter.cpp @@ -1,169 +1,170 @@ /* * Copyright (c) 2017 Wolthera van Hövell tot Westerflier * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_convert_height_to_normal_map_filter.h" #include "kis_wdg_convert_height_to_normal_map.h" #include #include +#include #include #include #include "kis_lod_transform.h" #include K_PLUGIN_FACTORY_WITH_JSON(KritaConvertHeightToNormalMapFilterFactory, "kritaconvertheighttonormalmap.json", registerPlugin();) KritaConvertHeightToNormalMapFilter::KritaConvertHeightToNormalMapFilter(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(KisFilterSP(new KisConvertHeightToNormalMapFilter())); } KritaConvertHeightToNormalMapFilter::~KritaConvertHeightToNormalMapFilter() { } -KisConvertHeightToNormalMapFilter::KisConvertHeightToNormalMapFilter(): KisFilter(id(), categoryEdgeDetection(), i18n("&Height to Normal Map...")) +KisConvertHeightToNormalMapFilter::KisConvertHeightToNormalMapFilter(): KisFilter(id(), FiltersCategoryEdgeDetectionId, i18n("&Height to Normal Map...")) { setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsLevelOfDetail(true); setColorSpaceIndependence(FULLY_INDEPENDENT); setShowConfigurationWidget(true); } void KisConvertHeightToNormalMapFilter::processImpl(KisPaintDeviceSP device, const QRect &rect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const { Q_ASSERT(device != 0); KisFilterConfigurationSP configuration = config ? config : new KisFilterConfiguration(id().id(), 1); KisLodTransformScalar t(device); QVariant value; configuration->getProperty("horizRadius", value); float horizontalRadius = t.scale(value.toFloat()); configuration->getProperty("vertRadius", value); float verticalRadius = t.scale(value.toFloat()); QBitArray channelFlags; if (configuration) { channelFlags = configuration->channelFlags(); } if (channelFlags.isEmpty() || !configuration) { channelFlags = device->colorSpace()->channelFlags(); } KisEdgeDetectionKernel::FilterType type = KisEdgeDetectionKernel::SobelVector; if (configuration->getString("type") == "prewitt") { type = KisEdgeDetectionKernel::Prewit; } else if (configuration->getString("type") == "simple") { type = KisEdgeDetectionKernel::Simple; } int channelToConvert = configuration->getInt("channelToConvert", 0); QVector channelOrder(3); QVector channelFlip(3); channelFlip.fill(false); int i = config->getInt("redSwizzle", 0); if (i%2==1 || i==2) { channelFlip[0] = true; } if (i==3) { channelFlip[0] = false; } channelOrder[device->colorSpace()->channels().at(0)->displayPosition()] = qMax(i/2,0); i = config->getInt("greenSwizzle", 2); if (i%2==1 || i==2) { channelFlip[1] = true; } if (i==3) { channelFlip[1] = false; } channelOrder[device->colorSpace()->channels().at(1)->displayPosition()] = qMax(i/2,0); i = config->getInt("blueSwizzle", 4); if (i%2==1 || i==2) { channelFlip[2] = true; } if (i==3) { channelFlip[2] = false; } channelOrder[device->colorSpace()->channels().at(2)->displayPosition()] = qMax(i/2,0); KisEdgeDetectionKernel::convertToNormalMap(device, rect, horizontalRadius, verticalRadius, type, channelToConvert, channelOrder, channelFlip, channelFlags, progressUpdater); } KisFilterConfigurationSP KisConvertHeightToNormalMapFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 1); config->setProperty("horizRadius", 1); config->setProperty("vertRadius", 1); config->setProperty("type", "sobol"); config->setProperty("channelToConvert", 0); config->setProperty("lockAspect", true); config->setProperty("redSwizzle", KisWdgConvertHeightToNormalMap::xPlus); config->setProperty("greenSwizzle", KisWdgConvertHeightToNormalMap::yPlus); config->setProperty("blueSwizzle", KisWdgConvertHeightToNormalMap::zPlus); return config; } KisConfigWidget *KisConvertHeightToNormalMapFilter::createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev) const { return new KisWdgConvertHeightToNormalMap(parent, dev->colorSpace()); } QRect KisConvertHeightToNormalMapFilter::neededRect(const QRect &rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; /** * NOTE: integer devision by two is done on purpose, * because the kernel size is always odd */ const int halfWidth = _config->getProperty("horizRadius", value) ? KisEdgeDetectionKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; const int halfHeight = _config->getProperty("vertRadius", value) ? KisEdgeDetectionKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; return rect.adjusted(-halfWidth * 2, -halfHeight * 2, halfWidth * 2, halfHeight * 2); } QRect KisConvertHeightToNormalMapFilter::changedRect(const QRect &rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; const int halfWidth = _config->getProperty("horizRadius", value) ? KisEdgeDetectionKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; const int halfHeight = _config->getProperty("vertRadius", value) ? KisEdgeDetectionKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; return rect.adjusted( -halfWidth, -halfHeight, halfWidth, halfHeight); } #include "kis_convert_height_to_normal_map_filter.moc" diff --git a/plugins/filters/convolutionfilters/convolutionfilters.cpp b/plugins/filters/convolutionfilters/convolutionfilters.cpp index 2121cf7454..cd8f030ce0 100644 --- a/plugins/filters/convolutionfilters/convolutionfilters.cpp +++ b/plugins/filters/convolutionfilters/convolutionfilters.cpp @@ -1,176 +1,177 @@ /* * This file is part of the KDE project * * Copyright (c) 2004 Cyrille Berger * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "convolutionfilters.h" #include #include #include #include #include +#include #include #include #include #include #include K_PLUGIN_FACTORY_WITH_JSON(KritaConvolutionFiltersFactory, "kritaconvolutionfilters.json", registerPlugin();) KritaConvolutionFilters::KritaConvolutionFilters(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry * manager = KisFilterRegistry::instance(); manager->add(new KisSharpenFilter()); manager->add(new KisMeanRemovalFilter()); manager->add(new KisEmbossLaplascianFilter()); manager->add(new KisEmbossInAllDirectionsFilter()); manager->add(new KisEmbossHorizontalVerticalFilter()); manager->add(new KisEmbossVerticalFilter()); manager->add(new KisEmbossHorizontalFilter()); } KritaConvolutionFilters::~KritaConvolutionFilters() { } KisSharpenFilter::KisSharpenFilter() - : KisConvolutionFilter(id(), categoryEnhance(), i18n("&Sharpen")) + : KisConvolutionFilter(id(), FiltersCategoryEnhanceId, i18n("&Sharpen")) { setSupportsPainting(true); setShowConfigurationWidget(false); Eigen::Matrix kernelMatrix(3, 3); kernelMatrix << 0, -2, 0, -2, 11, -2, 0, -2, 0; m_matrix = KisConvolutionKernel::fromMatrix(kernelMatrix, 0, 3); } KisMeanRemovalFilter::KisMeanRemovalFilter() - : KisConvolutionFilter(id(), categoryEnhance(), i18n("&Mean Removal")) + : KisConvolutionFilter(id(), FiltersCategoryEnhanceId, i18n("&Mean Removal")) { setSupportsPainting(false); setShowConfigurationWidget(false); Eigen::Matrix kernelMatrix(3, 3); kernelMatrix << -1, -1, -1, -1, 9, -1, -1, -1, -1; m_matrix = KisConvolutionKernel::fromMatrix(kernelMatrix, 0, 1); } KisEmbossLaplascianFilter::KisEmbossLaplascianFilter() - : KisConvolutionFilter(id(), categoryEmboss(), i18n("Emboss (Laplacian)")) + : KisConvolutionFilter(id(), FiltersCategoryEmbossId, i18n("Emboss (Laplacian)")) { setSupportsPainting(false); setShowConfigurationWidget(false); Eigen::Matrix kernelMatrix(3, 3); kernelMatrix << -1, 0, -1, 0, 4, 0, -1, 0, -1; m_matrix = KisConvolutionKernel::fromMatrix(kernelMatrix, 0.5, 1); setIgnoreAlpha(true); } KisEmbossInAllDirectionsFilter::KisEmbossInAllDirectionsFilter() - : KisConvolutionFilter(id(), categoryEmboss(), i18n("Emboss in All Directions")) + : KisConvolutionFilter(id(), FiltersCategoryEmbossId, i18n("Emboss in All Directions")) { setSupportsPainting(false); setShowConfigurationWidget(false); Eigen::Matrix kernelMatrix(3, 3); kernelMatrix << -1, -1, -1, -1, 8, -1, -1, -1, -1; m_matrix = KisConvolutionKernel::fromMatrix(kernelMatrix, 0.5, 1); setIgnoreAlpha(true); } KisEmbossHorizontalVerticalFilter::KisEmbossHorizontalVerticalFilter() - : KisConvolutionFilter(id(), categoryEmboss(), i18n("Emboss Horizontal && Vertical")) + : KisConvolutionFilter(id(), FiltersCategoryEmbossId, i18n("Emboss Horizontal && Vertical")) { setSupportsPainting(false); setShowConfigurationWidget(false); Eigen::Matrix kernelMatrix(3, 3); kernelMatrix << 0, -1, 0, -1, 4, -1, 0, -1, 0; m_matrix = KisConvolutionKernel::fromMatrix(kernelMatrix, 0.5, 1); setIgnoreAlpha(true); } KisEmbossVerticalFilter::KisEmbossVerticalFilter() - : KisConvolutionFilter(id(), categoryEmboss(), i18n("Emboss Vertical Only")) + : KisConvolutionFilter(id(), FiltersCategoryEmbossId, i18n("Emboss Vertical Only")) { setSupportsPainting(false); setShowConfigurationWidget(false); Eigen::Matrix kernelMatrix(3, 3); kernelMatrix << 0, -1, 0, 0, 2, 0, 0, -1, 0; m_matrix = KisConvolutionKernel::fromMatrix(kernelMatrix, 0.5, 1); setIgnoreAlpha(true); } KisEmbossHorizontalFilter::KisEmbossHorizontalFilter() : - KisConvolutionFilter(id(), categoryEmboss(), i18n("Emboss Horizontal Only")) + KisConvolutionFilter(id(), FiltersCategoryEmbossId, i18n("Emboss Horizontal Only")) { setSupportsPainting(false); setShowConfigurationWidget(false); Eigen::Matrix kernelMatrix(3, 3); kernelMatrix << 0, 0, 0, -1, 2, -1, 0, 0, 0; m_matrix = KisConvolutionKernel::fromMatrix(kernelMatrix, 0.5, 1); setIgnoreAlpha(true); } KisEmbossDiagonalFilter::KisEmbossDiagonalFilter() - : KisConvolutionFilter(id(), categoryEdgeDetection(), i18n("Top Edge Detection")) + : KisConvolutionFilter(id(), FiltersCategoryEdgeDetectionId, i18n("Top Edge Detection")) { setSupportsPainting(false); setShowConfigurationWidget(false); Eigen::Matrix kernelMatrix(3, 3); kernelMatrix << -1, 0, -1, 0, 4, 0, -1, 0, -1; m_matrix = KisConvolutionKernel::fromMatrix(kernelMatrix, 0.5, 1); setIgnoreAlpha(true); } #include "convolutionfilters.moc" diff --git a/plugins/filters/dodgeburn/DodgeBurn.cpp b/plugins/filters/dodgeburn/DodgeBurn.cpp index bea5f60275..3b286320e7 100644 --- a/plugins/filters/dodgeburn/DodgeBurn.cpp +++ b/plugins/filters/dodgeburn/DodgeBurn.cpp @@ -1,111 +1,112 @@ /* * Copyright (c) 2009 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "DodgeBurn.h" +#include #include #include #include "ui_DodgeBurnConfigurationBaseWidget.h" -KisFilterDodgeBurn::KisFilterDodgeBurn(const QString& id, const QString& prefix, const QString& name ) : KisColorTransformationFilter(KoID(id, name), categoryAdjust(), name), m_prefix(prefix) +KisFilterDodgeBurn::KisFilterDodgeBurn(const QString& id, const QString& prefix, const QString& name ) : KisColorTransformationFilter(KoID(id, name), FiltersCategoryAdjustId, name), m_prefix(prefix) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(true); } KisConfigWidget * KisFilterDodgeBurn::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); return new KisDodgeBurnConfigWidget(parent, id()); } KoColorTransformation* KisFilterDodgeBurn::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const { QHash params; QString suffix = "Midtones"; if (config) { params["exposure"] = config->getDouble("exposure", 0.5); int type = config->getInt("type", KisFilterDodgeBurn::MIDTONES); switch(type) { case KisFilterDodgeBurn::HIGHLIGHTS: suffix = "Highlights"; break; case KisFilterDodgeBurn::SHADOWS: suffix = "Shadows"; break; default: break; } } return cs->createColorTransformation(m_prefix + suffix, params); } KisDodgeBurnConfigWidget::KisDodgeBurnConfigWidget(QWidget * parent, const QString& id) : KisConfigWidget(parent), m_id(id) { m_page = new Ui_DodgeBurnConfigurationBaseWidget(); m_page->setupUi(this); connect(m_page->radioButtonHighlights, SIGNAL(toggled(bool)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->radioButtonMidtones, SIGNAL(toggled(bool)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->radioButtonShadows, SIGNAL(toggled(bool)), SIGNAL(sigConfigurationItemChanged())); connect(m_page->sliderExposure, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); } KisDodgeBurnConfigWidget::~KisDodgeBurnConfigWidget() { delete m_page; } KisPropertiesConfigurationSP KisDodgeBurnConfigWidget::configuration() const { KisColorTransformationConfigurationSP c = new KisColorTransformationConfiguration(m_id, 0); int type = 0; if(m_page->radioButtonHighlights->isChecked()) { type = KisFilterDodgeBurn::HIGHLIGHTS; } else if(m_page->radioButtonShadows->isChecked()) { type = KisFilterDodgeBurn::SHADOWS; } else { type = KisFilterDodgeBurn::MIDTONES; } c->setProperty("type", type); c->setProperty("exposure", m_page->sliderExposure->value() / 100.0); return c; } void KisDodgeBurnConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config) { int type = config->getInt("type", KisFilterDodgeBurn::MIDTONES); switch(type) { case KisFilterDodgeBurn::HIGHLIGHTS: m_page->radioButtonHighlights->setChecked(true); break; case KisFilterDodgeBurn::SHADOWS: m_page->radioButtonShadows->setChecked(true); break; default: case KisFilterDodgeBurn::MIDTONES: m_page->radioButtonMidtones->setChecked(true); break; } m_page->sliderExposure->setValue(config->getDouble("exposure", 0.5) * 100); } diff --git a/plugins/filters/edgedetection/kis_edge_detection_filter.cpp b/plugins/filters/edgedetection/kis_edge_detection_filter.cpp index 3bd48dbb19..dfc56fab22 100644 --- a/plugins/filters/edgedetection/kis_edge_detection_filter.cpp +++ b/plugins/filters/edgedetection/kis_edge_detection_filter.cpp @@ -1,158 +1,159 @@ /* * Copyright (c) 2017 Wolthera van Hövell tot Westerflier * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_edge_detection_filter.h" #include "kis_wdg_edge_detection.h" #include #include #include #include #include +#include #include #include #include #include #include "kis_lod_transform.h" #include #include #include K_PLUGIN_FACTORY_WITH_JSON(KritaEdgeDetectionFilterFactory, "kritaedgedetection.json", registerPlugin();) KritaEdgeDetectionFilter::KritaEdgeDetectionFilter(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(KisFilterSP(new KisEdgeDetectionFilter())); } KritaEdgeDetectionFilter::~KritaEdgeDetectionFilter() { } -KisEdgeDetectionFilter::KisEdgeDetectionFilter(): KisFilter(id(), categoryEdgeDetection(), i18n("&Edge Detection...")) +KisEdgeDetectionFilter::KisEdgeDetectionFilter(): KisFilter(id(), FiltersCategoryEdgeDetectionId, i18n("&Edge Detection...")) { setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsLevelOfDetail(true); setColorSpaceIndependence(FULLY_INDEPENDENT); setShowConfigurationWidget(true); } void KisEdgeDetectionFilter::processImpl(KisPaintDeviceSP device, const QRect &rect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const { Q_ASSERT(device != 0); KisFilterConfigurationSP configuration = config ? config : new KisFilterConfiguration(id().id(), 1); KisLodTransformScalar t(device); QVariant value; configuration->getProperty("horizRadius", value); float horizontalRadius = t.scale(value.toFloat()); configuration->getProperty("vertRadius", value); float verticalRadius = t.scale(value.toFloat()); QBitArray channelFlags; if (configuration) { channelFlags = configuration->channelFlags(); } if (channelFlags.isEmpty() || !configuration) { channelFlags = device->colorSpace()->channelFlags(); } KisEdgeDetectionKernel::FilterType type = KisEdgeDetectionKernel::SobelVector; if (config->getString("type") == "prewitt") { type = KisEdgeDetectionKernel::Prewit; } else if (config->getString("type") == "simple") { type = KisEdgeDetectionKernel::Simple; } KisEdgeDetectionKernel::FilterOutput output = KisEdgeDetectionKernel::pythagorean; if (config->getString("output") == "xGrowth") { output = KisEdgeDetectionKernel::xGrowth; } else if (config->getString("output") == "xFall") { output = KisEdgeDetectionKernel::xFall; } else if (config->getString("output") == "yGrowth") { output = KisEdgeDetectionKernel::yGrowth; } else if (config->getString("output") == "yFall") { output = KisEdgeDetectionKernel::yFall; } else if (config->getString("output") == "radian") { output = KisEdgeDetectionKernel::radian; } KisEdgeDetectionKernel::applyEdgeDetection(device, rect, horizontalRadius, verticalRadius, type, channelFlags, progressUpdater, output, config->getBool("transparency", false)); } KisFilterConfigurationSP KisEdgeDetectionFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 1); config->setProperty("horizRadius", 1); config->setProperty("vertRadius", 1); config->setProperty("type", "prewitt"); config->setProperty("output", "pythagorean"); config->setProperty("lockAspect", true); config->setProperty("transparency", false); return config; } KisConfigWidget *KisEdgeDetectionFilter::createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); return new KisWdgEdgeDetection(parent); } QRect KisEdgeDetectionFilter::neededRect(const QRect &rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; /** * NOTE: integer devision by two is done on purpose, * because the kernel size is always odd */ const int halfWidth = _config->getProperty("horizRadius", value) ? KisEdgeDetectionKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; const int halfHeight = _config->getProperty("vertRadius", value) ? KisEdgeDetectionKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; return rect.adjusted(-halfWidth * 2, -halfHeight * 2, halfWidth * 2, halfHeight * 2); } QRect KisEdgeDetectionFilter::changedRect(const QRect &rect, const KisFilterConfigurationSP _config, int lod) const { KisLodTransformScalar t(lod); QVariant value; const int halfWidth = _config->getProperty("horizRadius", value) ? KisEdgeDetectionKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; const int halfHeight = _config->getProperty("vertRadius", value) ? KisEdgeDetectionKernel::kernelSizeFromRadius(t.scale(value.toFloat())) / 2 : 5; return rect.adjusted( -halfWidth, -halfHeight, halfWidth, halfHeight); } #include "kis_edge_detection_filter.moc" diff --git a/plugins/filters/embossfilter/kis_emboss_filter.cpp b/plugins/filters/embossfilter/kis_emboss_filter.cpp index d4997110e3..fa2228363f 100644 --- a/plugins/filters/embossfilter/kis_emboss_filter.cpp +++ b/plugins/filters/embossfilter/kis_emboss_filter.cpp @@ -1,159 +1,160 @@ /* * This file is part of Krita * * Copyright (c) 2004 Michael Thaler * * ported from digikam, Copyrighted 2004 Gilles Caulier, * Original Emboss algorithm copyrighted 2004 by * Pieter Z. Voloshyn . * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_emboss_filter.h" #include #include #include #include #include #include #include #include "KoIntegerMaths.h" #include #include #include #include #include #include +#include #include #include #include #include "widgets/kis_multi_integer_filter_widget.h" #include -KisEmbossFilter::KisEmbossFilter() : KisFilter(id(), categoryEmboss(), i18n("&Emboss with Variable Depth...")) +KisEmbossFilter::KisEmbossFilter() : KisFilter(id(), FiltersCategoryEmbossId, i18n("&Emboss with Variable Depth...")) { setSupportsPainting(false); setColorSpaceIndependence(TO_RGBA8); setSupportsThreading(false); setSupportsAdjustmentLayers(false); } KisFilterConfigurationSP KisEmbossFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 0); config->setProperty("depth", 30); return config; } // This method have been ported from Pieter Z. Voloshyn algorithm code. /* Function to apply the Emboss effect * * data => The image data in RGBA mode. * Width => Width of image. * Height => Height of image. * d => Emboss value * * Theory => This is an amazing effect. And the theory is very simple to * understand. You get the diference between the colors and * increase it. After this, get the gray tone */ void KisEmbossFilter::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = applyRect.topLeft(); Q_ASSERT(device); //read the filter configuration values from the KisFilterConfiguration object quint32 embossdepth = config ? config->getInt("depth", 30) : 30; //the actual filter function from digikam. It needs a pointer to a quint8 array //with the actual pixel data. float Depth = embossdepth / 10.0; int R = 0, G = 0, B = 0; uchar Gray = 0; int Width = applyRect.width(); int Height = applyRect.height(); KisSequentialIteratorProgress it(device, applyRect, progressUpdater); QColor color1; QColor color2; KisRandomConstAccessorSP acc = device->createRandomAccessorNG(srcTopLeft.x(), srcTopLeft.y()); while (it.nextPixel()) { // XXX: COLORSPACE_INDEPENDENCE or at least work IN RGB16A device->colorSpace()->toQColor(it.oldRawData(), &color1); acc->moveTo(srcTopLeft.x() + it.x() + Lim_Max(it.x(), 1, Width), srcTopLeft.y() + it.y() + Lim_Max(it.y(), 1, Height)); device->colorSpace()->toQColor(acc->oldRawData(), &color2); R = abs((int)((color1.red() - color2.red()) * Depth + (quint8_MAX / 2))); G = abs((int)((color1.green() - color2.green()) * Depth + (quint8_MAX / 2))); B = abs((int)((color1.blue() - color2.blue()) * Depth + (quint8_MAX / 2))); Gray = CLAMP((R + G + B) / 3, 0, quint8_MAX); device->colorSpace()->fromQColor(QColor(Gray, Gray, Gray, color1.alpha()), it.rawData()); } } // This method have been ported from Pieter Z. Voloshyn algorithm code. /* This function limits the max and min values * defined by the developer * * Now => Original value * Up => Increments * Max => Maximum value * * Theory => This function is used in some functions to limit the * "for step". E.g. I have a picture with 309 pixels (width), and * my "for step" is 5. All the code goes alright until it reaches the * w = 305, because in the next step we will go to 310, but we want * to analyze all the pixels. So, this function will reduce the * "for step", when necessary, until we reach the last possible value */ int KisEmbossFilter::Lim_Max(int Now, int Up, int Max) const { --Max; while (Now > Max - Up) --Up; return (Up); } KisConfigWidget * KisEmbossFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); vKisIntegerWidgetParam param; param.push_back(KisIntegerWidgetParam(10, 300, 30, i18nc("Emboss depth", "Depth"), "depth")); KisConfigWidget * w = new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param); Q_CHECK_PTR(w); return w; } diff --git a/plugins/filters/example/example.cpp b/plugins/filters/example/example.cpp index d4017c388a..03d90164ea 100644 --- a/plugins/filters/example/example.cpp +++ b/plugins/filters/example/example.cpp @@ -1,73 +1,74 @@ /* * This file is part of the KDE project * * Copyright (c) 2004 Cyrille Berger * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "example.h" #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include "KoColorModelStandardIds.h" K_PLUGIN_FACTORY_WITH_JSON(KritaExampleFactory, "kritaexample.json", registerPlugin();) KritaExample::KritaExample(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(KisFilterSP(new KisFilterInvert())); } KritaExample::~KritaExample() { } -KisFilterInvert::KisFilterInvert() : KisColorTransformationFilter(id(), categoryAdjust(), i18n("&Invert")) +KisFilterInvert::KisFilterInvert() : KisColorTransformationFilter(id(), FiltersCategoryAdjustId, i18n("&Invert")) { setShortcut(QKeySequence(Qt::CTRL + Qt::Key_I)); setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(true); setShowConfigurationWidget(false); setSupportsLevelOfDetail(true); } KoColorTransformation* KisFilterInvert::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const { Q_UNUSED(config); return cs->createInvertTransformation(); } bool KisFilterInvert::needsTransparentPixels(const KisFilterConfigurationSP config, const KoColorSpace *cs) const { Q_UNUSED(config); return cs->colorModelId() == AlphaColorModelID; } #include "example.moc" diff --git a/plugins/filters/fastcolortransfer/fastcolortransfer.cpp b/plugins/filters/fastcolortransfer/fastcolortransfer.cpp index 4773a5af70..afdd17a703 100644 --- a/plugins/filters/fastcolortransfer/fastcolortransfer.cpp +++ b/plugins/filters/fastcolortransfer/fastcolortransfer.cpp @@ -1,172 +1,173 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "fastcolortransfer.h" #include #include #include #include #include #include #include #include #include +#include #include #include #include "kis_wdg_fastcolortransfer.h" #include "ui_wdgfastcolortransfer.h" #include #include K_PLUGIN_FACTORY_WITH_JSON(KritaFastColorTransferFactory, "kritafastcolortransfer.json", registerPlugin();) FastColorTransferPlugin::FastColorTransferPlugin(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(new KisFilterFastColorTransfer()); } FastColorTransferPlugin::~FastColorTransferPlugin() { } -KisFilterFastColorTransfer::KisFilterFastColorTransfer() : KisFilter(id(), categoryColors(), i18n("&Color Transfer...")) +KisFilterFastColorTransfer::KisFilterFastColorTransfer() : KisFilter(id(), FiltersCategoryColorId, i18n("&Color Transfer...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsThreading(false); setSupportsPainting(false); setSupportsAdjustmentLayers(false); } KisConfigWidget * KisFilterFastColorTransfer::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); return new KisWdgFastColorTransfer(parent); } KisFilterConfigurationSP KisFilterFastColorTransfer::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 1); config->setProperty("filename", ""); return config; } #define CLAMP(x,l,u) ((x)<(l)?(l):((x)>(u)?(u):(x))) void KisFilterFastColorTransfer::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater) const { Q_ASSERT(device != 0); dbgPlugins << "Start transferring color"; // Convert ref and src to LAB const KoColorSpace* labCS = KoColorSpaceRegistry::instance()->lab16(); if (!labCS) { dbgPlugins << "The LAB colorspace is not available."; return; } dbgPlugins << "convert a copy of src to lab"; const KoColorSpace* oldCS = device->colorSpace(); KisPaintDeviceSP srcLAB = new KisPaintDevice(*device.data()); dbgPlugins << "srcLab : " << srcLAB->extent(); KUndo2Command* cmd = srcLAB->convertTo(labCS, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); delete cmd; KoProgressUpdater compositeUpdater(progressUpdater, KoProgressUpdater::Unthreaded); KoUpdater *updaterStats = compositeUpdater.startSubtask(1); KoUpdater *updaterMap = compositeUpdater.startSubtask(2); // Compute the means and sigmas of src dbgPlugins << "Compute the means and sigmas of src"; double meanL_src = 0., meanA_src = 0., meanB_src = 0.; double sigmaL_src = 0., sigmaA_src = 0., sigmaB_src = 0.; { KisSequentialConstIteratorProgress srcIt(srcLAB, applyRect, updaterStats); while (srcIt.nextPixel()) { const quint16* data = reinterpret_cast(srcIt.oldRawData()); quint32 L = data[0]; quint32 A = data[1]; quint32 B = data[2]; meanL_src += L; meanA_src += A; meanB_src += B; sigmaL_src += L * L; sigmaA_src += A * A; sigmaB_src += B * B; } } double totalSize = 1. / (applyRect.width() * applyRect.height()); meanL_src *= totalSize; meanA_src *= totalSize; meanB_src *= totalSize; sigmaL_src *= totalSize; sigmaA_src *= totalSize; sigmaB_src *= totalSize; dbgPlugins << totalSize << "" << meanL_src << "" << meanA_src << "" << meanB_src << "" << sigmaL_src << "" << sigmaA_src << "" << sigmaB_src; double meanL_ref = config->getDouble("meanL"); double meanA_ref = config->getDouble("meanA"); double meanB_ref = config->getDouble("meanB"); double sigmaL_ref = config->getDouble("sigmaL"); double sigmaA_ref = config->getDouble("sigmaA"); double sigmaB_ref = config->getDouble("sigmaB"); // Transfer colors dbgPlugins << "Transfer colors"; { double coefL = sqrt((sigmaL_ref - meanL_ref * meanL_ref) / (sigmaL_src - meanL_src * meanL_src)); double coefA = sqrt((sigmaA_ref - meanA_ref * meanA_ref) / (sigmaA_src - meanA_src * meanA_src)); double coefB = sqrt((sigmaB_ref - meanB_ref * meanB_ref) / (sigmaB_src - meanB_src * meanB_src)); quint16 labPixel[4]; KisSequentialConstIteratorProgress srcLabIt(srcLAB, applyRect, updaterMap); KisSequentialIterator dstIt(device, applyRect); while (srcLabIt.nextPixel() && dstIt.nextPixel()) { const quint16* data = reinterpret_cast(srcLabIt.oldRawData()); labPixel[0] = (quint16)CLAMP(((double)data[0] - meanL_src) * coefL + meanL_ref, 0., 65535.); labPixel[1] = (quint16)CLAMP(((double)data[1] - meanA_src) * coefA + meanA_ref, 0., 65535.); labPixel[2] = (quint16)CLAMP(((double)data[2] - meanB_src) * coefB + meanB_ref, 0., 65535.); labPixel[3] = data[3]; oldCS->fromLabA16(reinterpret_cast(labPixel), dstIt.rawData(), 1); } } } #include "fastcolortransfer.moc" diff --git a/plugins/filters/gradientmap/krita_filter_gradient_map.cpp b/plugins/filters/gradientmap/krita_filter_gradient_map.cpp index 312207a8e9..367f99aaf9 100644 --- a/plugins/filters/gradientmap/krita_filter_gradient_map.cpp +++ b/plugins/filters/gradientmap/krita_filter_gradient_map.cpp @@ -1,105 +1,106 @@ /* * This file is part of the KDE project * * Copyright (c) 2016 Spencer Brown * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "krita_filter_gradient_map.h" #include #include #include #include #include +#include #include "kis_config_widget.h" #include #include #include #include #include #include "gradientmap.h" #include -KritaFilterGradientMap::KritaFilterGradientMap() : KisFilter(id(), categoryMap(), i18n("&Gradient Map...")) +KritaFilterGradientMap::KritaFilterGradientMap() : KisFilter(id(), FiltersCategoryMapId, i18n("&Gradient Map...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setShowConfigurationWidget(true); setSupportsLevelOfDetail(true); setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsThreading(true); } void KritaFilterGradientMap::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const { Q_ASSERT(!device.isNull()); QDomDocument doc; if (config->version()==1) { QDomElement elt = doc.createElement("gradient"); KoAbstractGradient *gradientAb = KoResourceServerProvider::instance()->gradientServer()->resourceByName(config->getString("gradientName")); if (!gradientAb) { qDebug() << "Could not find gradient" << config->getString("gradientName"); } gradientAb = KoResourceServerProvider::instance()->gradientServer()->resources().first(); KoStopGradient::fromQGradient(gradientAb->toQGradient())->toXML(doc, elt); doc.appendChild(elt); } else { doc.setContent(config->getString("gradientXML", "")); } KoStopGradient gradient = KoStopGradient::fromXML(doc.firstChildElement()); KoColor outColor(Qt::white, device->colorSpace()); KisSequentialIteratorProgress it(device, applyRect, progressUpdater); quint8 grey; const int pixelSize = device->colorSpace()->pixelSize(); while (it.nextPixel()) { grey = device->colorSpace()->intensity8(it.oldRawData()); gradient.colorAt(outColor,(qreal)grey/255); outColor.setOpacity(qMin(KoColor(it.oldRawData(), device->colorSpace()).opacityF(), outColor.opacityF())); outColor.convertTo(device->colorSpace()); memcpy(it.rawData(), outColor.data(), pixelSize); } } KisFilterConfigurationSP KritaFilterGradientMap::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("gradientmap", 2); KoAbstractGradient *gradient = KoResourceServerProvider::instance()->gradientServer()->resources().first(); KoStopGradient stopGradient; stopGradient.fromQGradient(gradient->toQGradient()); QDomDocument doc; QDomElement elt = doc.createElement("gradient"); stopGradient.toXML(doc, elt); doc.appendChild(elt); config->setProperty("gradientXML", doc.toString()); return config; } KisConfigWidget * KritaFilterGradientMap::createConfigurationWidget(QWidget * parent, const KisPaintDeviceSP dev) const { return new KritaGradientMapConfigWidget(parent, dev); } diff --git a/plugins/filters/halftone/kis_halftone_filter.cpp b/plugins/filters/halftone/kis_halftone_filter.cpp index 9c8c9db5ea..ac86b843df 100644 --- a/plugins/filters/halftone/kis_halftone_filter.cpp +++ b/plugins/filters/halftone/kis_halftone_filter.cpp @@ -1,269 +1,270 @@ /* * This file is part of Krita * * Copyright (c) 2016 Wolthera van Hövell tot Westerflier * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include +#include #include "kis_filter_configuration.h" #include #include #include #include #include #include #include #include "kis_halftone_filter.h" K_PLUGIN_FACTORY_WITH_JSON(KritaHalftoneFactory, "kritahalftone.json", registerPlugin();) KritaHalftone::KritaHalftone(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(new KisHalftoneFilter()); } KritaHalftone::~KritaHalftone() { } KisHalftoneFilter::KisHalftoneFilter() - : KisFilter(id(), categoryArtistic(), i18n("&Halftone...")) + : KisFilter(id(), FiltersCategoryArtisticId, i18n("&Halftone...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(false); setShowConfigurationWidget(true); setSupportsLevelOfDetail(false); setSupportsAdjustmentLayers(false); setSupportsThreading(false); } //I am pretty terrible at trigionometry, hence all the comments. void KisHalftoneFilter::processImpl(KisPaintDeviceSP device, const QRect &applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const { qreal cellSize = (qreal)config->getInt("cellSize", 8); qreal angle = fmod((qreal)config->getInt("patternAngle", 45), 90.0); KoColor foregroundC(Qt::black, device->colorSpace()); foregroundC.fromKoColor(config->getColor("foreGroundColor", KoColor(Qt::black, device->colorSpace()) ) ); KoColor backgroundC(Qt::white, device->colorSpace()); backgroundC.fromKoColor(config->getColor("backGroundColor", KoColor(Qt::white, device->colorSpace()) ) ); //First calculate the full diameter, using pythagoras theorem. qreal diameter = qSqrt((cellSize*cellSize)*2); qreal cellSpacingH = cellSize; qreal cellSpacingV = cellSize; qreal cellOffsetV = 0; if (angle>0.0){ //2/3=0.6 sin=o/h //0.6*3=2 sin*h=o //2/0.6=3 o/sin=h qreal angleRad = qDegreesToRadians(angle); //Horizontal cellspacing is the hypotenuse of the Angle and the cellSize(opposite). cellSpacingH = cellSize/qSin(angleRad); //Vertical cellspacing is the opposite of the Angle and the cellSize(hypotenuse). cellSpacingV = cellSize*qSin(angleRad); //cellSpacingoffset is the oppose of the (90-angle) and the vertical cellspacing(adjectant) toa t=o/a, t*a=o. cellOffsetV = qTan(qDegreesToRadians(90-angle))*cellSpacingV; } QPolygonF gridPoints; QRect totalRect(QPoint(0,0), applyRect.bottomRight()); if (gridPoints.size()<1) { int rows = (totalRect.height()/cellSpacingV)+3; for (int r=0; rexactBounds(); if (progressUpdater) { progressUpdater->setRange(0, (applyRect.height()/cellSpacingV+3)*(applyRect.width()/cellSpacingH+3)); } KisRandomConstAccessorSP itterator = device->createRandomConstAccessorNG( 0, 0); //itterator->numContiguousColumns(qCeil(cellSize)); //itterator->numContiguousRows(qCeil(cellSize)); KisPainter painter(device); painter.setCompositeOp(device->colorSpace()->compositeOp(COMPOSITE_OVER)); KisPaintDeviceSP dab = device->createCompositionSourceDevice(); KisPainter dbPainter(dab); KisSelectionSP alpha = new KisSelection(); alpha->pixelSelection()->copyAlphaFrom(device, applyRect); device->fill(applyRect, backgroundC); dbPainter.setAntiAliasPolygonFill(config->getBool("antiAliasing", true)); dbPainter.setPaintColor(foregroundC); dbPainter.setFillStyle(KisPainter::FillStyleForegroundColor); dbPainter.setCompositeOp(device->colorSpace()->compositeOp(COMPOSITE_OVER)); quint8 eightbit = 255; if (config->getBool("invert", false)) { eightbit = 0; } QRect cellRect(applyRect.topLeft()-QPoint(qFloor(cellSpacingH), qFloor(qMax(cellSpacingV, diameter))), applyRect.bottomRight()+QPoint(qCeil(cellSpacingH), qCeil(qMax(cellSpacingV, diameter)))); for (int i=0; imoveTo(center.x(), center.y()); quint8 intensity = device->colorSpace()->intensity8(itterator->oldRawData()); qreal size = diameter*((qAbs(intensity-eightbit))/255.0); QPoint sPoint(qMax(qFloor(samplePoint.x()), applyRect.left()), qMax(qFloor(samplePoint.y()), applyRect.top())); dbPainter.bitBlt(0, 0, device, sPoint.x(), sPoint.y(), diameter, diameter); dbPainter.paintEllipse((samplePoint.x()-qFloor(samplePoint.x()))+qCeil(size)-size, (samplePoint.y()-qFloor(samplePoint.y()))+qCeil(size)-size, size, size); dab->crop(qAbs(qMin(0, xdifference)), qAbs(qMin(0, ydifference)), diameter, diameter); //we only want to paint the bits actually in the apply rect...) painter.bitBlt(sPoint, dab, dab->exactBounds()); if (progressUpdater) { progressUpdater->setValue(i); } } } alpha->pixelSelection()->invert(); device->clearSelection(alpha); } KisFilterConfigurationSP KisHalftoneFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("halftone", 1); config->setProperty("cellSize", 8.0); config->setProperty("patternAngle", 45.0); QVariant v; KoColor black; black.fromQColor(QColor(Qt::black)); v.setValue(black); config->setProperty("foreGroundColor", v); KoColor white; white.fromQColor(QColor(Qt::white)); v.setValue(white); config->setProperty("backGroundColor", v); config->setProperty("antiAliasing", true); config->setProperty("invert", false); return config; } KisConfigWidget *KisHalftoneFilter::createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev) const { return new KisHalftoneConfigWidget(parent, dev); } //----------config---------// KisHalftoneConfigWidget::KisHalftoneConfigWidget(QWidget *parent, KisPaintDeviceSP dev) : KisConfigWidget(parent) { Q_ASSERT(dev); m_page.setupUi(this); KoColor white(Qt::white, dev->colorSpace()); KoColor black(Qt::black, dev->colorSpace()); m_page.bnforeground->setColor(white); m_page.bnbackground->setColor(black); m_page.bnforeground->setDefaultColor(white); m_page.bnbackground->setDefaultColor(black); m_page.sld_cellSize->setRange(3, 90); connect(m_page.sld_cellSize, SIGNAL(valueChanged(int)), SLOT(slotConfigChanged())); connect(m_page.dial_angle, SIGNAL(valueChanged(int)), m_page.spb_angle, SLOT(setValue(int))); connect(m_page.dial_angle, SIGNAL(valueChanged(int)), SLOT(slotConfigChanged())); connect(m_page.spb_angle, SIGNAL(valueChanged(int)), SLOT(slotConfigChanged())); connect(m_page.bnforeground, SIGNAL(changed(KoColor)), SLOT(slotConfigChanged())); connect(m_page.bnbackground, SIGNAL(changed(KoColor)), SLOT(slotConfigChanged())); connect(m_page.ckbAntialiasing, SIGNAL(toggled(bool)), SLOT(slotConfigChanged())); connect(m_page.ckbInvert, SIGNAL(toggled(bool)), SLOT(slotConfigChanged())); } KisHalftoneConfigWidget::~KisHalftoneConfigWidget() { } KisPropertiesConfigurationSP KisHalftoneConfigWidget::configuration() const { KisFilterConfiguration *config = new KisFilterConfiguration("halftone", 1); config->setProperty("cellSize", m_page.sld_cellSize->value()); config->setProperty("patternAngle", m_page.spb_angle->value()); QVariant v; v.setValue(m_page.bnforeground->color()); config->setProperty("foreGroundColor", v); v.setValue(m_page.bnbackground->color()); config->setProperty("backGroundColor", v); config->setProperty("antiAliasing", m_page.ckbAntialiasing->isChecked()); config->setProperty("invert", m_page.ckbInvert->isChecked()); return config; } void KisHalftoneConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config) { QVariant value; if (config->getProperty("cellSize", value)) { m_page.sld_cellSize->setValue(value.toUInt()); } if (config->getProperty("patternAngle", value)) { m_page.dial_angle->setValue(value.toUInt()); m_page.spb_angle->setValue(value.toUInt()); } if (config->getProperty("antiAliasing", value)) { m_page.ckbAntialiasing->setChecked(value.toBool()); } if (config->getProperty("invert", value)) { m_page.ckbInvert->setChecked(value.toBool()); } m_page.bnforeground->setColor(config->getColor("foreGroundColor",m_page.bnforeground->defaultColor())); m_page.bnbackground->setColor(config->getColor("backGroundColor",m_page.bnbackground->defaultColor())); } #include "kis_halftone_filter.moc" diff --git a/plugins/filters/imageenhancement/kis_simple_noise_reducer.cpp b/plugins/filters/imageenhancement/kis_simple_noise_reducer.cpp index eb48171fe9..3cfa603622 100644 --- a/plugins/filters/imageenhancement/kis_simple_noise_reducer.cpp +++ b/plugins/filters/imageenhancement/kis_simple_noise_reducer.cpp @@ -1,112 +1,113 @@ /* * Copyright (c) 2005 Cyrille Berger * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include //MSVC requires that Vc come first #include "kis_simple_noise_reducer.h" #include #include #include #include #include #include #include #include #include +#include #include #include #include #include #include KisSimpleNoiseReducer::KisSimpleNoiseReducer() - : KisFilter(id(), categoryEnhance(), i18n("&Gaussian Noise Reduction...")) + : KisFilter(id(), FiltersCategoryEnhanceId, i18n("&Gaussian Noise Reduction...")) { setSupportsPainting(false); } KisSimpleNoiseReducer::~KisSimpleNoiseReducer() { } KisConfigWidget * KisSimpleNoiseReducer::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); vKisIntegerWidgetParam param; param.push_back(KisIntegerWidgetParam(0, 255, 15, i18n("Threshold"), "threshold")); param.push_back(KisIntegerWidgetParam(0, 10, 1, i18n("Window size"), "windowsize")); return new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param); } KisFilterConfigurationSP KisSimpleNoiseReducer::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 0); config->setProperty("threshold", 15); config->setProperty("windowsize", 1); return config; } inline int ABS(int v) { if (v < 0) return -v; return v; } void KisSimpleNoiseReducer::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP _config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = applyRect.topLeft(); Q_ASSERT(device); KisFilterConfigurationSP config = _config ? _config : defaultConfiguration(); const int threshold = config->getInt("threshold", 15); const int windowsize = config->getInt("windowsize", 1); const KoColorSpace* cs = device->colorSpace(); // Compute the blur mask KisCircleMaskGenerator* kas = new KisCircleMaskGenerator(2*windowsize + 1, 1, windowsize, windowsize, 2, true); KisConvolutionKernelSP kernel = KisConvolutionKernel::fromMaskGenerator(kas); delete kas; KisPaintDeviceSP interm = new KisPaintDevice(*device); // TODO no need for a full copy and then a transaction KisConvolutionPainter painter(interm); painter.beginTransaction(); painter.applyMatrix(kernel, interm, srcTopLeft, srcTopLeft, applyRect.size(), BORDER_REPEAT); painter.deleteTransaction(); KisSequentialConstIteratorProgress intermIt(interm, applyRect, progressUpdater); KisSequentialIterator dstIt(device, applyRect); while (dstIt.nextPixel() && intermIt.nextPixel()) { const quint8 diff = cs->difference(dstIt.oldRawData(), intermIt.oldRawData()); if (diff > threshold) { memcpy(dstIt.rawData(), intermIt.oldRawData(), cs->pixelSize()); } } } diff --git a/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.cpp b/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.cpp index 46595fa27d..4b92fe6554 100644 --- a/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.cpp +++ b/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.cpp @@ -1,124 +1,125 @@ /* * This file is part of the KDE project * * Copyright (c) 2005 Cyrille Berger * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_wavelet_noise_reduction.h" #include #include #include #include #include #include #include +#include #include #include #include "kis_global.h" KisWaveletNoiseReduction::KisWaveletNoiseReduction() - : KisFilter(id(), categoryEnhance(), i18n("&Wavelet Noise Reducer...")) + : KisFilter(id(), FiltersCategoryEnhanceId, i18n("&Wavelet Noise Reducer...")) { setSupportsPainting(false); setSupportsThreading(false); } KisWaveletNoiseReduction::~KisWaveletNoiseReduction() { } KisConfigWidget * KisWaveletNoiseReduction::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { vKisDoubleWidgetParam param; param.push_back(KisDoubleWidgetParam(0.0, 256.0, BEST_WAVELET_THRESHOLD_VALUE, i18n("Threshold"), "threshold")); return new KisMultiDoubleFilterWidget(id().id(), parent, id().id(), param); } KisFilterConfigurationSP KisWaveletNoiseReduction::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 0); config->setProperty("threshold", BEST_WAVELET_THRESHOLD_VALUE); return config; } void KisWaveletNoiseReduction::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP _config, KoUpdater* progressUpdater ) const { Q_ASSERT(device); KisFilterConfigurationSP config = _config ? _config : defaultConfiguration(); const float threshold = config->getDouble("threshold", BEST_WAVELET_THRESHOLD_VALUE); KisMathToolbox mathToolbox; // dbgFilters << size <<"" << maxrectsize <<"" << srcTopLeft.x() <<"" << srcTopLeft.y(); // dbgFilters <<"Transforming..."; KisMathToolbox::KisWavelet* buff = 0; KisMathToolbox::KisWavelet* wav = 0; try { buff = mathToolbox.initWavelet(device, applyRect); } catch (std::bad_alloc) { if (buff) delete buff; return; } try { wav = mathToolbox.fastWaveletTransformation(device, applyRect, buff); } catch (std::bad_alloc) { if (wav) delete wav; return; } float* const fin = wav->coeffs + wav->depth * pow2(wav->size); float* const begin = wav->coeffs + wav->depth; const int size = fin - begin; const int progressOffset = int(std::ceil(std::log2(size / 100))); const int progressMask = (1 << progressOffset) - 1; const int numProgressSteps = size >> progressOffset; int pointsProcessed = 0; progressUpdater->setRange(0, numProgressSteps); for (float* it = begin; it < fin; it++) { if (*it > threshold) { *it -= threshold; } else if (*it < -threshold) { *it += threshold; } else { *it = 0.; } if (!(pointsProcessed & progressMask)) { progressUpdater->setValue(pointsProcessed >> progressOffset); } pointsProcessed++; } mathToolbox.fastWaveletUntransformation(device, applyRect, wav, buff); delete wav; delete buff; } diff --git a/plugins/filters/indexcolors/indexcolors.cpp b/plugins/filters/indexcolors/indexcolors.cpp index 8754592529..6ab5a6f1eb 100644 --- a/plugins/filters/indexcolors/indexcolors.cpp +++ b/plugins/filters/indexcolors/indexcolors.cpp @@ -1,144 +1,145 @@ /* * Copyright 2014 Manuel Riecke * * Permission to use, copy, modify, and distribute this software * and its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice appear in all * copies and that both that the copyright notice and this * permission notice and warranty disclaimer appear in supporting * documentation, and that the name of the author not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * * The author disclaim all warranties with regard to this * software, including all implied warranties of merchantability * and fitness. In no event shall the author be liable for any * special, indirect or consequential damages or any damages * whatsoever resulting from loss of use, data or profits, whether * in an action of contract, negligence or other tortious action, * arising out of or in connection with the use or performance of * this software. */ #include "indexcolors.h" #include #include #include #include #include +#include #include #include #include "kiswdgindexcolors.h" #include "palettegeneratorconfig.h" K_PLUGIN_FACTORY_WITH_JSON(IndexColorsFactory, "kritaindexcolors.json", registerPlugin();) IndexColors::IndexColors(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(KisFilterSP(new KisFilterIndexColors())); } IndexColors::~IndexColors() { } -KisFilterIndexColors::KisFilterIndexColors() : KisColorTransformationFilter(id(), categoryArtistic(), i18n("&Index Colors...")) +KisFilterIndexColors::KisFilterIndexColors() : KisColorTransformationFilter(id(), FiltersCategoryArtisticId, i18n("&Index Colors...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); // Technically it is TO_LAB16 but that would only display a warning we don't want // This filter will always degrade the color space, that is it's purpose setSupportsPainting(true); setShowConfigurationWidget(true); } KoColorTransformation* KisFilterIndexColors::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const { IndexColorPalette pal; PaletteGeneratorConfig palCfg; palCfg.fromByteArray(config->getProperty("paletteGen").toByteArray()); pal = palCfg.generate(); if(config->getBool("reduceColorsEnabled")) { int maxClrs = config->getInt("colorLimit"); while(pal.numColors() > maxClrs) pal.mergeMostReduantColors(); } pal.similarityFactors.L = config->getFloat("LFactor"); pal.similarityFactors.a = config->getFloat("aFactor"); pal.similarityFactors.b = config->getFloat("bFactor"); return new KisIndexColorTransformation(pal, cs, config->getInt("alphaSteps")); } KisConfigWidget* KisFilterIndexColors::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); KisWdgIndexColors* w = new KisWdgIndexColors(parent); w->setup( QStringList() << i18nc("Color palette shade", "Bright") << i18nc("Color palette shade", "Light") << i18nc("Color palette shade", "Base") << i18nc("Color palette shade", "Shadow") , 4 ); return w; } KisFilterConfigurationSP KisFilterIndexColors::factoryConfiguration() const { KisColorTransformationConfigurationSP config = new KisColorTransformationConfiguration(id().id(), 0); PaletteGeneratorConfig palCfg; // Default constructor is factory config config->setProperty("paletteGen", palCfg.toByteArray()); config->setProperty("LFactor", 1.f); config->setProperty("aFactor", 1.f); config->setProperty("bFactor", 1.f); config->setProperty("reduceColorsEnabled", false); config->setProperty("colorLimit", 32); config->setProperty("alphaSteps", 1); return config; } KisIndexColorTransformation::KisIndexColorTransformation(IndexColorPalette palette, const KoColorSpace* cs, int alphaSteps) : m_colorSpace(cs), m_psize(cs->pixelSize()) { m_palette = palette; static const qreal max = KoColorSpaceMathsTraits::max; if(alphaSteps > 0) { m_alphaStep = max / alphaSteps; m_alphaHalfStep = m_alphaStep / 2; } else { m_alphaStep = 0; m_alphaHalfStep = 0; } } void KisIndexColorTransformation::transform(const quint8* src, quint8* dst, qint32 nPixels) const { union { quint16 laba[4]; LabColor lab; } clr; while (nPixels--) { m_colorSpace->toLabA16(src, reinterpret_cast(clr.laba), 1); clr.lab = m_palette.getNearestIndex(clr.lab); if(m_alphaStep) { quint16 amod = clr.laba[3] % m_alphaStep; clr.laba[3] = clr.laba[3] + (amod > m_alphaHalfStep ? m_alphaStep - amod : -amod); } m_colorSpace->fromLabA16(reinterpret_cast(clr.laba), dst, 1); src += m_psize; dst += m_psize; } } #include "indexcolors.moc" diff --git a/plugins/filters/levelfilter/kis_level_filter.cpp b/plugins/filters/levelfilter/kis_level_filter.cpp index 8ecb295a46..4374171f46 100644 --- a/plugins/filters/levelfilter/kis_level_filter.cpp +++ b/plugins/filters/levelfilter/kis_level_filter.cpp @@ -1,344 +1,345 @@ /* * This file is part of Krita * * Copyright (c) 2006 Frederic Coiffier * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_level_filter.h" #include #include #include #include #include #include #include #include #include #include #include #include "kis_paint_device.h" #include "kis_histogram.h" #include "kis_painter.h" #include "KisGradientSlider.h" #include "kis_processing_information.h" #include "kis_selection.h" #include "kis_types.h" +#include #include "filter/kis_color_transformation_configuration.h" KisLevelFilter::KisLevelFilter() - : KisColorTransformationFilter(id(), categoryAdjust(), i18n("&Levels...")) + : KisColorTransformationFilter(id(), FiltersCategoryAdjustId, i18n("&Levels...")) { setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L)); setSupportsPainting(false); setColorSpaceIndependence(TO_LAB16); } KisLevelFilter::~KisLevelFilter() { } KisConfigWidget * KisLevelFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { return new KisLevelConfigWidget(parent, dev); } KoColorTransformation* KisLevelFilter::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const { if (!config) { warnKrita << "No configuration object for level filter\n"; return 0; } Q_ASSERT(config); int blackvalue = config->getInt("blackvalue"); int whitevalue = config->getInt("whitevalue", 255); double gammavalue = config->getDouble("gammavalue", 1.0); int outblackvalue = config->getInt("outblackvalue"); int outwhitevalue = config->getInt("outwhitevalue", 255); quint16 transfer[256]; for (int i = 0; i < 256; i++) { if (i <= blackvalue) transfer[i] = outblackvalue; else if (i < whitevalue) { double a = (double)(i - blackvalue) / (double)(whitevalue - blackvalue); a = (double)(outwhitevalue - outblackvalue) * pow(a, (1.0 / gammavalue)); transfer[i] = int(outblackvalue + a); } else transfer[i] = outwhitevalue; // TODO use floats instead of integer in the configuration transfer[i] = ((int)transfer[i] * 0xFFFF) / 0xFF ; } return cs->createBrightnessContrastAdjustment(transfer); } KisLevelConfigWidget::KisLevelConfigWidget(QWidget * parent, KisPaintDeviceSP dev) : KisConfigWidget(parent) { Q_ASSERT(dev); m_page.setupUi(this); m_page.ingradient->enableGamma(true); m_page.blackspin->setValue(0); m_page.whitespin->setValue(255); m_page.gammaspin->setValue(1.0); m_page.ingradient->slotModifyGamma(1.0); m_page.outblackspin->setValue(0); m_page.outwhitespin->setValue(255); connect(m_page.blackspin, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page.whitespin, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page.ingradient, SIGNAL(sigModifiedGamma(double)), SIGNAL(sigConfigurationItemChanged())); connect(m_page.blackspin, SIGNAL(valueChanged(int)), m_page.ingradient, SLOT(slotModifyBlack(int))); connect(m_page.whitespin, SIGNAL(valueChanged(int)), m_page.ingradient, SLOT(slotModifyWhite(int))); connect(m_page.gammaspin, SIGNAL(valueChanged(double)), m_page.ingradient, SLOT(slotModifyGamma(double))); connect(m_page.blackspin, SIGNAL(valueChanged(int)), this, SLOT(slotModifyInWhiteLimit(int))); connect(m_page.whitespin, SIGNAL(valueChanged(int)), this, SLOT(slotModifyInBlackLimit(int))); connect(m_page.ingradient, SIGNAL(sigModifiedBlack(int)), m_page.blackspin, SLOT(setValue(int))); connect(m_page.ingradient, SIGNAL(sigModifiedWhite(int)), m_page.whitespin, SLOT(setValue(int))); connect(m_page.ingradient, SIGNAL(sigModifiedGamma(double)), m_page.gammaspin, SLOT(setValue(double))); connect(m_page.outblackspin, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page.outwhitespin, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page.outblackspin, SIGNAL(valueChanged(int)), m_page.outgradient, SLOT(slotModifyBlack(int))); connect(m_page.outwhitespin, SIGNAL(valueChanged(int)), m_page.outgradient, SLOT(slotModifyWhite(int))); connect(m_page.outblackspin, SIGNAL(valueChanged(int)), this, SLOT(slotModifyOutWhiteLimit(int))); connect(m_page.outwhitespin, SIGNAL(valueChanged(int)), this, SLOT(slotModifyOutBlackLimit(int))); connect(m_page.outgradient, SIGNAL(sigModifiedBlack(int)), m_page.outblackspin, SLOT(setValue(int))); connect(m_page.outgradient, SIGNAL(sigModifiedWhite(int)), m_page.outwhitespin, SLOT(setValue(int))); connect(m_page.butauto, SIGNAL(clicked(bool)), this, SLOT(slotAutoLevel(void))); connect(m_page.butinvert, SIGNAL(clicked(bool)), this, SLOT(slotInvert(void))); connect((QObject*)(m_page.chkLogarithmic), SIGNAL(toggled(bool)), this, SLOT(slotDrawHistogram(bool))); KoHistogramProducer *producer = new KoGenericLabHistogramProducer(); m_histogram.reset( new KisHistogram(dev, dev->exactBounds(), producer, LINEAR) ); m_histlog = false; m_page.histview->resize(288,100); m_inverted = false; slotDrawHistogram(); } KisLevelConfigWidget::~KisLevelConfigWidget() { } void KisLevelConfigWidget::slotDrawHistogram(bool logarithmic) { int wHeight = m_page.histview->height(); int wHeightMinusOne = wHeight - 1; int wWidth = m_page.histview->width(); if (m_histlog != logarithmic) { // Update the m_histogram if (logarithmic) m_histogram->setHistogramType(LOGARITHMIC); else m_histogram->setHistogramType(LINEAR); m_histlog = logarithmic; } QPalette appPalette = QApplication::palette(); QPixmap pix(wWidth-100, wHeight); pix.fill(QColor(appPalette.color(QPalette::Base))); QPainter p(&pix); p.setPen(QPen(Qt::gray, 1, Qt::SolidLine)); double highest = (double)m_histogram->calculations().getHighest(); qint32 bins = m_histogram->producer()->numberOfBins(); // use nearest neighbour interpolation if (m_histogram->getHistogramType() == LINEAR) { double factor = (double)(wHeight - wHeight / 5.0) / highest; for (int i = 0; i < wWidth; i++) { int binNo = qRound((double)i / wWidth * (bins - 1)); if ((int)m_histogram->getValue(binNo) != 0) p.drawLine(i, wHeightMinusOne, i, wHeightMinusOne - (int)m_histogram->getValue(binNo) * factor); } } else { double factor = (double)(wHeight - wHeight / 5.0) / (double)log(highest); for (int i = 0; i < wWidth; i++) { int binNo = qRound((double)i / wWidth * (bins - 1)) ; if ((int)m_histogram->getValue(binNo) != 0) p.drawLine(i, wHeightMinusOne, i, wHeightMinusOne - log((double)m_histogram->getValue(binNo)) * factor); } } m_page.histview->setPixmap(pix); } void KisLevelConfigWidget::slotModifyInBlackLimit(int limit) { m_page.blackspin->setMaximum(limit - 1); } void KisLevelConfigWidget::slotModifyInWhiteLimit(int limit) { m_page.whitespin->setMinimum(limit + 1); } void KisLevelConfigWidget::slotModifyOutBlackLimit(int limit) { if (m_inverted) { m_page.outblackspin->setMinimum(limit + 1); } else { m_page.outblackspin->setMaximum(limit - 1); } } void KisLevelConfigWidget::slotModifyOutWhiteLimit(int limit) { if (m_inverted) { m_page.outwhitespin->setMaximum(limit - 1); } else { m_page.outwhitespin->setMinimum(limit + 1); } } void KisLevelConfigWidget::slotAutoLevel(void) { Q_ASSERT(m_histogram); qint32 num_bins = m_histogram->producer()->numberOfBins(); Q_ASSERT(num_bins > 1); int chosen_low_bin = 0, chosen_high_bin = num_bins-1; int count_thus_far = m_histogram->getValue(0); const int total_count = m_histogram->producer()->count(); const double threshold = 0.006; // find the low and hi point/bins based on summing count percentages // // this implementation is a port of GIMP's auto level implementation // (use a GPLv2 version as reference, specifically commit 51bfd07f18ef045a3e43632218fd92cae9ff1e48) for (int bin=0; bin<(num_bins-1); ++bin) { int next_count_thus_far = count_thus_far + m_histogram->getValue(bin+1); double this_percentage = static_cast(count_thus_far) / total_count; double next_percentage = static_cast(next_count_thus_far) / total_count; //dbgKrita << "bin" << bin << "this_percentage" << this_percentage << "next_percentage" << next_percentage; if (fabs(this_percentage - threshold) < fabs(next_percentage - threshold)) { chosen_low_bin = bin; break; } count_thus_far = next_count_thus_far; } count_thus_far = m_histogram->getValue(num_bins-1); for (int bin=(num_bins-1); bin>0; --bin) { int next_count_thus_far = count_thus_far + m_histogram->getValue(bin-1); double this_percentage = static_cast(count_thus_far) / total_count; double next_percentage = static_cast(next_count_thus_far) / total_count; //dbgKrita << "hi-bin" << bin << "this_percentage" << this_percentage << "next_percentage" << next_percentage; if (fabs(this_percentage - threshold) < fabs(next_percentage - threshold)) { chosen_high_bin = bin; break; } count_thus_far = next_count_thus_far; } if (chosen_low_bin < chosen_high_bin) { m_page.blackspin->setValue(chosen_low_bin); m_page.ingradient->slotModifyBlack(chosen_low_bin); m_page.whitespin->setValue(chosen_high_bin); m_page.ingradient->slotModifyWhite(chosen_high_bin); } } void KisLevelConfigWidget::slotInvert(void) { m_inverted = !m_inverted; int white = m_page.outwhitespin->value(); int black = m_page.outblackspin->value(); resetOutSpinLimit(); m_page.outgradient->setInverted(m_inverted); m_page.outwhitespin->setValue(black); m_page.outblackspin->setValue(white); } KisPropertiesConfigurationSP KisLevelConfigWidget::configuration() const { KisColorTransformationConfiguration * config = new KisColorTransformationConfiguration(KisLevelFilter::id().id(), 1); config->setProperty("blackvalue", m_page.blackspin->value()); config->setProperty("whitevalue", m_page.whitespin->value()); config->setProperty("gammavalue", m_page.gammaspin->value()); config->setProperty("outblackvalue", m_page.outblackspin->value()); config->setProperty("outwhitevalue", m_page.outwhitespin->value()); return config; } void KisLevelConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config) { QVariant value; if (config->getProperty("blackvalue", value)) { m_page.blackspin->setValue(value.toUInt()); m_page.ingradient->slotModifyBlack(value.toUInt()); } if (config->getProperty("whitevalue", value)) { m_page.whitespin->setValue(value.toUInt()); m_page.ingradient->slotModifyWhite(value.toUInt()); } if (config->getProperty("gammavalue", value)) { m_page.gammaspin->setValue(value.toUInt()); m_page.ingradient->slotModifyGamma(value.toDouble()); } if (config->getProperty("outblackvalue", value)) { m_page.outblackspin->setValue(value.toUInt()); m_page.outgradient->slotModifyBlack(value.toUInt()); } if (config->getProperty("outwhitevalue", value)) { m_page.outwhitespin->setValue(value.toUInt()); m_page.outgradient->slotModifyWhite(value.toUInt()); } } void KisLevelConfigWidget::resetOutSpinLimit() { if (m_inverted) { m_page.outblackspin->setMaximum(255); m_page.outwhitespin->setMinimum(0); } else { m_page.outblackspin->setMinimum(0); m_page.outwhitespin->setMaximum(255); } } diff --git a/plugins/filters/noisefilter/noisefilter.cpp b/plugins/filters/noisefilter/noisefilter.cpp index 403df4b30c..2dd29c3e05 100644 --- a/plugins/filters/noisefilter/noisefilter.cpp +++ b/plugins/filters/noisefilter/noisefilter.cpp @@ -1,148 +1,149 @@ /* * This file is part of the KDE project * * Copyright (c) 2005 Cyrille Berger * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "noisefilter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include "kis_wdg_noise.h" #include "ui_wdgnoiseoptions.h" #include K_PLUGIN_FACTORY_WITH_JSON(KritaNoiseFilterFactory, "kritanoisefilter.json", registerPlugin();) KritaNoiseFilter::KritaNoiseFilter(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(new KisFilterNoise()); } KritaNoiseFilter::~KritaNoiseFilter() { } -KisFilterNoise::KisFilterNoise() : KisFilter(id(), categoryOther(), i18n("&Random Noise...")) +KisFilterNoise::KisFilterNoise() : KisFilter(id(), FiltersCategoryOtherId, i18n("&Random Noise...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(true); } KisFilterConfigurationSP KisFilterNoise::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("noise", 1); config->setProperty("level", 50); config->setProperty("opacity", 100); config->setProperty("seedThreshold", rand()); config->setProperty("seedRed", rand()); config->setProperty("seedGreen", rand()); config->setProperty("seedBlue", rand()); return config; } KisConfigWidget * KisFilterNoise::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); return new KisWdgNoise((KisFilter*)this, (QWidget*)parent); } void KisFilterNoise::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { Q_ASSERT(!device.isNull()); const KoColorSpace * cs = device->colorSpace(); QVariant value; const int level = (config && config->getProperty("level", value)) ? value.toInt() : 50; const int opacity = (config && config->getProperty("opacity", value)) ? value.toInt() : 100; quint8* interm = new quint8[cs->pixelSize()]; const double threshold = (100.0 - level) * 0.01; qint16 weights[2]; weights[0] = (255 * opacity) / 100; weights[1] = 255 - weights[0]; const quint8* pixels[2]; pixels[0] = interm; KoMixColorsOp * mixOp = cs->mixColorsOp(); int seedThreshold = rand(); int seedRed = rand(); int seedGreen = rand(); int seedBlue = rand(); if (config) { seedThreshold = config->getInt("seedThreshold", seedThreshold); seedRed = config->getInt("seedRed", seedRed); seedGreen = config->getInt("seedGreen", seedGreen); seedBlue = config->getInt("seedBlue", seedBlue); } KisRandomGenerator randt(seedThreshold); KisRandomGenerator randr(seedRed); KisRandomGenerator randg(seedGreen); KisRandomGenerator randb(seedBlue); KisSequentialIteratorProgress it(device, applyRect, progressUpdater); while (it.nextPixel()) { if (randt.doubleRandomAt(it.x(), it.y()) > threshold) { // XXX: Added static_cast to get rid of warnings QColor c = qRgb(static_cast((double)randr.doubleRandomAt(it.x(), it.y()) * 255), static_cast((double)randg.doubleRandomAt(it.x(), it.y()) * 255), static_cast((double)randb.doubleRandomAt(it.x(), it.y()) * 255)); cs->fromQColor(c, interm, 0); pixels[1] = it.oldRawData(); mixOp->mixColors(pixels, weights, 2, it.rawData()); } } delete [] interm; } #include "noisefilter.moc" diff --git a/plugins/filters/normalize/kis_normalize.cpp b/plugins/filters/normalize/kis_normalize.cpp index 3eb77992e4..4726dd0d59 100644 --- a/plugins/filters/normalize/kis_normalize.cpp +++ b/plugins/filters/normalize/kis_normalize.cpp @@ -1,129 +1,130 @@ /* * * Copyright (c) 2015 Wolthera van Hövell tot Westerflier * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_normalize.h" #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include K_PLUGIN_FACTORY_WITH_JSON(KritaNormalizeFilterFactory, "kritanormalize.json", registerPlugin();) KritaNormalizeFilter::KritaNormalizeFilter(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(KisFilterSP(new KisFilterNormalize())); } KritaNormalizeFilter::~KritaNormalizeFilter() { } KisFilterNormalize::KisFilterNormalize() - : KisColorTransformationFilter(KoID("normalize" , i18n("Normalize")) - , KisFilter::categoryMap(), i18n("&Normalize...")) + : KisColorTransformationFilter(KoID("normalize", i18n("Normalize")), + FiltersCategoryMapId, i18n("&Normalize...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(true); setShowConfigurationWidget(false); } KoColorTransformation* KisFilterNormalize::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const { Q_UNUSED(config); return new KisNormalizeTransformation(cs); } KisNormalizeTransformation::KisNormalizeTransformation(const KoColorSpace* cs) : m_colorSpace(cs), m_psize(cs->pixelSize()) { } void KisNormalizeTransformation::transform(const quint8* src, quint8* dst, qint32 nPixels) const { QVector3D normal_vector; QVector channelValues(4); //if (m_colorSpace->colorDepthId().id()!="F16" && m_colorSpace->colorDepthId().id()!="F32" && m_colorSpace->colorDepthId().id()!="F64") { /* I don't know why, but the results of this are unexpected with a floating point space. * And manipulating the pixels gives strange results. */ while (nPixels--) { m_colorSpace->normalisedChannelsValue(src, channelValues); normal_vector.setX(channelValues[2]*2-1.0); normal_vector.setY(channelValues[1]*2-1.0); normal_vector.setZ(channelValues[0]*2-1.0); normal_vector.normalize(); channelValues[0]=normal_vector.z()*0.5+0.5; channelValues[1]=normal_vector.y()*0.5+0.5; channelValues[2]=normal_vector.x()*0.5+0.5; //channelValues[3]=1.0; m_colorSpace->fromNormalisedChannelsValue(dst, channelValues); dst[3]=src[3]; src += m_psize; dst += m_psize; } /* } else { while (nPixels--) { m_colorSpace->normalisedChannelsValue(src, channelValues); qreal max = qMax(channelValues[2], qMax(channelValues[1], channelValues[0])); qreal min = qMin(channelValues[2], qMin(channelValues[1], channelValues[0])); qreal range = max-min; normal_vector.setX( ((channelValues[2]-min)/range) *2.0-1.0); normal_vector.setY( ((channelValues[1]-min)/range) *2.0-1.0); normal_vector.setZ( ((channelValues[0]-min)/range) *2.0-1.0); normal_vector.normalize(); channelValues[2]=normal_vector.x()*0.5+0.5; channelValues[1]=normal_vector.y()*0.5+0.5; channelValues[0]=normal_vector.z()*0.5+0.5; //channelValues[3]=1.0; m_colorSpace->fromNormalisedChannelsValue(dst, channelValues); dst[3]=src[3]; //hack to trunucate values. m_colorSpace->toRgbA16(dst, reinterpret_cast(m_rgba), 1); m_colorSpace->fromRgbA16(reinterpret_cast(m_rgba), dst, 1); src += m_psize; dst += m_psize; } }*/ } #include "kis_normalize.moc" diff --git a/plugins/filters/oilpaintfilter/kis_oilpaint_filter.cpp b/plugins/filters/oilpaintfilter/kis_oilpaint_filter.cpp index 8df5ab8c87..8e2bb0d81b 100644 --- a/plugins/filters/oilpaintfilter/kis_oilpaint_filter.cpp +++ b/plugins/filters/oilpaintfilter/kis_oilpaint_filter.cpp @@ -1,203 +1,204 @@ /* * This file is part of Krita * * Copyright (c) 2004 Michael Thaler * Copyright (c) 2008 Cyrille Berger * * ported from digikam, Copyrighted by Gilles Caulier, * Original Oilpaint algorithm copyrighted 2004 by * Pieter Z. Voloshyn . * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_oilpaint_filter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include "widgets/kis_multi_integer_filter_widget.h" -KisOilPaintFilter::KisOilPaintFilter() : KisFilter(id(), KisFilter::categoryArtistic(), i18n("&Oilpaint...")) +KisOilPaintFilter::KisOilPaintFilter() : KisFilter(id(), FiltersCategoryArtisticId, i18n("&Oilpaint...")) { setSupportsPainting(true); setSupportsThreading(false); setSupportsAdjustmentLayers(true); } void KisOilPaintFilter::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { Q_ASSERT(!device.isNull()); //read the filter configuration values from the KisFilterConfiguration object const quint32 brushSize = config ? config->getInt("brushSize", 1) : 1; const quint32 smooth = config ? config->getInt("smooth", 30) : 30; OilPaint(device, device, applyRect, brushSize, smooth, progressUpdater); } // This method have been ported from Pieter Z. Voloshyn algorithm code. /* Function to apply the OilPaint effect. * * data => The image data in RGBA mode. * w => Width of image. * h => Height of image. * BrushSize => Brush size. * Smoothness => Smooth value. * * Theory => Using MostFrequentColor function we take the main color in * a matrix and simply write at the original position. */ void KisOilPaintFilter::OilPaint(const KisPaintDeviceSP src, KisPaintDeviceSP dst, const QRect &applyRect, int BrushSize, int Smoothness, KoUpdater* progressUpdater) const { KisSequentialConstIteratorProgress it(src, applyRect, progressUpdater); KisSequentialIterator dstIt(dst, applyRect); while (it.nextPixel() && dstIt.nextPixel()) { MostFrequentColor(src, dstIt.rawData(), applyRect, it.x(), it.y(), BrushSize, Smoothness); } } // This method has been ported from Pieter Z. Voloshyn's algorithm code in Digikam. /* Function to determine the most frequent color in a matrix * * Bits => Bits array * Width => Image width * Height => Image height * X => Position horizontal * Y => Position vertical * Radius => Is the radius of the matrix to be analyzed * Intensity => Intensity to calculate * * Theory => This function creates a matrix with the analyzed pixel in * the center of this matrix and find the most frequenty color */ void KisOilPaintFilter::MostFrequentColor(KisPaintDeviceSP src, quint8* dst, const QRect& bounds, int X, int Y, int Radius, int Intensity) const { uint I; double Scale = Intensity / 255.0; // Alloc some arrays to be used uchar *IntensityCount = new uchar[(Intensity + 1) * sizeof(uchar)]; const KoColorSpace* cs = src->colorSpace(); QVector channel(cs->channelCount()); QVector* AverageChannels = new QVector[(Intensity + 1)]; // Erase the array memset(IntensityCount, 0, (Intensity + 1) * sizeof(uchar)); int startx = qMax(X - Radius, bounds.left()); int starty = qMax(Y - Radius, bounds.top()); int width = (2 * Radius) + 1; if ((startx + width - 1) > bounds.right()) width = bounds.right() - startx + 1; Q_ASSERT((startx + width - 1) <= bounds.right()); int height = (2 * Radius) + 1; if ((starty + height) > bounds.bottom()) height = bounds.bottom() - starty + 1; Q_ASSERT((starty + height - 1) <= bounds.bottom()); KisSequentialConstIterator srcIt(src, QRect(startx, starty, width, height)); while (srcIt.nextPixel()) { cs->normalisedChannelsValue(srcIt.rawDataConst(), channel); I = (uint)(cs->intensity8(srcIt.rawDataConst()) * Scale); IntensityCount[I]++; if (IntensityCount[I] == 1) { AverageChannels[I] = channel; } else { for (int i = 0; i < channel.size(); i++) { AverageChannels[I][i] += channel[i]; } } } I = 0; int MaxInstance = 0; for (int i = 0 ; i <= Intensity ; ++i) { if (IntensityCount[i] > MaxInstance) { I = i; MaxInstance = IntensityCount[i]; } } if (MaxInstance != 0) { channel = AverageChannels[I]; for (int i = 0; i < channel.size(); i++) { channel[i] /= MaxInstance; } cs->fromNormalisedChannelsValue(dst, channel); } else { memset(dst, 0, cs->pixelSize()); cs->setOpacity(dst, OPACITY_OPAQUE_U8, 1); } delete [] IntensityCount; // free all the arrays delete [] AverageChannels; } KisConfigWidget * KisOilPaintFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { vKisIntegerWidgetParam param; param.push_back(KisIntegerWidgetParam(1, 5, 1, i18n("Brush size"), "brushSize")); param.push_back(KisIntegerWidgetParam(10, 255, 30, i18nc("smooth out the painting strokes the filter creates", "Smooth"), "smooth")); KisMultiIntegerFilterWidget * w = new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param); w->setConfiguration(factoryConfiguration()); return w; } KisFilterConfigurationSP KisOilPaintFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("oilpaint", 1); config->setProperty("brushSize", 1); config->setProperty("smooth", 30); return config; } diff --git a/plugins/filters/phongbumpmap/kis_phong_bumpmap_filter.cpp b/plugins/filters/phongbumpmap/kis_phong_bumpmap_filter.cpp index 21959aeed2..d3bae8c93e 100644 --- a/plugins/filters/phongbumpmap/kis_phong_bumpmap_filter.cpp +++ b/plugins/filters/phongbumpmap/kis_phong_bumpmap_filter.cpp @@ -1,238 +1,239 @@ /* * Copyright (c) 2010-2011 José Luis Vergara * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_phong_bumpmap_filter.h" #include "kis_phong_bumpmap_config_widget.h" #include "phong_pixel_processor.h" #include "kis_debug.h" #include "kis_paint_device.h" #include "kis_config_widget.h" #include "KoUpdater.h" #include "kis_math_toolbox.h" #include "KoColorSpaceRegistry.h" #include +#include #include #include "kis_iterator_ng.h" #include "kundo2command.h" #include "kis_painter.h" KisFilterPhongBumpmap::KisFilterPhongBumpmap() - : KisFilter(KoID("phongbumpmap" , i18n("Phong Bumpmap")), - KisFilter::categoryMap(), i18n("&Phong Bumpmap...")) + : KisFilter(KoID("phongbumpmap", i18n("Phong Bumpmap")), + FiltersCategoryMapId, i18n("&Phong Bumpmap...")) { setColorSpaceIndependence(TO_LAB16); setSupportsPainting(true); setSupportsLevelOfDetail(true); } void KisFilterPhongBumpmap::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater ) const { if (!config) return; if (progressUpdater) progressUpdater->setProgress(0); QString userChosenHeightChannel = config->getString(PHONG_HEIGHT_CHANNEL, "FAIL"); bool m_usenormalmap = config->getBool(USE_NORMALMAP_IS_ENABLED); if (userChosenHeightChannel == "FAIL") { qDebug("FIX YOUR FILTER"); return; } KoChannelInfo *m_heightChannel = 0; Q_FOREACH (KoChannelInfo* channel, device->colorSpace()->channels()) { if (userChosenHeightChannel == channel->name()) { m_heightChannel = channel; } } if (!m_heightChannel) { m_heightChannel = device->colorSpace()->channels().first(); } KIS_ASSERT_RECOVER_RETURN(m_heightChannel); QRect inputArea = applyRect; QRect outputArea = applyRect; if (m_usenormalmap==false) { inputArea.adjust(-1, -1, 1, 1); } quint32 posup; quint32 posdown; quint32 posleft; quint32 posright; QColor I; //Reflected light if (progressUpdater) progressUpdater->setProgress(1); //======Preparation paraphlenalia======= //Hardcoded facts about Phong Bumpmap: it _will_ generate an RGBA16 bumpmap const quint8 BYTE_DEPTH_OF_BUMPMAP = 2; // 16 bits per channel const quint8 CHANNEL_COUNT_OF_BUMPMAP = 4; // RGBA const quint32 pixelsOfInputArea = abs(inputArea.width() * inputArea.height()); const quint32 pixelsOfOutputArea = abs(outputArea.width() * outputArea.height()); const quint8 pixelSize = BYTE_DEPTH_OF_BUMPMAP * CHANNEL_COUNT_OF_BUMPMAP; const quint32 bytesToFillBumpmapArea = pixelsOfOutputArea * pixelSize; QVector bumpmap(bytesToFillBumpmapArea); quint8 *bumpmapDataPointer = bumpmap.data(); quint32 ki = KoChannelInfo::displayPositionToChannelIndex(m_heightChannel->displayPosition(), device->colorSpace()->channels()); PhongPixelProcessor tileRenderer(pixelsOfInputArea, config); if (progressUpdater) progressUpdater->setProgress(2); //===============RENDER================= QVector toDoubleFuncPtr(device->colorSpace()->channels().count()); KisMathToolbox mathToolbox; if (!mathToolbox.getToDoubleChannelPtr(device->colorSpace()->channels(), toDoubleFuncPtr)) { return; } KisHLineConstIteratorSP iterator; quint32 curPixel = 0; iterator = device->createHLineConstIteratorNG(inputArea.x(), inputArea.y(), inputArea.width() ); if (m_usenormalmap==false) { for (qint32 srcRow = 0; srcRow < inputArea.height(); ++srcRow) { do { const quint8 *data = iterator->oldRawData(); tileRenderer.realheightmap[curPixel] = toDoubleFuncPtr[ki](data, device->colorSpace()->channels()[ki]->pos()); curPixel++; } while (iterator->nextPixel()); iterator->nextRow(); } if (progressUpdater) progressUpdater->setProgress(50); const int tileHeightMinus1 = inputArea.height() - 1; const int tileWidthMinus1 = inputArea.width() - 1; // Foreach INNER pixel in tile for (int y = 1; y < tileHeightMinus1; ++y) { for (int x = 1; x < tileWidthMinus1; ++x) { posup = (y + 1) * inputArea.width() + x; posdown = (y - 1) * inputArea.width() + x; posleft = y * inputArea.width() + x - 1; posright = y * inputArea.width() + x + 1; memcpy(bumpmapDataPointer, tileRenderer.IlluminatePixelFromHeightmap(posup, posdown, posleft, posright).data(), pixelSize); bumpmapDataPointer += pixelSize; } } } else { for (qint32 srcRow = 0; srcRow < inputArea.height(); ++srcRow) { do { const quint8 *data = iterator->oldRawData(); tileRenderer.realheightmap[curPixel] = toDoubleFuncPtr[ki](data, device->colorSpace()->channels()[ki]->pos()); QVector current_pixel_values(4); device->colorSpace()->normalisedChannelsValue(data, current_pixel_values ); //dbgKrita<< "Vector:" << current_pixel_values[2] << "," << current_pixel_values[1] << "," << current_pixel_values[0]; memcpy(bumpmapDataPointer, tileRenderer.IlluminatePixelFromNormalmap(current_pixel_values[2], current_pixel_values[1], current_pixel_values[0]).data(), pixelSize); curPixel++; //pointer that crashes here, but not in the other if statement. bumpmapDataPointer += pixelSize; } while (iterator->nextPixel()); iterator->nextRow(); } } if (progressUpdater) progressUpdater->setProgress(90); KisPaintDeviceSP bumpmapPaintDevice = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb16()); bumpmapPaintDevice->writeBytes(bumpmap.data(), outputArea.x(), outputArea.y(), outputArea.width(), outputArea.height()); KUndo2Command *leaker = bumpmapPaintDevice->convertTo(device->colorSpace(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()); KisPainter copier(device); copier.bitBlt(outputArea.x(), outputArea.y(), bumpmapPaintDevice, outputArea.x(), outputArea.y(), outputArea.width(), outputArea.height()); //device->prepareClone(bumpmapPaintDevice); //device->makeCloneFrom(bumpmapPaintDevice, bumpmapPaintDevice->extent()); // THIS COULD BE BUG GY delete leaker; if (progressUpdater) progressUpdater->setProgress(100); } KisFilterConfigurationSP KisFilterPhongBumpmap::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id(), 2); config->setProperty(PHONG_AMBIENT_REFLECTIVITY, 0.2); config->setProperty(PHONG_DIFFUSE_REFLECTIVITY, 0.5); config->setProperty(PHONG_SPECULAR_REFLECTIVITY, 0.3); config->setProperty(PHONG_SHINYNESS_EXPONENT, 2); config->setProperty(USE_NORMALMAP_IS_ENABLED, false); config->setProperty(PHONG_DIFFUSE_REFLECTIVITY_IS_ENABLED, true); config->setProperty(PHONG_SPECULAR_REFLECTIVITY_IS_ENABLED, true); // Indexes are off by 1 simply because arrays start at 0 and the GUI naming scheme started at 1 config->setProperty(PHONG_ILLUMINANT_IS_ENABLED[0], true); config->setProperty(PHONG_ILLUMINANT_IS_ENABLED[1], true); config->setProperty(PHONG_ILLUMINANT_IS_ENABLED[2], false); config->setProperty(PHONG_ILLUMINANT_IS_ENABLED[3], false); config->setProperty(PHONG_ILLUMINANT_COLOR[0], QColor(255, 255, 0)); config->setProperty(PHONG_ILLUMINANT_COLOR[1], QColor(255, 0, 0)); config->setProperty(PHONG_ILLUMINANT_COLOR[2], QColor(0, 0, 255)); config->setProperty(PHONG_ILLUMINANT_COLOR[3], QColor(0, 255, 0)); config->setProperty(PHONG_ILLUMINANT_AZIMUTH[0], 50); config->setProperty(PHONG_ILLUMINANT_AZIMUTH[1], 100); config->setProperty(PHONG_ILLUMINANT_AZIMUTH[2], 150); config->setProperty(PHONG_ILLUMINANT_AZIMUTH[3], 200); config->setProperty(PHONG_ILLUMINANT_INCLINATION[0], 25); config->setProperty(PHONG_ILLUMINANT_INCLINATION[1], 20); config->setProperty(PHONG_ILLUMINANT_INCLINATION[2], 30); config->setProperty(PHONG_ILLUMINANT_INCLINATION[3], 40); return config; } QRect KisFilterPhongBumpmap::neededRect(const QRect &rect, const KisFilterConfigurationSP /*config*/, int /*lod*/) const { return rect.adjusted(-1, -1, 1, 1); } QRect KisFilterPhongBumpmap::changedRect(const QRect &rect, const KisFilterConfigurationSP /*config*/, int /*lod*/) const { return rect; } KisConfigWidget *KisFilterPhongBumpmap::createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev) const { KisPhongBumpmapConfigWidget *w = new KisPhongBumpmapConfigWidget(dev, parent); return w; } diff --git a/plugins/filters/pixelizefilter/kis_pixelize_filter.cpp b/plugins/filters/pixelizefilter/kis_pixelize_filter.cpp index 34c422ce23..704fab4ef1 100644 --- a/plugins/filters/pixelizefilter/kis_pixelize_filter.cpp +++ b/plugins/filters/pixelizefilter/kis_pixelize_filter.cpp @@ -1,162 +1,163 @@ /* * This file is part of Krita * * Copyright (c) 2005 Michael Thaler * * ported from Gimp, Copyright (C) 1997 Eiichi Takamori * original pixelize.c for GIMP 0.54 by Tracy Scott * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_pixelize_filter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include "widgets/kis_multi_integer_filter_widget.h" #include #include #include "kis_algebra_2d.h" #include "kis_lod_transform.h" -KisPixelizeFilter::KisPixelizeFilter() : KisFilter(id(), KisFilter::categoryArtistic(), i18n("&Pixelize...")) +KisPixelizeFilter::KisPixelizeFilter() : KisFilter(id(), FiltersCategoryArtisticId, i18n("&Pixelize...")) { setSupportsPainting(true); setSupportsThreading(true); setSupportsAdjustmentLayers(true); setSupportsLevelOfDetail(true); setColorSpaceIndependence(FULLY_INDEPENDENT); } void KisPixelizeFilter::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { Q_ASSERT(device); KisLodTransformScalar t(device); const int pixelWidth = qCeil(t.scale(config ? qMax(1, config->getInt("pixelWidth", 10)) : 10)); const int pixelHeight = qCeil(t.scale(config ? qMax(1, config->getInt("pixelHeight", 10)) : 10)); const qint32 pixelSize = device->pixelSize(); const QRect deviceBounds = device->defaultBounds()->bounds(); const int bufferSize = pixelSize * pixelWidth * pixelHeight; QScopedArrayPointer buffer(new quint8[bufferSize]); KoColor pixelColor(Qt::black, device->colorSpace()); KoMixColorsOp *mixOp = device->colorSpace()->mixColorsOp(); using namespace KisAlgebra2D; const qint32 firstCol = divideFloor(applyRect.x(), pixelWidth); const qint32 firstRow = divideFloor(applyRect.y(), pixelHeight); const qint32 lastCol = divideFloor(applyRect.x() + applyRect.width() - 1, pixelWidth); const qint32 lastRow = divideFloor(applyRect.y() + applyRect.height() - 1, pixelHeight); progressUpdater->setRange(firstRow, lastRow); for(qint32 i = firstRow; i <= lastRow; i++) { for(qint32 j = firstCol; j <= lastCol; j++) { const QRect maxPatchRect(j * pixelWidth, i * pixelHeight, pixelWidth, pixelHeight); const QRect pixelRect = maxPatchRect & deviceBounds; const int numColors = pixelRect.width() * pixelRect.height(); //read KisSequentialConstIterator srcIt(device, pixelRect); memset(buffer.data(), 0, bufferSize); quint8 *bufferPtr = buffer.data(); while (srcIt.nextPixel()) { memcpy(bufferPtr, srcIt.oldRawData(), pixelSize); bufferPtr += pixelSize; } // mix all the colors mixOp->mixColors(buffer.data(), numColors, pixelColor.data()); // write only colors in applyRect const QRect writeRect = pixelRect & applyRect; KisSequentialIterator dstIt(device, writeRect); while (dstIt.nextPixel()) { memcpy(dstIt.rawData(), pixelColor.data(), pixelSize); } } progressUpdater->setValue(i); } } QRect KisPixelizeFilter::neededRect(const QRect &rect, const KisFilterConfigurationSP config, int lod) const { KisLodTransformScalar t(lod); const int pixelWidth = qCeil(t.scale(config ? qMax(1, config->getInt("pixelWidth", 10)) : 10)); const int pixelHeight = qCeil(t.scale(config ? qMax(1, config->getInt("pixelHeight", 10)) : 10)); // TODO: make more precise calculation of the rect, including the alignment return rect.adjusted(-2*pixelWidth, -2*pixelHeight, 2*pixelWidth, 2*pixelHeight); } QRect KisPixelizeFilter::changedRect(const QRect &rect, const KisFilterConfigurationSP config, int lod) const { return neededRect(rect, config, lod); } KisConfigWidget * KisPixelizeFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { vKisIntegerWidgetParam param; param.push_back(KisIntegerWidgetParam(2, 512, 10, i18n("Pixel width"), "pixelWidth")); param.push_back(KisIntegerWidgetParam(2, 512, 10, i18n("Pixel height"), "pixelHeight")); return new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param); } KisFilterConfigurationSP KisPixelizeFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("pixelize", 1); config->setProperty("pixelWidth", 10); config->setProperty("pixelHeight", 10); return config; } diff --git a/plugins/filters/posterize/posterize.cpp b/plugins/filters/posterize/posterize.cpp index 4b7628b849..f62bdded0e 100644 --- a/plugins/filters/posterize/posterize.cpp +++ b/plugins/filters/posterize/posterize.cpp @@ -1,110 +1,111 @@ /* * Copyright (c) 2014 Manuel Riecke * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "posterize.h" #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include #include K_PLUGIN_FACTORY_WITH_JSON(PosterizeFactory, "kritaposterize.json", registerPlugin();) Posterize::Posterize(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(KisFilterSP(new KisFilterPosterize())); } Posterize::~Posterize() { } -KisFilterPosterize::KisFilterPosterize() : KisColorTransformationFilter(id(), categoryArtistic(), i18n("&Posterize...")) +KisFilterPosterize::KisFilterPosterize() : KisColorTransformationFilter(id(), FiltersCategoryArtisticId, i18n("&Posterize...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(true); setShowConfigurationWidget(true); } KoColorTransformation* KisFilterPosterize::createTransformation(const KoColorSpace* cs, const KisFilterConfigurationSP config) const { return new KisPosterizeColorTransformation(config->getInt("steps", 16), cs); } KisPosterizeColorTransformation::KisPosterizeColorTransformation(int steps, const KoColorSpace* cs) : m_colorSpace(cs), m_psize(cs->pixelSize()) { m_step = KoColorSpaceMathsTraits::max / steps; m_halfStep = m_step / 2; } KisConfigWidget* KisFilterPosterize::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); vKisIntegerWidgetParam param; param.push_back(KisIntegerWidgetParam(2, 128, 16, i18n("Steps"), "steps")); return new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param); } KisFilterConfigurationSP KisFilterPosterize::factoryConfiguration() const { KisColorTransformationConfigurationSP config = new KisColorTransformationConfiguration(id().id(), 0); config->setProperty("steps", 16); return config; } void KisPosterizeColorTransformation::transform(const quint8* src, quint8* dst, qint32 nPixels) const { quint16 m_rgba[4]; quint16 m_mod[4]; while (nPixels--) { m_colorSpace->toRgbA16(src, reinterpret_cast(m_rgba), 1); m_mod[0] = m_rgba[0] % m_step; m_mod[1] = m_rgba[1] % m_step; m_mod[2] = m_rgba[2] % m_step; m_mod[3] = m_rgba[3] % m_step; m_rgba[0] = m_rgba[0] + (m_mod[0] > m_halfStep ? m_step - m_mod[0] : -m_mod[0]); m_rgba[1] = m_rgba[1] + (m_mod[1] > m_halfStep ? m_step - m_mod[1] : -m_mod[1]); m_rgba[2] = m_rgba[2] + (m_mod[2] > m_halfStep ? m_step - m_mod[2] : -m_mod[2]); m_rgba[3] = m_rgba[3] + (m_mod[3] > m_halfStep ? m_step - m_mod[3] : -m_mod[3]); m_colorSpace->fromRgbA16(reinterpret_cast(m_rgba), dst, 1); src += m_psize; dst += m_psize; } } #include "posterize.moc" diff --git a/plugins/filters/raindropsfilter/kis_raindrops_filter.cpp b/plugins/filters/raindropsfilter/kis_raindrops_filter.cpp index d8ba327d32..6a4a61d61d 100644 --- a/plugins/filters/raindropsfilter/kis_raindrops_filter.cpp +++ b/plugins/filters/raindropsfilter/kis_raindrops_filter.cpp @@ -1,396 +1,397 @@ /* * This file is part of the KDE project * * Copyright (c) 2004 Michael Thaler * * ported from digikam, copyrighted 2004 by Gilles Caulier, * Original RainDrops algorithm copyrighted 2004 by * Pieter Z. Voloshyn . * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_raindrops_filter.h" #include #include #include #include #include #include #include #include #include #include "KoIntegerMaths.h" #include +#include #include #include #include #include #include #include #include #include #include #include "widgets/kis_multi_integer_filter_widget.h" KisRainDropsFilter::KisRainDropsFilter() - : KisFilter(id(), KisFilter::categoryArtistic(), i18n("&Raindrops...")) + : KisFilter(id(), FiltersCategoryArtisticId, i18n("&Raindrops...")) { setSupportsPainting(false); setSupportsThreading(false); setSupportsAdjustmentLayers(true); } // This method have been ported from Pieter Z. Voloshyn algorithm code. /* Function to apply the RainDrops effect (inspired from Jason Waltman code) * * data => The image data in RGBA mode. * Width => Width of image. * Height => Height of image. * DropSize => Raindrop size * number => Maximum number of raindrops * fishEyes => FishEye coefficient * * Theory => This functions does several math's functions and the engine * is simple to understand, but a little hard to implement. A * control will indicate if there is or not a raindrop in that * area, if not, a fisheye effect with a random size (max=DropSize) * will be applied, after this, a shadow will be applied too. * and after this, a blur function will finish the effect. */ void KisRainDropsFilter::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { QPoint srcTopLeft = applyRect.topLeft(); Q_ASSERT(device); //read the filter configuration values from the KisFilterConfiguration object quint32 DropSize = config->getInt("dropSize", 80); quint32 number = config->getInt("number", 80); quint32 fishEyes = config->getInt("fishEyes", 30); qsrand(config->getInt("seed")); if (fishEyes <= 0) fishEyes = 1; if (fishEyes > 100) fishEyes = 100; int Width = applyRect.width(); int Height = applyRect.height(); bool** BoolMatrix = CreateBoolArray(Width, Height); int i, j, k, l, m, n; // loop variables int Bright; // Bright value for shadows and highlights int x, y; // center coordinates int Counter = 0; // Counter (duh !) int NewSize; // Size of current raindrop int halfSize; // Half of the current raindrop int Radius; // Maximum radius for raindrop int BlurRadius; // Blur Radius int BlurPixels; double r, a; // polar coordinates double OldRadius; // Radius before processing double NewfishEyes = (double)fishEyes * 0.01; // FishEye fishEyesicients double s; double R, G, B; bool FindAnother = false; // To search for good coordinates const KoColorSpace * cs = device->colorSpace(); // Init boolean Matrix. for (i = 0 ; i < Width; ++i) { for (j = 0 ; j < Height; ++j) { BoolMatrix[i][j] = false; } } progressUpdater->setRange(0, number); KisRandomAccessorSP dstAccessor = device->createRandomAccessorNG(srcTopLeft.x(), srcTopLeft.y()); for (uint NumBlurs = 0; NumBlurs <= number; ++NumBlurs) { NewSize = (int)(qrand() * ((double)(DropSize - 5) / RAND_MAX) + 5); halfSize = NewSize / 2; Radius = halfSize; s = Radius / log(NewfishEyes * Radius + 1); Counter = 0; do { FindAnother = false; y = (int)(qrand() * ((double)(Width - 1) / RAND_MAX)); x = (int)(qrand() * ((double)(Height - 1) / RAND_MAX)); if (BoolMatrix[y][x]) FindAnother = true; else for (i = x - halfSize ; i <= x + halfSize; i++) for (j = y - halfSize ; j <= y + halfSize; j++) if ((i >= 0) && (i < Height) && (j >= 0) && (j < Width)) if (BoolMatrix[j][i]) FindAnother = true; Counter++; } while (FindAnother && Counter < 10000); if (Counter >= 10000) { NumBlurs = number; break; } for (i = -1 * halfSize ; i < NewSize - halfSize; i++) { for (j = -1 * halfSize ; j < NewSize - halfSize; j++) { r = sqrt((double)i * i + j * j); a = atan2(static_cast(i), static_cast(j)); if (r <= Radius) { OldRadius = r; r = (exp(r / s) - 1) / NewfishEyes; k = x + (int)(r * sin(a)); l = y + (int)(r * cos(a)); m = x + i; n = y + j; if ((k >= 0) && (k < Height) && (l >= 0) && (l < Width)) { if ((m >= 0) && (m < Height) && (n >= 0) && (n < Width)) { Bright = 0; if (OldRadius >= 0.9 * Radius) { if ((a <= 0) && (a > -2.25)) Bright = -80; else if ((a <= -2.25) && (a > -2.5)) Bright = -40; else if ((a <= 0.25) && (a > 0)) Bright = -40; } else if (OldRadius >= 0.8 * Radius) { if ((a <= -0.75) && (a > -1.50)) Bright = -40; else if ((a <= 0.10) && (a > -0.75)) Bright = -30; else if ((a <= -1.50) && (a > -2.35)) Bright = -30; } else if (OldRadius >= 0.7 * Radius) { if ((a <= -0.10) && (a > -2.0)) Bright = -20; else if ((a <= 2.50) && (a > 1.90)) Bright = 60; } else if (OldRadius >= 0.6 * Radius) { if ((a <= -0.50) && (a > -1.75)) Bright = -20; else if ((a <= 0) && (a > -0.25)) Bright = 20; else if ((a <= -2.0) && (a > -2.25)) Bright = 20; } else if (OldRadius >= 0.5 * Radius) { if ((a <= -0.25) && (a > -0.50)) Bright = 30; else if ((a <= -1.75) && (a > -2.0)) Bright = 30; } else if (OldRadius >= 0.4 * Radius) { if ((a <= -0.5) && (a > -1.75)) Bright = 40; } else if (OldRadius >= 0.3 * Radius) { if ((a <= 0) && (a > -2.25)) Bright = 30; } else if (OldRadius >= 0.2 * Radius) { if ((a <= -0.5) && (a > -1.75)) Bright = 20; } BoolMatrix[n][m] = true; QColor originalColor; dstAccessor->moveTo(srcTopLeft.x() + l, srcTopLeft.y() + k); cs->toQColor(dstAccessor->oldRawData(), &originalColor); int newRed = CLAMP(originalColor.red() + Bright, 0, quint8_MAX); int newGreen = CLAMP(originalColor.green() + Bright, 0, quint8_MAX); int newBlue = CLAMP(originalColor.blue() + Bright, 0, quint8_MAX); QColor newColor; newColor.setRgb(newRed, newGreen, newBlue); dstAccessor->moveTo(srcTopLeft.x() + n, srcTopLeft.y() + m); cs->fromQColor(newColor, dstAccessor->rawData()); } } } } } BlurRadius = NewSize / 25 + 1; for (i = -1 * halfSize - BlurRadius ; i < NewSize - halfSize + BlurRadius; i++) { for (j = -1 * halfSize - BlurRadius; j < NewSize - halfSize + BlurRadius; ++j) { r = sqrt((double)i * i + j * j); if (r <= Radius * 1.1) { R = G = B = 0; BlurPixels = 0; for (k = -1 * BlurRadius; k < BlurRadius + 1; k++) for (l = -1 * BlurRadius; l < BlurRadius + 1; l++) { m = x + i + k; n = y + j + l; if ((m >= 0) && (m < Height) && (n >= 0) && (n < Width)) { QColor color; dstAccessor->moveTo(srcTopLeft.x() + n, srcTopLeft.y() + m); cs->toQColor(dstAccessor->rawData(), &color); R += color.red(); G += color.green(); B += color.blue(); BlurPixels++; } } m = x + i; n = y + j; if ((m >= 0) && (m < Height) && (n >= 0) && (n < Width)) { QColor color; color.setRgb((int)(R / BlurPixels), (int)(G / BlurPixels), (int)(B / BlurPixels)); dstAccessor->moveTo(srcTopLeft.x() + n, srcTopLeft.y() + m); cs->fromQColor(color, dstAccessor->rawData()); } } } } progressUpdater->setValue(NumBlurs); } FreeBoolArray(BoolMatrix, Width); } // This method have been ported from Pieter Z. Voloshyn algorithm code. /* Function to free a dynamic boolean array * * lpbArray => Dynamic boolean array * Columns => The array bidimension value * * Theory => An easy to understand 'for' statement */ void KisRainDropsFilter::FreeBoolArray(bool** lpbArray, uint Columns) const { for (uint i = 0; i < Columns; ++i) free(lpbArray[i]); free(lpbArray); } /* Function to create a bidimentional dynamic boolean array * * Columns => Number of columns * Rows => Number of rows * * Theory => Using 'for' statement, we can alloc multiple dynamic arrays * To create more dimensions, just add some 'for's, ok? */ bool** KisRainDropsFilter::CreateBoolArray(uint Columns, uint Rows) const { bool** lpbArray = 0; lpbArray = (bool**) malloc(Columns * sizeof(bool*)); if (lpbArray == 0) return (0); for (uint i = 0; i < Columns; ++i) { lpbArray[i] = (bool*) malloc(Rows * sizeof(bool)); if (lpbArray[i] == 0) { FreeBoolArray(lpbArray, Columns); return (0); } } return (lpbArray); } // This method have been ported from Pieter Z. Voloshyn algorithm code. /* This function limits the RGB values * * ColorValue => Here, is an RGB value to be analyzed * * Theory => A color is represented in RGB value (e.g. 0xFFFFFF is * white color). But R, G and B values have 256 values to be used * so, this function analyzes the value and limits to this range */ uchar KisRainDropsFilter::LimitValues(int ColorValue) const { if (ColorValue > 255) // MAX = 255 ColorValue = 255; if (ColorValue < 0) // MIN = 0 ColorValue = 0; return ((uchar) ColorValue); } KisConfigWidget * KisRainDropsFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { vKisIntegerWidgetParam param; param.push_back(KisIntegerWidgetParam(1, 200, 80, i18n("Drop size"), "dropsize")); param.push_back(KisIntegerWidgetParam(1, 500, 80, i18n("Number"), "number")); param.push_back(KisIntegerWidgetParam(1, 100, 30, i18n("Fish eyes"), "fishEyes")); KisMultiIntegerFilterWidget * w = new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param); w->setConfiguration(factoryConfiguration()); return w; } KisFilterConfigurationSP KisRainDropsFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("raindrops", 2); config->setProperty("dropsize", 80); config->setProperty("number", 80); config->setProperty("fishEyes", 30); config->setProperty("seed", QTime::currentTime().msec()); return config; } diff --git a/plugins/filters/randompickfilter/randompickfilter.cpp b/plugins/filters/randompickfilter/randompickfilter.cpp index 0ab8aac28e..3d612485a9 100644 --- a/plugins/filters/randompickfilter/randompickfilter.cpp +++ b/plugins/filters/randompickfilter/randompickfilter.cpp @@ -1,156 +1,157 @@ /* * This file is part of the KDE project * * Copyright (c) 2005 Cyrille Berger * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "randompickfilter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include "kis_wdg_random_pick.h" #include "ui_wdgrandompickoptions.h" #include #include K_PLUGIN_FACTORY_WITH_JSON(KritaRandomPickFilterFactory, "kritarandompickfilter.json", registerPlugin();) KritaRandomPickFilter::KritaRandomPickFilter(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(new KisFilterRandomPick()); } KritaRandomPickFilter::~KritaRandomPickFilter() { } -KisFilterRandomPick::KisFilterRandomPick() : KisFilter(id(), categoryOther(), i18n("&Random Pick...")) +KisFilterRandomPick::KisFilterRandomPick() : KisFilter(id(), FiltersCategoryOtherId, i18n("&Random Pick...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(true); } void KisFilterRandomPick::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { Q_UNUSED(config); Q_ASSERT(!device.isNull()); const KoColorSpace * cs = device->colorSpace(); QVariant value; int level = (config && config->getProperty("level", value)) ? value.toInt() : 50; int opacity = (config && config->getProperty("opacity", value)) ? value.toInt() : 100; double windowsize = (config && config->getProperty("windowsize", value)) ? value.toDouble() : 2.5; int seedThreshold = rand(); int seedH = rand(); int seedV = rand(); if (config) { seedThreshold = config->getInt("seedThreshold", seedThreshold); seedH = config->getInt("seedH", seedH); seedV = config->getInt("seedV", seedV); } KisRandomGenerator randT(seedThreshold); KisRandomGenerator randH(seedH); KisRandomGenerator randV(seedV); KisSequentialIteratorProgress dstIt(device, applyRect, progressUpdater); KisRandomConstAccessorSP srcRA = device->createRandomConstAccessorNG(0, 0); double threshold = (100 - level) / 100.0; qint16 weights[2]; weights[0] = (255 * opacity) / 100; weights[1] = 255 - weights[0]; const quint8* pixels[2]; KoMixColorsOp * mixOp = cs->mixColorsOp(); while (dstIt.nextPixel()) { if (randT.doubleRandomAt(dstIt.x(), dstIt.y()) > threshold) { int x = static_cast(dstIt.x() + windowsize * (randH.doubleRandomAt(dstIt.x(), dstIt.y()) - 0.5)); int y = static_cast(dstIt.y() + windowsize * (randV.doubleRandomAt(dstIt.x(), dstIt.y()) -0.5)); srcRA->moveTo(x, y); pixels[0] = srcRA->oldRawData(); pixels[1] = dstIt.oldRawData(); mixOp->mixColors(pixels, weights, 2, dstIt.rawData()); } } } KisConfigWidget * KisFilterRandomPick::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP dev) const { Q_UNUSED(dev); return new KisWdgRandomPick((KisFilter*)this, (QWidget*)parent); } KisFilterConfigurationSP KisFilterRandomPick::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("randompick", 1); config->setProperty("level", 50); config->setProperty("windowsize", 2.5); config->setProperty("opacity", 100); config->setProperty("seedThreshold", rand()); config->setProperty("seedH", rand()); config->setProperty("seedV", rand()); return config; } QRect KisFilterRandomPick::neededRect(const QRect& rect, const KisFilterConfigurationSP config, int lod) const { Q_UNUSED(lod); QVariant value; int windowsize = ceil((config && config->getProperty("windowsize", value)) ? value.toDouble() : 2.5); return rect.adjusted(-windowsize, -windowsize, windowsize, windowsize); } QRect KisFilterRandomPick::changedRect(const QRect &rect, const KisFilterConfigurationSP config, int lod) const { return neededRect(rect, config, lod); } #include "randompickfilter.moc" diff --git a/plugins/filters/roundcorners/kis_round_corners_filter.cpp b/plugins/filters/roundcorners/kis_round_corners_filter.cpp index 5848e975f7..f0843fde5a 100644 --- a/plugins/filters/roundcorners/kis_round_corners_filter.cpp +++ b/plugins/filters/roundcorners/kis_round_corners_filter.cpp @@ -1,154 +1,155 @@ /* * This file is part of Krita * * Copyright (c) 2005 Michael Thaler * * ported from Gimp, Copyright (C) 1997 Eiichi Takamori * original pixelize.c for GIMP 0.54 by Tracy Scott * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_round_corners_filter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include #include #include -KisRoundCornersFilter::KisRoundCornersFilter() : KisFilter(id(), KisFilter::categoryMap(), i18n("&Round Corners...")) +KisRoundCornersFilter::KisRoundCornersFilter() : KisFilter(id(), FiltersCategoryMapId, i18n("&Round Corners...")) { setSupportsPainting(false); } void fadeOneCorner(KisPaintDeviceSP device, const QPoint &basePoint, const QRect &processRect, const qreal thresholdSq, KoUpdater* progressUpdater) { const KoColorSpace *cs = device->colorSpace(); KisSequentialIteratorProgress dstIt(device, processRect, progressUpdater); while (dstIt.nextPixel()) { const QPointF point(dstIt.x(), dstIt.y()); const qreal distanceSq = kisSquareDistance(point, basePoint); if (distanceSq >= thresholdSq) { cs->setOpacity(dstIt.rawData(), OPACITY_TRANSPARENT_U8, 1); } } } void KisRoundCornersFilter::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { Q_UNUSED(config); Q_ASSERT(!device.isNull()); if (!device || !config) { warnKrita << "Invalid parameters for round corner filter"; dbgPlugins << device << " " << config; return; } const QRect bounds = device->defaultBounds()->bounds(); const qint32 radius = qMin(KisAlgebra2D::minDimension(bounds) / 2, qMax(1, config->getInt("radius" , 30))); const qreal radiusSq = pow2(radius); struct CornerJob { QRect rc; QPoint pt; KoUpdater *progressUpdater; }; QVector jobs; KoProgressUpdater compositeUpdater(progressUpdater, KoProgressUpdater::Unthreaded); { QRect rc(bounds.x(), bounds.y(), radius, radius); QPoint pt(rc.bottomRight()); jobs << CornerJob({rc, pt, compositeUpdater.startSubtask()}); } { QRect rc(bounds.x() + bounds.width() - radius, bounds.y(), radius, radius); QPoint pt(rc.bottomLeft()); jobs << CornerJob({rc, pt, compositeUpdater.startSubtask()}); } { QRect rc(bounds.x(), bounds.y() + bounds.height() - radius, radius, radius); QPoint pt(rc.topRight()); jobs << CornerJob({rc, pt, compositeUpdater.startSubtask()}); } { QRect rc(bounds.x() + bounds.width() - radius, bounds.y() + bounds.height() - radius, radius, radius); QPoint pt(rc.topLeft()); jobs << CornerJob({rc, pt, compositeUpdater.startSubtask()}); } Q_FOREACH (const CornerJob &job, jobs) { const QRect processRect = job.rc & applyRect; if (!processRect.isEmpty()) { fadeOneCorner(device, job.pt, processRect, radiusSq, job.progressUpdater); } } } KisConfigWidget * KisRoundCornersFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { vKisIntegerWidgetParam param; param.push_back(KisIntegerWidgetParam(2, 100, 30, i18n("Radius"), "radius")); return new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param); } KisFilterConfigurationSP KisRoundCornersFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("roundcorners", 1); config->setProperty("radius", 30); return config; } diff --git a/plugins/filters/smalltilesfilter/kis_small_tiles_filter.cpp b/plugins/filters/smalltilesfilter/kis_small_tiles_filter.cpp index 0d1c3dd3c1..3479eeb6f1 100644 --- a/plugins/filters/smalltilesfilter/kis_small_tiles_filter.cpp +++ b/plugins/filters/smalltilesfilter/kis_small_tiles_filter.cpp @@ -1,112 +1,113 @@ /* * This file is part of Krita * * Copyright (c) 2005 Michael Thaler * * ported from Gimp, Copyright (C) 1997 Eiichi Takamori * original pixelize.c for GIMP 0.54 by Tracy Scott * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_small_tiles_filter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include "widgets/kis_multi_integer_filter_widget.h" -KisSmallTilesFilter::KisSmallTilesFilter() : KisFilter(id(), KisFilter::categoryMap(), i18n("&Small Tiles...")) +KisSmallTilesFilter::KisSmallTilesFilter() : KisFilter(id(), FiltersCategoryMapId, i18n("&Small Tiles...")) { setSupportsPainting(true); setSupportsThreading(false); setSupportsAdjustmentLayers(false); } void KisSmallTilesFilter::processImpl(KisPaintDeviceSP device, const QRect& /*applyRect*/, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { Q_ASSERT(!device.isNull()); //read the filter configuration values from the KisFilterConfiguration object quint32 numberOfTiles = config->getInt("numberOfTiles", 2); QRect srcRect = device->exactBounds(); int w = static_cast(srcRect.width() / numberOfTiles); int h = static_cast(srcRect.height() / numberOfTiles); KisPaintDeviceSP tile = device->createThumbnailDevice(srcRect.width() / numberOfTiles, srcRect.height() / numberOfTiles); if (tile.isNull()) return; KisPainter gc(device); gc.setCompositeOp(COMPOSITE_COPY); if (progressUpdater) { progressUpdater->setRange(0, numberOfTiles); } for (uint y = 0; y < numberOfTiles; ++y) { for (uint x = 0; x < numberOfTiles; ++x) { gc.bitBlt(w * x, h * y, tile, 0, 0, w, h); } if (progressUpdater) progressUpdater->setValue(y); } gc.end(); } KisConfigWidget * KisSmallTilesFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { vKisIntegerWidgetParam param; param.push_back(KisIntegerWidgetParam(2, 5, 1, i18n("Number of tiles"), "numberOfTiles")); return new KisMultiIntegerFilterWidget(id().id(), parent, id().id(), param); } KisFilterConfigurationSP KisSmallTilesFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("smalltiles", 1); config->setProperty("numberOfTiles", 2); return config; } diff --git a/plugins/filters/threshold/threshold.cpp b/plugins/filters/threshold/threshold.cpp index 8c52a1d02f..9c4fefbeeb 100644 --- a/plugins/filters/threshold/threshold.cpp +++ b/plugins/filters/threshold/threshold.cpp @@ -1,215 +1,216 @@ /* * This file is part of the KDE project * * Copyright (c) 2016 Boudewijn Rempt * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "threshold.h" #include #include #include #include #include #include #include +#include #include #include #include "KisGradientSlider.h" #include "kis_histogram.h" #include #include "kis_paint_device.h" #include "kis_painter.h" #include #include #include #include #include #include "KoColorModelStandardIds.h" #include #include #include K_PLUGIN_FACTORY_WITH_JSON(KritaThresholdFactory, "kritathreshold.json", registerPlugin();) KritaThreshold::KritaThreshold(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(new KisFilterThreshold()); } KritaThreshold::~KritaThreshold() { } KisFilterThreshold::KisFilterThreshold() - : KisFilter(id(), categoryAdjust(), i18n("&Threshold...")) + : KisFilter(id(), FiltersCategoryAdjustId, i18n("&Threshold...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(false); setShowConfigurationWidget(true); setSupportsLevelOfDetail(true); setSupportsAdjustmentLayers(true); setSupportsThreading(true); } void KisFilterThreshold::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater *progressUpdater) const { Q_ASSERT(!device.isNull()); const int threshold = config->getInt("threshold"); KoColor white(Qt::white, device->colorSpace()); KoColor black(Qt::black, device->colorSpace()); KisSequentialIteratorProgress it(device, applyRect, progressUpdater); const int pixelSize = device->colorSpace()->pixelSize(); while (it.nextPixel()) { if (device->colorSpace()->intensity8(it.oldRawData()) > threshold) { white.setOpacity(device->colorSpace()->opacityU8(it.oldRawData())); memcpy(it.rawData(), white.data(), pixelSize); } else { black.setOpacity(device->colorSpace()->opacityU8(it.oldRawData())); memcpy(it.rawData(), black.data(), pixelSize); } } } KisFilterConfigurationSP KisFilterThreshold::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("threshold", 1); config->setProperty("threshold", 128); return config; } KisConfigWidget *KisFilterThreshold::createConfigurationWidget(QWidget *parent, const KisPaintDeviceSP dev) const { return new KisThresholdConfigWidget(parent, dev); } KisThresholdConfigWidget::KisThresholdConfigWidget(QWidget * parent, KisPaintDeviceSP dev) : KisConfigWidget(parent) { Q_ASSERT(dev); m_page.setupUi(this); m_page.thresholdGradient->enableGamma(false); m_page.thresholdGradient->enableWhite(false); m_page.intThreshold->setValue(128); connect(m_page.intThreshold, SIGNAL(valueChanged(int)), SIGNAL(sigConfigurationItemChanged())); connect(m_page.thresholdGradient, SIGNAL(sigModifiedGamma(double)), SIGNAL(sigConfigurationItemChanged())); connect(m_page.intThreshold, SIGNAL(valueChanged(int)), m_page.thresholdGradient, SLOT(slotModifyBlack(int))); connect(m_page.thresholdGradient, SIGNAL(sigModifiedBlack(int)), m_page.intThreshold, SLOT(setValue(int))); connect((QObject*)(m_page.chkLogarithmic), SIGNAL(toggled(bool)), this, SLOT(slotDrawHistogram(bool))); KoHistogramProducer *producer = new KoGenericLabHistogramProducer(); m_histogram.reset( new KisHistogram(dev, dev->exactBounds(), producer, LINEAR) ); m_histlog = false; m_page.histview->resize(288,100); slotDrawHistogram(); } KisThresholdConfigWidget::~KisThresholdConfigWidget() { } void KisThresholdConfigWidget::slotDrawHistogram(bool logarithmic) { int wHeight = m_page.histview->height(); int wHeightMinusOne = wHeight - 1; int wWidth = m_page.histview->width(); if (m_histlog != logarithmic) { // Update the m_histogram if (logarithmic) m_histogram->setHistogramType(LOGARITHMIC); else m_histogram->setHistogramType(LINEAR); m_histlog = logarithmic; } QPalette appPalette = QApplication::palette(); QPixmap pix(wWidth-100, wHeight); pix.fill(QColor(appPalette.color(QPalette::Base))); QPainter p(&pix); p.setPen(QPen(Qt::gray, 1, Qt::SolidLine)); double highest = (double)m_histogram->calculations().getHighest(); qint32 bins = m_histogram->producer()->numberOfBins(); // use nearest neighbour interpolation if (m_histogram->getHistogramType() == LINEAR) { double factor = (double)(wHeight - wHeight / 5.0) / highest; for (int i = 0; i < wWidth; i++) { int binNo = qRound((double)i / wWidth * (bins - 1)); if ((int)m_histogram->getValue(binNo) != 0) p.drawLine(i, wHeightMinusOne, i, wHeightMinusOne - (int)m_histogram->getValue(binNo) * factor); } } else { double factor = (double)(wHeight - wHeight / 5.0) / (double)log(highest); for (int i = 0; i < wWidth; i++) { int binNo = qRound((double)i / wWidth * (bins - 1)) ; if ((int)m_histogram->getValue(binNo) != 0) p.drawLine(i, wHeightMinusOne, i, wHeightMinusOne - log((double)m_histogram->getValue(binNo)) * factor); } } m_page.histview->setPixmap(pix); } void KisThresholdConfigWidget::slotSetThreshold(int limit) { m_page.intThreshold->setMaximum(limit - 1); } KisPropertiesConfigurationSP KisThresholdConfigWidget::configuration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("threshold", 1); config->setProperty("threshold", m_page.intThreshold->value()); return config; } void KisThresholdConfigWidget::setConfiguration(const KisPropertiesConfigurationSP config) { QVariant value; if (config->getProperty("threshold", value)) { m_page.intThreshold->setValue(value.toUInt()); m_page.thresholdGradient->slotModifyBlack(value.toUInt()); } } #include "threshold.moc" diff --git a/plugins/filters/unsharp/kis_unsharp_filter.cpp b/plugins/filters/unsharp/kis_unsharp_filter.cpp index 2c6ffbcd3b..e860a0d522 100644 --- a/plugins/filters/unsharp/kis_unsharp_filter.cpp +++ b/plugins/filters/unsharp/kis_unsharp_filter.cpp @@ -1,228 +1,229 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include //MSVC requires that Vc come first #include "kis_unsharp_filter.h" #include #include #include #include #include +#include #include #include #include #include #include #include #include "kis_lod_transform.h" #include "kis_wdg_unsharp.h" #include "ui_wdgunsharp.h" #include "KoColorSpaceTraits.h" #include -KisUnsharpFilter::KisUnsharpFilter() : KisFilter(id(), categoryEnhance(), i18n("&Unsharp Mask...")) +KisUnsharpFilter::KisUnsharpFilter() : KisFilter(id(), FiltersCategoryEnhanceId, i18n("&Unsharp Mask...")) { setSupportsPainting(true); setSupportsAdjustmentLayers(true); setSupportsThreading(true); /** * Officially Unsharp Mask doesn't support LoD, because it * generates subtle artifacts when the unsharp radius is smaller * than current zoom level. But LoD devices can still appear when * the filter is used in Adjustment Layer. So the actual LoD is * still counted on. */ setSupportsLevelOfDetail(false); setColorSpaceIndependence(FULLY_INDEPENDENT); } KisConfigWidget * KisUnsharpFilter::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { return new KisWdgUnsharp(parent); } KisFilterConfigurationSP KisUnsharpFilter::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration(id().id(), 1); config->setProperty("halfSize", 1); config->setProperty("amount", 0.5); config->setProperty("threshold", 0); config->setProperty("lightnessOnly", true); return config; } void KisUnsharpFilter::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP _config, KoUpdater* progressUpdater ) const { QPointer filterUpdater = 0; QPointer convolutionUpdater = 0; QScopedPointer updater; if (progressUpdater) { updater.reset(new KoProgressUpdater(progressUpdater)); updater->start(100, i18n("Unsharp Mask")); // Two sub-sub tasks that each go from 0 to 100. convolutionUpdater = updater->startSubtask(); filterUpdater = updater->startSubtask(); } KisFilterConfigurationSP config = _config ? _config : new KisFilterConfiguration(id().id(), 1); QVariant value; KisLodTransformScalar t(device); const qreal halfSize = t.scale(config->getProperty("halfSize", value) ? value.toDouble() : 1.0); const qreal amount = (config->getProperty("amount", value)) ? value.toDouble() : 0.5; const uint threshold = (config->getProperty("threshold", value)) ? value.toUInt() : 0; const uint lightnessOnly = (config->getProperty("lightnessOnly", value)) ? value.toBool() : true; QBitArray channelFlags = config->channelFlags(); KisGaussianKernel::applyGaussian(device, applyRect, halfSize, halfSize, channelFlags, convolutionUpdater); qreal weights[2]; qreal factor = 128; weights[0] = factor * (1. + amount); weights[1] = -factor * amount; if (lightnessOnly) { processLightnessOnly(device, applyRect, threshold, weights, factor, channelFlags, filterUpdater); } else { processRaw(device, applyRect, threshold, weights, factor, channelFlags, filterUpdater); } } void KisUnsharpFilter::processRaw(KisPaintDeviceSP device, const QRect &rect, quint8 threshold, qreal weights[2], qreal factor, const QBitArray &channelFlags, KoUpdater *progressUpdater) const { const KoColorSpace *cs = device->colorSpace(); const int pixelSize = cs->pixelSize(); KoConvolutionOp * convolutionOp = cs->convolutionOp(); quint8 *colors[2]; colors[0] = new quint8[pixelSize]; colors[1] = new quint8[pixelSize]; KisSequentialIteratorProgress dstIt(device, rect, progressUpdater); while (dstIt.nextPixel()) { quint8 diff = 0; if (threshold == 1) { if (memcmp(dstIt.oldRawData(), dstIt.rawDataConst(), cs->pixelSize()) == 0) { diff = 1; } } else { diff = cs->difference(dstIt.oldRawData(), dstIt.rawDataConst()); } if (diff >= threshold) { memcpy(colors[0], dstIt.oldRawData(), pixelSize); memcpy(colors[1], dstIt.rawDataConst(), pixelSize); convolutionOp->convolveColors(colors, weights, dstIt.rawData(), factor, 0, 2, channelFlags); } else { memcpy(dstIt.rawData(), dstIt.oldRawData(), pixelSize); } } delete[] colors[0]; delete[] colors[1]; } void KisUnsharpFilter::processLightnessOnly(KisPaintDeviceSP device, const QRect &rect, quint8 threshold, qreal weights[2], qreal factor, const QBitArray & /*channelFlags*/, KoUpdater *progressUpdater) const { const KoColorSpace *cs = device->colorSpace(); const int pixelSize = cs->pixelSize(); quint16 labColorSrc[4]; quint16 labColorDst[4]; const int posL = 0; const int posAplha = 3; const qreal factorInv = 1.0 / factor; KisSequentialIteratorProgress dstIt(device, rect, progressUpdater); while (dstIt.nextPixel()) { quint8 diff = cs->differenceA(dstIt.oldRawData(), dstIt.rawDataConst()); if (diff >= threshold) { cs->toLabA16(dstIt.oldRawData(), (quint8*)labColorSrc, 1); cs->toLabA16(dstIt.rawDataConst(), (quint8*)labColorDst, 1); qint32 valueL = (labColorSrc[posL] * weights[0] + labColorDst[posL] * weights[1]) * factorInv; labColorSrc[posL] = CLAMP(valueL, KoColorSpaceMathsTraits::min, KoColorSpaceMathsTraits::max); qint32 valueAlpha = (labColorSrc[posAplha] * weights[0] + labColorDst[posAplha] * weights[1]) * factorInv; labColorSrc[posAplha] = CLAMP(valueAlpha, KoColorSpaceMathsTraits::min, KoColorSpaceMathsTraits::max); cs->fromLabA16((quint8*)labColorSrc, dstIt.rawData(), 1); } else { memcpy(dstIt.rawData(), dstIt.oldRawData(), pixelSize); } } } QRect KisUnsharpFilter::neededRect(const QRect & rect, const KisFilterConfigurationSP config, int lod) const { KisLodTransformScalar t(lod); QVariant value; const qreal halfSize = t.scale(config->getProperty("halfSize", value) ? value.toDouble() : 1.0); return rect.adjusted(-halfSize * 2, -halfSize * 2, halfSize * 2, halfSize * 2); } QRect KisUnsharpFilter::changedRect(const QRect & rect, const KisFilterConfigurationSP config, int lod) const { KisLodTransformScalar t(lod); QVariant value; const qreal halfSize = t.scale(config->getProperty("halfSize", value) ? value.toDouble() : 1.0); return rect.adjusted( -halfSize, -halfSize, halfSize, halfSize); } diff --git a/plugins/filters/wavefilter/wavefilter.cpp b/plugins/filters/wavefilter/wavefilter.cpp index 682ccda5b8..d074187b84 100644 --- a/plugins/filters/wavefilter/wavefilter.cpp +++ b/plugins/filters/wavefilter/wavefilter.cpp @@ -1,176 +1,177 @@ /* * This file is part of the KDE project * * Copyright (c) 2005 Cyrille Berger * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "wavefilter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include "kis_wdg_wave.h" #include "ui_wdgwaveoptions.h" #include #include K_PLUGIN_FACTORY_WITH_JSON(KritaWaveFilterFactory, "kritawavefilter.json", registerPlugin();) class KisWaveCurve { public: virtual ~KisWaveCurve() {} virtual double valueAt(int x, int y) = 0; }; class KisSinusoidalWaveCurve : public KisWaveCurve { public: KisSinusoidalWaveCurve(int amplitude, int wavelength, int shift) : m_amplitude(amplitude), m_wavelength(wavelength), m_shift(shift) { } ~KisSinusoidalWaveCurve() override {} double valueAt(int x, int y) override { return y + m_amplitude * cos((double)(m_shift + x) / m_wavelength); } private: int m_amplitude, m_wavelength, m_shift; }; class KisTriangleWaveCurve : public KisWaveCurve { public: KisTriangleWaveCurve(int amplitude, int wavelength, int shift) : m_amplitude(amplitude), m_wavelength(wavelength), m_shift(shift) { } ~KisTriangleWaveCurve() override {} double valueAt(int x, int y) override { return y + m_amplitude * pow(-1.0, (m_shift + x) / m_wavelength) *(0.5 - (double)((m_shift + x) % m_wavelength) / m_wavelength); } private: int m_amplitude, m_wavelength, m_shift; }; KritaWaveFilter::KritaWaveFilter(QObject *parent, const QVariantList &) : QObject(parent) { KisFilterRegistry::instance()->add(new KisFilterWave()); } KritaWaveFilter::~KritaWaveFilter() { } -KisFilterWave::KisFilterWave() : KisFilter(id(), categoryOther(), i18n("&Wave...")) +KisFilterWave::KisFilterWave() : KisFilter(id(), FiltersCategoryOtherId, i18n("&Wave...")) { setColorSpaceIndependence(FULLY_INDEPENDENT); setSupportsPainting(false); setSupportsAdjustmentLayers(false); } KisFilterConfigurationSP KisFilterWave::factoryConfiguration() const { KisFilterConfigurationSP config = new KisFilterConfiguration("wave", 1); config->setProperty("horizontalwavelength", 50); config->setProperty("horizontalshift", 50); config->setProperty("horizontalamplitude", 4); config->setProperty("horizontalshape", 0); config->setProperty("verticalwavelength", 50); config->setProperty("verticalshift", 50); config->setProperty("verticalamplitude", 4); config->setProperty("verticalshape", 0); return config; } KisConfigWidget * KisFilterWave::createConfigurationWidget(QWidget* parent, const KisPaintDeviceSP) const { return new KisWdgWave((KisFilter*)this, (QWidget*)parent); } void KisFilterWave::processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfigurationSP config, KoUpdater* progressUpdater ) const { Q_ASSERT(device.data() != 0); QVariant value; int horizontalwavelength = (config && config->getProperty("horizontalwavelength", value)) ? value.toInt() : 50; int horizontalshift = (config && config->getProperty("horizontalshift", value)) ? value.toInt() : 50; int horizontalamplitude = (config && config->getProperty("horizontalamplitude", value)) ? value.toInt() : 4; int horizontalshape = (config && config->getProperty("horizontalshape", value)) ? value.toInt() : 0; int verticalwavelength = (config && config->getProperty("verticalwavelength", value)) ? value.toInt() : 50; int verticalshift = (config && config->getProperty("verticalshift", value)) ? value.toInt() : 50; int verticalamplitude = (config && config->getProperty("verticalamplitude", value)) ? value.toInt() : 4; int verticalshape = (config && config->getProperty("verticalshape", value)) ? value.toInt() : 0; KisWaveCurve* verticalcurve; if (verticalshape == 1) verticalcurve = new KisTriangleWaveCurve(verticalamplitude, verticalwavelength, verticalshift); else verticalcurve = new KisSinusoidalWaveCurve(verticalamplitude, verticalwavelength, verticalshift); KisWaveCurve* horizontalcurve; if (horizontalshape == 1) horizontalcurve = new KisTriangleWaveCurve(horizontalamplitude, horizontalwavelength, horizontalshift); else horizontalcurve = new KisSinusoidalWaveCurve(horizontalamplitude, horizontalwavelength, horizontalshift); KisSequentialIteratorProgress dstIt(device, applyRect, progressUpdater); KisRandomSubAccessorSP srcRSA = device->createRandomSubAccessor(); while (dstIt.nextPixel()) { double xv = horizontalcurve->valueAt(dstIt.y(), dstIt.x()); double yv = verticalcurve->valueAt(dstIt.x(), dstIt.y()); srcRSA->moveTo(QPointF(xv, yv)); srcRSA->sampledOldRawData(dstIt.rawData()); } delete horizontalcurve; delete verticalcurve; } QRect KisFilterWave::neededRect(const QRect& rect, const KisFilterConfigurationSP config, int lod) const { Q_UNUSED(lod); QVariant value; int horizontalamplitude = (config && config->getProperty("horizontalamplitude", value)) ? value.toInt() : 4; int verticalamplitude = (config && config->getProperty("verticalamplitude", value)) ? value.toInt() : 4; return rect.adjusted(-horizontalamplitude, -verticalamplitude, horizontalamplitude, verticalamplitude); } #include "wavefilter.moc"