summaryrefslogtreecommitdiffstats
path: root/chalk/plugins
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2011-06-26 00:41:16 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2011-06-26 00:41:16 +0000
commit698569f8428ca088f764d704034a1330517b98c0 (patch)
treebf45be6946ebbbee9cce5a5bcf838f4c952d87e6 /chalk/plugins
parent2785103a6bd4de55bd26d79e34d0fdd4b329a73a (diff)
downloadkoffice-698569f8428ca088f764d704034a1330517b98c0.tar.gz
koffice-698569f8428ca088f764d704034a1330517b98c0.zip
Finish rebranding of Krita as Chalk
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1238363 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'chalk/plugins')
-rw-r--r--chalk/plugins/Makefile.am5
-rw-r--r--chalk/plugins/README42
-rw-r--r--chalk/plugins/configure.in.in2
-rw-r--r--chalk/plugins/filters/Makefile.am4
-rw-r--r--chalk/plugins/filters/blur/Makefile.am22
-rw-r--r--chalk/plugins/filters/blur/blur.cc50
-rw-r--r--chalk/plugins/filters/blur/blur.h37
-rw-r--r--chalk/plugins/filters/blur/chalkblurfilter.desktop38
-rw-r--r--chalk/plugins/filters/blur/kis_blur_filter.cc143
-rw-r--r--chalk/plugins/filters/blur/kis_blur_filter.h49
-rw-r--r--chalk/plugins/filters/blur/kis_wdg_blur.cc116
-rw-r--r--chalk/plugins/filters/blur/kis_wdg_blur.h50
-rw-r--r--chalk/plugins/filters/blur/wdgblur.ui227
-rw-r--r--chalk/plugins/filters/bumpmap/Makefile.am19
-rw-r--r--chalk/plugins/filters/bumpmap/bumpmap.cc533
-rw-r--r--chalk/plugins/filters/bumpmap/bumpmap.h130
-rw-r--r--chalk/plugins/filters/bumpmap/chalkbumpmapfilter.desktop71
-rw-r--r--chalk/plugins/filters/bumpmap/wdgbumpmap.ui374
-rw-r--r--chalk/plugins/filters/cimg/.kdev_ignore0
-rw-r--r--chalk/plugins/filters/cimg/CImg.h19174
-rw-r--r--chalk/plugins/filters/cimg/Makefile.am35
-rw-r--r--chalk/plugins/filters/cimg/chalkcimg.desktop79
-rw-r--r--chalk/plugins/filters/cimg/kis_cimg_filter.cc711
-rw-r--r--chalk/plugins/filters/cimg/kis_cimg_filter.h124
-rw-r--r--chalk/plugins/filters/cimg/kis_cimg_plugin.cc44
-rw-r--r--chalk/plugins/filters/cimg/kis_cimg_plugin.h32
-rw-r--r--chalk/plugins/filters/cimg/kis_cimgconfig_widget.cc94
-rw-r--r--chalk/plugins/filters/cimg/kis_cimgconfig_widget.h50
-rw-r--r--chalk/plugins/filters/cimg/wdg_cimg.ui298
-rw-r--r--chalk/plugins/filters/colorify/Colorify.cpp122
-rw-r--r--chalk/plugins/filters/colorify/Colorify.h56
-rw-r--r--chalk/plugins/filters/colorify/KisWdgColorify.cpp50
-rw-r--r--chalk/plugins/filters/colorify/KisWdgColorify.h45
-rw-r--r--chalk/plugins/filters/colorify/Makefile.am23
-rw-r--r--chalk/plugins/filters/colorify/WdgColorifyBase.ui97
-rw-r--r--chalk/plugins/filters/colorify/chalkcolorifyfilter.desktop42
-rw-r--r--chalk/plugins/filters/colors/Makefile.am21
-rw-r--r--chalk/plugins/filters/colors/chalkextensioncolorsfilters.desktop42
-rw-r--r--chalk/plugins/filters/colors/colors.cc53
-rw-r--r--chalk/plugins/filters/colors/colors.h37
-rw-r--r--chalk/plugins/filters/colors/kis_color_to_alpha.cc95
-rw-r--r--chalk/plugins/filters/colors/kis_color_to_alpha.h47
-rw-r--r--chalk/plugins/filters/colors/kis_minmax_filters.cc162
-rw-r--r--chalk/plugins/filters/colors/kis_minmax_filters.h56
-rw-r--r--chalk/plugins/filters/colors/kis_wdg_color_to_alpha.cc55
-rw-r--r--chalk/plugins/filters/colors/kis_wdg_color_to_alpha.h45
-rw-r--r--chalk/plugins/filters/colors/wdgcolortoalphabase.ui113
-rw-r--r--chalk/plugins/filters/colorsfilters/Makefile.am26
-rw-r--r--chalk/plugins/filters/colorsfilters/chalkcolorsfilter.desktop94
-rw-r--r--chalk/plugins/filters/colorsfilters/colorsfilters.cc315
-rw-r--r--chalk/plugins/filters/colorsfilters/colorsfilters.h73
-rw-r--r--chalk/plugins/filters/colorsfilters/kis_brightness_contrast_filter.cc347
-rw-r--r--chalk/plugins/filters/colorsfilters/kis_brightness_contrast_filter.h84
-rw-r--r--chalk/plugins/filters/colorsfilters/kis_perchannel_filter.cc421
-rw-r--r--chalk/plugins/filters/colorsfilters/kis_perchannel_filter.h100
-rw-r--r--chalk/plugins/filters/colorsfilters/wdg_brightness_contrast.ui292
-rw-r--r--chalk/plugins/filters/colorsfilters/wdg_perchannel.ui190
-rw-r--r--chalk/plugins/filters/convolutionfilters/Makefile.am28
-rw-r--r--chalk/plugins/filters/convolutionfilters/chalkconvolutionfilters.desktop75
-rw-r--r--chalk/plugins/filters/convolutionfilters/convolutionfilters.cc176
-rw-r--r--chalk/plugins/filters/convolutionfilters/convolutionfilters.h152
-rw-r--r--chalk/plugins/filters/convolutionfilters/kis_convolution_filter.cc138
-rw-r--r--chalk/plugins/filters/convolutionfilters/kis_convolution_filter.h99
-rw-r--r--chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter.cc93
-rw-r--r--chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter.h54
-rw-r--r--chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter_configuration_base_widget.ui189
-rw-r--r--chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter_configuration_widget.cc83
-rw-r--r--chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter_configuration_widget.h46
-rw-r--r--chalk/plugins/filters/cubismfilter/Makefile.am24
-rw-r--r--chalk/plugins/filters/cubismfilter/chalkcubismfilter.desktop85
-rw-r--r--chalk/plugins/filters/cubismfilter/kis_cubism_filter.cc453
-rw-r--r--chalk/plugins/filters/cubismfilter/kis_cubism_filter.h78
-rw-r--r--chalk/plugins/filters/cubismfilter/kis_cubism_filter_plugin.cc42
-rw-r--r--chalk/plugins/filters/cubismfilter/kis_cubism_filter_plugin.h32
-rw-r--r--chalk/plugins/filters/cubismfilter/kis_polygon.cc102
-rw-r--r--chalk/plugins/filters/cubismfilter/kis_polygon.h37
-rw-r--r--chalk/plugins/filters/embossfilter/Makefile.am24
-rw-r--r--chalk/plugins/filters/embossfilter/chalkembossfilter.desktop71
-rw-r--r--chalk/plugins/filters/embossfilter/kis_emboss_filter.cc179
-rw-r--r--chalk/plugins/filters/embossfilter/kis_emboss_filter.h62
-rw-r--r--chalk/plugins/filters/embossfilter/kis_emboss_filter_plugin.cc40
-rw-r--r--chalk/plugins/filters/embossfilter/kis_emboss_filter_plugin.h32
-rw-r--r--chalk/plugins/filters/example/Makefile.am22
-rw-r--r--chalk/plugins/filters/example/chalkexample.desktop81
-rw-r--r--chalk/plugins/filters/example/example.cc95
-rw-r--r--chalk/plugins/filters/example/example.h47
-rw-r--r--chalk/plugins/filters/fastcolortransfer/Makefile.am23
-rw-r--r--chalk/plugins/filters/fastcolortransfer/chalkfastcolortransfer.desktop69
-rw-r--r--chalk/plugins/filters/fastcolortransfer/fastcolortransfer.cc206
-rw-r--r--chalk/plugins/filters/fastcolortransfer/fastcolortransfer.h55
-rw-r--r--chalk/plugins/filters/fastcolortransfer/kis_wdg_fastcolortransfer.cpp50
-rw-r--r--chalk/plugins/filters/fastcolortransfer/kis_wdg_fastcolortransfer.h47
-rw-r--r--chalk/plugins/filters/fastcolortransfer/wdgfastcolortransfer.ui75
-rw-r--r--chalk/plugins/filters/halftone/kis_halftone.cpp190
-rw-r--r--chalk/plugins/filters/halftone/kis_halftone.h79
-rw-r--r--chalk/plugins/filters/imageenhancement/Makefile.am27
-rw-r--r--chalk/plugins/filters/imageenhancement/chalkimageenhancement.desktop80
-rw-r--r--chalk/plugins/filters/imageenhancement/imageenhancement.cpp73
-rw-r--r--chalk/plugins/filters/imageenhancement/imageenhancement.h34
-rw-r--r--chalk/plugins/filters/imageenhancement/kis_simple_noise_reducer.cpp129
-rw-r--r--chalk/plugins/filters/imageenhancement/kis_simple_noise_reducer.h59
-rw-r--r--chalk/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.cpp130
-rw-r--r--chalk/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.h68
-rw-r--r--chalk/plugins/filters/lenscorrectionfilter/Makefile.am23
-rw-r--r--chalk/plugins/filters/lenscorrectionfilter/chalklenscorrectionfilter.desktop69
-rw-r--r--chalk/plugins/filters/lenscorrectionfilter/kis_wdg_lens_correction.cpp74
-rw-r--r--chalk/plugins/filters/lenscorrectionfilter/kis_wdg_lens_correction.h44
-rw-r--r--chalk/plugins/filters/lenscorrectionfilter/lenscorrectionfilter.cc152
-rw-r--r--chalk/plugins/filters/lenscorrectionfilter/lenscorrectionfilter.h53
-rw-r--r--chalk/plugins/filters/lenscorrectionfilter/wdglenscorrectionoptions.ui229
-rw-r--r--chalk/plugins/filters/levelfilter/Makefile.am25
-rw-r--r--chalk/plugins/filters/levelfilter/chalklevelfilter.desktop73
-rw-r--r--chalk/plugins/filters/levelfilter/kgradientslider.cc338
-rw-r--r--chalk/plugins/filters/levelfilter/kgradientslider.h85
-rw-r--r--chalk/plugins/filters/levelfilter/kis_level_filter.cc324
-rw-r--r--chalk/plugins/filters/levelfilter/kis_level_filter.h94
-rw-r--r--chalk/plugins/filters/levelfilter/levelfilter.cc67
-rw-r--r--chalk/plugins/filters/levelfilter/levelfilter.h35
-rw-r--r--chalk/plugins/filters/levelfilter/wdg_level.ui331
-rw-r--r--chalk/plugins/filters/noisefilter/Makefile.am23
-rw-r--r--chalk/plugins/filters/noisefilter/chalknoisefilter.desktop77
-rw-r--r--chalk/plugins/filters/noisefilter/kis_wdg_noise.cpp59
-rw-r--r--chalk/plugins/filters/noisefilter/kis_wdg_noise.h44
-rw-r--r--chalk/plugins/filters/noisefilter/noisefilter.cc128
-rw-r--r--chalk/plugins/filters/noisefilter/noisefilter.h52
-rw-r--r--chalk/plugins/filters/noisefilter/wdgnoiseoptions.ui111
-rw-r--r--chalk/plugins/filters/oilpaintfilter/Makefile.am24
-rw-r--r--chalk/plugins/filters/oilpaintfilter/chalkoilpaintfilter.desktop77
-rw-r--r--chalk/plugins/filters/oilpaintfilter/kis_oilpaint_filter.cc256
-rw-r--r--chalk/plugins/filters/oilpaintfilter/kis_oilpaint_filter.h69
-rw-r--r--chalk/plugins/filters/oilpaintfilter/kis_oilpaint_filter_plugin.cc43
-rw-r--r--chalk/plugins/filters/oilpaintfilter/kis_oilpaint_filter_plugin.h32
-rw-r--r--chalk/plugins/filters/pixelizefilter/Makefile.am24
-rw-r--r--chalk/plugins/filters/pixelizefilter/chalkpixelizefilter.desktop83
-rw-r--r--chalk/plugins/filters/pixelizefilter/kis_pixelize_filter.cc188
-rw-r--r--chalk/plugins/filters/pixelizefilter/kis_pixelize_filter.h61
-rw-r--r--chalk/plugins/filters/pixelizefilter/kis_pixelize_filter_plugin.cc43
-rw-r--r--chalk/plugins/filters/pixelizefilter/kis_pixelize_filter_plugin.h32
-rw-r--r--chalk/plugins/filters/raindropsfilter/Makefile.am24
-rw-r--r--chalk/plugins/filters/raindropsfilter/chalkraindropsfilter.desktop81
-rw-r--r--chalk/plugins/filters/raindropsfilter/kis_raindrops_filter.cc439
-rw-r--r--chalk/plugins/filters/raindropsfilter/kis_raindrops_filter.h67
-rw-r--r--chalk/plugins/filters/raindropsfilter/kis_raindrops_filter_plugin.cc44
-rw-r--r--chalk/plugins/filters/raindropsfilter/kis_raindrops_filter_plugin.h33
-rw-r--r--chalk/plugins/filters/randompickfilter/Makefile.am23
-rw-r--r--chalk/plugins/filters/randompickfilter/chalkrandompickfilter.desktop65
-rw-r--r--chalk/plugins/filters/randompickfilter/kis_wdg_random_pick.cpp64
-rw-r--r--chalk/plugins/filters/randompickfilter/kis_wdg_random_pick.h44
-rw-r--r--chalk/plugins/filters/randompickfilter/randompickfilter.cc131
-rw-r--r--chalk/plugins/filters/randompickfilter/randompickfilter.h52
-rw-r--r--chalk/plugins/filters/randompickfilter/wdgrandompickoptions.ui135
-rw-r--r--chalk/plugins/filters/roundcorners/Makefile.am23
-rw-r--r--chalk/plugins/filters/roundcorners/chalkroundcornersfilter.desktop39
-rw-r--r--chalk/plugins/filters/roundcorners/kis_round_corners_filter.cc158
-rw-r--r--chalk/plugins/filters/roundcorners/kis_round_corners_filter.h58
-rw-r--r--chalk/plugins/filters/roundcorners/kis_round_corners_filter_plugin.cc43
-rw-r--r--chalk/plugins/filters/roundcorners/kis_round_corners_filter_plugin.h32
-rw-r--r--chalk/plugins/filters/smalltilesfilter/Makefile.am23
-rw-r--r--chalk/plugins/filters/smalltilesfilter/chalksmalltilesfilter.desktop39
-rw-r--r--chalk/plugins/filters/smalltilesfilter/kis_small_tiles_filter.cc187
-rw-r--r--chalk/plugins/filters/smalltilesfilter/kis_small_tiles_filter.h70
-rw-r--r--chalk/plugins/filters/smalltilesfilter/kis_small_tiles_filter_plugin.cc43
-rw-r--r--chalk/plugins/filters/smalltilesfilter/kis_small_tiles_filter_plugin.h32
-rw-r--r--chalk/plugins/filters/sobelfilter/Makefile.am23
-rw-r--r--chalk/plugins/filters/sobelfilter/chalksobelfilter.desktop39
-rw-r--r--chalk/plugins/filters/sobelfilter/kis_sobel_filter.cc217
-rw-r--r--chalk/plugins/filters/sobelfilter/kis_sobel_filter.h75
-rw-r--r--chalk/plugins/filters/sobelfilter/kis_sobel_filter_plugin.cc43
-rw-r--r--chalk/plugins/filters/sobelfilter/kis_sobel_filter_plugin.h32
-rw-r--r--chalk/plugins/filters/threadtest/Makefile.am18
-rw-r--r--chalk/plugins/filters/threadtest/chalkthreadtest.desktop38
-rw-r--r--chalk/plugins/filters/threadtest/threadtest.cc140
-rw-r--r--chalk/plugins/filters/threadtest/threadtest.h46
-rw-r--r--chalk/plugins/filters/unsharp/Makefile.am20
-rw-r--r--chalk/plugins/filters/unsharp/chalkunsharpfilter.desktop40
-rw-r--r--chalk/plugins/filters/unsharp/kis_unsharp_filter.cc152
-rw-r--r--chalk/plugins/filters/unsharp/kis_unsharp_filter.h47
-rw-r--r--chalk/plugins/filters/unsharp/kis_wdg_unsharp.cc52
-rw-r--r--chalk/plugins/filters/unsharp/kis_wdg_unsharp.h45
-rw-r--r--chalk/plugins/filters/unsharp/unsharp.cc50
-rw-r--r--chalk/plugins/filters/unsharp/unsharp.h37
-rw-r--r--chalk/plugins/filters/unsharp/wdgunsharp.ui138
-rw-r--r--chalk/plugins/filters/wavefilter/Makefile.am23
-rw-r--r--chalk/plugins/filters/wavefilter/chalkwavefilter.desktop72
-rw-r--r--chalk/plugins/filters/wavefilter/kis_wdg_wave.cpp90
-rw-r--r--chalk/plugins/filters/wavefilter/kis_wdg_wave.h44
-rw-r--r--chalk/plugins/filters/wavefilter/wavefilter.cc169
-rw-r--r--chalk/plugins/filters/wavefilter/wavefilter.h53
-rw-r--r--chalk/plugins/filters/wavefilter/wdgwaveoptions.ui281
-rw-r--r--chalk/plugins/paintops/Makefile.am2
-rw-r--r--chalk/plugins/paintops/defaultpaintops/Makefile.am39
-rw-r--r--chalk/plugins/paintops/defaultpaintops/README3
-rw-r--r--chalk/plugins/paintops/defaultpaintops/airbrush.pngbin0 -> 1038 bytes
-rw-r--r--chalk/plugins/paintops/defaultpaintops/chalkdefaultpaintops.desktop93
-rw-r--r--chalk/plugins/paintops/defaultpaintops/defaultpaintops_plugin.cc70
-rw-r--r--chalk/plugins/paintops/defaultpaintops/defaultpaintops_plugin.h36
-rw-r--r--chalk/plugins/paintops/defaultpaintops/eraser.pngbin0 -> 735 bytes
-rw-r--r--chalk/plugins/paintops/defaultpaintops/kis_airbrushop.cc150
-rw-r--r--chalk/plugins/paintops/defaultpaintops/kis_airbrushop.h60
-rw-r--r--chalk/plugins/paintops/defaultpaintops/kis_brushop.cc284
-rw-r--r--chalk/plugins/paintops/defaultpaintops/kis_brushop.h113
-rw-r--r--chalk/plugins/paintops/defaultpaintops/kis_convolveop.cc58
-rw-r--r--chalk/plugins/paintops/defaultpaintops/kis_convolveop.h56
-rw-r--r--chalk/plugins/paintops/defaultpaintops/kis_dlgbrushcurvecontrol.ui271
-rw-r--r--chalk/plugins/paintops/defaultpaintops/kis_duplicateop.cc341
-rw-r--r--chalk/plugins/paintops/defaultpaintops/kis_duplicateop.h62
-rw-r--r--chalk/plugins/paintops/defaultpaintops/kis_eraseop.cc140
-rw-r--r--chalk/plugins/paintops/defaultpaintops/kis_eraseop.h56
-rw-r--r--chalk/plugins/paintops/defaultpaintops/kis_penop.cc132
-rw-r--r--chalk/plugins/paintops/defaultpaintops/kis_penop.h58
-rw-r--r--chalk/plugins/paintops/defaultpaintops/kis_smudgeop.cc328
-rw-r--r--chalk/plugins/paintops/defaultpaintops/kis_smudgeop.h118
-rw-r--r--chalk/plugins/paintops/defaultpaintops/paintbrush.pngbin0 -> 770 bytes
-rw-r--r--chalk/plugins/paintops/defaultpaintops/pencil.pngbin0 -> 794 bytes
-rw-r--r--chalk/plugins/paintops/defaultpaintops/src/README2
-rw-r--r--chalk/plugins/paintops/defaultpaintops/src/pencil_01.svg637
-rw-r--r--chalk/plugins/paintops/defaultpaintops/src/pencil_jonathan_dietrich_01.svg434
-rw-r--r--chalk/plugins/paintops/defaultpaintops/src/pennello_mauro_olivo_01.svg616
-rw-r--r--chalk/plugins/tools/Makefile.am3
-rw-r--r--chalk/plugins/tools/defaulttools/Makefile.am83
-rw-r--r--chalk/plugins/tools/defaulttools/chalkdefaulttools.desktop56
-rw-r--r--chalk/plugins/tools/defaulttools/closedhand_cursor.xpm28
-rw-r--r--chalk/plugins/tools/defaulttools/default_tools.cc88
-rw-r--r--chalk/plugins/tools/defaulttools/default_tools.h44
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_brush.cc167
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_brush.h87
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_colorpicker.cc298
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_colorpicker.h88
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_duplicate.cc255
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_duplicate.h92
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_ellipse.cc186
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_ellipse.h91
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_fill.cc233
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_fill.h109
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_gradient.cc309
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_gradient.h124
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_line.cc254
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_line.h100
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_move.cc181
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_move.h89
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_pan.cc96
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_pan.h80
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_rectangle.cc187
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_rectangle.h96
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_text.cc198
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_text.h81
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_zoom.cc191
-rw-r--r--chalk/plugins/tools/defaulttools/kis_tool_zoom.h98
-rw-r--r--chalk/plugins/tools/defaulttools/openhand_cursor.xpm28
-rw-r--r--chalk/plugins/tools/defaulttools/tool_color_fill.pngbin0 -> 1102 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_colorpicker.pngbin0 -> 713 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_duplicate.pngbin0 -> 1087 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_duplicate_cursor.pngbin0 -> 309 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_ellipse.pngbin0 -> 524 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_ellipse_cursor.pngbin0 -> 309 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_fill_cursor.pngbin0 -> 516 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_freehand.pngbin0 -> 658 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_freehand_cursor.pngbin0 -> 261 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_gradient.pngbin0 -> 386 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_gradient_cursor.pngbin0 -> 294 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_line.pngbin0 -> 354 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_line_cursor.pngbin0 -> 248 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_move.pngbin0 -> 664 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_pan.pngbin0 -> 863 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_rectangle.pngbin0 -> 334 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_rectangle_cursor.pngbin0 -> 230 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_text.pngbin0 -> 891 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_text_cursor.pngbin0 -> 300 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_zoom.pngbin0 -> 877 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_zoom_minus_cursor.pngbin0 -> 283 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/tool_zoom_plus_cursor.pngbin0 -> 302 bytes
-rw-r--r--chalk/plugins/tools/defaulttools/wdgcolorpicker.ui167
-rw-r--r--chalk/plugins/tools/selectiontools/Makefile.am56
-rw-r--r--chalk/plugins/tools/selectiontools/chalkselectiontools.desktop52
-rw-r--r--chalk/plugins/tools/selectiontools/kis_tool_move_selection.cc223
-rw-r--r--chalk/plugins/tools/selectiontools/kis_tool_move_selection.h75
-rw-r--r--chalk/plugins/tools/selectiontools/kis_tool_select_brush.cc168
-rw-r--r--chalk/plugins/tools/selectiontools/kis_tool_select_brush.h83
-rw-r--r--chalk/plugins/tools/selectiontools/kis_tool_select_contiguous.cc234
-rw-r--r--chalk/plugins/tools/selectiontools/kis_tool_select_contiguous.h95
-rw-r--r--chalk/plugins/tools/selectiontools/kis_tool_select_elliptical.cc321
-rw-r--r--chalk/plugins/tools/selectiontools/kis_tool_select_elliptical.h99
-rw-r--r--chalk/plugins/tools/selectiontools/kis_tool_select_eraser.cc156
-rw-r--r--chalk/plugins/tools/selectiontools/kis_tool_select_eraser.h82
-rw-r--r--chalk/plugins/tools/selectiontools/kis_tool_select_outline.cc295
-rw-r--r--chalk/plugins/tools/selectiontools/kis_tool_select_outline.h101
-rw-r--r--chalk/plugins/tools/selectiontools/kis_tool_select_polygonal.cc315
-rw-r--r--chalk/plugins/tools/selectiontools/kis_tool_select_polygonal.h106
-rw-r--r--chalk/plugins/tools/selectiontools/kis_tool_select_rectangular.cc323
-rw-r--r--chalk/plugins/tools/selectiontools/kis_tool_select_rectangular.h95
-rw-r--r--chalk/plugins/tools/selectiontools/selection_tools.cc77
-rw-r--r--chalk/plugins/tools/selectiontools/selection_tools.h44
-rw-r--r--chalk/plugins/tools/selectiontools/tool_brush_selection.pngbin0 -> 1052 bytes
-rw-r--r--chalk/plugins/tools/selectiontools/tool_brush_selection.svg827
-rw-r--r--chalk/plugins/tools/selectiontools/tool_brush_selection_cursor.pngbin0 -> 339 bytes
-rw-r--r--chalk/plugins/tools/selectiontools/tool_contiguous_selection.pngbin0 -> 836 bytes
-rw-r--r--chalk/plugins/tools/selectiontools/tool_contiguous_selection_cursor.pngbin0 -> 321 bytes
-rw-r--r--chalk/plugins/tools/selectiontools/tool_elliptical_selection.pngbin0 -> 703 bytes
-rw-r--r--chalk/plugins/tools/selectiontools/tool_elliptical_selection.svg256
-rw-r--r--chalk/plugins/tools/selectiontools/tool_elliptical_selection_cursor.pngbin0 -> 296 bytes
-rw-r--r--chalk/plugins/tools/selectiontools/tool_eraser_selection.pngbin0 -> 1087 bytes
-rw-r--r--chalk/plugins/tools/selectiontools/tool_eraser_selection.svg1993
-rw-r--r--chalk/plugins/tools/selectiontools/tool_eraser_selection_cursor.pngbin0 -> 341 bytes
-rw-r--r--chalk/plugins/tools/selectiontools/tool_outline_selection.pngbin0 -> 556 bytes
-rw-r--r--chalk/plugins/tools/selectiontools/tool_outline_selection.svg329
-rw-r--r--chalk/plugins/tools/selectiontools/tool_outline_selection_cursor.pngbin0 -> 359 bytes
-rw-r--r--chalk/plugins/tools/selectiontools/tool_polygonal_selection.pngbin0 -> 576 bytes
-rw-r--r--chalk/plugins/tools/selectiontools/tool_polygonal_selection.svg364
-rw-r--r--chalk/plugins/tools/selectiontools/tool_polygonal_selection_cursor.pngbin0 -> 433 bytes
-rw-r--r--chalk/plugins/tools/selectiontools/tool_rect_selection.pngbin0 -> 523 bytes
-rw-r--r--chalk/plugins/tools/selectiontools/tool_rect_selection.svg191
-rw-r--r--chalk/plugins/tools/selectiontools/tool_rectangular_selection_cursor.pngbin0 -> 224 bytes
-rw-r--r--chalk/plugins/tools/tool_crop/Makefile.am37
-rw-r--r--chalk/plugins/tools/tool_crop/chalktoolcrop.desktop47
-rw-r--r--chalk/plugins/tools/tool_crop/kis_tool_crop.cc925
-rw-r--r--chalk/plugins/tools/tool_crop/kis_tool_crop.h149
-rw-r--r--chalk/plugins/tools/tool_crop/tool_crop.cc62
-rw-r--r--chalk/plugins/tools/tool_crop/tool_crop.h43
-rw-r--r--chalk/plugins/tools/tool_crop/tool_crop.pngbin0 -> 693 bytes
-rw-r--r--chalk/plugins/tools/tool_crop/tool_crop_cursor.pngbin0 -> 306 bytes
-rw-r--r--chalk/plugins/tools/tool_crop/wdg_tool_crop.ui216
-rw-r--r--chalk/plugins/tools/tool_curves/Makefile.am56
-rw-r--r--chalk/plugins/tools/tool_curves/chalktoolcurves.desktop36
-rw-r--r--chalk/plugins/tools/tool_curves/kis_curve_framework.cc260
-rw-r--r--chalk/plugins/tools/tool_curves/kis_curve_framework.h354
-rw-r--r--chalk/plugins/tools/tool_curves/kis_tool_bezier.cc366
-rw-r--r--chalk/plugins/tools/tool_curves/kis_tool_bezier.h98
-rw-r--r--chalk/plugins/tools/tool_curves/kis_tool_bezier_paint.cc115
-rw-r--r--chalk/plugins/tools/tool_curves/kis_tool_bezier_paint.h63
-rw-r--r--chalk/plugins/tools/tool_curves/kis_tool_bezier_select.cc104
-rw-r--r--chalk/plugins/tools/tool_curves/kis_tool_bezier_select.h63
-rw-r--r--chalk/plugins/tools/tool_curves/kis_tool_curve.cc593
-rw-r--r--chalk/plugins/tools/tool_curves/kis_tool_curve.h205
-rw-r--r--chalk/plugins/tools/tool_curves/kis_tool_example.cc108
-rw-r--r--chalk/plugins/tools/tool_curves/kis_tool_example.h67
-rw-r--r--chalk/plugins/tools/tool_curves/kis_tool_moutline.cc809
-rw-r--r--chalk/plugins/tools/tool_curves/kis_tool_moutline.h132
-rw-r--r--chalk/plugins/tools/tool_curves/tool_bezier_cursor.pngbin0 -> 2854 bytes
-rw-r--r--chalk/plugins/tools/tool_curves/tool_bezier_paint.pngbin0 -> 680 bytes
-rw-r--r--chalk/plugins/tools/tool_curves/tool_bezier_select.pngbin0 -> 637 bytes
-rw-r--r--chalk/plugins/tools/tool_curves/tool_curve_dragging.pngbin0 -> 2956 bytes
-rw-r--r--chalk/plugins/tools/tool_curves/tool_curves.cc67
-rw-r--r--chalk/plugins/tools/tool_curves/tool_curves.h36
-rw-r--r--chalk/plugins/tools/tool_curves/tool_example.pngbin0 -> 2918 bytes
-rw-r--r--chalk/plugins/tools/tool_curves/tool_example_cursor.pngbin0 -> 2854 bytes
-rw-r--r--chalk/plugins/tools/tool_curves/tool_moutline.pngbin0 -> 778 bytes
-rw-r--r--chalk/plugins/tools/tool_curves/tool_moutline_cursor.pngbin0 -> 2858 bytes
-rw-r--r--chalk/plugins/tools/tool_curves/tool_moutline_editing.pngbin0 -> 2968 bytes
-rw-r--r--chalk/plugins/tools/tool_curves/wdg_tool_example.ui128
-rw-r--r--chalk/plugins/tools/tool_filter/Makefile.am38
-rw-r--r--chalk/plugins/tools/tool_filter/chalktoolfilter.desktop92
-rw-r--r--chalk/plugins/tools/tool_filter/kis_filterop.cc154
-rw-r--r--chalk/plugins/tools/tool_filter/kis_filterop.h63
-rw-r--r--chalk/plugins/tools/tool_filter/kis_tool_filter.cc154
-rw-r--r--chalk/plugins/tools/tool_filter/kis_tool_filter.h81
-rw-r--r--chalk/plugins/tools/tool_filter/tool_filter.cc68
-rw-r--r--chalk/plugins/tools/tool_filter/tool_filter.h43
-rw-r--r--chalk/plugins/tools/tool_filter/tool_filter.pngbin0 -> 497 bytes
-rw-r--r--chalk/plugins/tools/tool_filter/tool_filter.svg468
-rw-r--r--chalk/plugins/tools/tool_filter/tool_filter_cursor.pngbin0 -> 295 bytes
-rw-r--r--chalk/plugins/tools/tool_perspectivegrid/Makefile.am35
-rw-r--r--chalk/plugins/tools/tool_perspectivegrid/chalktoolperspectivegrid.desktop35
-rw-r--r--chalk/plugins/tools/tool_perspectivegrid/kis_tool_perspectivegrid.cc499
-rw-r--r--chalk/plugins/tools/tool_perspectivegrid/kis_tool_perspectivegrid.h111
-rw-r--r--chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.cc62
-rw-r--r--chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.h43
-rw-r--r--chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.pngbin0 -> 738 bytes
-rw-r--r--chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.svg87
-rw-r--r--chalk/plugins/tools/tool_perspectivetransform/Makefile.am35
-rw-r--r--chalk/plugins/tools/tool_perspectivetransform/chalktoolperspectivetransform.desktop37
-rw-r--r--chalk/plugins/tools/tool_perspectivetransform/kis_tool_perspectivetransform.cc742
-rw-r--r--chalk/plugins/tools/tool_perspectivetransform/kis_tool_perspectivetransform.h131
-rw-r--r--chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.cc63
-rw-r--r--chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.h43
-rw-r--r--chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.pngbin0 -> 691 bytes
-rw-r--r--chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.svg87
-rw-r--r--chalk/plugins/tools/tool_polygon/Makefile.am36
-rw-r--r--chalk/plugins/tools/tool_polygon/chalktoolpolygon.desktop52
-rw-r--r--chalk/plugins/tools/tool_polygon/kis_tool_polygon.cc252
-rw-r--r--chalk/plugins/tools/tool_polygon/kis_tool_polygon.h102
-rw-r--r--chalk/plugins/tools/tool_polygon/tool_polygon.cc62
-rw-r--r--chalk/plugins/tools/tool_polygon/tool_polygon.h39
-rw-r--r--chalk/plugins/tools/tool_polygon/tool_polygon.pngbin0 -> 773 bytes
-rw-r--r--chalk/plugins/tools/tool_polygon/tool_polygon_cursor.pngbin0 -> 402 bytes
-rw-r--r--chalk/plugins/tools/tool_polyline/Makefile.am36
-rw-r--r--chalk/plugins/tools/tool_polyline/chalktoolpolyline.desktop49
-rw-r--r--chalk/plugins/tools/tool_polyline/kis_tool_polyline.cc271
-rw-r--r--chalk/plugins/tools/tool_polyline/kis_tool_polyline.h109
-rw-r--r--chalk/plugins/tools/tool_polyline/polyline.pngbin0 -> 587 bytes
-rw-r--r--chalk/plugins/tools/tool_polyline/tool_polyline.cc64
-rw-r--r--chalk/plugins/tools/tool_polyline/tool_polyline.h43
-rw-r--r--chalk/plugins/tools/tool_polyline/tool_polyline_cursor.pngbin0 -> 397 bytes
-rw-r--r--chalk/plugins/tools/tool_selectsimilar/Makefile.am32
-rw-r--r--chalk/plugins/tools/tool_selectsimilar/chalktoolselectsimilar.desktop43
-rw-r--r--chalk/plugins/tools/tool_selectsimilar/kis_tool_selectsimilar.cc271
-rw-r--r--chalk/plugins/tools/tool_selectsimilar/kis_tool_selectsimilar.h102
-rw-r--r--chalk/plugins/tools/tool_selectsimilar/selectsimilar.cc61
-rw-r--r--chalk/plugins/tools/tool_selectsimilar/selectsimilar.h35
-rw-r--r--chalk/plugins/tools/tool_selectsimilar/tool_similar_selection.pngbin0 -> 724 bytes
-rw-r--r--chalk/plugins/tools/tool_selectsimilar/tool_similar_selection.svg2118
-rw-r--r--chalk/plugins/tools/tool_selectsimilar/tool_similar_selection_minus_cursor.pngbin0 -> 613 bytes
-rw-r--r--chalk/plugins/tools/tool_selectsimilar/tool_similar_selection_plus_cursor.pngbin0 -> 630 bytes
-rw-r--r--chalk/plugins/tools/tool_star/Makefile.am37
-rw-r--r--chalk/plugins/tools/tool_star/chalktoolstar.desktop52
-rw-r--r--chalk/plugins/tools/tool_star/kis_tool_star.cc245
-rw-r--r--chalk/plugins/tools/tool_star/kis_tool_star.h101
-rw-r--r--chalk/plugins/tools/tool_star/tool_star.cc62
-rw-r--r--chalk/plugins/tools/tool_star/tool_star.h43
-rw-r--r--chalk/plugins/tools/tool_star/tool_star.pngbin0 -> 625 bytes
-rw-r--r--chalk/plugins/tools/tool_star/tool_star_cursor.pngbin0 -> 367 bytes
-rw-r--r--chalk/plugins/tools/tool_star/wdg_tool_star.ui128
-rw-r--r--chalk/plugins/tools/tool_transform/Makefile.am37
-rw-r--r--chalk/plugins/tools/tool_transform/chalktooltransform.desktop46
-rw-r--r--chalk/plugins/tools/tool_transform/kis_tool_transform.cc916
-rw-r--r--chalk/plugins/tools/tool_transform/kis_tool_transform.h155
-rw-r--r--chalk/plugins/tools/tool_transform/rotate_cursor.xpm29
-rw-r--r--chalk/plugins/tools/tool_transform/tool_transform.cc64
-rw-r--r--chalk/plugins/tools/tool_transform/tool_transform.h43
-rw-r--r--chalk/plugins/tools/tool_transform/tool_transform.pngbin0 -> 458 bytes
-rw-r--r--chalk/plugins/tools/tool_transform/wdg_tool_transform.ui243
-rw-r--r--chalk/plugins/viewplugins/Makefile.am24
-rw-r--r--chalk/plugins/viewplugins/colorrange/Makefile.am25
-rw-r--r--chalk/plugins/viewplugins/colorrange/chalkcolorrange.desktop40
-rw-r--r--chalk/plugins/viewplugins/colorrange/colorrange.cc82
-rw-r--r--chalk/plugins/viewplugins/colorrange/colorrange.h45
-rw-r--r--chalk/plugins/viewplugins/colorrange/colorrange.rc10
-rw-r--r--chalk/plugins/viewplugins/colorrange/dlg_colorrange.cc351
-rw-r--r--chalk/plugins/viewplugins/colorrange/dlg_colorrange.h100
-rw-r--r--chalk/plugins/viewplugins/colorrange/wdg_colorrange.ui252
-rw-r--r--chalk/plugins/viewplugins/colorspaceconversion/Makefile.am27
-rw-r--r--chalk/plugins/viewplugins/colorspaceconversion/chalkcolorspaceconversion.desktop40
-rw-r--r--chalk/plugins/viewplugins/colorspaceconversion/colorspaceconversion.cc155
-rw-r--r--chalk/plugins/viewplugins/colorspaceconversion/colorspaceconversion.h51
-rw-r--r--chalk/plugins/viewplugins/colorspaceconversion/colorspaceconversion.rc11
-rw-r--r--chalk/plugins/viewplugins/colorspaceconversion/dlg_colorspaceconversion.cc91
-rw-r--r--chalk/plugins/viewplugins/colorspaceconversion/dlg_colorspaceconversion.h50
-rw-r--r--chalk/plugins/viewplugins/colorspaceconversion/wdgconvertcolorspace.ui218
-rw-r--r--chalk/plugins/viewplugins/dropshadow/Makefile.am31
-rw-r--r--chalk/plugins/viewplugins/dropshadow/chalkdropshadow.desktop39
-rw-r--r--chalk/plugins/viewplugins/dropshadow/dlg_dropshadow.cc117
-rw-r--r--chalk/plugins/viewplugins/dropshadow/dlg_dropshadow.h60
-rw-r--r--chalk/plugins/viewplugins/dropshadow/dropshadow.rc11
-rw-r--r--chalk/plugins/viewplugins/dropshadow/kis_dropshadow.cc758
-rw-r--r--chalk/plugins/viewplugins/dropshadow/kis_dropshadow.h72
-rw-r--r--chalk/plugins/viewplugins/dropshadow/kis_dropshadow_plugin.cc91
-rw-r--r--chalk/plugins/viewplugins/dropshadow/kis_dropshadow_plugin.h46
-rw-r--r--chalk/plugins/viewplugins/dropshadow/wdg_dropshadow.ui235
-rw-r--r--chalk/plugins/viewplugins/filtersgallery/Makefile.am26
-rw-r--r--chalk/plugins/viewplugins/filtersgallery/chalkfiltersgallery.desktop45
-rw-r--r--chalk/plugins/viewplugins/filtersgallery/chalkfiltersgallery.rc9
-rw-r--r--chalk/plugins/viewplugins/filtersgallery/filters_gallery.cc138
-rw-r--r--chalk/plugins/viewplugins/filtersgallery/filters_gallery.h54
-rw-r--r--chalk/plugins/viewplugins/filtersgallery/kis_dlg_filtersgallery.cc133
-rw-r--r--chalk/plugins/viewplugins/filtersgallery/kis_dlg_filtersgallery.h69
-rw-r--r--chalk/plugins/viewplugins/filtersgallery/kis_wdg_filtersgallery.ui123
-rw-r--r--chalk/plugins/viewplugins/histogram/Makefile.am25
-rw-r--r--chalk/plugins/viewplugins/histogram/chalkhistogram.desktop43
-rw-r--r--chalk/plugins/viewplugins/histogram/dlg_histogram.cc68
-rw-r--r--chalk/plugins/viewplugins/histogram/dlg_histogram.h58
-rw-r--r--chalk/plugins/viewplugins/histogram/histogram.cc105
-rw-r--r--chalk/plugins/viewplugins/histogram/histogram.h50
-rw-r--r--chalk/plugins/viewplugins/histogram/histogram.rc10
-rw-r--r--chalk/plugins/viewplugins/histogram/kis_histogram_widget.cc147
-rw-r--r--chalk/plugins/viewplugins/histogram/kis_histogram_widget.h55
-rw-r--r--chalk/plugins/viewplugins/histogram/wdghistogram.ui229
-rw-r--r--chalk/plugins/viewplugins/histogram_docker/Makefile.am22
-rw-r--r--chalk/plugins/viewplugins/histogram_docker/chalkhistogramdocker.desktop40
-rw-r--r--chalk/plugins/viewplugins/histogram_docker/chalkhistogramdocker.rc3
-rw-r--r--chalk/plugins/viewplugins/histogram_docker/histogramdocker.cc192
-rw-r--r--chalk/plugins/viewplugins/histogram_docker/histogramdocker.h81
-rw-r--r--chalk/plugins/viewplugins/histogram_docker/kis_accumulating_producer.cc102
-rw-r--r--chalk/plugins/viewplugins/histogram_docker/kis_accumulating_producer.h77
-rw-r--r--chalk/plugins/viewplugins/histogram_docker/kis_cachedhistogram.cc37
-rw-r--r--chalk/plugins/viewplugins/histogram_docker/kis_cachedhistogram.h53
-rw-r--r--chalk/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.cc162
-rw-r--r--chalk/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.h81
-rw-r--r--chalk/plugins/viewplugins/history_docker/Makefile.am18
-rw-r--r--chalk/plugins/viewplugins/history_docker/chalkhistorydocker.desktop73
-rw-r--r--chalk/plugins/viewplugins/history_docker/historydocker.cc58
-rw-r--r--chalk/plugins/viewplugins/history_docker/historydocker.h34
-rw-r--r--chalk/plugins/viewplugins/imagesize/Makefile.am25
-rw-r--r--chalk/plugins/viewplugins/imagesize/chalkimagesize.desktop39
-rw-r--r--chalk/plugins/viewplugins/imagesize/configure.in.in1
-rw-r--r--chalk/plugins/viewplugins/imagesize/dlg_imagesize.cc277
-rw-r--r--chalk/plugins/viewplugins/imagesize/dlg_imagesize.h83
-rw-r--r--chalk/plugins/viewplugins/imagesize/dlg_layersize.cc261
-rw-r--r--chalk/plugins/viewplugins/imagesize/dlg_layersize.h74
-rw-r--r--chalk/plugins/viewplugins/imagesize/imagesize.cc190
-rw-r--r--chalk/plugins/viewplugins/imagesize/imagesize.h49
-rw-r--r--chalk/plugins/viewplugins/imagesize/imagesize.rc15
-rw-r--r--chalk/plugins/viewplugins/imagesize/wdg_imagesize.ui365
-rw-r--r--chalk/plugins/viewplugins/imagesize/wdg_layersize.ui234
-rw-r--r--chalk/plugins/viewplugins/imagesize/wdg_resolution.ui152
-rw-r--r--chalk/plugins/viewplugins/modify_selection/Makefile.am27
-rw-r--r--chalk/plugins/viewplugins/modify_selection/chalkmodifyselection.desktop40
-rw-r--r--chalk/plugins/viewplugins/modify_selection/dlg_border_selection.cc76
-rw-r--r--chalk/plugins/viewplugins/modify_selection/dlg_border_selection.h49
-rw-r--r--chalk/plugins/viewplugins/modify_selection/dlg_grow_selection.cc76
-rw-r--r--chalk/plugins/viewplugins/modify_selection/dlg_grow_selection.h49
-rw-r--r--chalk/plugins/viewplugins/modify_selection/dlg_shrink_selection.cc81
-rw-r--r--chalk/plugins/viewplugins/modify_selection/dlg_shrink_selection.h50
-rw-r--r--chalk/plugins/viewplugins/modify_selection/modify_selection.cc158
-rw-r--r--chalk/plugins/viewplugins/modify_selection/modify_selection.h47
-rw-r--r--chalk/plugins/viewplugins/modify_selection/modify_selection.rc10
-rw-r--r--chalk/plugins/viewplugins/modify_selection/wdg_border_selection.ui57
-rw-r--r--chalk/plugins/viewplugins/modify_selection/wdg_grow_selection.ui57
-rw-r--r--chalk/plugins/viewplugins/modify_selection/wdg_shrink_selection.ui68
-rw-r--r--chalk/plugins/viewplugins/performancetest/Makefile.am25
-rw-r--r--chalk/plugins/viewplugins/performancetest/chalkperftest.desktop41
-rw-r--r--chalk/plugins/viewplugins/performancetest/dlg_perftest.cc110
-rw-r--r--chalk/plugins/viewplugins/performancetest/dlg_perftest.h56
-rw-r--r--chalk/plugins/viewplugins/performancetest/perftest.cc1198
-rw-r--r--chalk/plugins/viewplugins/performancetest/perftest.h76
-rw-r--r--chalk/plugins/viewplugins/performancetest/perftest.rc9
-rw-r--r--chalk/plugins/viewplugins/performancetest/wdg_perftest.ui283
-rw-r--r--chalk/plugins/viewplugins/rotateimage/Makefile.am25
-rw-r--r--chalk/plugins/viewplugins/rotateimage/chalkrotateimage.desktop40
-rw-r--r--chalk/plugins/viewplugins/rotateimage/dlg_rotateimage.cc147
-rw-r--r--chalk/plugins/viewplugins/rotateimage/dlg_rotateimage.h66
-rw-r--r--chalk/plugins/viewplugins/rotateimage/rotateimage.cc134
-rw-r--r--chalk/plugins/viewplugins/rotateimage/rotateimage.h50
-rw-r--r--chalk/plugins/viewplugins/rotateimage/rotateimage.rc25
-rw-r--r--chalk/plugins/viewplugins/rotateimage/wdg_rotateimage.ui245
-rw-r--r--chalk/plugins/viewplugins/screenshot/Makefile.am27
-rw-r--r--chalk/plugins/viewplugins/screenshot/chalkscreenshot.desktop47
-rw-r--r--chalk/plugins/viewplugins/screenshot/ksnapshot.cpp499
-rw-r--r--chalk/plugins/viewplugins/screenshot/ksnapshot.h137
-rw-r--r--chalk/plugins/viewplugins/screenshot/ksnapshotwidget.ui335
-rw-r--r--chalk/plugins/viewplugins/screenshot/ksnapshotwidget.ui.h118
-rw-r--r--chalk/plugins/viewplugins/screenshot/main.cpp38
-rw-r--r--chalk/plugins/viewplugins/screenshot/regiongrabber.cpp170
-rw-r--r--chalk/plugins/viewplugins/screenshot/regiongrabber.h72
-rw-r--r--chalk/plugins/viewplugins/screenshot/screenshot-chalk.rc9
-rw-r--r--chalk/plugins/viewplugins/screenshot/screenshot-kpresenter.rc9
-rw-r--r--chalk/plugins/viewplugins/screenshot/screenshot-kword.rc9
-rw-r--r--chalk/plugins/viewplugins/screenshot/screenshot.cpp78
-rw-r--r--chalk/plugins/viewplugins/screenshot/screenshot.h43
-rw-r--r--chalk/plugins/viewplugins/scripting/Makefile.am29
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/Makefile.am30
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/chalkcoremodule.cpp288
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/chalkcoremodule.h205
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_brush.cpp41
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_brush.h48
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_color.cpp42
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_color.h49
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_doc.cpp46
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_doc.h53
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_filter.cpp76
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_filter.h76
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_filter_configuration.cpp72
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_filter_configuration.h65
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_histogram.cpp104
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_histogram.h115
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_image.cpp148
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_image.h94
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_iterator.h307
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_paint_layer.cpp207
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_paint_layer.h140
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_painter.cpp358
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_painter.h242
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_pattern.cpp39
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_pattern.h48
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_script_progress.cpp67
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_script_progress.h77
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_wavelet.cpp114
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkcore/krs_wavelet.h92
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkscripting.desktop81
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkscripting/Makefile.am19
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkscripting/kis_script_monitor.cpp51
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkscripting/kis_script_monitor.h51
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkscripting/kis_script_progress.cpp64
-rw-r--r--chalk/plugins/viewplugins/scripting/chalkscripting/kis_script_progress.h54
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/Makefile.am3
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/python/Makefile.am5
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/python/invert.py48
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/python/invertpython.rc9
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/python/reshapehisto.py300
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/python/reshapehisto.rc9
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/ruby/Makefile.am18
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/ruby/changecs.rb5
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/ruby/changecs.rc9
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/ruby/filterstest.rb31
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/ruby/filterstest.rc9
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/ruby/invert.rb45
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/ruby/invertruby.rc9
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/ruby/randompaint.rb98
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/ruby/randompaint.rc9
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/ruby/torture-filters.rb70
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/ruby/torture-filters.rc9
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/ruby/torture-painting.rb133
-rw-r--r--chalk/plugins/viewplugins/scripting/samples/ruby/torture-painting.rc9
-rw-r--r--chalk/plugins/viewplugins/scripting/scripting.cc111
-rw-r--r--chalk/plugins/viewplugins/scripting/scripting.h54
-rw-r--r--chalk/plugins/viewplugins/scripting/scripting.rc10
-rw-r--r--chalk/plugins/viewplugins/selectopaque/Makefile.am25
-rw-r--r--chalk/plugins/viewplugins/selectopaque/chalkselectopaque.desktop26
-rw-r--r--chalk/plugins/viewplugins/selectopaque/selectopaque.cc116
-rw-r--r--chalk/plugins/viewplugins/selectopaque/selectopaque.h45
-rw-r--r--chalk/plugins/viewplugins/selectopaque/selectopaque.rc10
-rw-r--r--chalk/plugins/viewplugins/separate_channels/Makefile.am27
-rw-r--r--chalk/plugins/viewplugins/separate_channels/chalkseparatechannels.desktop42
-rw-r--r--chalk/plugins/viewplugins/separate_channels/dlg_separate.cc110
-rw-r--r--chalk/plugins/viewplugins/separate_channels/dlg_separate.h68
-rw-r--r--chalk/plugins/viewplugins/separate_channels/imageseparate.rc9
-rw-r--r--chalk/plugins/viewplugins/separate_channels/kis_channel_separator.cc301
-rw-r--r--chalk/plugins/viewplugins/separate_channels/kis_channel_separator.h70
-rw-r--r--chalk/plugins/viewplugins/separate_channels/kis_separate_channels_plugin.cc96
-rw-r--r--chalk/plugins/viewplugins/separate_channels/kis_separate_channels_plugin.h46
-rw-r--r--chalk/plugins/viewplugins/separate_channels/wdg_separations.ui182
-rw-r--r--chalk/plugins/viewplugins/shearimage/Makefile.am25
-rw-r--r--chalk/plugins/viewplugins/shearimage/chalkshearimage.desktop37
-rw-r--r--chalk/plugins/viewplugins/shearimage/dlg_shearimage.cc96
-rw-r--r--chalk/plugins/viewplugins/shearimage/dlg_shearimage.h55
-rw-r--r--chalk/plugins/viewplugins/shearimage/shearimage.cc113
-rw-r--r--chalk/plugins/viewplugins/shearimage/shearimage.h47
-rw-r--r--chalk/plugins/viewplugins/shearimage/shearimage.rc13
-rw-r--r--chalk/plugins/viewplugins/shearimage/wdg_shearimage.ui102
-rw-r--r--chalk/plugins/viewplugins/substrate/Makefile.am26
-rw-r--r--chalk/plugins/viewplugins/substrate/chalksubstrate.desktop35
-rw-r--r--chalk/plugins/viewplugins/substrate/dlg_substrate.cc59
-rw-r--r--chalk/plugins/viewplugins/substrate/dlg_substrate.h62
-rw-r--r--chalk/plugins/viewplugins/substrate/kis_repeating_substrate.cc0
-rw-r--r--chalk/plugins/viewplugins/substrate/kis_repeating_substrate.h69
-rw-r--r--chalk/plugins/viewplugins/substrate/substrate.cc78
-rw-r--r--chalk/plugins/viewplugins/substrate/substrate.h45
-rw-r--r--chalk/plugins/viewplugins/substrate/substrate.rc8
-rw-r--r--chalk/plugins/viewplugins/substrate/wdgsubstrate.ui221
-rw-r--r--chalk/plugins/viewplugins/variations/Makefile.am26
-rw-r--r--chalk/plugins/viewplugins/variations/chalkvariations.desktop40
-rw-r--r--chalk/plugins/viewplugins/variations/dlg_variations.cc58
-rw-r--r--chalk/plugins/viewplugins/variations/dlg_variations.h62
-rw-r--r--chalk/plugins/viewplugins/variations/variations.cc88
-rw-r--r--chalk/plugins/viewplugins/variations/variations.h45
-rw-r--r--chalk/plugins/viewplugins/variations/variations.rc8
-rw-r--r--chalk/plugins/viewplugins/variations/wdg_variations.ui897
635 files changed, 86924 insertions, 0 deletions
diff --git a/chalk/plugins/Makefile.am b/chalk/plugins/Makefile.am
new file mode 100644
index 00000000..468df77e
--- /dev/null
+++ b/chalk/plugins/Makefile.am
@@ -0,0 +1,5 @@
+SUBDIRS = \
+ filters \
+ paintops \
+ tools \
+ viewplugins
diff --git a/chalk/plugins/README b/chalk/plugins/README
new file mode 100644
index 00000000..33af951e
--- /dev/null
+++ b/chalk/plugins/README
@@ -0,0 +1,42 @@
+About plugins
+
+Plugins are components with a GUI that perform some action for Chalk.
+Note that plugins are only loaded when a KisView is constructed; note
+also that every plugin is reloaded when a new KisView is created.
+
+Plugins are _not_ allowed to depend on each other. You may _not_
+#include a header file from a plugin anywhere but in that same plugin.
+You can however choose to group a cluster of related functions in
+one plugin, like with the selection tools.
+
+There are several kinds of plugins for Chalk:
+
+* Tools
+
+ Tools have the Chalk/Tool servicetype. A tool plugin registers
+ the tool factories it provides with the tool registry. A tool must descend
+ from the KisTool interface. There are several base classes for
+ specialized tools, like painting and non painting tools.
+
+* Paintops
+
+ Paintops implement methods for changing pixels that can be used
+ by painting tools. Examples are brush, pen, airbrush. Paintop plugins
+ have the Chalk/Paintop servicetype, register paintop factories they
+ provide the paintop registry. Paintops inherit KisPaintOp.
+
+* Filters
+
+ Filters implement methods of changin a rectangular area of pixels. Filter
+ plugins have the Chalk/Filter servicetype and are registered with
+ the filter registry. A filter inherits the KisFilter class and may
+ provide a configuration widget and a configuration object.
+
+* Extensions
+
+ Extensions are loaded by every view instance. They provide user interface
+ elements such as dialog boxes and wizards. Their parent is KisView and
+ they provide an .rc file to merge their gui with the view gui. Extensions
+ have the servicetype Chalk/Plugin. They are not loaded automatically by
+ the KParts mechanism; please do not create ordinary kparts that are to
+ be loaded by the Chalk view since KParts are not versioned.
diff --git a/chalk/plugins/configure.in.in b/chalk/plugins/configure.in.in
new file mode 100644
index 00000000..c1845fdc
--- /dev/null
+++ b/chalk/plugins/configure.in.in
@@ -0,0 +1,2 @@
+KDE_CHECK_HEADER(kjsembed/jsproxy_imp.h, have_kjsembed=yes, have_kjsembed=no)
+AM_CONDITIONAL(use_kjsembed, test x$have_kjsembed = xyes)
diff --git a/chalk/plugins/filters/Makefile.am b/chalk/plugins/filters/Makefile.am
new file mode 100644
index 00000000..19ff6736
--- /dev/null
+++ b/chalk/plugins/filters/Makefile.am
@@ -0,0 +1,4 @@
+SUBDIRS = bumpmap cimg convolutionfilters embossfilter example imageenhancement \
+ oilpaintfilter pixelizefilter raindropsfilter roundcorners smalltilesfilter \
+ sobelfilter colorsfilters noisefilter wavefilter randompickfilter \
+ lenscorrectionfilter blur colors fastcolortransfer unsharp levelfilter colorify
diff --git a/chalk/plugins/filters/blur/Makefile.am b/chalk/plugins/filters/blur/Makefile.am
new file mode 100644
index 00000000..8ccfbe5f
--- /dev/null
+++ b/chalk/plugins/filters/blur/Makefile.am
@@ -0,0 +1,22 @@
+chalkrcdir = $(kde_datadir)/chalk/chalkplugins
+
+kde_services_DATA = chalkblurfilter.desktop
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkblurfilter_la_SOURCES = wdgblur.ui blur.cc kis_blur_filter.cc kis_wdg_blur.cc
+
+kde_module_LTLIBRARIES = chalkblurfilter.la
+noinst_HEADERS = blur.h kis_blur_filter.h
+
+chalkblurfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui
+chalkblurfilter_la_LIBADD = ../../../libchalkcommon.la
+
+METASOURCES = AUTO
+
diff --git a/chalk/plugins/filters/blur/blur.cc b/chalk/plugins/filters/blur/blur.cc
new file mode 100644
index 00000000..bcf798b9
--- /dev/null
+++ b/chalk/plugins/filters/blur/blur.cc
@@ -0,0 +1,50 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 "blur.h"
+
+#include <kgenericfactory.h>
+
+#include "kis_blur_filter.h"
+
+typedef KGenericFactory<BlurFilterPlugin> BlurFilterPluginFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkblurfilter, BlurFilterPluginFactory( "chalk" ) )
+
+BlurFilterPlugin::BlurFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(BlurFilterPluginFactory::instance());
+
+
+ kdDebug(41006) << "Extensions Convolution Filters plugin. Class: "
+ << className()
+ << ", Parent: "
+ << tqparent -> className()
+ << "\n";
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisBlurFilter());
+ }
+}
+
+BlurFilterPlugin::~BlurFilterPlugin()
+{
+}
diff --git a/chalk/plugins/filters/blur/blur.h b/chalk/plugins/filters/blur/blur.h
new file mode 100644
index 00000000..8ce31706
--- /dev/null
+++ b/chalk/plugins/filters/blur/blur.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 BLURPLUGIN_H
+#define BLURPLUGIN_H
+
+// TODO: remove that
+#define LCMS_HEADER <lcms.h>
+// TODO: remove it !
+
+#include <kparts/plugin.h>
+
+class BlurFilterPlugin : public KParts::Plugin
+{
+public:
+ BlurFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~BlurFilterPlugin();
+};
+
+#endif
diff --git a/chalk/plugins/filters/blur/chalkblurfilter.desktop b/chalk/plugins/filters/blur/chalkblurfilter.desktop
new file mode 100644
index 00000000..5adb437b
--- /dev/null
+++ b/chalk/plugins/filters/blur/chalkblurfilter.desktop
@@ -0,0 +1,38 @@
+[Desktop Entry]
+Icon=
+Name=Convolution Filters (Extension)
+Name[bg]=Изкривяващи филтри (разширения)
+Name[ca]=Filtres d'enrotllament (Extensió)
+Name[da]=Foldningsfiltre (Udvidelse)
+Name[de]=Faltungsfilter (Erweiterung)
+Name[el]=Φίλτρα περιέλιξης (Επέκταση)
+Name[es]=Filtros de convolución (Extensión)
+Name[et]=Konvolutsioonifiltrid (laiendus)
+Name[fa]=پالایه‌های هم‌پیچش )پسوند(
+Name[fr]=Filtres de convolution (extension)
+Name[fy]=Ferdraaiïngsfilters (útwreiding)
+Name[ga]=Scagairí Conbhlóide (Eisínteacht)
+Name[gl]=Filtros de Convolución (Extensións)
+Name[hu]=Konvolúciószűrők (kiterjesztés)
+Name[it]=Filtri di convoluzione (estensione)
+Name[ja]=コンボリューションフィルタ (拡張)
+Name[km]=តម្រង​អង្កាញ់ (ផ្នែក​បន្ថែម)
+Name[nb]=Konvolusjonsfiltre (Utvidelse)
+Name[nds]=Fooldenfilters (Verwiedern)
+Name[ne]=कुण्डलीकरण फिल्टरहरू (अपवाद)
+Name[nl]=Verdraaiïngsfilters (uitbreiding)
+Name[pl]=Filtry splotowe (rozszerzenie)
+Name[pt]=Filtros de Convolução (Extensão)
+Name[pt_BR]=Filtros de Convolução (Extensão)
+Name[ru]=Свёртка (расширение)
+Name[sk]=Filtre zatočenia (rozšírenie)
+Name[sl]=Konvolucijski filtri (razširitev)
+Name[sr]=Конволуциони филтери (проширење)
+Name[sr@Latn]=Konvolucioni filteri (proširenje)
+Name[sv]=Faltningsfilter (utökning)
+Name[uk]=Фільтри згортки (розширення)
+Name[zh_TW]=皺褶過濾器(延伸)
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkblurfilter
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/blur/kis_blur_filter.cc b/chalk/plugins/filters/blur/kis_blur_filter.cc
new file mode 100644
index 00000000..8709c073
--- /dev/null
+++ b/chalk/plugins/filters/blur/kis_blur_filter.cc
@@ -0,0 +1,143 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_blur_filter.h"
+
+#include <kcombobox.h>
+#include <knuminput.h>
+
+#include <kis_autobrush_resource.h>
+#include <kis_convolution_painter.h>
+#include <kis_iterators_pixel.h>
+#include <kis_progress_display_interface.h>
+#include <kis_progress_subject.h>
+
+
+#include "kis_wdg_blur.h"
+#include "wdgblur.h"
+
+KisKernelSP kernelFromTQImage(const TQImage& img)
+{
+ KisKernelSP k = new KisKernel;
+ k->width = img.width();
+ k->height = img.height();
+ k->offset = 0;
+ uint count = k->width * k->height;
+ k->data = new TQ_INT32[count];
+ TQ_INT32* itData = k->data;
+ TQ_UINT8* itImg = (TQ_UINT8*)img.bits();
+ k->factor = 0;
+ for(uint i = 0; i < count; ++i , ++itData, itImg+=4)
+ {
+ *itData = 255 - ( *itImg + *(itImg+1) + *(itImg+2) ) / 3;
+ k->factor += *itData;
+ }
+ return k;
+}
+
+KisBlurFilter::KisBlurFilter() : KisFilter(id(), "blur", i18n("&Blur..."))
+{
+}
+
+KisFilterConfigWidget * KisBlurFilter::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP )
+{
+ return new KisWdgBlur(this, tqparent, "configuration of color to alpha");
+}
+
+KisFilterConfiguration* KisBlurFilter::configuration(TQWidget* w)
+{
+ KisWdgBlur * wCTA = dynamic_cast<KisWdgBlur*>(w);
+ if(!wCTA) return 0;
+ KisFilterConfiguration* config = new KisFilterConfiguration(id().id(), 1);
+ if(wCTA)
+ {
+ config->setProperty("halfWidth", wCTA->widget()->intHalfWidth->value() );
+ config->setProperty("halfHeight", wCTA->widget()->intHalfWidth->value() );
+ config->setProperty("rotate", wCTA->widget()->intAngle->value() );
+ config->setProperty("strength", wCTA->widget()->intStrength->value() );
+ config->setProperty("tqshape", wCTA->widget()->cbShape->currentItem());
+ }
+ return config;
+}
+
+void KisBlurFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* config, const TQRect& rect)
+{
+ Q_ASSERT(src != 0);
+ Q_ASSERT(dst != 0);
+
+ setProgressTotalSteps(rect.width() * rect.height());
+
+ if(!config) config = new KisFilterConfiguration(id().id(), 1);
+
+ TQVariant value;
+ int tqshape = (config->getProperty("tqshape", value)) ? value.toInt() : 0;
+ uint halfWidth = (config->getProperty("halfWidth", value)) ? value.toUInt() : 5;
+ uint width = 2 * halfWidth + 1;
+ uint halfHeight = (config->getProperty("halfHeight", value)) ? value.toUInt() : 5;
+ uint height = 2 * halfHeight + 1;
+ 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;
+
+ KisAutobrushShape* kas;
+ kdDebug() << width << " " << height << " " << hFade << " " << vFade << endl;
+ switch(tqshape)
+ {
+ case 1:
+ kas = new KisAutobrushRectShape(width, height , hFade, vFade);
+ break;
+ case 0:
+ default:
+ kas = new KisAutobrushCircleShape(width, height, hFade, vFade);
+ break;
+ }
+ TQImage tqmask;
+ kas->createBrush(&tqmask);
+
+ tqmask.convertDepth(1);
+
+ if( rotate != 0)
+ {
+ TQWMatrix m;
+ m.rotate( rotate );
+ tqmask = tqmask.xForm( m );
+ if( (tqmask.height() & 1) || tqmask.width() & 1)
+ {
+ tqmask.smoothScale( tqmask.width() + !(tqmask.width() & 1), tqmask.height() + !(tqmask.height() & 1) );
+ }
+ }
+
+ KisConvolutionPainter painter( dst );
+ if (m_progressDisplay)
+ m_progressDisplay->setSubject( &painter, true, true );
+
+ KisKernelSP kernel = kernelFromTQImage(tqmask); // TODO: for 1.6 reuse the chalk's core function for creating kernel : KisKernel::fromTQImage
+
+ painter.applyMatrix(kernel, rect.x(), rect.y(), rect.width(), rect.height(), BORDER_REPEAT, KisChannelInfo::FLAG_COLOR_AND_ALPHA);
+
+ if (painter.cancelRequested()) {
+ cancel();
+ }
+
+ setProgressDone(); // Must be called even if you don't really support progression
+}
+
diff --git a/chalk/plugins/filters/blur/kis_blur_filter.h b/chalk/plugins/filters/blur/kis_blur_filter.h
new file mode 100644
index 00000000..88655186
--- /dev/null
+++ b/chalk/plugins/filters/blur/kis_blur_filter.h
@@ -0,0 +1,49 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ * Copyright (c) 2007 Benjamin Schleimer <bensch128@yahoo.com>
+ *
+ * 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_BLUR_FILTER_H
+#define KIS_BLUR_FILTER_H
+
+// TODO: remove that
+#define LCMS_HEADER <lcms.h>
+// TODO: remove it !
+
+#include "kis_filter.h"
+
+class KisBlurFilter : public KisFilter
+{
+ public:
+ KisBlurFilter();
+ public:
+ virtual void process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration*, const TQRect&);
+ static inline KisID id() { return KisID("blur", i18n("Blur")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ virtual bool supportsAdjustmentLayers() { return false; }
+ virtual bool supportsThreading() { return false; }
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return FULLY_INDEPENDENT; };
+ public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration* configuration(TQWidget*);
+};
+
+#endif
diff --git a/chalk/plugins/filters/blur/kis_wdg_blur.cc b/chalk/plugins/filters/blur/kis_wdg_blur.cc
new file mode 100644
index 00000000..bfed7474
--- /dev/null
+++ b/chalk/plugins/filters/blur/kis_wdg_blur.cc
@@ -0,0 +1,116 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_wdg_blur.h"
+
+#include <tqlayout.h>
+#include <tqtoolbutton.h>
+
+#include <kcombobox.h>
+#include <knuminput.h>
+
+#include <KoImageResource.h>
+
+#include <kis_filter.h>
+
+#include "wdgblur.h"
+
+KisWdgBlur::KisWdgBlur( KisFilter* nfilter, TQWidget * tqparent, const char * name) : KisFilterConfigWidget ( tqparent, name )
+{
+ Q_UNUSED( nfilter );
+
+ TQGridLayout *widgetLayout = new TQGridLayout(this, 1, 1);
+ m_widget = new WdgBlur(this);
+ widgetLayout -> addWidget(m_widget,0,0);
+
+ linkSpacingToggled(true);
+
+ connect( widget()->bnLinkSize, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(linkSpacingToggled( bool )));
+ connect( widget()->intHalfWidth, TQT_SIGNAL(valueChanged(int)),this,TQT_SLOT(spinBoxHalfWidthChanged(int)));
+ connect( widget()->intHalfHeight, TQT_SIGNAL(valueChanged(int)),this,TQT_SLOT(spinBoxHalfHeightChanged(int)));
+
+ connect( widget()->intStrength, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->intAngle, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->cbShape, TQT_SIGNAL( activated(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+}
+
+
+void KisWdgBlur::setConfiguration(KisFilterConfiguration* config)
+{
+ TQVariant value;
+ if (config->getProperty("tqshape", value))
+ {
+ widget()->cbShape->setCurrentItem( value.toUInt() );
+ }
+ if (config->getProperty("halfWidth", value))
+ {
+ widget()->intHalfWidth->setValue( value.toUInt() );
+ }
+ if (config->getProperty("halfHeight", value))
+ {
+ widget()->intHalfHeight->setValue( value.toUInt() );
+ }
+ if (config->getProperty("rotate", value))
+ {
+ widget()->intAngle->setValue( value.toUInt() );
+ }
+ if (config->getProperty("strength", value))
+ {
+ widget()->intStrength->setValue( value.toUInt() );
+ }
+}
+
+void KisWdgBlur::linkSpacingToggled(bool b)
+{
+ m_halfSizeLink = b;
+ KoImageResource kir;
+ if (b) {
+ widget()->bnLinkSize->setPixmap(kir.chain());
+ }
+ else {
+ widget()->bnLinkSize->setPixmap(kir.chainBroken());
+ }
+}
+
+void KisWdgBlur::spinBoxHalfWidthChanged(int v)
+{
+ if(m_halfSizeLink) {
+ widget()->intHalfHeight->setValue(v);
+ }
+/* if( widget()->intHalfHeight->value() == v && widget()->cbShape->currentItem() != 1)
+ widget()->intAngle->setEnabled(false);
+ else
+ widget()->intAngle->setEnabled(true);*/
+ emit sigPleaseUpdatePreview();
+}
+
+void KisWdgBlur::spinBoxHalfHeightChanged(int v)
+{
+ if(m_halfSizeLink) {
+ widget()->intHalfWidth->setValue(v);
+ }
+/* if( widget()->intHalfWidth->value() == v && widget()->cbShape->currentItem() != 1)
+ widget()->intAngle->setEnabled(false);
+ else
+ widget()->intAngle->setEnabled(true);*/
+ emit sigPleaseUpdatePreview();
+}
+
+#include "kis_wdg_blur.moc"
diff --git a/chalk/plugins/filters/blur/kis_wdg_blur.h b/chalk/plugins/filters/blur/kis_wdg_blur.h
new file mode 100644
index 00000000..c0cc4834
--- /dev/null
+++ b/chalk/plugins/filters/blur/kis_wdg_blur.h
@@ -0,0 +1,50 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_WDG_BLUR_H_
+#define _KIS_WDG_BLUR_H_
+
+// TODO: remove that
+#define LCMS_HEADER <lcms.h>
+// TODO: remove it !
+
+#include <kis_filter_config_widget.h>
+
+class KisFilter;
+class WdgBlur;
+
+class KisWdgBlur : public KisFilterConfigWidget
+{
+ Q_OBJECT
+ TQ_OBJECT
+ public:
+ KisWdgBlur( KisFilter* nfilter, TQWidget * tqparent, const char * name);
+ inline WdgBlur* widget() { return m_widget; };
+ virtual void setConfiguration(KisFilterConfiguration*);
+ private slots:
+ void linkSpacingToggled(bool);
+ void spinBoxHalfWidthChanged(int );
+ void spinBoxHalfHeightChanged(int );
+ private:
+ bool m_halfSizeLink;
+ WdgBlur* m_widget;
+};
+
+#endif
diff --git a/chalk/plugins/filters/blur/wdgblur.ui b/chalk/plugins/filters/blur/wdgblur.ui
new file mode 100644
index 00000000..06119596
--- /dev/null
+++ b/chalk/plugins/filters/blur/wdgblur.ui
@@ -0,0 +1,227 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgBlur</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgBlur</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>430</width>
+ <height>218</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <spacer row="0" column="1">
+ <property name="name">
+ <cstring>spacer5_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tqlayout17</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQToolButton" row="0" column="2" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>bnLinkSize</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>16</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>16</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="toggleButton">
+ <bool>true</bool>
+ </property>
+ <property name="on">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="4" column="1" rowspan="1" colspan="2">
+ <item>
+ <property name="text">
+ <string>Circle</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Rectangle</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>cbShape</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel5</cstring>
+ </property>
+ <property name="text">
+ <string>Angle:</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Strength:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="0" column="1">
+ <property name="name">
+ <cstring>intHalfWidth</cstring>
+ </property>
+ <property name="value">
+ <number>10</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="maxValue">
+ <number>1000</number>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="1" column="1">
+ <property name="name">
+ <cstring>intHalfHeight</cstring>
+ </property>
+ <property name="value">
+ <number>10</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="maxValue">
+ <number>1000</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Half-width:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="4" column="0">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Shape:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="2" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>intStrength</cstring>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Half-height:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="3" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>intAngle</cstring>
+ </property>
+ <property name="minValue">
+ <number>-180</number>
+ </property>
+ <property name="maxValue">
+ <number>180</number>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcombobox.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/filters/bumpmap/Makefile.am b/chalk/plugins/filters/bumpmap/Makefile.am
new file mode 100644
index 00000000..ae6530ae
--- /dev/null
+++ b/chalk/plugins/filters/bumpmap/Makefile.am
@@ -0,0 +1,19 @@
+kde_services_DATA = chalkbumpmapfilter.desktop
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$(srcdir)/../../../../lib/kofficecore \
+ $(all_includes)
+
+chalkbumpmap_la_SOURCES = bumpmap.cc wdgbumpmap.ui
+
+kde_module_LTLIBRARIES = chalkbumpmap.la
+noinst_HEADERS = bumpmap.h
+
+chalkbumpmap_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkbumpmap_la_LIBADD = ../../../libchalkcommon.la
+
+chalkbumpmap_la_METASOURCES = AUTO
diff --git a/chalk/plugins/filters/bumpmap/bumpmap.cc b/chalk/plugins/filters/bumpmap/bumpmap.cc
new file mode 100644
index 00000000..455889d5
--- /dev/null
+++ b/chalk/plugins/filters/bumpmap/bumpmap.cc
@@ -0,0 +1,533 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Boudewijn <boud@valdyas.org>
+ * Copyright (c) 2007 Benjamin Schleimer <bensch128@yahoo.com>
+ *
+ * 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.
+ *
+ *
+ * This implementation completely and utterly based on the gimp's bumpmap.c,
+ * copyright:
+ * Copyright (C) 1997 Federico Mena Quintero <federico@nuclecu.unam.mx>
+ * Copyright (C) 1997-2000 Jens Lautenbacher <jtl@gimp.org>
+ * Copyright (C) 2000 Sven Neumann <sven@gimp.org>
+ *
+ */
+
+#include <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+#include <tqlayout.h>
+#include <tqcombobox.h>
+#include <tqcheckbox.h>
+#include <tqbuttongroup.h>
+#include <tqradiobutton.h>
+#include <tqstring.h>
+#include <tqpushbutton.h>
+#include <tqlineedit.h>
+
+#include <knuminput.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <kcombobox.h>
+
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_filter_registry.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_layer.h>
+#include <kis_paint_layer.h>
+#include <kis_group_layer.h>
+#include <kis_adjustment_layer.h>
+
+#include "wdgbumpmap.h"
+#include "bumpmap.h"
+
+#define MOD(x, y) \
+ ((x) < 0 ? ((y) - 1 - ((y) - 1 - (x)) % (y)) : (x) % (y))
+
+typedef KGenericFactory<ChalkBumpmap> ChalkBumpmapFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkbumpmap, ChalkBumpmapFactory( "chalk" ) )
+
+ChalkBumpmap::ChalkBumpmap(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ChalkBumpmapFactory::instance());
+
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisFilterBumpmap());
+ }
+}
+
+ChalkBumpmap::~ChalkBumpmap()
+{
+}
+
+KisFilterBumpmap::KisFilterBumpmap() : KisFilter(id(), "map", i18n("&Bumpmap..."))
+{
+}
+
+namespace {
+ void convertRow(KisPaintDevice * orig, TQ_UINT8 * row, TQ_INT32 x, TQ_INT32 y, TQ_INT32 w, TQ_UINT8 * lut, TQ_INT32 waterlevel)
+ {
+ KisColorSpace * csOrig = orig->colorSpace();
+
+ KisHLineIteratorPixel origIt = orig->createHLineIterator(x, y, w, false);
+ for (int i = 0; i < w; ++i) {
+ row[0] = csOrig->intensity8(origIt.rawData());
+ row[0] = lut[waterlevel + ((row[0] - waterlevel) * csOrig->getAlpha(origIt.rawData())) / 255];
+
+ ++row;
+ ++origIt;
+ }
+ }
+
+}
+
+void KisFilterBumpmap::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* cfg, const TQRect& rect)
+{
+ if (!src) return;
+ if (!dst) return;
+ if (!cfg) return;
+ if (!rect.isValid()) return;
+ if (rect.isNull()) return;
+ if (rect.isEmpty()) return;
+
+ KisBumpmapConfiguration * config = (KisBumpmapConfiguration*)cfg;
+
+ TQ_INT32 xofs, yofs; /// The x,y offset values
+ TQ_INT32 lx, ly; /* X and Y components of light vector */
+ TQ_INT32 nz2, nzlz; /* nz^2, nz*lz */
+ TQ_INT32 background; /* Shade for vertical normals */
+ double compensation; /* Background compensation */
+ TQ_UINT8 lut[256]; /* Look-up table for modes */
+
+ double azimuth;
+ double elevation;
+ TQ_INT32 lz, nz;
+ TQ_INT32 i;
+ double n;
+
+ // ------------------ Prepare parameters
+
+ /* Convert the offsets */
+ xofs = -config->xofs;
+ yofs = -config->yofs;
+
+ /* Convert to radians */
+ azimuth = M_PI * config->azimuth / 180.0;
+ elevation = M_PI * config->elevation / 180.0;
+
+ /* Calculate the light vector */
+ lx = (TQ_INT32)(cos(azimuth) * cos(elevation) * 255.0);
+ ly = (TQ_INT32)(sin(azimuth) * cos(elevation) * 255.0);
+
+ lz = (TQ_INT32)(sin(elevation) * 255.0);
+
+ /* Calculate constant Z component of surface normal */
+ nz = (TQ_INT32)((6 * 255) / config->depth);
+ nz2 = nz * nz;
+ nzlz = nz * lz;
+
+ /* Optimize for vertical normals */
+ background = lz;
+
+ /* Calculate darkness compensation factor */
+ compensation = sin(elevation);
+
+ /* Create look-up table for map type */
+ for (i = 0; i < 256; i++)
+ {
+ switch (config->type)
+ {
+ case SPHERICAL:
+ n = i / 255.0 - 1.0;
+ lut[i] = (int) (255.0 * sqrt(1.0 - n * n) + 0.5);
+ break;
+
+ case SINUSOIDAL:
+ n = i / 255.0;
+ lut[i] = (int) (255.0 *
+ (sin((-M_PI / 2.0) + M_PI * n) + 1.0) /
+ 2.0 + 0.5);
+ break;
+
+ case LINEAR:
+ default:
+ lut[i] = i;
+ }
+
+ if (config->invert)
+ lut[i] = 255 - lut[i];
+ }
+
+
+ // Crate a grayscale layer from the bumpmap layer.
+ TQRect bmRect;
+ KisPaintDevice * bumpmap;
+
+ if (!config->bumpmap.isNull() && src->image()) {
+ KisLayerSP l = src->image()->findLayer(config->bumpmap);
+ KisPaintDeviceSP bumplayer = 0;
+
+ KisPaintLayer * pl = dynamic_cast<KisPaintLayer*>(l.data());
+ if (pl) {
+ bumplayer = pl->paintDevice();
+ }
+ else {
+ KisGroupLayer * gl = dynamic_cast<KisGroupLayer*>(l.data());
+ if (gl) {
+ bumplayer = gl->projection(gl->extent());
+ }
+ else {
+ KisAdjustmentLayer * al = dynamic_cast<KisAdjustmentLayer*>(l.data());
+ if (al) {
+ bumplayer = al->cachedPaintDevice();
+ }
+ }
+ }
+
+
+ if (bumplayer) {
+ bmRect = bumplayer->exactBounds();
+ bumpmap = bumplayer.data();
+ }
+ else {
+ bmRect = rect;
+ bumpmap = src;
+ }
+ }
+
+ if(!bmRect.isValid()) {
+ bmRect = rect;
+ bumpmap = src;
+ }
+
+ kdDebug(12345) << "KisFilterBumpmap::process: rect=" << rect << ", bumpmap rect=" << bmRect << "\n";
+
+ setProgressTotalSteps(rect.height());
+
+ // ---------------------- Load initial three bumpmap scanlines
+
+ KisColorSpace * srcCs = src->colorSpace();
+ TQValueVector<KisChannelInfo *> channels = srcCs->channels();
+
+ // One byte per pixel, converted from the bumpmap layer.
+ TQ_UINT8 * bm_row1 = new TQ_UINT8[bmRect.width()];
+ TQ_UINT8 * bm_row2 = new TQ_UINT8[bmRect.width()];
+ TQ_UINT8 * bm_row3 = new TQ_UINT8[bmRect.width()];
+ TQ_UINT8 * tmp_row;
+
+ // ------------------- Map the bumps
+ TQ_INT32 yofs1, yofs2, yofs3;
+
+ // ------------------- Initialize offsets
+ if (config->tiled) {
+ yofs2 = MOD (yofs, bmRect.height());
+ yofs1 = MOD (yofs2 - 1, bmRect.height());
+ yofs3 = MOD (yofs2 + 1, bmRect.height());
+ }
+ else {
+ yofs2 = 0;
+ yofs1 = yofs2 - 1;
+ yofs3 = yofs2 + 1;
+ }
+ convertRow(bumpmap, bm_row1, bmRect.x(), yofs1+bmRect.top(), bmRect.width(), lut, config->waterlevel);
+ convertRow(bumpmap, bm_row2, bmRect.x(), yofs2+bmRect.top(), bmRect.width(), lut, config->waterlevel);
+ convertRow(bumpmap, bm_row3, bmRect.x(), yofs3+bmRect.top(), bmRect.width(), lut, config->waterlevel);
+
+ for (int y = rect.top(); y<=rect.bottom(); y++) {
+ const TQ_INT32 yBump = y+yofs;
+ if(config->tiled || (bmRect.top()<=yBump && yBump<=bmRect.bottom()) ) {
+ // Get the iterators
+ KisHLineIteratorPixel dstIt = dst->createHLineIterator(rect.x(), y, rect.width(), true);
+ KisHLineIteratorPixel srcIt = src->createHLineIterator(rect.x(), y, rect.width(), false);
+
+ //while (x < sel_w || cancelRequested()) {
+ while (!srcIt.isDone() && !cancelRequested()) {
+ if (srcIt.isSelected()) {
+
+ const TQ_INT32 xBump = srcIt.x()+xofs;
+ TQ_INT32 nx, ny;
+ // Calculate surface normal from bumpmap
+ if (config->tiled || bmRect.left() <= xBump && xBump <= bmRect.right()) {
+
+ TQ_INT32 xofs1, xofs2, xofs3;
+ if (config->tiled) {
+ xofs2 = MOD (xBump-bmRect.left(), bmRect.width());
+ xofs1 = MOD (xofs2 - 1, bmRect.width());
+ xofs3 = MOD (xofs2 + 1, bmRect.width());
+ } else {
+ xofs2 = MOD (xBump-bmRect.left(), bmRect.width());
+ xofs1 = ::max (xofs2 - 1, 0);
+ xofs3 = ::min (xofs2 + 1, bmRect.width());
+ }
+
+ nx = (bm_row1[xofs1] + bm_row2[xofs1] + bm_row3[xofs1] -
+ bm_row1[xofs3] - bm_row2[xofs3] - bm_row3[xofs3]);
+ ny = (bm_row3[xofs1] + bm_row3[xofs2] + bm_row3[xofs3] -
+ bm_row1[xofs1] - bm_row1[xofs2] - bm_row1[xofs3]);
+ } else {
+ nx = 0;
+ ny = 0;
+ }
+
+ // Shade
+ TQ_INT32 shade;
+ if ((nx == 0) && (ny == 0)) {
+ shade = background;
+ } else {
+ TQ_INT32 ndotl = (nx * lx) + (ny * ly) + nzlz;
+
+ if (ndotl < 0) {
+ shade = (TQ_INT32)(compensation * config->ambient);
+ } else {
+ shade = (TQ_INT32)(ndotl / sqrt(nx * nx + ny * ny + nz2));
+ shade = (TQ_INT32)(shade + TQMAX(0, (255 * compensation - shade)) * config->ambient / 255);
+ }
+ }
+
+ // Paint
+ srcCs->darken(srcIt.rawData(), dstIt.rawData(), shade, config->compensate, compensation, 1);
+ }
+
+ ++srcIt;
+ ++dstIt;
+ }
+
+ // Go to the next row
+ tmp_row = bm_row1;
+ bm_row1 = bm_row2;
+ bm_row2 = bm_row3;
+ bm_row3 = tmp_row;
+
+ yofs2++;
+ if (yofs2 >= bmRect.height()) { yofs2 = 0; }
+
+ if (config->tiled) {
+ yofs3 = MOD (yofs2 + 1, bmRect.height());
+ } else {
+ yofs3 = yofs2 + 1;
+ }
+ convertRow(bumpmap, bm_row3, bmRect.x(), yofs3+bmRect.top(), bmRect.width(), lut, config->waterlevel);
+ }
+
+ incProgress();
+ }
+
+ delete [] bm_row1;
+ delete [] bm_row2;
+ delete [] bm_row3;
+ setProgressDone();
+
+}
+
+KisFilterConfigWidget * KisFilterBumpmap::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev)
+{
+ KisBumpmapConfigWidget * w = new KisBumpmapConfigWidget(this, dev, tqparent);
+
+
+ return w;
+}
+
+KisFilterConfiguration * KisFilterBumpmap::configuration(TQWidget * w)
+{
+
+ KisBumpmapConfigWidget * widget = dynamic_cast<KisBumpmapConfigWidget *>(w);
+ if (widget == 0) {
+ return new KisBumpmapConfiguration();
+ }
+ else {
+ return widget->config();
+ }
+}
+
+KisFilterConfiguration * KisFilterBumpmap::configuration()
+{
+ return new KisBumpmapConfiguration();
+}
+
+
+KisBumpmapConfiguration::KisBumpmapConfiguration()
+ : KisFilterConfiguration( "bumpmap", 1 )
+{
+ bumpmap = TQString();
+ azimuth = 135.0;
+ elevation = 45.0;
+ depth = 3;
+ xofs = 0;
+ yofs = 0;
+ waterlevel = 0;
+ ambient = 0;
+ compensate = true;
+ invert = false;
+ tiled = true;
+ type = chalk::LINEAR;
+}
+void KisBumpmapConfiguration::fromXML(const TQString & s)
+{
+ KisFilterConfiguration::fromXML( s );
+
+ bumpmap = TQString();
+ azimuth = 135.0;
+ elevation = 45.0;
+ depth = 3;
+ xofs = 0;
+ yofs = 0;
+ waterlevel = 0;
+ ambient = 0;
+ compensate = true;
+ invert = false;
+ tiled = true;
+ type = chalk::LINEAR;
+
+ TQVariant v;
+
+ v = getProperty("bumpmap");
+ if (v.isValid()) { bumpmap = v.asString(); }
+ v = getProperty("azimuth");
+ if (v.isValid()) { azimuth = v.asDouble(); }
+ v = getProperty("elevation");
+ if (v.isValid()) { elevation = v.asDouble();}
+ v = getProperty("depth");
+ if (v.isValid()) { depth = v.asDouble(); }
+ v = getProperty("xofs");
+ if (v.isValid()) { xofs = v.asInt(); }
+ v = getProperty("yofs");
+ if (v.isValid()) { yofs = v.asInt();}
+ v = getProperty("waterlevel");
+ if (v.isValid()) { waterlevel = v.asInt();}
+ v = getProperty("ambient");
+ if (v.isValid()) { ambient = v.asInt();}
+ v = getProperty("compensate");
+ if (v.isValid()) { compensate = v.asBool(); }
+ v = getProperty("invert");
+ if (v.isValid()) { invert = v.asBool(); }
+ v = getProperty("tiled");
+ if (v.isValid()) { tiled = v.asBool();}
+ v = getProperty("type");
+ if (v.isValid()) { type = (enumBumpmapType)v.asInt(); }
+
+}
+
+
+TQString KisBumpmapConfiguration::toString()
+{
+ m_properties.clear();
+
+ //setProperty("bumpmap", TQVariant(bumpmap));
+ setProperty("azimuth", TQVariant(azimuth));
+ setProperty("elevation", TQVariant(elevation));
+ setProperty("depth", TQVariant(depth));
+ setProperty("xofs", TQVariant(xofs));
+ setProperty("yofs", TQVariant(yofs));
+ setProperty("waterlevel", TQVariant(waterlevel));
+ setProperty("ambient", TQVariant(ambient));
+ setProperty("compensate", TQVariant(compensate));
+ setProperty("invert", TQVariant(invert));
+ setProperty("tiled", TQVariant(tiled));
+ setProperty("type", TQVariant(type));
+
+ return KisFilterConfiguration::toString();
+}
+
+KisBumpmapConfigWidget::KisBumpmapConfigWidget(KisFilter *, KisPaintDeviceSP dev, TQWidget * tqparent, const char * name, WFlags f)
+ : KisFilterConfigWidget(tqparent, name, f)
+{
+ m_page = new WdgBumpmap(this);
+ TQHBoxLayout * l = new TQHBoxLayout(this);
+ Q_CHECK_PTR(l);
+
+ l->add(m_page);
+
+ // Find all of the layers in the group
+ if(dev->image() ) {
+ KisGroupLayerSP root = dev->image()->rootLayer();
+ for(KisLayerSP layer = root->firstChild(); layer; layer = layer->nextSibling())
+ {
+ m_page->cboxSourceLayer->insertItem(layer->name());
+ }
+ }
+
+ // Connect all of the widgets to update signal
+ connect( m_page->radioLinear, TQT_SIGNAL( toggled(bool)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->radioSpherical, TQT_SIGNAL( toggled(bool)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->radioSinusoidal, TQT_SIGNAL( toggled(bool)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->chkCompensate, TQT_SIGNAL( toggled(bool)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->chkInvert, TQT_SIGNAL( toggled(bool)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->chkTiled, TQT_SIGNAL( toggled(bool)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->dblAzimuth, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->dblElevation, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->dblDepth, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->intXOffset, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->intYOffset, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->intWaterLevel, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->intAmbient, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+}
+
+KisBumpmapConfiguration * KisBumpmapConfigWidget::config()
+{
+ KisBumpmapConfiguration * cfg = new KisBumpmapConfiguration();
+ cfg->bumpmap = m_page->cboxSourceLayer->currentText();
+ cfg->azimuth = m_page->dblAzimuth->value();
+ cfg->elevation = m_page->dblElevation->value();
+ cfg->depth = m_page->dblDepth->value();
+ cfg->xofs = m_page->intXOffset->value();
+ cfg->yofs = m_page->intYOffset->value();
+ cfg->waterlevel = m_page->intWaterLevel->value();
+ cfg->ambient = m_page->intAmbient->value();
+ cfg->compensate = m_page->chkCompensate->isChecked();
+ cfg->invert = m_page->chkInvert->isChecked();
+ cfg->tiled = m_page->chkTiled->isChecked();
+ cfg->type = (enumBumpmapType)m_page->grpType->selectedId();
+
+ return cfg;
+}
+
+void KisBumpmapConfigWidget::setConfiguration(KisFilterConfiguration * config)
+{
+ KisBumpmapConfiguration * cfg = dynamic_cast<KisBumpmapConfiguration*>(config);
+ if (!cfg) return;
+
+ // NOTE: maybe we should find the item instead?
+ m_page->cboxSourceLayer->setCurrentText( cfg->bumpmap );
+ m_page->dblAzimuth->setValue(cfg->azimuth);
+ m_page->dblElevation->setValue(cfg->elevation);
+ m_page->dblDepth->setValue(cfg->depth);
+ m_page->intXOffset->setValue(cfg->xofs);
+ m_page->intYOffset->setValue(cfg->yofs);
+ m_page->intWaterLevel->setValue(cfg->waterlevel);
+ m_page->intAmbient->setValue(cfg->ambient);
+ m_page->chkCompensate->setChecked(cfg->compensate);
+ m_page->chkInvert->setChecked(cfg->invert);
+ m_page->chkTiled->setChecked(cfg->tiled);
+ m_page->grpType->setButton(cfg->type);
+
+}
+
+#include "bumpmap.moc"
diff --git a/chalk/plugins/filters/bumpmap/bumpmap.h b/chalk/plugins/filters/bumpmap/bumpmap.h
new file mode 100644
index 00000000..b1c16b1a
--- /dev/null
+++ b/chalk/plugins/filters/bumpmap/bumpmap.h
@@ -0,0 +1,130 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2007 Benjamin Schleimer <bensch128@yahoo.com>
+ *
+ * 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 BUMPMAP_H
+#define BUMPMAP_H
+
+#include <tqwidget.h>
+
+#include <kparts/plugin.h>
+
+#include <kis_types.h>
+#include <kis_filter.h>
+#include "kis_filter_config_widget.h"
+
+class WdgBumpMap;
+
+namespace chalk {
+
+ enum enumBumpmapType {
+ LINEAR = 0,
+ SPHERICAL = 1,
+ SINUSOIDAL = 2
+ };
+
+}
+
+using namespace chalk;
+
+
+
+class ChalkBumpmap : public KParts::Plugin
+{
+public:
+ ChalkBumpmap(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ChalkBumpmap();
+};
+
+
+/**
+ * First stab at a bumpmapping filter. For now, this is taken both
+ * from the Gimp source and the code from emboss.c:
+ * ANSI C code from the article
+ * "Fast Embossing Effects on Raster Image Data"
+ * by John Schlag, jfs@kerner.com
+ * in "Graphics Gems IV", Academic Press, 1994
+ */
+class KisFilterBumpmap : public KisFilter
+{
+public:
+ KisFilterBumpmap();
+public:
+ virtual void process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration*, const TQRect&);
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return TO_LAB16; };
+ static inline KisID id() { return KisID("bumpmap", i18n("Bumpmap")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return true; }
+ virtual bool supportsAdjustmentLayers() { return false; }
+ virtual bool supportsThreading() { return false; }
+
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration * configuration(TQWidget*);
+ virtual KisFilterConfiguration * configuration();
+
+};
+
+
+
+class KisBumpmapConfiguration : public KisFilterConfiguration {
+
+public:
+
+ KisBumpmapConfiguration();
+ virtual void fromXML( const TQString& );
+ virtual TQString toString();
+
+public:
+
+ TQString bumpmap;
+ double azimuth;
+ double elevation;
+ double depth;
+ TQ_INT32 xofs;
+ TQ_INT32 yofs;
+ TQ_INT32 waterlevel;
+ TQ_INT32 ambient;
+ bool compensate;
+ bool invert;
+ bool tiled;
+ enumBumpmapType type;
+
+};
+
+
+class KisBumpmapConfigWidget : public KisFilterConfigWidget {
+
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisBumpmapConfigWidget(KisFilter * filter, KisPaintDeviceSP dev, TQWidget * tqparent, const char * name = 0, WFlags f = 0 );
+ virtual ~KisBumpmapConfigWidget() {};
+
+ KisBumpmapConfiguration * config();
+ void setConfiguration(KisFilterConfiguration * config);
+
+private:
+
+ WdgBumpmap * m_page;
+};
+
+#endif
diff --git a/chalk/plugins/filters/bumpmap/chalkbumpmapfilter.desktop b/chalk/plugins/filters/bumpmap/chalkbumpmapfilter.desktop
new file mode 100644
index 00000000..727810df
--- /dev/null
+++ b/chalk/plugins/filters/bumpmap/chalkbumpmapfilter.desktop
@@ -0,0 +1,71 @@
+[Desktop Entry]
+Name=Bumpmap Filter
+Name[bg]=Филтър Bumpmap
+Name[ca]=Filtre Bumpmap
+Name[cy]=Hidlen chwyddfap
+Name[da]=Bumpkortfilter
+Name[de]=Bumpmap-Filter
+Name[el]=Φίλτρο ανάγλυφου χάρτη
+Name[es]=Filtro de mapa de colisiones
+Name[et]=Kühmukaardi filter
+Name[fa]=پالایۀ Bumpmap
+Name[fr]=Filtre bumpmap
+Name[fy]=Bumpmapfilter
+Name[ga]=Scagaire Bumpmap
+Name[gl]=Filtro de Bumpmaps
+Name[hu]=Bumpmap szűrő
+Name[is]=Bumpmap sía
+Name[it]=Filtro bumpmap
+Name[ja]=Bumpmap フィルタ
+Name[km]=តម្រង​ផែនទី​រដិបរដុប
+Name[nb]=Dumpkart-filter
+Name[nds]=Bumpmap-Filter
+Name[ne]=बम्पम्याप फिल्टर
+Name[nl]=Bumpmapfilter
+Name[pl]=Filtr odwzorowania nierówności
+Name[pt]=Filtro de 'Bumpmaps'
+Name[pt_BR]=Filtro de 'Bumpmaps'
+Name[ru]=Рельеф
+Name[sl]=Filter nagubanosti
+Name[sr]=Филтер мапе рељефа
+Name[sr@Latn]=Filter mape reljefa
+Name[sv]=Bulkartefilter
+Name[uk]=Рельєф
+Name[zh_TW]=Bumpmap 過濾器
+Comment=Bumpmap filter
+Comment[bg]=Филтър Bumpmap
+Comment[ca]=Filtre de Bumpmap
+Comment[cy]=Hidlen chwyddfap
+Comment[da]=Bumpkortfilter
+Comment[de]=Bumpmap-Filter
+Comment[el]=Φίλτρο ανάγλυφου χάρτη
+Comment[es]=Filtro de mapa de colisiones
+Comment[et]=Kühmukaardi filter
+Comment[fa]=پالایۀ Bumpmap
+Comment[fr]=Filtre bumpmap
+Comment[fy]=Bumpmapfilter
+Comment[ga]=Scagaire Bumpmap
+Comment[gl]=Filtro de bumpmaps
+Comment[hu]=Bumpmap szűrő
+Comment[is]=Bumpmap sía
+Comment[it]=Filtro bumpmap
+Comment[ja]=Bumpmap フィルタ
+Comment[km]=តម្រង​ផែនទី​រដិបរដុប
+Comment[nb]=Dumpkart-filter
+Comment[nds]=Bumpmap-Filter
+Comment[ne]=बम्पम्याप फिल्टर
+Comment[nl]=Bumpmapfilter
+Comment[pl]=Filtr odwzorowania nierówności (ang. bumpmap)
+Comment[pt]=Filtro de 'bumpmaps'
+Comment[pt_BR]=Filtro de 'bumpmaps'
+Comment[ru]=Рельеф
+Comment[sl]=Filter za nagubanost
+Comment[sr]=Филтер мапе рељефа
+Comment[sr@Latn]=Filter mape reljefa
+Comment[sv]=Bulkartefilter
+Comment[uk]=Фільтр рельєфу
+Comment[zh_TW]=Bumpmap 的過濾器
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkbumpmap
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/bumpmap/wdgbumpmap.ui b/chalk/plugins/filters/bumpmap/wdgbumpmap.ui
new file mode 100644
index 00000000..a783dd85
--- /dev/null
+++ b/chalk/plugins/filters/bumpmap/wdgbumpmap.ui
@@ -0,0 +1,374 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgBumpmap</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgBumpmap</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>520</width>
+ <height>603</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQFrame" row="3" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>frame3</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Bumpmapping&lt;/b&gt; is a process where two layers are
+combined to give one layer the illusion of &lt;i&gt;depth&lt;/i&gt;. One layer
+will contain your image, the other a grayscale or black-and-white
+representation of height, which is the bumpmap. If you do not specify a bumpmap
+layer, the current layer will be used.</string>
+ </property>
+ <property name="textFormat">
+ <enum>RichText</enum>
+ </property>
+ <property name="tqalignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="TQGroupBox" row="2" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>grpSettings</cstring>
+ </property>
+ <property name="title">
+ <string>Settings</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignAuto</set>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KDoubleSpinBox" row="1" column="1">
+ <property name="name">
+ <cstring>dblElevation</cstring>
+ </property>
+ <property name="maxValue">
+ <number>90</number>
+ </property>
+ <property name="minValue">
+ <number>0.5</number>
+ </property>
+ <property name="value">
+ <number>45</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Elevation:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>dblElevation</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel5</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Depth:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>dblDepth</cstring>
+ </property>
+ </widget>
+ <widget class="KDoubleSpinBox" row="2" column="1">
+ <property name="name">
+ <cstring>dblDepth</cstring>
+ </property>
+ <property name="maxValue">
+ <number>65</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>3</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Azimuth:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>dblAzimuth</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="2" column="3">
+ <property name="name">
+ <cstring>intWaterLevel</cstring>
+ </property>
+ <property name="maxValue">
+ <number>255</number>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="1" column="3">
+ <property name="name">
+ <cstring>intYOffset</cstring>
+ </property>
+ <property name="minValue">
+ <number>-99</number>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="3" column="3">
+ <property name="name">
+ <cstring>intAmbient</cstring>
+ </property>
+ <property name="maxValue">
+ <number>255</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="2">
+ <property name="name">
+ <cstring>textLabel8</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Water level:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>intWaterLevel</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="2">
+ <property name="name">
+ <cstring>textLabel9</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Ambient light:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>intAmbient</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="0" column="3">
+ <property name="name">
+ <cstring>intXOffset</cstring>
+ </property>
+ <property name="minValue">
+ <number>-99</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="2">
+ <property name="name">
+ <cstring>textLabel7</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Y offset:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>intYOffset</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="2">
+ <property name="name">
+ <cstring>textLabel6</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;X offset:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>intXOffset</cstring>
+ </property>
+ </widget>
+ <widget class="KDoubleSpinBox" row="0" column="1">
+ <property name="name">
+ <cstring>dblAzimuth</cstring>
+ </property>
+ <property name="maxValue">
+ <number>360</number>
+ </property>
+ <property name="value">
+ <number>135</number>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQButtonGroup" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>grpType</cstring>
+ </property>
+ <property name="title">
+ <string>&amp;Type</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>radioLinear</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Linear</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>radioSpherical</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Spherical</string>
+ </property>
+ </widget>
+ <widget class="TQRadioButton" row="2" column="0">
+ <property name="name">
+ <cstring>radioSinusoidal</cstring>
+ </property>
+ <property name="text">
+ <string>S&amp;inusoidal</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQGroupBox" row="1" column="2">
+ <property name="name">
+ <cstring>grpOptions</cstring>
+ </property>
+ <property name="title">
+ <string>Options</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>chkCompensate</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Compensate for darkening</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="2" column="0">
+ <property name="name">
+ <cstring>chkTiled</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Tile bumpmap</string>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>chkInvert</cstring>
+ </property>
+ <property name="text">
+ <string>I&amp;nvert bumpmap</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lblLayer</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Bumpmap layer:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>txtSourceLayer</cstring>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="0" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>cboxSourceLayer</cstring>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>radioLinear</tabstop>
+ <tabstop>chkCompensate</tabstop>
+ <tabstop>chkInvert</tabstop>
+ <tabstop>chkTiled</tabstop>
+ <tabstop>dblAzimuth</tabstop>
+ <tabstop>dblElevation</tabstop>
+ <tabstop>dblDepth</tabstop>
+ <tabstop>intXOffset</tabstop>
+ <tabstop>intYOffset</tabstop>
+ <tabstop>intWaterLevel</tabstop>
+ <tabstop>intAmbient</tabstop>
+</tabstops>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>kcombobox.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/filters/cimg/.kdev_ignore b/chalk/plugins/filters/cimg/.kdev_ignore
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/chalk/plugins/filters/cimg/.kdev_ignore
diff --git a/chalk/plugins/filters/cimg/CImg.h b/chalk/plugins/filters/cimg/CImg.h
new file mode 100644
index 00000000..871cb496
--- /dev/null
+++ b/chalk/plugins/filters/cimg/CImg.h
@@ -0,0 +1,19174 @@
+/*
+ #
+ # File : CImg.h
+ #
+ # Description : The C++ Template Image Processing Library
+ # ( http://cimg.sourceforge.net )
+ #
+ # Copyright : David Tschumperle
+ # ( http://www.greyc.ensicaen.fr/~dtschump/ )
+ #
+ # This software is governed by the CeCILL license under French law and
+ # abiding by the rules of distribution of free software. You can use,
+ # modify and or redistribute the software under the terms of the CeCILL
+ # license as circulated by CEA, CNRS and INRIA at the following URL
+ # "http://www.cecill.info".
+ #
+ # As a counterpart to the access to the source code and rights to copy,
+ # modify and redistribute granted by the license, users are provided only
+ # with a limited warranty and the software's author, the holder of the
+ # economic rights, and the successive licensors have only limited
+ # liability.
+ #
+ # In this respect, the user's attention is drawn to the risks associated
+ # with loading, using, modifying and/or developing or reproducing the
+ # software by the user in light of its specific status of free software,
+ # that may mean that it is complicated to manipulate, and that also
+ # therefore means that it is reserved for developers and experienced
+ # professionals having in-depth computer knowledge. Users are therefore
+ # encouraged to load and test the software's suitability as regards their
+ # requirements in conditions enabling the security of their systems and/or
+ # data to be ensured and, more generally, to use and operate it in the
+ # same conditions as regards security.
+ #
+ # The fact that you are presently reading this means that you have had
+ # knowledge of the CeCILL license and that you accept its terms.
+ #
+ */
+
+#ifndef cimg_version
+#define cimg_version 1.14
+
+// Avoid strange warning messages on Visual C++ express 2005.
+#if ( defined(_MSC_VER) && _MSC_VER>=1400 )
+#define _CRT_SECURE_NO_DEPRECATE 1
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#endif
+
+// Standard C++ includes
+#include <cstdio>
+#include <cstdlib>
+#include <cstdarg>
+#include <cstring>
+#include <cmath>
+#include <ctime>
+
+// Overcome VisualC++ 6.0 and DMC compilers namespace 'std::' bug
+#if ( defined(_MSC_VER) && _MSC_VER<=1200 ) || defined(__DMC__)
+#define std
+#endif
+
+/*
+ #
+ # Set CImg configuration flags.
+ #
+ # If compilation flags are not adapted to your system,
+ # you may override their values, before including
+ # the header file "CImg.h" (use the #define directive).
+ #
+ */
+
+// Try to detect the current system and set value of 'cimg_OS'.
+#ifndef cimg_OS
+#if defined(sun) || defined(__sun) || defined(linux) || defined(__linux) \
+ || defined(__linux__) || defined(__CYGWIN__) || defined(BSD) || defined(__FreeBSD__) \
+ || defined(__OPENBSD__) || defined(__MACOSX__) || defined(__APPLE__) || defined(sgi) \
+ || defined(__sgi)
+// Unix-like (Linux, Solaris, BSD, Irix,...)
+#define cimg_OS 1
+#ifndef cimg_display_type
+#define cimg_display_type 1
+#endif
+#ifndef cimg_color_terminal
+#define cimg_color_terminal
+#endif
+#elif defined(_WIN32) || defined(__WIN32__)
+// Windows
+#define cimg_OS 2
+#ifndef cimg_display_type
+#define cimg_display_type 2
+#endif
+#else
+// Unknown configuration : will compile with minimal dependencies.
+#define cimg_OS 0
+#ifndef cimg_display_type
+#define cimg_display_type 0
+#endif
+#endif
+#endif
+
+// Debug configuration.
+//
+// Define 'cimg_debug' to : 0 to remove dynamic debug messages (exceptions are still thrown)
+// 1 to display dynamic debug messages (default behavior).
+// 2 to add memory access controls (may slow down the code, but display extra warning messages)
+#ifndef cimg_debug
+#define cimg_debug 1
+#endif
+
+// Architecture-dependent includes.
+#if cimg_OS==1
+#include <sys/time.h>
+#include <unistd.h>
+#elif cimg_OS==2
+#include <windows.h>
+// Discard unuseful macros in windows.h
+// to allow compilation with VC++ 6.0.
+#ifdef min
+#undef min
+#undef max
+#undef abs
+#endif
+#endif
+#if cimg_display_type==1
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <pthread.h>
+#ifdef cimg_use_xshm
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <X11/extensions/XShm.h>
+#endif
+#endif
+
+// Configuration for native PNG and JPEG support
+// Define 'cimg_use_png' or 'cimg_use_jpeg' to enable native PNG or JPEG files support.
+// This requires you link your code with the zlib/png or jpeg libraries.
+// Without these libraries, PNG and JPEG support will be done by the Image Magick's 'convert' tool, if installed
+// (this is the case on most unix plateforms).
+#ifdef cimg_use_png
+extern "C" {
+#include "png.h"
+}
+#endif
+#ifdef cimg_use_jpeg
+extern "C" {
+#include "jpeglib.h"
+}
+#endif
+
+/*
+ #
+ #
+ # Define some useful macros. Macros of the CImg Library are prefixed by 'cimg_'
+ # Documented macros below may be safely used in your own code
+ # (particularly useful for option parsing, image loops and neighborhoods).
+ #
+ #
+ */
+
+// Macros used to describe the program usage, and retrieve command line arguments
+// (See corresponding module 'Retrieving command line arguments' in the generated documentation).
+#define cimg_usage(usage) cimg_library::cimg::option((const char*)0,argc,argv,(const char*)0,usage)
+#define cimg_option(name,defaut,usage) cimg_library::cimg::option(name,argc,argv,defaut,usage)
+
+// Macros used for neighborhood definitions and manipulations.
+// (see module 'Using Image Loops' in the generated documentation).
+#define CImg_2x2x1(I,T) T I##cc,I##nc=0,I##cn,I##nn=0
+#define CImg_3x1x1(I,T) T I##pp,I##cp,I##np=0
+#define CImg_3x3x1(I,T) T I##pp,I##cp,I##np=0,I##pc,I##cc,I##nc=0,I##pn,I##cn,I##nn=0
+#define CImg_4x1x1(I,T) T I##pp,I##cp,I##np=0,I##ap=0
+#define CImg_4x4x1(I,T) T I##pp,I##cp,I##np=0,I##ap=0, \
+ I##pc,I##cc,I##nc=0,I##ac=0, \
+ I##pn,I##cn,I##nn=0,I##an=0, \
+ I##pa,I##ca,I##na=0,I##aa=0
+#define CImg_5x1x1(I,T) T I##bb,I##pb,I##cb,I##nb=0,I##ab=0
+#define CImg_5x5x1(I,T) T I##bb,I##pb,I##cb,I##nb=0,I##ab=0, \
+ I##bp,I##pp,I##cp,I##np=0,I##ap=0, \
+ I##bc,I##pc,I##cc,I##nc=0,I##ac=0, \
+ I##bn,I##pn,I##cn,I##nn=0,I##an=0, \
+ I##ba,I##pa,I##ca,I##na=0,I##aa=0
+#define CImg_2x2x2(I,T) T I##ccc,I##ncc=0,I##cnc,I##nnc=0, \
+ I##ccn,I##ncn=0,I##cnn,I##nnn=0
+#define CImg_3x3x3(I,T) T I##ppp,I##cpp,I##npp=0,I##pcp,I##ccp,I##ncp=0,I##pnp,I##cnp,I##nnp=0, \
+ I##ppc,I##cpc,I##npc=0,I##pcc,I##ccc,I##ncc=0,I##pnc,I##cnc,I##nnc=0, \
+ I##ppn,I##cpn,I##npn=0,I##pcn,I##ccn,I##ncn=0,I##pnn,I##cnn,I##nnn=0
+
+#define CImg_2x2x1_ref(I,T,tab) T &I##cc=(tab)[0],&I##nc=(tab)[1],&I##cn=(tab)[2],&I##nn=(tab)[3]
+#define CImg_3x3x1_ref(I,T,tab) T &I##pp=(tab)[0],&I##cp=(tab)[1],&I##np=(tab)[2], \
+ &I##pc=(tab)[3],&I##cc=(tab)[4],&I##nc=(tab)[5], \
+ &I##pn=(tab)[6],&I##cn=(tab)[7],&I##nn=(tab)[8]
+#define CImg_4x4x1_ref(I,T,tab) T &I##pp=(tab)[0],&I##cp=(tab)[1],&I##np=(tab)[2],&I##ap=(tab)[3], \
+ &I##pc=(tab)[4],&I##cc=(tab)[5],&I##nc=(tab)[6],&I##ap=(tab)[7], \
+ &I##pn=(tab)[8],&I##cn=(tab)[9],&I##nn=(tab)[10],&I##aa=(tab)[11], \
+ &I##pa=(tab)[12],&I##ca=(tab)[13],&I##na=(tab)[14],&I##aa=(tab)[15]
+#define CImg_5x5x1_ref(I,T,tab) T &I##bb=(tab)[0],&I##pb=(tab)[1],&I##cb=(tab)[2],&I##nb=(tab)[3],&I##ab=(tab)[4], \
+ &I##bp=(tab)[5],&I##pp=(tab)[6],&I##cp=(tab)[7],&I##np=(tab)[8],&I##ap=(tab)[9], \
+ &I##bc=(tab)[10],&I##pc=(tab)[11],&I##cc=(tab)[12],&I##nc=(tab)[13],&I##ac=(tab)[14], \
+ &I##bn=(tab)[15],&I##pn=(tab)[16],&I##cn=(tab)[17],&I##nn=(tab)[18],&I##an=(tab)[19], \
+ &I##ba=(tab)[20],&I##pa=(tab)[21],&I##ca=(tab)[22],&I##na=(tab)[23],&I##aa=(tab)[24]
+#define CImg_2x2x2_ref(I,T,tab) T &I##ccc=(tab)[0],&I##ncc=(tab)[1],&I##cnc=(tab)[2],&I##nnc=(tab)[3], \
+ &I##ccn=(tab)[4],&I##ncn=(tab)[5],&I##cnn=(tab)[6],&I##nnn=(tab)[7]
+#define CImg_3x3x3_ref(I,T,tab) T &I##ppp=(tab)[0],&I##cpp=(tab)[1],&I##npp=(tab)[2], \
+ &I##pcp=(tab)[3],&I##ccp=(tab)[4],&I##ncp=(tab)[5], \
+ &I##pnp=(tab)[6],&I##cnp=(tab)[7],&I##nnp=(tab)[8], \
+ &I##ppc=(tab)[9],&I##cpc=(tab)[10],&I##npc=(tab)[11], \
+ &I##pcc=(tab)[12],&I##ccc=(tab)[13],&I##ncc=(tab)[14], \
+ &I##pnc=(tab)[15],&I##cnc=(tab)[16],&I##nnc=(tab)[17], \
+ &I##ppn=(tab)[18],&I##cpn=(tab)[19],&I##npn=(tab)[20], \
+ &I##pcn=(tab)[21],&I##ccn=(tab)[22],&I##ncn=(tab)[23], \
+ &I##pnn=(tab)[24],&I##cnn=(tab)[25],&I##nnn=(tab)[26]
+
+#define cimg_copy2x2x1(J,I) I##cc=J##cc, I##nc=J##nc, I##cn=J##cn, I##nn=J##nn
+#define cimg_copy3x3x1(J,I) I##pp=J##pp, I##cp=J##cp, I##np=J##np, \
+ I##pc=J##pc, I##cc=J##cc, I##nc=J##nc, \
+ I##pn=J##pn, I##cn=J##cn, I##nn=J##nn
+#define cimg_copy5x5x1(J,I) I##bb=J##bb, I##pb=J##pb, I##cb=J##cb, I##nb=J##nb, I##ab=J##ab, \
+ I##bp=J##bp, I##pp=J##pp, I##cp=J##cp, I##np=J##np, I##ap=J##ap, \
+ I##bc=J##bc, I##pc=J##pc, I##cc=J##cc, I##nc=J##nc, I##ac=J##ac, \
+ I##bn=J##bn, I##pn=J##pn, I##cn=J##cn, I##nn=J##nn, I##an=J##an, \
+ I##ba=J##ba, I##pa=J##pa, I##ca=J##ca, I##na=J##na, I##aa=J##aa
+
+#define cimg_squaresum2x2x1(I) ( I##cc*I##cc + I##nc*I##nc + I##cn*I##cn + I##nn*I##nn )
+#define cimg_squaresum3x3x1(I) ( I##pp*I##pp + I##cp*I##cp + I##np*I##np + \
+ I##pc*I##pc + I##cc*I##cc + I##nc*I##nc + \
+ I##pn*I##pn + I##cn*I##cn + I##nn*I##nn )
+#define cimg_squaresum4x4x1(I) ( I##pp*I##pp + I##cp*I##cp + I##np*I##np + I##ap*I##ap + \
+ I##pc*I##pc + I##cc*I##cc + I##nc*I##nc + I##ac*I##ac + \
+ I##pn*I##pn + I##cn*I##cn + I##nn*I##nn + I##an*I##an + \
+ I##pa*I##pa + I##ca*I##ca + I##na*I##na + I##aa*I##aa )
+#define cimg_squaresum5x5x1(I) ( I##bb*I##bb + I##pb*I##pb + I##cb*I##cb + I##nb*I##nb + I##ab*I##ab + \
+ I##bp*I##bp + I##pp*I##pp + I##cp*I##cp + I##np*I##np + I##ap*I##ap + \
+ I##bc*I##bc + I##pc*I##pc + I##cc*I##cc + I##nc*I##nc + I##ac*I##ac + \
+ I##bn*I##bn + I##pn*I##pn + I##cn*I##cn + I##nn*I##nn + I##an*I##an + \
+ I##ba*I##ba + I##pa*I##pa + I##ca*I##ca + I##na*I##na + I##aa*I##aa )
+#define cimg_squaresum2x2x2(I) ( I##ccc*I##ccc + I##ncc*I##ncc + I##cnc*I##cnc + I##nnc*I##nnc + \
+ I##ccn*I##ccn + I##ncn*I##ncn + I##cnn*I##cnn + I##nnn*I##nnn )
+#define cimg_squaresum3x3x3(I) ( I##ppp*I##ppp + I##cpp*I##cpp + I##npp*I##npp + \
+ I##pcp*I##pcp + I##ccp*I##ccp + I##ncp*I##ncp + \
+ I##pnp*I##pnp + I##cnp*I##cnp + I##nnp*I##nnp + \
+ I##ppc*I##ppc + I##cpc*I##cpc + I##npc*I##npc + \
+ I##pcc*I##pcc + I##ccc*I##ccc + I##ncc*I##ncc + \
+ I##pnc*I##pnc + I##cnc*I##cnc + I##nnc*I##nnc + \
+ I##ppn*I##ppn + I##cpn*I##cpn + I##npn*I##npn + \
+ I##pcn*I##pcn + I##ccn*I##ccn + I##ncn*I##ncn + \
+ I##pnn*I##pnn + I##cnn*I##cnn + I##nnn*I##nnn )
+
+#define cimg_corr2x2x1(I,m) ( I##cc*(m)(0,0)+I##nc*(m)(1,0)+I##cn*(m)(0,1)+I##nn*(m)(1,1) )
+#define cimg_corr3x3x1(I,m) ( I##pp*(m)(0,0)+I##cp*(m)(1,0)+I##np*(m)(2,0) + \
+ I##pc*(m)(0,1)+I##cc*(m)(1,1)+I##nc*(m)(2,1) + \
+ I##pn*(m)(0,2)+I##cn*(m)(1,2)+I##nn*(m)(2,2) )
+#define cimg_corr4x4x1(I,m) ( I##pp*(m)(0,0)+I##cp*(m)(1,0)+I##np*(m)(2,0)+I##ap*(m)(3,0) + \
+ I##pc*(m)(0,1)+I##cc*(m)(1,1)+I##nc*(m)(2,1)+I##ac*(m)(3,1) + \
+ I##pn*(m)(0,2)+I##cn*(m)(1,2)+I##nn*(m)(2,2)+I##an*(m)(3,2) + \
+ I##pa*(m)(0,3)+I##ca*(m)(1,3)+I##na*(m)(2,3)+I##aa*(m)(3,3) )
+#define cimg_corr5x5x1(I,m) ( I##bb*(m)(0,0)+I##pb*(m)(1,0)+I##cb*(m)(2,0)+I##nb*(m)(3,0)+I##ab*(m)(4,0) + \
+ I##bp*(m)(0,1)+I##pp*(m)(1,1)+I##cp*(m)(2,1)+I##np*(m)(3,1)+I##ap*(m)(4,1) + \
+ I##bc*(m)(0,2)+I##pc*(m)(1,2)+I##cc*(m)(2,2)+I##nc*(m)(3,2)+I##ac*(m)(4,2) + \
+ I##bn*(m)(0,3)+I##pn*(m)(1,3)+I##cn*(m)(2,3)+I##nn*(m)(3,3)+I##an*(m)(4,3) + \
+ I##ba*(m)(0,4)+I##pa*(m)(1,4)+I##ca*(m)(2,4)+I##na*(m)(3,4)+I##aa*(m)(4,4) )
+#define cimg_corr2x2x2(I,m) ( I##ccc*(m)(0,0,0)+I##ncc*(m)(1,0,0)+I##cnc*(m)(0,1,0)+I##nnc*(m)(1,1,0) + \
+ I##ccn*(m)(0,0,1)+I##ncn*(m)(1,0,1)+I##cnn*(m)(0,1,1)+I##nnn*(m)(1,1,1) )
+#define cimg_corr3x3x3(I,m) ( I##ppp*(m)(0,0,0)+I##cpp*(m)(1,0,0)+I##npp*(m)(2,0,0) + \
+ I##pcp*(m)(0,1,0)+I##ccp*(m)(1,1,0)+I##ncp*(m)(2,1,0) + \
+ I##pnp*(m)(0,2,0)+I##cnp*(m)(1,2,0)+I##nnp*(m)(2,2,0) + \
+ I##ppc*(m)(0,0,1)+I##cpc*(m)(1,0,1)+I##npc*(m)(2,0,1) + \
+ I##pcc*(m)(0,1,1)+I##ccc*(m)(1,1,1)+I##ncc*(m)(2,1,1) + \
+ I##pnc*(m)(0,2,1)+I##cnc*(m)(1,2,1)+I##nnc*(m)(2,2,1) + \
+ I##ppn*(m)(0,0,2)+I##cpn*(m)(1,0,2)+I##npn*(m)(2,0,2) + \
+ I##pcn*(m)(0,1,2)+I##ccn*(m)(1,1,2)+I##ncn*(m)(2,1,2) + \
+ I##pnn*(m)(0,2,2)+I##cnn*(m)(1,2,2)+I##nnn*(m)(2,2,2) )
+
+#define cimg_conv2x2x1(I,m) ( I##cc*(m)(1,1)+I##nc*(m)(0,1)+I##cn*(m)(1,0)+I##nn*(m)(0,0) )
+#define cimg_conv3x3x1(I,m) ( I##pp*(m)(2,2)+I##cp*(m)(1,2)+I##np*(m)(0,2) + \
+ I##pc*(m)(2,1)+I##cc*(m)(1,1)+I##nc*(m)(0,1) + \
+ I##pn*(m)(2,0)+I##cn*(m)(1,0)+I##nn*(m)(0,0) )
+#define cimg_conv4x4x1(I,m) ( I##pp*(m)(3,3)+I##cp*(m)(2,3)+I##np*(m)(1,3)+I##ap*(m)(0,3) + \
+ I##pc*(m)(3,2)+I##cc*(m)(2,2)+I##nc*(m)(1,2)+I##ac*(m)(0,2) + \
+ I##pn*(m)(3,1)+I##cn*(m)(2,1)+I##nn*(m)(1,1)+I##an*(m)(0,1) + \
+ I##pa*(m)(3,0)+I##ca*(m)(2,0)+I##na*(m)(1,0)+I##aa*(m)(0,0) )
+#define cimg_conv5x5x1(I,m) ( I##bb*(m)(4,4)+I##pb*(m)(3,4)+I##cb*(m)(2,4)+I##nb*(m)(1,4)+I##ab*(m)(0,4) + \
+ I##bp*(m)(4,3)+I##pp*(m)(3,3)+I##cp*(m)(2,3)+I##np*(m)(1,3)+I##ap*(m)(0,3) + \
+ I##bc*(m)(4,2)+I##pc*(m)(3,2)+I##cc*(m)(2,2)+I##nc*(m)(1,2)+I##ac*(m)(0,2) + \
+ I##bn*(m)(4,1)+I##pn*(m)(3,1)+I##cn*(m)(2,1)+I##nn*(m)(1,1)+I##an*(m)(0,1) + \
+ I##ba*(m)(4,0)+I##pa*(m)(3,0)+I##ca*(m)(2,0)+I##na*(m)(1,0)+I##aa*(m)(0,0) )
+#define cimg_conv2x2x2(I,m) ( I##ccc*(m)(1,1,1)+I##ncc*(m)(0,1,1)+I##cnc*(m)(1,0,1)+I##nnc*(m)(0,0,1) + \
+ I##ccn*(m)(1,1,0)+I##ncn*(m)(0,1,0)+I##cnn*(m)(1,0,0)+I##nnn*(m)(0,0,0) )
+#define cimg_conv3x3x3(I,m) ( I##ppp*(m)(2,2,2)+I##cpp*(m)(1,2,2)+I##npp*(m)(0,2,2) + \
+ I##pcp*(m)(2,1,2)+I##ccp*(m)(1,1,2)+I##ncp*(m)(0,1,2) + \
+ I##pnp*(m)(2,0,2)+I##cnp*(m)(1,0,2)+I##nnp*(m)(0,0,2) + \
+ I##ppc*(m)(2,2,1)+I##cpc*(m)(1,2,1)+I##npc*(m)(0,2,1) + \
+ I##pcc*(m)(2,1,1)+I##ccc*(m)(1,1,1)+I##ncc*(m)(0,1,1) + \
+ I##pnc*(m)(2,0,1)+I##cnc*(m)(1,0,1)+I##nnc*(m)(0,0,1) + \
+ I##ppn*(m)(2,2,0)+I##cpn*(m)(1,2,0)+I##npn*(m)(0,2,0) + \
+ I##pcn*(m)(2,1,0)+I##ccn*(m)(1,1,0)+I##ncn*(m)(0,1,0) + \
+ I##pnn*(m)(2,0,0)+I##cnn*(m)(1,0,0)+I##nnn*(m)(0,0,0) )
+
+#define cimg_get2x2x1(img,x,y,z,v,I) \
+ I##cc=(img)(x, y,z,v), I##nc=(img)(_n##x, y,z,v), \
+ I##cn=(img)(x,_n##y,z,v), I##nn=(img)(_n##x,_n##y,z,v)
+#define cimg_get3x3x1(img,x,y,z,v,I) \
+ I##pp=(img)(_p##x,_p##y,z,v), I##cp=(img)(x,_p##y,z,v), I##np=(img)(_n##x,_p##y,z,v), \
+ I##pc=(img)(_p##x, y,z,v), I##cc=(img)(x, y,z,v), I##nc=(img)(_n##x, y,z,v), \
+ I##pn=(img)(_p##x,_n##y,z,v), I##cn=(img)(x,_n##y,z,v), I##nn=(img)(_n##x,_n##y,z,v)
+#define cimg_get4x4x1(img,x,y,z,v,I) \
+ I##pp=(img)(_p##x,_p##y,z,v), I##cp=(img)(x,_p##y,z,v), I##np=(img)(_n##x,_p##y,z,v), I##ap=(img)(_a##x,_p##y,z,v), \
+ I##pc=(img)(_p##x, y,z,v), I##cc=(img)(x, y,z,v), I##nc=(img)(_n##x, y,z,v), I##ac=(img)(_a##x, y,z,v), \
+ I##pn=(img)(_p##x,_n##y,z,v), I##cn=(img)(x,_n##y,z,v), I##nn=(img)(_n##x,_n##y,z,v), I##an=(img)(_a##x,_n##y,z,v), \
+ I##pa=(img)(_p##x,_a##y,z,v), I##ca=(img)(x,_a##y,z,v), I##na=(img)(_n##x,_a##y,z,v), I##aa=(img)(_a##x,_a##y,z,v)
+#define cimg_get5x5x1(img,x,y,z,v,I) \
+ I##bb=(img)(_b##x,_b##y,z,v), I##pb=(img)(_p##x,_b##y,z,v), I##cb=(img)(x,_b##y,z,v), I##nb=(img)(_n##x,_b##y,z,v), I##ab=(img)(_a##x,_b##y,z,v), \
+ I##bp=(img)(_b##x,_p##y,z,v), I##pp=(img)(_p##x,_p##y,z,v), I##cp=(img)(x,_p##y,z,v), I##np=(img)(_n##x,_p##y,z,v), I##ap=(img)(_a##x,_p##y,z,v), \
+ I##bc=(img)(_b##x, y,z,v), I##pc=(img)(_p##x, y,z,v), I##cc=(img)(x, y,z,v), I##nc=(img)(_n##x, y,z,v), I##ac=(img)(_a##x, y,z,v), \
+ I##bn=(img)(_b##x,_n##y,z,v), I##pn=(img)(_p##x,_n##y,z,v), I##cn=(img)(x,_n##y,z,v), I##nn=(img)(_n##x,_n##y,z,v), I##an=(img)(_a##x,_n##y,z,v), \
+ I##ba=(img)(_b##x,_a##y,z,v), I##pa=(img)(_p##x,_a##y,z,v), I##ca=(img)(x,_a##y,z,v), I##na=(img)(_n##x,_a##y,z,v), I##aa=(img)(_a##x,_a##y,z,v)
+#define cimg_get2x2x2(img,x,y,z,v,I) \
+ I##ccc=(img)(x,y, z,v), I##ncc=(img)(_n##x,y, z,v), I##cnc=(img)(x,_n##y, z,v), I##nnc=(img)(_n##x,_n##y, z,v), \
+ I##ccc=(img)(x,y,_n##z,v), I##ncc=(img)(_n##x,y,_n##z,v), I##cnc=(img)(x,_n##y,_n##z,v), I##nnc=(img)(_n##x,_n##y,_n##z,v)
+#define cimg_get3x3x3(img,x,y,z,v,I) \
+ I##ppp=(img)(_p##x,_p##y,_p##z,v), I##cpp=(img)(x,_p##y,_p##z,v), I##npp=(img)(_n##x,_p##y,_p##z,v), \
+ I##pcp=(img)(_p##x, y,_p##z,v), I##ccp=(img)(x, y,_p##z,v), I##ncp=(img)(_n##x, y,_p##z,v), \
+ I##pnp=(img)(_p##x,_n##y,_p##z,v), I##cnp=(img)(x,_n##y,_p##z,v), I##nnp=(img)(_n##x,_n##y,_p##z,v), \
+ I##ppc=(img)(_p##x,_p##y, z,v), I##cpc=(img)(x,_p##y, z,v), I##npc=(img)(_n##x,_p##y, z,v), \
+ I##pcc=(img)(_p##x, y, z,v), I##ccc=(img)(x, y, z,v), I##ncc=(img)(_n##x, y, z,v), \
+ I##pnc=(img)(_p##x,_n##y, z,v), I##cnc=(img)(x,_n##y, z,v), I##nnc=(img)(_n##x,_n##y, z,v), \
+ I##ppn=(img)(_p##x,_p##y,_n##z,v), I##cpn=(img)(x,_p##y,_n##z,v), I##npn=(img)(_n##x,_p##y,_n##z,v), \
+ I##pcn=(img)(_p##x, y,_n##z,v), I##ccn=(img)(x, y,_n##z,v), I##ncn=(img)(_n##x, y,_n##z,v), \
+ I##pnn=(img)(_p##x,_n##y,_n##z,v), I##cnn=(img)(x,_n##y,_n##z,v), I##nnn=(img)(_n##x,_n##y,_n##z,v)
+
+#define CImg_2x2(I,T) CImg_2x2x1(I,T)
+#define CImg_3x3(I,T) CImg_3x3x1(I,T)
+#define CImg_4x4(I,T) CImg_4x4x1(I,T)
+#define CImg_5x5(I,T) CImg_5x5x1(I,T)
+#define CImg_2x2_ref(I,T,tab) CImg_2x2x1_ref(I,T,tab)
+#define CImg_3x3_ref(I,T,tab) CImg_3x3x1_ref(I,T,tab)
+#define CImg_4x4_ref(I,T,tab) CImg_4x4x1_ref(I,T,tab)
+#define CImg_5x5_ref(I,T,tab) CImg_5x5x1_ref(I,T,tab)
+#define cimg_copy2x2(J,I) cimg_copy2x2x1(J,I)
+#define cimg_copy3x3(J,I) cimg_copy3x3x1(J,I)
+#define cimg_copy5x5(J,I) cimg_copy5x5x1(J,I)
+#define cimg_squaresum2x2(I) cimg_squaresum2x2x1(I)
+#define cimg_squaresum3x3(I) cimg_squaresum3x3x1(I)
+#define cimg_squaresum4x4(I) cimg_squaresum4x4x1(I)
+#define cimg_squaresum5x5(I) cimg_squaresum5x5x1(I)
+#define cimg_corr2x2(I) cimg_corr2x2x1(I)
+#define cimg_corr3x3(I) cimg_corr3x3x1(I)
+#define cimg_corr4x4(I) cimg_corr4x4x1(I)
+#define cimg_corr5x5(I) cimg_corr5x5x1(I)
+#define cimg_conv2x2(I) cimg_conv2x2x1(I)
+#define cimg_conv3x3(I) cimg_conv3x3x1(I)
+#define cimg_conv4x4(I) cimg_conv4x4x1(I)
+#define cimg_conv5x5(I) cimg_conv5x5x1(I)
+#define cimg_get2x2(img,x,y,z,k,I) cimg_get2x2x1(img,x,y,z,k,I)
+#define cimg_get3x3(img,x,y,z,k,I) cimg_get3x3x1(img,x,y,z,k,I)
+#define cimg_get4x4(img,x,y,z,k,I) cimg_get4x4x1(img,x,y,z,k,I)
+#define cimg_get5x5(img,x,y,z,k,I) cimg_get5x5x1(img,x,y,z,k,I)
+#define cimg_map2x2(img,x,y,z,k,I) cimg_map2x2x1(img,x,y,z,k,I)
+#define cimg_map3x3(img,x,y,z,k,I) cimg_map3x3x1(img,x,y,z,k,I)
+#define cimg_map4x4(img,x,y,z,k,I) cimg_map4x4x1(img,x,y,z,k,I)
+#define cimg_map5x5(img,x,y,z,k,I) cimg_map5x5x1(img,x,y,z,k,I)
+
+// Macros used to define special image loops.
+// (see module 'Using Image Loops' in the generated documentation).
+#define cimg_map(img,ptr,T_ptr) for (T_ptr *ptr=(img).data+(img).size(); (ptr--)>(img).data; )
+#define cimgl_map(list,l) for (unsigned int l=0; l<(list).size; l++)
+#define cimg_mapoff(img,off) for (unsigned int off=0; off<(img).size(); off++)
+#define cimg_mapX(img,x) for (int x=0; x<(int)((img).width); x++)
+#define cimg_mapY(img,y) for (int y=0; y<(int)((img).height);y++)
+#define cimg_mapZ(img,z) for (int z=0; z<(int)((img).depth); z++)
+#define cimg_mapV(img,v) for (int v=0; v<(int)((img).dim); v++)
+#define cimg_mapXY(img,x,y) cimg_mapY(img,y) cimg_mapX(img,x)
+#define cimg_mapXZ(img,x,z) cimg_mapZ(img,z) cimg_mapX(img,x)
+#define cimg_mapYZ(img,y,z) cimg_mapZ(img,z) cimg_mapY(img,y)
+#define cimg_mapXV(img,x,v) cimg_mapV(img,v) cimg_mapX(img,x)
+#define cimg_mapYV(img,y,v) cimg_mapV(img,v) cimg_mapY(img,y)
+#define cimg_mapZV(img,z,v) cimg_mapV(img,v) cimg_mapZ(img,z)
+#define cimg_mapXYZ(img,x,y,z) cimg_mapZ(img,z) cimg_mapXY(img,x,y)
+#define cimg_mapXYV(img,x,y,v) cimg_mapV(img,v) cimg_mapXY(img,x,y)
+#define cimg_mapXZV(img,x,z,v) cimg_mapV(img,v) cimg_mapXZ(img,x,z)
+#define cimg_mapYZV(img,y,z,v) cimg_mapV(img,v) cimg_mapYZ(img,y,z)
+#define cimg_mapXYZV(img,x,y,z,v) cimg_mapV(img,v) cimg_mapXYZ(img,x,y,z)
+#define cimg_imapX(img,x,n) for (int x=(n); x<(int)((img).width-(n)); x++)
+#define cimg_imapY(img,y,n) for (int y=(n); y<(int)((img).height-(n)); y++)
+#define cimg_imapZ(img,z,n) for (int z=(n); z<(int)((img).depth-(n)); z++)
+#define cimg_imapV(img,v,n) for (int v=(n); v<(int)((img).dim-(n)); v++)
+#define cimg_imapXY(img,x,y,n) cimg_imapY(img,y,n) cimg_imapX(img,x,n)
+#define cimg_imapXYZ(img,x,y,z,n) cimg_imapZ(img,z,n) cimg_imapXY(img,x,y,n)
+#define cimg_bmapX(img,x,n) for (int x=0; x<(int)((img).width); x==(n)-1?(x=(img).width-(n)): x++)
+#define cimg_bmapY(img,y,n) for (int y=0; y<(int)((img).height); y==(n)-1?(x=(img).height-(n)):y++)
+#define cimg_bmapZ(img,z,n) for (int z=0; z<(int)((img).depth); z==(n)-1?(x=(img).depth-(n)): z++)
+#define cimg_bmapV(img,v,n) for (int v=0; v<(int)((img).dim); v==(n)-1?(x=(img).dim-(n)): v++)
+#define cimg_bmapXY(img,x,y,n) cimg_mapY(img,y) for (int x=0; x<(int)((img).width); (y<(n) || y>=(int)((img).height)-(n))?x++: \
+ ((x<(n)-1 || x>=(int)((img).width)-(n))?x++:(x=(img).width-(n))))
+#define cimg_bmapXYZ(img,x,y,z,n) cimg_mapYZ(img,y,z) for (int x=0; x<(int)((img).width); (y<(n) || y>=(int)((img).height)-(n) || z<(n) || z>=(int)((img).depth)-(n))?x++: \
+ ((x<(n)-1 || x>=(int)((img).width)-(n))?x++:(x=(img).width-(n))))
+#define cimg_2mapX(img,x) for (int x=0,_n##x=1; _n##x<(int)((img).width) || x==--_n##x; x++, _n##x++)
+#define cimg_2mapY(img,y) for (int y=0,_n##y=1; _n##y<(int)((img).height) || y==--_n##y; y++, _n##y++)
+#define cimg_2mapZ(img,z) for (int z=0,_n##z=1; _n##z<(int)((img).depth) || z==--_n##z; z++, _n##z++)
+#define cimg_2mapXY(img,x,y) cimg_2mapY(img,y) cimg_2mapX(img,x)
+#define cimg_2mapXZ(img,x,z) cimg_2mapZ(img,z) cimg_2mapX(img,x)
+#define cimg_2mapYZ(img,y,z) cimg_2mapZ(img,z) cimg_2mapY(img,y)
+#define cimg_2mapXYZ(img,x,y,z) cimg_2mapZ(img,z) cimg_2mapXY(img,x,y)
+#define cimg_3mapX(img,x) for (int x=0,_p##x=0,_n##x=1; _n##x<(int)((img).width) || x==--_n##x; _p##x=x++,_n##x++)
+#define cimg_3mapY(img,y) for (int y=0,_p##y=0,_n##y=1; _n##y<(int)((img).height) || y==--_n##y; _p##y=y++,_n##y++)
+#define cimg_3mapZ(img,z) for (int z=0,_p##z=0,_n##z=1; _n##z<(int)((img).depth) || z==--_n##z; _p##z=z++,_n##z++)
+#define cimg_3mapXY(img,x,y) cimg_3mapY(img,y) cimg_3mapX(img,x)
+#define cimg_3mapXZ(img,x,z) cimg_3mapZ(img,z) cimg_3mapX(img,x)
+#define cimg_3mapYZ(img,y,z) cimg_3mapZ(img,z) cimg_3mapY(img,y)
+#define cimg_3mapXYZ(img,x,y,z) cimg_3mapZ(img,z) cimg_3mapXY(img,x,y)
+#define cimg_4mapX(img,x) for (int _p##x=0,x=0,_n##x=1,_a##x=2; \
+ _a##x<(int)((img).width) || _n##x==--_a##x || x==(_a##x=--_n##x); \
+ _p##x=x++,_n##x++,_a##x++)
+#define cimg_4mapY(img,y) for (int _p##y=0,y=0,_n##y=1,_a##y=2; \
+ _a##y<(int)((img).height) || _n##y==--_a##y || y==(_a##y=--_n##y); \
+ _p##y=y++,_n##y++,_a##y++)
+#define cimg_4mapZ(img,z) for (int _p##z=0,z=0,_n##z=1,_a##z=2; \
+ _a##z<(int)((img).depth) || _n##z==--_a##z || z==(_a##z=--_n##z); \
+ _p##z=z++,_n##z++,_a##z++)
+#define cimg_4mapXY(img,x,y) cimg_4mapY(img,y) cimg_4mapX(img,x)
+#define cimg_4mapXZ(img,x,z) cimg_4mapZ(img,z) cimg_4mapX(img,x)
+#define cimg_4mapYZ(img,y,z) cimg_4mapZ(img,z) cimg_4mapY(img,y)
+#define cimg_4mapXYZ(img,x,y,z) cimg_4mapZ(img,z) cimg_4mapXY(img,x,y)
+#define cimg_5mapX(img,x) for (int _b##x=0,_p##x=0,x=0,_n##x=1,_a##x=2; \
+ _a##x<(int)((img).width) || _n##x==--_a##x || x==(_a##x=--_n##x); \
+ _b##x=_p##x,_p##x=x++,_n##x++,_a##x++)
+#define cimg_5mapY(img,y) for (int _b##y=0,_p##y=0,y=0,_n##y=1,_a##y=2; \
+ _a##y<(int)((img).height) || _n##y==--_a##y || y==(_a##y=--_n##y); \
+ _b##y=_p##y,_p##y=y++,_n##y++,_a##y++)
+#define cimg_5mapZ(img,z) for (int _b##z=0,_p##z=0,z=0,_n##z=1,_a##z=2; \
+ _a##z<(int)((img).depth) || _n##z==--_a##z || z==(_a##z=--_n##z); \
+ _b##z=_p##z,_p##z=z++,_n##z++,_a##z++)
+#define cimg_5mapXY(img,x,y) cimg_5mapY(img,y) cimg_5mapX(img,x)
+#define cimg_5mapXZ(img,x,z) cimg_5mapZ(img,z) cimg_5mapX(img,x)
+#define cimg_5mapYZ(img,y,z) cimg_5mapZ(img,z) cimg_5mapY(img,y)
+#define cimg_5mapXYZ(img,x,y,z) cimg_5mapZ(img,z) cimg_5mapXY(img,x,y)
+
+#define cimg_map2x2x1(img,x,y,z,v,I) cimg_2mapY(img,y) \
+ for (int _n##x=1, x=(int)((I##cc=(img)(0, y,z,v)), \
+ (I##cn=(img)(0,_n##y,z,v)), \
+ 0); \
+ (_n##x<(int)((img).width) && ((I##nc=(img)(_n##x, y,z,v)), \
+ (I##nn=(img)(_n##x,_n##y,z,v)), \
+ 1)) || x==--_n##x; \
+ I##cc=I##nc, I##cn=I##nn, \
+ x++,_n##x++ )
+
+#define cimg_map3x3x1(img,x,y,z,v,I) cimg_3mapY(img,y) \
+ for (int _n##x=1, _p##x=(int)((I##cp=I##pp=(img)(0,_p##y,z,v)), \
+ (I##cc=I##pc=(img)(0, y,z,v)), \
+ (I##cn=I##pn=(img)(0,_n##y,z,v))), \
+ x=_p##x=0; \
+ (_n##x<(int)((img).width) && ((I##np=(img)(_n##x,_p##y,z,v)), \
+ (I##nc=(img)(_n##x, y,z,v)), \
+ (I##nn=(img)(_n##x,_n##y,z,v)), \
+ 1)) || x==--_n##x; \
+ I##pp=I##cp, I##pc=I##cc, I##pn=I##cn, \
+ I##cp=I##np, I##cc=I##nc, I##cn=I##nn, \
+ _p##x=x++,_n##x++ )
+
+
+#define cimg_map4x4x1(img,x,y,z,v,I) cimg_4mapY(img,y) \
+ for (int _a##x=2, _n##x=1, x=(int)((I##cp=I##pp=(img)(0,_p##y,z,v)), \
+ (I##cc=I##pc=(img)(0, y,z,v)), \
+ (I##cn=I##pn=(img)(0,_n##y,z,v)), \
+ (I##ca=I##pa=(img)(0,_a##y,z,v)), \
+ (I##np=(img)(_n##x,_p##y,z,v)), \
+ (I##nc=(img)(_n##x, y,z,v)), \
+ (I##nn=(img)(_n##x,_n##y,z,v)), \
+ (I##na=(img)(_n##x,_a##y,z,v)), \
+ 0), _p##x=0; \
+ (_a##x<(int)((img).width) && ((I##ap=(img)(_a##x,_p##y,z,v)), \
+ (I##ac=(img)(_a##x, y,z,v)), \
+ (I##an=(img)(_a##x,_n##y,z,v)), \
+ (I##aa=(img)(_a##x,_a##y,z,v)), \
+ 1)) || _n##x==--_a##x || x==(_a##x=--_n##x); \
+ I##pp=I##cp, I##pc=I##cc, I##pn=I##cn, I##pa=I##ca, \
+ I##cp=I##np, I##cc=I##nc, I##cn=I##nn, I##ca=I##na, \
+ I##np=I##ap, I##nc=I##ac, I##nn=I##an, I##na=I##aa, \
+ _p##x=x++, _n##x++, _a##x++ )
+
+#define cimg_map5x5x1(img,x,y,z,v,I) cimg_5mapY(img,y) \
+ for (int _a##x=2, _n##x=1, _b##x=(int)((I##cb=I##pb=I##bb=(img)(0,_b##y,z,v)), \
+ (I##cp=I##pp=I##bp=(img)(0,_p##y,z,v)), \
+ (I##cc=I##pc=I##bc=(img)(0, y,z,v)), \
+ (I##cn=I##pn=I##bn=(img)(0,_n##y,z,v)), \
+ (I##ca=I##pa=I##ba=(img)(0,_a##y,z,v)), \
+ (I##nb=(img)(_n##x,_b##y,z,v)), \
+ (I##np=(img)(_n##x,_p##y,z,v)), \
+ (I##nc=(img)(_n##x, y,z,v)), \
+ (I##nn=(img)(_n##x,_n##y,z,v)), \
+ (I##na=(img)(_n##x,_a##y,z,v))), \
+ x=0, _p##x=_b##x=0; \
+ (_a##x<(int)((img).width) && ((I##ab=(img)(_a##x,_b##y,z,v)), \
+ (I##ap=(img)(_a##x,_p##y,z,v)), \
+ (I##ac=(img)(_a##x, y,z,v)), \
+ (I##an=(img)(_a##x,_n##y,z,v)), \
+ (I##aa=(img)(_a##x,_a##y,z,v)), \
+ 1)) || _n##x==--_a##x || x==(_a##x=--_n##x); \
+ I##bb=I##pb, I##bp=I##pp, I##bc=I##pc, I##bn=I##pn, I##ba=I##pa, \
+ I##pb=I##cb, I##pp=I##cp, I##pc=I##cc, I##pn=I##cn, I##pa=I##ca, \
+ I##cb=I##nb, I##cp=I##np, I##cc=I##nc, I##cn=I##nn, I##ca=I##na, \
+ I##nb=I##ab, I##np=I##ap, I##nc=I##ac, I##nn=I##an, I##na=I##aa, \
+ _b##x=_p##x, _p##x=x++, _n##x++, _a##x++ )
+
+#define cimg_map2x2x2(img,x,y,z,v,I) cimg_2mapYZ(img,y,z) \
+ for (int _n##x=1, x=(int)((I##ccc=(img)(0, y, z,v)), \
+ (I##cnc=(img)(0,_n##y, z,v)), \
+ (I##ccn=(img)(0, y,_n##z,v)), \
+ (I##cnn=(img)(0,_n##y,_n##z,v)), \
+ 0); \
+ (_n##x<(int)((img).width) && ((I##ncc=(img)(_n##x, y, z,v)), \
+ (I##nnc=(img)(_n##x,_n##y, z,v)), \
+ (I##ncn=(img)(_n##x, y,_n##z,v)), \
+ (I##nnn=(img)(_n##x,_n##y,_n##z,v)), \
+ 1)) || x==--_n##x; \
+ I##ccc=I##ncc, I##cnc=I##nnc, \
+ I##ccn=I##ncn, I##cnn=I##nnn, \
+ x++, _n##x++ )
+
+#define cimg_map3x3x3(img,x,y,z,v,I) cimg_3mapYZ(img,y,z) \
+ for (int _n##x=1, _p##x=(int)((I##cpp=I##ppp=(img)(0,_p##y,_p##z,v)), \
+ (I##ccp=I##pcp=(img)(0, y,_p##z,v)), \
+ (I##cnp=I##pnp=(img)(0,_n##y,_p##z,v)), \
+ (I##cpc=I##ppc=(img)(0,_p##y, z,v)), \
+ (I##ccc=I##pcc=(img)(0, y, z,v)), \
+ (I##cnc=I##pnc=(img)(0,_n##y, z,v)), \
+ (I##cpn=I##ppn=(img)(0,_p##y,_n##z,v)), \
+ (I##ccn=I##pcn=(img)(0, y,_n##z,v)), \
+ (I##cnn=I##pnn=(img)(0,_n##y,_n##z,v))),\
+ x=_p##x=0; \
+ (_n##x<(int)((img).width) && ((I##npp=(img)(_n##x,_p##y,_p##z,v)), \
+ (I##ncp=(img)(_n##x, y,_p##z,v)), \
+ (I##nnp=(img)(_n##x,_n##y,_p##z,v)), \
+ (I##npc=(img)(_n##x,_p##y, z,v)), \
+ (I##ncc=(img)(_n##x, y, z,v)), \
+ (I##nnc=(img)(_n##x,_n##y, z,v)), \
+ (I##npn=(img)(_n##x,_p##y,_n##z,v)), \
+ (I##ncn=(img)(_n##x, y,_n##z,v)), \
+ (I##nnn=(img)(_n##x,_n##y,_n##z,v)), \
+ 1)) || x==--_n##x; \
+ I##ppp=I##cpp, I##pcp=I##ccp, I##pnp=I##cnp, \
+ I##cpp=I##npp, I##ccp=I##ncp, I##cnp=I##nnp, \
+ I##ppc=I##cpc, I##pcc=I##ccc, I##pnc=I##cnc, \
+ I##cpc=I##npc, I##ccc=I##ncc, I##cnc=I##nnc, \
+ I##ppn=I##cpn, I##pcn=I##ccn, I##pnn=I##cnn, \
+ I##cpn=I##npn, I##ccn=I##ncn, I##cnn=I##nnn, \
+ _p##x=x++, _n##x++ )
+
+/*
+ #------------------------------------------------
+ #
+ #
+ # Definition of the cimg_library:: namespace
+ #
+ #
+ #------------------------------------------------
+ */
+
+//! Namespace that encompasses all classes and functions of the %CImg library.
+/**
+ This namespace is defined to avoid class names collisions that could happen
+ with the include of other C++ header files. Anyway, it should not happen
+ very often and you may start most of your programs with
+ \code
+ #include "CImg.h"
+ using namespace cimg_library;
+ \endcode
+ to simplify the declaration of %CImg Library objects variables afterward.
+**/
+
+namespace cimg_library {
+
+ // Define the CImg classes.
+ template<typename T=float> struct CImg;
+ template<typename T=float> struct CImgl;
+ struct CImgStats;
+ struct CImgDisplay;
+ struct CImgException;
+
+ namespace cimg {
+
+ // The bodies of the functions below are defined at the end of the file
+ inline int dialog(const char *title,const char *msg,const char *button1_txt="OK",
+ const char *button2_txt=NULL,const char *button3_txt=NULL,
+ const char *button4_txt=NULL,const char *button5_txt=NULL,
+ const char *button6_txt=NULL,const bool centering = false);
+
+ template<typename tfunc, typename tp, typename tf>
+ inline void marching_cubes(const tfunc& func, const float isovalue,
+ const float x0,const float y0,const float z0,
+ const float x1,const float y1,const float z1,
+ const float resx,const float resy,const float resz,
+ CImgl<tp>& points, CImgl<tf>& primitives,
+ const bool invert_faces = false);
+
+ template<typename tfunc, typename tp, typename tf>
+ inline void marching_squares(const tfunc& func, const float isovalue,
+ const float x0,const float y0,
+ const float x1,const float y1,
+ const float resx,const float resy,
+ CImgl<tp>& points, CImgl<tf>& primitives);
+ }
+
+ /*
+ #----------------------------------------------
+ #
+ #
+ # Definition of the CImgException structures
+ #
+ #
+ #----------------------------------------------
+ */
+
+ // Never use the following macro in your own code !
+#define cimg_exception_err(etype,disp_flag) \
+ if (cimg_debug>=1) { \
+ std::va_list ap; \
+ va_start(ap,format); \
+ std::vsprintf(message,format,ap); \
+ va_end(ap); \
+ if (disp_flag) { \
+ try { cimg::dialog(etype,message,"Abort"); } \
+ catch (CImgException&) { std::fprintf(stderr,"# %s :\n%s\n\n",etype,message); } \
+ } else std::fprintf(stderr,"# %s :\n%s\n\n",etype,message); \
+ }
+
+ //! Class which is thrown when an error occured during a %CImg library function call.
+ /**
+
+ \section ex1 Overview
+
+ CImgException is the base class of %CImg exceptions.
+ Exceptions are thrown by the %CImg Library when an error occured in a %CImg library function call.
+ CImgException is seldom thrown itself. Children classes that specify the kind of error encountered
+ are generally used instead. These sub-classes are :
+
+ - \b CImgInstanceException : Thrown when the instance associated to the called %CImg function is not
+ correctly defined. Generally, this exception is thrown when one tries to process \a empty images. The example
+ below will throw a \a CImgInstanceException.
+ \code
+ CImg<float> img; // Construct an empty image.
+ img.blur(10); // Try to blur the image.
+ \endcode
+
+ - \b CImgArgumentException : Thrown when one of the arguments given to the called %CImg function is not correct.
+ Generally, this exception is thrown when arguments passed to the function are outside an admissible range of values.
+ The example below will throw a \a CImgArgumentException.
+ \code
+ CImg<float> img(100,100,1,3); // Define a 100x100 color image with float pixels.
+ img = NULL; // Try to fill pixels from the NULL pointer (invalid argument to operator=() ).
+ \endcode
+
+ - \b CImgIOException : Thrown when an error occured when trying to load or save image files.
+ The example below will throw a \a CImgIOException.
+ \code
+ CImg<float> img("file_doesnt_exist.jpg"); // Try to load a file that doesn't exist.
+ \endcode
+
+ - \b CImgDisplayException : Thrown when an error occured when trying to display an image in a window.
+ This exception is thrown when image display request cannot be satisfied.
+
+ The tqparent class CImgException may be thrown itself when errors that cannot be classified in one of
+ the above type occur. It is recommended not to throw CImgExceptions yourself, since there are normally
+ reserved to %CImg Library functions.
+ \b CImgInstanceException, \b CImgArgumentException, \b CImgIOException and \b CImgDisplayException are simple
+ subclasses of CImgException and are thus not detailled more in this reference documentation.
+
+ \section ex2 Exception handling
+
+ When an error occurs, the %CImg Library first displays the error in a modal window.
+ Then, it throws an instance of the corresponding exception class, generally leading the program to stop
+ (this is the default behavior).
+ You can bypass this default behavior by handling the exceptions yourself,
+ using a code block <tt>try { ... } catch() { ... }</tt>.
+ In this case, you can avoid the apparition of the modal window, by
+ defining the environment variable <tt>cimg_debug</tt> to 0 before including the %CImg header file.
+ The example below shows how to cleanly handle %CImg Library exceptions :
+ \code
+ #define cimg_debug 0 // Disable modal window in CImg exceptions.
+ #define "CImg.h"
+ int main() {
+ try {
+ ...; // Here, do what you want.
+ }
+ catch (CImgInstanceException &e) {
+ std::fprintf(stderr,"CImg Library Error : %s",e.message); // Display your own error message
+ ... // Do what you want now.
+ }
+ }
+ \endcode
+ **/
+ struct CImgException {
+ char message[1024]; //!< Message associated with the error that thrown the exception.
+ CImgException() { message[0]='\0'; }
+ CImgException(const char *format,...) { cimg_exception_err("CImgException",true); }
+ };
+
+ // The \ref CImgInstanceException class is used to throw an exception related
+ // to a non suitable instance encountered in a library function call.
+ struct CImgInstanceException : CImgException {
+ CImgInstanceException(const char *format,...) { cimg_exception_err("CImgInstanceException",true); }
+ };
+
+ // The \ref CImgArgumentException class is used to throw an exception related
+ // to invalid arguments encountered in a library function call.
+ struct CImgArgumentException : CImgException {
+ CImgArgumentException(const char *format,...) { cimg_exception_err("CImgArgumentException",true); }
+ };
+
+ // The \ref CImgIOException class is used to throw an exception related
+ // to Input/Output file problems encountered in a library function call.
+ struct CImgIOException : CImgException {
+ CImgIOException(const char *format,...) { cimg_exception_err("CImgIOException",true); }
+ };
+
+ // The CImgDisplayException class is used to throw an exception related to display problems
+ // encountered in a library function call.
+ struct CImgDisplayException : CImgException {
+ CImgDisplayException(const char *format,...) { cimg_exception_err("CImgDisplayException",false); }
+ };
+
+ /*
+ #-------------------------------------
+ #
+ #
+ # Definition of the namespace 'cimg'
+ #
+ #
+ #-------------------------------------
+ */
+
+ //! Namespace that encompasses \a low-level functions and variables of the %CImg Library.
+ /**
+ Most of the functions and variables within this namespace are used by the library for low-level processing.
+ Nevertheless, documented variables and functions of this namespace may be used safely in your own source code.
+
+ \warning Never write <tt>using namespace cimg_library::cimg;</tt> in your source code, since a lot of functions of the
+ <tt>cimg::</tt> namespace have prototypes similar to standard C functions defined in the global namespace <tt>::</tt>.
+ **/
+ namespace cimg {
+
+ // Define the trait that will be used to determine the best data type to work with.
+ template<typename T,typename t> struct largest { typedef t type; };
+ template<> struct largest<unsigned char,bool> { typedef unsigned char type; };
+ template<> struct largest<unsigned char,char> { typedef short type; };
+ template<> struct largest<char,bool> { typedef char type; };
+ template<> struct largest<char,unsigned char> { typedef short type; };
+ template<> struct largest<char,unsigned short> { typedef int type; };
+ template<> struct largest<char,unsigned int> { typedef float type; };
+ template<> struct largest<char,unsigned long> { typedef float type; };
+ template<> struct largest<unsigned short,bool> { typedef unsigned short type; };
+ template<> struct largest<unsigned short,unsigned char> { typedef unsigned short type; };
+ template<> struct largest<unsigned short,char> { typedef short type; };
+ template<> struct largest<unsigned short,short> { typedef int type; };
+ template<> struct largest<short,bool> { typedef short type; };
+ template<> struct largest<short,unsigned char> { typedef short type; };
+ template<> struct largest<short,char> { typedef short type; };
+ template<> struct largest<short,unsigned short> { typedef int type; };
+ template<> struct largest<short,unsigned int> { typedef float type; };
+ template<> struct largest<short,unsigned long> { typedef float type; };
+ template<> struct largest<unsigned int,bool> { typedef unsigned int type; };
+ template<> struct largest<unsigned int,unsigned char> { typedef unsigned int type; };
+ template<> struct largest<unsigned int,char> { typedef unsigned int type; };
+ template<> struct largest<unsigned int,unsigned short> { typedef unsigned int type; };
+ template<> struct largest<unsigned int,short> { typedef float type; };
+ template<> struct largest<unsigned int,int> { typedef float type; };
+ template<> struct largest<int,bool> { typedef int type; };
+ template<> struct largest<int,unsigned char> { typedef int type; };
+ template<> struct largest<int,char> { typedef int type; };
+ template<> struct largest<int,unsigned short> { typedef int type; };
+ template<> struct largest<int,short> { typedef int type; };
+ template<> struct largest<int,unsigned int> { typedef float type; };
+ template<> struct largest<int,unsigned long> { typedef float type; };
+ template<> struct largest<float,bool> { typedef float type; };
+ template<> struct largest<float,unsigned char> { typedef float type; };
+ template<> struct largest<float,char> { typedef float type; };
+ template<> struct largest<float,unsigned short> { typedef float type; };
+ template<> struct largest<float,short> { typedef float type; };
+ template<> struct largest<float,unsigned int> { typedef float type; };
+ template<> struct largest<float,int> { typedef float type; };
+ template<> struct largest<float,unsigned long> { typedef float type; };
+ template<> struct largest<float,long> { typedef float type; };
+ template<> struct largest<double,bool> { typedef double type; };
+ template<> struct largest<double,unsigned char> { typedef double type; };
+ template<> struct largest<double,char> { typedef double type; };
+ template<> struct largest<double,unsigned short> { typedef double type; };
+ template<> struct largest<double,short> { typedef double type; };
+ template<> struct largest<double,unsigned int> { typedef double type; };
+ template<> struct largest<double,int> { typedef double type; };
+ template<> struct largest<double,unsigned long> { typedef double type; };
+ template<> struct largest<double,long> { typedef double type; };
+ template<> struct largest<double,float> { typedef double type; };
+
+ // Define internal library variables.
+#if cimg_display_type==1
+ struct X11info {
+ pthread_mutex_t* mutex;
+ pthread_t* event_thread;
+ CImgDisplay* wins[1024];
+ Display* display;
+ unsigned int nb_wins;
+ bool thread_finished;
+ unsigned int nb_bits;
+ GC* gc;
+ bool blue_first;
+ bool byte_order;
+ bool shm_enabled;
+ X11info():mutex(NULL),event_thread(NULL),display(NULL),nb_wins(0),
+ thread_finished(false),nb_bits(0),gc(NULL),blue_first(false),byte_order(false),shm_enabled(false) {};
+ };
+#if defined(cimg_module)
+ X11info& X11attr();
+#elif defined(cimg_main)
+ X11info& X11attr() { static X11info val; return val; }
+#else
+ inline X11info& X11attr() { static X11info val; return val; }
+#endif
+#endif
+#ifdef cimg_color_terminal
+ const char t_normal[9] = {0x1b,'[','0',';','0',';','0','m','\0'};
+ const char t_red[11] = {0x1b,'[','4',';','3','1',';','5','9','m','\0'};
+ const char t_bold[5] = {0x1b,'[','1','m','\0'};
+ const char t_purple[11] = {0x1b,'[','0',';','3','5',';','5','9','m','\0'};
+#else
+ const char t_normal[1] = {'\0'};
+ const char *const t_red = cimg::t_normal, *const t_bold = cimg::t_normal, *const t_purple = cimg::t_normal;
+#endif
+
+#if cimg_display_type==1
+ // Keycodes for X11-based graphical systems
+ const unsigned int keyESC = XK_Escape;
+ const unsigned int keyF1 = XK_F1;
+ const unsigned int keyF2 = XK_F2;
+ const unsigned int keyF3 = XK_F3;
+ const unsigned int keyF4 = XK_F4;
+ const unsigned int keyF5 = XK_F5;
+ const unsigned int keyF6 = XK_F6;
+ const unsigned int keyF7 = XK_F7;
+ const unsigned int keyF8 = XK_F8;
+ const unsigned int keyF9 = XK_F9;
+ const unsigned int keyF10 = XK_F10;
+ const unsigned int keyF11 = XK_F11;
+ const unsigned int keyF12 = XK_F12;
+ const unsigned int keyPAUSE = XK_Pause;
+ const unsigned int key1 = XK_1;
+ const unsigned int key2 = XK_2;
+ const unsigned int key3 = XK_3;
+ const unsigned int key4 = XK_4;
+ const unsigned int key5 = XK_5;
+ const unsigned int key6 = XK_6;
+ const unsigned int key7 = XK_7;
+ const unsigned int key8 = XK_8;
+ const unsigned int key9 = XK_9;
+ const unsigned int key0 = XK_0;
+ const unsigned int keyBACKSPACE = XK_BackSpace;
+ const unsigned int keyINSERT = XK_Insert;
+ const unsigned int keyHOME = XK_Home;
+ const unsigned int keyPAGEUP = XK_Page_Up;
+ const unsigned int keyTAB = XK_Tab;
+ const unsigned int keyQ = XK_q;
+ const unsigned int keyW = XK_w;
+ const unsigned int keyE = XK_e;
+ const unsigned int keyR = XK_r;
+ const unsigned int keyT = XK_t;
+ const unsigned int keyY = XK_y;
+ const unsigned int keyU = XK_u;
+ const unsigned int keyI = XK_i;
+ const unsigned int keyO = XK_o;
+ const unsigned int keyP = XK_p;
+ const unsigned int keyDELETE = XK_Delete;
+ const unsigned int keyEND = XK_End;
+ const unsigned int keyPAGEDOWN = XK_Page_Down;
+ const unsigned int keyCAPSLOCK = XK_Caps_Lock;
+ const unsigned int keyA = XK_a;
+ const unsigned int keyS = XK_s;
+ const unsigned int keyD = XK_d;
+ const unsigned int keyF = XK_f;
+ const unsigned int keyG = XK_g;
+ const unsigned int keyH = XK_h;
+ const unsigned int keyJ = XK_j;
+ const unsigned int keyK = XK_k;
+ const unsigned int keyL = XK_l;
+ const unsigned int keyENTER = XK_Return;
+ const unsigned int keySHIFTLEFT = XK_Shift_L;
+ const unsigned int keyZ = XK_z;
+ const unsigned int keyX = XK_x;
+ const unsigned int keyC = XK_c;
+ const unsigned int keyV = XK_v;
+ const unsigned int keyB = XK_b;
+ const unsigned int keyN = XK_n;
+ const unsigned int keyM = XK_m;
+ const unsigned int keySHIFTRIGHT = XK_Shift_R;
+ const unsigned int keyARROWUP = XK_Up;
+ const unsigned int keyCTRLLEFT = XK_Control_L;
+ const unsigned int keyAPPLEFT = XK_Super_L;
+ const unsigned int keySPACE = XK_space;
+ const unsigned int keyALTGR = XK_Alt_R;
+ const unsigned int keyAPPRIGHT = XK_Super_R;
+ const unsigned int keyMENU = XK_Menu;
+ const unsigned int keyCTRLRIGHT = XK_Control_R;
+ const unsigned int keyARROWLEFT = XK_Left;
+ const unsigned int keyARROWDOWN = XK_Down;
+ const unsigned int keyARROWRIGHT = XK_Right;
+#endif
+
+#if cimg_display_type==0 || (cimg_display_type==2 && cimg_OS==2)
+ // Keycodes for Windows-OS
+ const unsigned int keyESC = 27;
+ const unsigned int keyF1 = 112;
+ const unsigned int keyF2 = 113;
+ const unsigned int keyF3 = 114;
+ const unsigned int keyF4 = 115;
+ const unsigned int keyF5 = 116;
+ const unsigned int keyF6 = 117;
+ const unsigned int keyF7 = 118;
+ const unsigned int keyF8 = 119;
+ const unsigned int keyF9 = 120;
+ const unsigned int keyF10 = 121;
+ const unsigned int keyF11 = 122;
+ const unsigned int keyF12 = 123;
+ const unsigned int keyPAUSE = 19;
+ const unsigned int key1 = 49;
+ const unsigned int key2 = 50;
+ const unsigned int key3 = 51;
+ const unsigned int key4 = 52;
+ const unsigned int key5 = 53;
+ const unsigned int key6 = 54;
+ const unsigned int key7 = 55;
+ const unsigned int key8 = 56;
+ const unsigned int key9 = 57;
+ const unsigned int key0 = 48;
+ const unsigned int keyBACKSPACE = 8;
+ const unsigned int keyINSERT = 45;
+ const unsigned int keyHOME = 36;
+ const unsigned int keyPAGEUP = 33;
+ const unsigned int keyTAB = 9;
+ const unsigned int keyQ = 81;
+ const unsigned int keyW = 87;
+ const unsigned int keyE = 69;
+ const unsigned int keyR = 82;
+ const unsigned int keyT = 84;
+ const unsigned int keyY = 89;
+ const unsigned int keyU = 85;
+ const unsigned int keyI = 73;
+ const unsigned int keyO = 79;
+ const unsigned int keyP = 80;
+ const unsigned int keyDELETE = 8;
+ const unsigned int keyEND = 35;
+ const unsigned int keyPAGEDOWN = 34;
+ const unsigned int keyCAPSLOCK = 20;
+ const unsigned int keyA = 65;
+ const unsigned int keyS = 83;
+ const unsigned int keyD = 68;
+ const unsigned int keyF = 70;
+ const unsigned int keyG = 71;
+ const unsigned int keyH = 72;
+ const unsigned int keyJ = 74;
+ const unsigned int keyK = 75;
+ const unsigned int keyL = 76;
+ const unsigned int keyENTER = 13;
+ const unsigned int keySHIFTLEFT = 16;
+ const unsigned int keyZ = 90;
+ const unsigned int keyX = 88;
+ const unsigned int keyC = 67;
+ const unsigned int keyV = 86;
+ const unsigned int keyB = 66;
+ const unsigned int keyN = 78;
+ const unsigned int keyM = 77;
+ const unsigned int keySHIFTRIGHT = 16;
+ const unsigned int keyARROWUP = 38;
+ const unsigned int keyCTRLLEFT = 17;
+ const unsigned int keyAPPLEFT = 91;
+ const unsigned int keySPACE = 32;
+ const unsigned int keyALTGR = 17;
+ const unsigned int keyAPPRIGHT = 92;
+ const unsigned int keyMENU = 93;
+ const unsigned int keyCTRLRIGHT = 17;
+ const unsigned int keyARROWLEFT = 37;
+ const unsigned int keyARROWDOWN = 40;
+ const unsigned int keyARROWRIGHT = 39;
+#endif
+
+#ifdef PI
+#undef PI
+#endif
+ const double PI = 3.14159265358979323846; //!< Definition of the mathematical constant PI
+ const int infinity_int = 0x7f800000;
+ const double infinity = (double)*(float*)&cimg::infinity_int;
+
+ // Definition of a 7x11 font, used to return a default font for drawing text.
+ const unsigned int font7x11[7*11*256/32] = {
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x90,0x0,0x7f0000,0x40000,0x0,0x0,0x4010c0a4,0x82000040,0x11848402,0x18480050,0x80430292,0x8023,0x9008000,
+ 0x40218140,0x4000040,0x21800402,0x18000051,0x1060500,0x8083,0x10000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x24002,0x4031,0x80000000,0x10000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x81c0400,0x40020000,0x80070080,0x40440e00,0x0,0x0,0x1,0x88180000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x200000,0x0,0x0,0x80000,0x0,0x0,0x20212140,0x5000020,0x22400204,0x240000a0,0x40848500,0x4044,0x80010038,0x20424285,0xa000020,
+ 0x42428204,0x2428e0a0,0x82090a14,0x4104,0x85022014,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10240a7,0x88484040,0x40800000,0x270c3,0x87811e0e,
+ 0x7c70e000,0x78,0x3c23c1ef,0x1f3e1e89,0xf1c44819,0xa23cf0f3,0xc3cff120,0xc18307f4,0x4040400,0x20000,0x80080080,0x40200,0x0,
+ 0x40000,0x2,0x8040000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8188,0x50603800,0xf3c00000,0x1c004003,0xc700003e,0x18180,0xc993880,0x10204081,
+ 0x2071ef9,0xf3e7cf9f,0x3e7c7911,0xe3c78f1e,0x7d1224,0x48906048,0x0,0x4000000,0x0,0x9000,0x0,0x0,0x2000,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x10240aa,0x14944080,0x23610000,0x68940,0x40831010,0x8891306,0x802044,0x44522208,0x90202088,0x40448819,0xb242890a,0x24011111,
+ 0x49448814,0x4040a00,0xe2c3c7,0x8e3f3cb9,0xc1c44216,0xee38b0f2,0xe78f9120,0xc18507e2,0x8040000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x101c207,0x88a04001,0x9c00000,0x2200a041,0x8200113a,0x8240,0x50a3110,0x2850a142,0x850c2081,0x2040204,0x8104592,0x142850a1,
+ 0x42cd1224,0x4888bc48,0x70e1c387,0xe3b3c70,0xe1c38e1c,0x38707171,0xc3870e1c,0x10791224,0x48906c41,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x10003ee,0x15140080,0x21810000,0x48840,0x40851020,0x8911306,0x31fd804,0x9c522408,0x90204088,0x4045081a,0xba42890a,0x24011111,
+ 0x49285024,0x2041b00,0x132408,0x910844c8,0x4044821b,0x7244c913,0x24041111,0x49488822,0x8040000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x28204,0x85006001,0x6a414000,0x3a004043,0xc700113a,0x8245,0x50a3a00,0x2850a142,0x850c4081,0x2040204,0x81045d2,0x142850a1,
+ 0x24951224,0x48852250,0x8102040,0x81054089,0x12244204,0x8108992,0x24489122,0x991224,0x4888b222,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x1000143,0xa988080,0x2147c01f,0x88840,0x83091c2c,0x1070f000,0xc000608,0xa48bc408,0x9e3c46f8,0x40460816,0xaa42f10b,0xc3811111,
+ 0x35102044,0x1041100,0xf22408,0x9f084488,0x40470212,0x62448912,0x6041111,0x55308846,0x8061c80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x1028704,0x8f805801,0x4be28fdf,0x220001f0,0x111a,0x60000182,0x82c5c710,0x44891224,0x489640f1,0xe3c78204,0x810e552,0x142850a1,
+ 0x18a51224,0x48822250,0x78f1e3c7,0x8f1f40f9,0xf3e7c204,0x8108912,0x24489122,0x7ea91224,0x4888a222,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x10007e2,0x85648080,0x20010000,0x88841,0x8f8232,0x20881000,0xc1fc610,0xbefa2408,0x90204288,0x40450816,0xa642810a,0x4041110a,
+ 0x36282084,0x1042080,0x1122408,0x90084488,0x40450212,0x62448912,0x184110a,0x55305082,0x8042700,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x1028207,0x82004801,0x68050040,0x1c000040,0x110a,0x60000001,0x45484d10,0x7cf9f3e7,0xcf944081,0x2040204,0x8104532,0x142850a1,
+ 0x18a51224,0x48822248,0x89122448,0x91244081,0x2040204,0x8108912,0x24489122,0xc91224,0x48852214,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x282,
+ 0x89630080,0x20010c00,0x30108842,0x810222,0x20882306,0x3001800,0x408a2208,0x90202288,0x40448814,0xa642810a,0x2041110a,0x26442104,
+ 0x840000,0x1122408,0x90084488,0x40448212,0x62448912,0x84130a,0x36485102,0x8040000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x101c208,0x4f802801,
+ 0x8028040,0x40,0x130a,0x2,0x85e897a0,0x44891224,0x489c2081,0x2040204,0x8104532,0x142850a1,0x24cd1224,0x48823c44,0x89122448,
+ 0x91244081,0x2040204,0x8108912,0x24489122,0xc93264,0xc9852214,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100028f,0x109f0080,0x20010c00,
+ 0x303071f3,0xc7011c1c,0x4071c306,0x802010,0x3907c1ef,0x1f201e89,0xf3844f90,0xa23c80f2,0x17810e04,0x228223f4,0x840000,0xfbc3c7,
+ 0x8f083c88,0x40444212,0x6238f0f2,0x7039d04,0x228423e2,0x8040000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1008780,0x2201800,0xf0014000,0x1f0,
+ 0x1d0a,0x5,0x851e140,0x83060c18,0x30671ef9,0xf3e7cf9f,0x3e7c7911,0xe3c78f1e,0x42f8e1c3,0x8702205c,0x7cf9f3e7,0xcf9b3c78,0xf1e3c204,
+ 0x8107111,0xc3870e1c,0x10f1d3a7,0x4e823c08,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2,0x40,0x40000400,0x200000,0x0,0x2,0x0,0x0,0x0,0x0,0x18,
+ 0x0,0x4,0x44007f,0x0,0x400,0x400000,0x8010,0x0,0x6002,0x8040000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000000,0x200800,0x0,0x0,0x100a,
+ 0x400000,0x44,0x0,0x400,0x0,0x0,0x0,0x0,0x0,0x0,0x800,0x0,0x0,0x0,0x0,0x62018,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x31,0x80000800,
+ 0x400000,0x0,0x4,0x0,0x0,0x0,0x0,0xc,0x0,0x7,0x3c0000,0x0,0x3800,0x3800000,0x8010,0x0,0x1c001,0x881c0000,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x207000,0x0,0x0,0x100a,0xc00000,0x3c,0x0,0xc00,0x0,0x0,0x0,0x0,0x0,0x0,0x1800,0x0,0x0,0x0,0x0,0x1c2070
+ };
+
+ // Definition of a 10x13 font (used in dialog boxes).
+ const unsigned int font10x13[256*10*13/32] = {
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80100c0,
+ 0x68000300,0x801,0xc00010,0x100c000,0x68100,0x100c0680,0x2,0x403000,0x1000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfc,0x0,0x0,0x0,0x0,0x0,0x4020120,
+ 0x58120480,0x402,0x1205008,0x2012050,0x58080,0x20120581,0x40000001,0x804812,0x2000000,0x0,0x300,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x140,0x80000,0x200402,0x800000,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x7010,0x7000000,0x8000200,0x20000,0xc0002000,0x8008,0x0,0x0,0x0,0x0,0x808,0x4000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x80000000,0x0,0x0,0x0,0x40000,0x0,0x0,0x0,0x0,0x480,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x70,0x80100c0,0x68000480,0x1001,
+ 0xc00010,0x1018000,0x68100,0x100c0680,0x4,0x403000,0x1020000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20140,0x28081883,0x200801,
+ 0x2a00000,0x10,0x1c0201c0,0x70040f80,0xc0f81c07,0x0,0x70,0x3e0303c0,0x3c3c0f83,0xe03c2107,0xe08810,0x18c31070,0x3c0703c0,
+ 0x783e0842,0x22222208,0x83e04010,0x1008000,0x4000200,0x20001,0x2002,0x408008,0x0,0x0,0x100000,0x0,0x1008,0x2000000,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20080,0x38000880,0x8078140f,0x81c00000,0x3e000,0xc020180,0x60080001,0xe0000002,0xc00042,0x108e2010,
+ 0xc0300c0,0x300c0303,0xf83c3e0f,0x83e0f81c,0x701c070,0x3c0c41c0,0x701c0701,0xc0001d08,0x42108421,0x8820088,0x4020120,0x58140480,
+ 0x802,0x1205008,0x3014050,0xc058080,0x20120581,0x40000002,0x804814,0x2020050,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20140,
+ 0x281e2484,0x80200801,0x1c02000,0x10,0x22060220,0x880c0801,0x82208,0x80000001,0x20008,0x41030220,0x40220802,0x402102,0x209010,
+ 0x18c31088,0x22088220,0x80080842,0x22222208,0x80204010,0x1014000,0x200,0x20001,0x2000,0x8008,0x0,0x0,0x100000,0x0,0x1008,
+ 0x2000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x40000500,0x80800010,0x40200000,0x41000,0x12020040,0x10000003,0xa0000006,
+ 0x12000c4,0x31014000,0xc0300c0,0x300c0302,0x80402008,0x2008008,0x2008020,0x220c4220,0x88220882,0x20002208,0x42108421,0x8820088,
+ 0x0,0x300,0x0,0x0,0x0,0x14000000,0x0,0x200200,0x0,0x20000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000,0xfc282504,0x80001000,
+ 0x82a02000,0x20,0x22020020,0x8140802,0x102208,0x80801006,0x18008,0x9c848220,0x80210802,0x802102,0x20a010,0x15429104,0x22104220,
+ 0x80080842,0x22221405,0x404008,0x1022000,0x703c0,0x381e0701,0xc0783c02,0xc09008,0x1d83c070,0x3c078140,0x381c0882,0x21242208,
+ 0x81e01008,0x2000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x201e0,0x40220500,0x80800027,0x20e02800,0x9c800,0x12020040,
+ 0x20000883,0xa0200002,0x120a044,0x11064010,0x12048120,0x48120484,0x80802008,0x2008008,0x2008020,0x210a4411,0x4411044,0x10884508,
+ 0x42108421,0x503c0b0,0x1c0701c0,0x701c0707,0x70381c07,0x1c07008,0x2008020,0x20f01c0,0x701c0701,0xc0201c08,0x82208822,0x883c088,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000,0x50281903,0x20001000,0x80802000,0x20,0x22020040,0x30240f03,0xc0101c08,0x80801018,
+ 0x1fc06010,0xa48483c0,0x80210f03,0xe0803f02,0x20c010,0x15429104,0x22104220,0x70080841,0x41540805,0x804008,0x1041000,0x8220,
+ 0x40220881,0x882202,0x40a008,0x12422088,0x22088180,0x40100882,0x21241408,0x80201008,0x2031000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x20280,0x401c0200,0x700028,0x21205000,0x92800,0xc1fc080,0x10000883,0xa0200002,0x1205049,0x12c19010,0x12048120,0x48120484,
+ 0xf0803c0f,0x3c0f008,0x2008020,0x790a4411,0x4411044,0x10504908,0x42108421,0x5022088,0x2008020,0x8020080,0x88402208,0x82208808,
+ 0x2008020,0x1e088220,0x88220882,0x20002608,0x82208822,0x8822088,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000,0x501c0264,
+ 0xa0001000,0x8001fc00,0x7000020,0x22020080,0x83e0082,0x20202207,0x80000020,0x1020,0xa4848220,0x80210802,0x9c2102,0x20c010,
+ 0x12425104,0x3c1043c0,0x8080841,0x41540802,0x804008,0x1000000,0x78220,0x40220f81,0x882202,0x40c008,0x12422088,0x22088100,
+ 0x60100881,0x41540805,0x406008,0x1849000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20280,0xf0140200,0x880028,0x20e0a03f,0x709c800,
+ 0x201c0,0x60000881,0xa0000007,0xc0284b,0x122eb020,0x12048120,0x48120487,0x80802008,0x2008008,0x2008020,0x21094411,0x4411044,
+ 0x10204908,0x42108421,0x2022088,0x1e0781e0,0x781e0787,0xf8403e0f,0x83e0f808,0x2008020,0x22088220,0x88220882,0x21fc2a08,0x82208822,
+ 0x5022050,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20001,0xf80a0294,0x40001000,0x80002000,0x20,0x22020100,0x8040082,0x20202200,
+ 0x80000018,0x1fc06020,0xa48fc220,0x80210802,0x842102,0x20a010,0x12425104,0x20104240,0x8080841,0x41541402,0x1004008,0x1000000,
+ 0x88220,0x40220801,0x882202,0x40a008,0x12422088,0x22088100,0x18100881,0x41540805,0x801008,0x2046000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x20280,0x401c0f80,0x80880028,0x20005001,0x94800,0x20000,0x880,0xa0000000,0x5015,0x4215040,0x3f0fc3f0,0xfc3f0fc8,
+ 0x80802008,0x2008008,0x2008020,0x21094411,0x4411044,0x10505108,0x42108421,0x203c088,0x22088220,0x88220888,0x80402008,0x2008008,
+ 0x2008020,0x22088220,0x88220882,0x20002a08,0x82208822,0x5022050,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xa00a0494,0x60001000,
+ 0x80002004,0x8020,0x22020200,0x88040882,0x20402201,0x801006,0x18000,0x9f084220,0x40220802,0x442102,0x209010,0x10423088,0x20088220,
+ 0x8080840,0x80882202,0x2004008,0x1000000,0x88220,0x40220881,0x882202,0x409008,0x12422088,0x22088100,0x8100880,0x80881402,
+ 0x1001008,0x2000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20280,0x40220200,0x80700027,0x20002801,0x92800,0x1fc000,0x980,
+ 0xa0000000,0xa017,0x84417840,0x21084210,0x84210848,0x80402008,0x2008008,0x2008020,0x2208c220,0x88220882,0x20882208,0x42108421,
+ 0x2020088,0x22088220,0x88220888,0xc8402208,0x82208808,0x2008020,0x22088220,0x88220882,0x20203208,0x82208822,0x2022020,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000,0xa03c0463,0x90000801,0x2004,0x8040,0x1c0703e0,0x70040701,0xc0401c06,0x801001,0x20020,
+ 0x400843c0,0x3c3c0f82,0x3c2107,0x1c0881e,0x10423070,0x20070210,0xf0080780,0x80882202,0x3e04004,0x1000000,0x783c0,0x381e0701,
+ 0x782202,0x408808,0x12422070,0x3c078100,0x700c0780,0x80882202,0x1e01008,0x2000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x201e0,
+ 0xf8000200,0x80080010,0x40000001,0x41000,0x0,0xe80,0xa0000000,0x21,0x8e21038,0x21084210,0x84210848,0xf83c3e0f,0x83e0f81c,
+ 0x701c070,0x3c08c1c0,0x701c0701,0xc0005c07,0x81e0781e,0x20200b0,0x1e0781e0,0x781e0787,0x30381c07,0x1c07008,0x2008020,0x1c0881c0,
+ 0x701c0701,0xc0201c07,0x81e0781e,0x203c020,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80000,0x801,0x4,0x40,0x0,0x0,0x0,0x1000,
+ 0x0,0x3c000000,0x0,0x0,0x0,0x0,0x10000,0x0,0x0,0x4004,0x1000000,0x0,0x0,0x80000,0x400000,0x0,0x20008000,0x0,0x4,0x1008,0x2000000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x0,0x8008000f,0x80000000,0x3e000,0x0,0x800,0xa0000400,0x0,0x0,0x0,0x0,0x80000,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100000,0x0,0x0,0x0,0x0,0x2000,0x0,0x4020040,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80000,
+ 0x402,0x8,0x40,0x0,0x0,0x0,0x2000,0x0,0x0,0x0,0x0,0x0,0x0,0xc000,0x0,0x0,0x7004,0x70000fc,0x0,0x0,0x700000,0x800000,0x0,0x20008000,
+ 0x0,0x4,0x808,0x4000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x0,0x80f00000,0x0,0x0,0x0,0x800,0xa0001800,0x0,0x0,0x0,0x0,
+ 0x300000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600000,0x0,0x0,0x0,0x0,0x0,0x0,0x4020040
+ };
+
+ // Definition of a 8x17 font
+ const unsigned int font8x17[8*17*256/32] = {
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x2400,0x2400,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20081834,0x1c0000,0x20081800,0x20081800,0x342008,
+ 0x18340000,0x200818,0x80000,0x0,0x180000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4200000,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x380000,0x4000,0x2000c00,0x40100840,0x70000000,0x0,0x0,0x1c,0x10700000,0x7,0x0,
+ 0x1800,0x1800,0x0,0x0,0x0,0x14,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1010242c,0x14140000,0x10102414,0x10102414,0x2c1010,0x242c1400,
+ 0x101024,0x14100038,0x0,0x240000,0x0,0x0,0x30000000,0x0,0x0,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x12,0x0,0x8100000,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10,0x80000,0x10004000,0x2001000,0x40000040,0x10000000,0x0,0x0,0x10,0x10100000,0x4,
+ 0x0,0x18000000,0x0,0x0,0x0,0x34002400,0x2400,0x0,0x0,0x0,0x3c,0x0,0x8000000,0x0,0x60607800,0x0,0x140000,0x0,0x0,0x0,0x0,0x0,
+ 0x44,0x10081834,0x240000,0x10081800,0x10081800,0x1c341008,0x18340000,0x100818,0x84000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x102812,
+ 0x8601c10,0x8100800,0x2,0x1c383e3e,0x67e1e7f,0x3e3c0000,0x38,0x1e087e1e,0x7c7f7f1e,0x417c1c42,0x4063611c,0x7e1c7e3e,0xfe414181,
+ 0x63827f10,0x40081000,0x8004000,0x2001000,0x40000040,0x10000000,0x0,0x10000000,0x10,0x10100000,0x3c000008,0x0,0x24003e00,
+ 0x3f007f00,0x0,0x0,0x2ce91800,0x1882,0x10101c,0xc2103c,0x143c3c00,0x3c00,0x18003c3c,0x10001f00,0x181c00,0x20200810,0x8080808,
+ 0x8083e1e,0x7f7f7f7f,0x7c7c7c7c,0x7c611c1c,0x1c1c1c00,0x1e414141,0x41824044,0x810242c,0x14180000,0x8102414,0x8102414,0x382c0810,
+ 0x242c1400,0x81024,0x14104014,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x102816,0x3e902010,0x10084910,0x4,0x22084343,0xa402102,0x41620000,
+ 0x44,0x33144121,0x42404021,0x41100444,0x40636122,0x43224361,0x10416381,0x22440310,0x20082800,0x4000,0x2001000,0x40000040,
+ 0x10000000,0x0,0x10000000,0x10,0x10100000,0x24000008,0x0,0x606100,0x68000300,0x8106c,0x34000000,0x4f0000,0x44,0x101020,0x441040,
+ 0x420200,0x4200,0x24000404,0x7d00,0x82200,0x20203010,0x14141414,0x14082821,0x40404040,0x10101010,0x42612222,0x22222200,0x23414141,
+ 0x41447e48,0x0,0x0,0x0,0x0,0x4000000,0x18,0x0,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10287f,0x49902010,0x10083e10,0x4,0x41080101,
+ 0x1a404002,0x41411818,0x1004004,0x21144140,0x41404040,0x41100448,0x40555141,0x41414140,0x10412281,0x14280610,0x20084400,0x1c7c1c,
+ 0x3e3c7c3a,0x5c703844,0x107f5c3c,0x7c3e3c3c,0x7e424281,0x66427e10,0x10100000,0x40100008,0x1010,0xa04000,0x48100610,0x100c3024,
+ 0x24000000,0x4f3c00,0x2c107e28,0x3820,0x42281060,0x9d1e12,0xbd00,0x24100818,0x427d00,0x82248,0x20200800,0x14141414,0x14142840,
+ 0x40404040,0x10101010,0x41514141,0x41414142,0x43414141,0x41284350,0x1c1c1c1c,0x1c1c6c1c,0x3c3c3c3c,0x70707070,0x3c5c3c3c,
+ 0x3c3c3c18,0x3e424242,0x42427c42,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x102824,0x48623010,0x10081c10,0x8,0x41080103,0x127c5e04,
+ 0x41411818,0xe7f3808,0x4f144140,0x41404040,0x41100450,0x40555141,0x41414160,0x1041225a,0x1c280410,0x1008c600,0x226622,0x66661066,
+ 0x62100848,0x10496266,0x66663242,0x10426681,0x24220260,0x100c0000,0xf8280008,0x1010,0x606000,0x48280428,0x28042014,0x48000000,
+ 0x494200,0x52280228,0x105420,0x3cee1058,0xa12236,0xa500,0x18101004,0x427d00,0x8226c,0x76767e10,0x14141414,0x14142840,0x40404040,
+ 0x10101010,0x41514141,0x41414124,0x45414141,0x41284150,0x22222222,0x22221222,0x66666666,0x10101010,0x66626666,0x66666600,
+ 0x66424242,0x42226622,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100024,0x381c4900,0x10086bfe,0x8,0x4908021c,0x22036304,0x3e630000,
+ 0x70000710,0x51227e40,0x417f7f43,0x7f100470,0x40554941,0x43417e3e,0x1041225a,0x8100810,0x10080000,0x24240,0x42421042,0x42100850,
+ 0x10494242,0x42422040,0x1042245a,0x18240410,0x10103900,0x407c003e,0x1818,0x1c3e10,0x4f7c087c,0x7c002010,0x48000000,0x4008,
+ 0x527c0410,0x105078,0x2410104c,0xa13e6c,0x7f00b900,0xfe3c3c,0x421d18,0x1c1c36,0x38383810,0x22222222,0x22144e40,0x7f7f7f7f,
+ 0x10101010,0xf1494141,0x41414118,0x49414141,0x4110435c,0x2020202,0x2021240,0x42424242,0x10101010,0x42424242,0x424242ff,0x4e424242,
+ 0x42244224,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000fe,0xe664d00,0x10080810,0x380010,0x41080c03,0x42014108,0x633d0000,0x70000710,
+ 0x51224140,0x41404041,0x41100448,0x40494541,0x7e414203,0x1041145a,0x14101010,0x10080000,0x3e4240,0x427e1042,0x42100870,0x10494242,
+ 0x4242203c,0x1042245a,0x18241810,0x10104600,0xf8f60008,0x1010,0x600320,0x48f610f6,0xf6000000,0x187eff,0x3c04,0x5ef61810,0x105020,
+ 0x24fe0064,0x9d006c,0x138ad00,0x100000,0x420518,0x36,0xc0c0c020,0x22222222,0x22224840,0x40404040,0x10101010,0x41454141,0x41414118,
+ 0x51414141,0x41107e46,0x3e3e3e3e,0x3e3e7e40,0x7e7e7e7e,0x10101010,0x42424242,0x42424200,0x5a424242,0x42244224,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x28,0x9094500,0x10080010,0x10,0x41081801,0x7f014118,0x41010000,0xe7f3800,0x513e4140,0x41404041,0x41100444,
+ 0x40414541,0x40414101,0x10411466,0x36103010,0x8080000,0x424240,0x42401042,0x42100848,0x10494242,0x42422002,0x10423c5a,0x18142010,
+ 0x10100000,0x407c0010,0x1010,0x260140,0x487c307c,0x7c000000,0x180000,0x202,0x507c2010,0x105020,0x3c10003c,0x423e36,0x1004200,
+ 0x100000,0x420500,0x3e6c,0x41e0440,0x3e3e3e3e,0x3e3e7840,0x40404040,0x10101010,0x41454141,0x41414124,0x61414141,0x41104042,
+ 0x42424242,0x42425040,0x40404040,0x10101010,0x42424242,0x42424218,0x72424242,0x42144214,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100048,
+ 0x49096200,0x8100010,0x18001810,0x22082043,0x2432310,0x61421818,0x1004010,0x4f634121,0x42404021,0x41104444,0x40414322,0x40234143,
+ 0x10411466,0x22106010,0x8080000,0x466622,0x66621066,0x42100844,0x10494266,0x66662042,0x10461824,0x24184010,0x10100000,0x24381010,
+ 0x34001018,0xda4320,0x68386038,0x38000000,0x0,0x4204,0x50384010,0x105420,0x4210100c,0x3c0012,0x3c00,0x0,0x460500,0x48,0xc020c44,
+ 0x63636363,0x63228821,0x40404040,0x10101010,0x42432222,0x22222242,0x62414141,0x41104042,0x46464646,0x46465022,0x62626262,
+ 0x10101010,0x66426666,0x66666618,0x66464646,0x46186618,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100048,0x3e063d00,0x8100000,0x18001820,
+ 0x1c3e7f3e,0x23c1e20,0x3e3c1818,0x10,0x20417e1e,0x7c7f401e,0x417c3842,0x7f41431c,0x401e40be,0x103e0866,0x41107f10,0x4080000,
+ 0x3a5c1c,0x3a3c103a,0x427c0842,0xe49423c,0x7c3e203c,0xe3a1824,0x66087e10,0x10100000,0x3c103010,0x245a1010,0x5a3e10,0x3f107f10,
+ 0x10000000,0x0,0x3c08,0x2e107e10,0x1038fc,0x101004,0x0,0x0,0xfe0000,0x7f0500,0x0,0x14041438,0x41414141,0x41418e1e,0x7f7f7f7f,
+ 0x7c7c7c7c,0x7c431c1c,0x1c1c1c00,0xbc3e3e3e,0x3e10405c,0x3a3a3a3a,0x3a3a6e1c,0x3c3c3c3c,0x7c7c7c7c,0x3c423c3c,0x3c3c3c00,
+ 0x7c3a3a3a,0x3a087c08,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8000000,0x4200000,0x10000020,0x0,0x0,0x10,0x0,0x30000000,0x0,
+ 0x0,0x0,0x60000,0x0,0x1c,0x4380000,0x0,0x2,0x800,0x0,0x40020000,0x0,0x8000c,0x10600000,0x2010,0x48000000,0x240000,0x0,0x0,
+ 0x0,0x0,0x0,0x1000,0x1078,0x0,0x0,0x0,0x400500,0x0,0x1e081e00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x84008,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8000000,0x0,0x20000040,0x0,0x0,0x20,0x0,0x1e000000,0x0,0x0,0x0,0x20000,0x0,
+ 0x0,0x2000000,0x0,0x26,0x800,0x0,0x40020000,0x0,0x100000,0x10000000,0x2030,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000,0x1000,0x0,
+ 0x0,0x0,0x400000,0x8000000,0x41e0400,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x104010,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfe,0x0,0x1c,0x7000,0x0,0x40020000,0x0,0x300000,
+ 0x0,0xe0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000,0x0,0x0,0x0,0x400000,0x38000000,0x0,0x0,0x1c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x1c,0x0,0x0,0x0,0x0,0x0,0x304030,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 };
+
+ // Definition of a 10x19 font
+ const unsigned int font10x19[10*19*256/32] = {
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3600000,0x36000,0x0,0x0,0x0,0x0,0x6c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x180181c0,0xe81b0300,0x1801,0x81c06c18,0x181c06c,0xe8180,0x181c0e81,0xb0000006,0x60701b,0x1800000,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c00000,0x1c000,0x0,0x0,0x0,0x0,0x6c,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0xc030360,0xb81b0480,0xc03,0x3606c0c,0x303606c,0xb80c0,0x30360b81,0xb0000003,0xc0d81b,0x3000000,0x0,
+ 0x300,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x800,0x0,0x0,0x0,0x0,0x0,0x2200000,
+ 0x22000,0x0,0x0,0x0,0x0,0x0,0x0,0x30000,0x0,0xe0,0x38078000,0x0,0x480,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3000c080,0x480,0x3000,
+ 0xc0800030,0xc08000,0x300,0xc080000,0xc,0x302000,0xc00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20120,0x41c01,0xe020060c,
+ 0x800000,0x4,0x1e0703e0,0xf8060fc1,0xe1fe1e07,0x80000000,0x78,0x307e0,0x3c7c1fe7,0xf83c408f,0x80f10440,0x18660878,0x7e0787e0,
+ 0x78ff9024,0xa0140a0,0x27f83840,0x700e000,0x18000400,0x8000,0x70004002,0x410078,0x0,0x0,0x0,0x0,0x1808,0xc000000,0xf000000,
+ 0xe000000,0x1400,0x1e0001f,0x8007f800,0x0,0x0,0x3a3b,0x61400000,0x14202,0x20000,0x38002020,0x3c1b00,0x3e00000,0xf8,0x1c0001c0,
+ 0x78060001,0xf800000e,0x1e00020,0x8004020,0xc0300c0,0x300c0301,0xf83c7f9f,0xe7f9fe3e,0xf83e0f8,0x7c1821e0,0x781e0781,0xe0001f10,
+ 0x24090240,0xa02400f8,0x18018140,0xe81b0480,0x1801,0x81406c18,0x181406c,0x190e8180,0x18140e81,0xb0000006,0x60501b,0x184006c,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20120,0x26042202,0x200c06,0x800000,0x8,0x210d0611,0x40e0803,0x10026188,0x40000000,
+ 0x8c,0xf030418,0xc6431004,0xc64082,0x110840,0x18660884,0x41084410,0x8c081024,0xa012110,0x40082020,0x101b000,0xc000400,0x8000,
+ 0x80004002,0x410008,0x0,0x0,0x100000,0x0,0x2008,0x2000000,0x18800000,0x10000000,0x2200,0x2300024,0x800,0x0,0x0,0x2e13,0x60800000,
+ 0x8104,0x20040,0x64001040,0x80401b07,0x80100000,0x1e000,0x22000020,0x40c0003,0xc8000002,0x3300020,0x8004020,0xc0300c0,0x300c0301,
+ 0x40c64010,0x4010008,0x2008020,0x43182210,0x84210842,0x10002190,0x24090240,0x9044018c,0xc030220,0xb81b0300,0xc03,0x2206c0c,
+ 0x302206c,0x1e0b80c0,0x30220b81,0xb0000003,0xc0881b,0x304006c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20120,0x241f2202,
+ 0x200802,0x4900000,0x8,0x21010408,0x20a0802,0x44090,0x20000000,0x4,0x11878408,0x80411004,0x804082,0x111040,0x1ce50986,0x40986409,
+ 0x81022,0x12012108,0x80102020,0x1031800,0x400,0x8000,0x80004000,0x10008,0x0,0x0,0x100000,0x0,0x2008,0x2000000,0x10000000,
+ 0x10000000,0x18,0x4000044,0x1000,0x30180,0xd81b0000,0x13,0xe0000000,0x88,0x40,0x400018c0,0x80400018,0x61f00000,0x61800,0x22020020,
+ 0x4000007,0xc8000002,0x2100020,0x8038000,0x1e0781e0,0x781e0301,0x40804010,0x4010008,0x2008020,0x41142619,0x86619866,0x18002190,
+ 0x24090240,0x8887e104,0x0,0x0,0x0,0x0,0x0,0x2000000,0x0,0x0,0x0,0x40000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20120,0x2434a202,
+ 0x200802,0x3e00000,0x10,0x40810008,0x21a0804,0x44090,0x20000000,0x80040004,0x20848409,0x409004,0x1004082,0x112040,0x14a50902,
+ 0x40902409,0x81022,0x11321208,0x80202010,0x1060c00,0x7c5e0,0x781e8783,0xf07a5f0e,0x1c10808,0xfc5f078,0x5e07a170,0x7c7e1024,
+ 0xa016190,0x27f82008,0x2000000,0x20000000,0x10000000,0x80200024,0x4000044,0x2000,0x18180,0xc8320000,0x12,0xa1f00037,0x7f888,
+ 0x1e0,0x40410880,0x80600017,0xa2100000,0x5e800,0x22020040,0x38001027,0xc8000002,0x2100020,0x8004020,0x12048120,0x48120482,
+ 0x41004010,0x4010008,0x2008020,0x40942409,0x2409024,0x9044390,0x24090240,0x88841918,0x1f07c1f0,0x7c1f07c3,0x70781e07,0x81e07838,
+ 0xe0380e0,0x1f17c1e0,0x781e0781,0xe0001f90,0x24090240,0x9025e102,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20001,0xff241c41,
+ 0x1001,0x1c02000,0x10,0x40810008,0x6120f85,0xe0086190,0x20c03007,0x8007800c,0x27848419,0x409004,0x1004082,0x114040,0x14a48902,
+ 0x40902409,0x81022,0x11321205,0x602010,0x1000000,0x86610,0x84218840,0x80866182,0x411008,0x9261884,0x61086189,0x82101022,0x12012108,
+ 0x40082008,0x2000000,0x20030000,0x20000000,0x80200024,0x4000044,0x3006030,0xc018100,0x4c260000,0x12,0x26080048,0x83000850,
+ 0x20250,0x403e0500,0x8078002c,0x12302200,0x92400,0x1c0200c0,0x4001027,0xc8000002,0x3308820,0x8004020,0x12048120,0x48120482,
+ 0x41004010,0x4010008,0x2008020,0x40922409,0x2409024,0x8884690,0x24090240,0x85040920,0x21886218,0x86218860,0x88842108,0x42108408,
+ 0x2008020,0x21186210,0x84210842,0x10302190,0x24090240,0x88461084,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000,0x4c240182,
+ 0x80001001,0x6b02000,0x20,0x4c810010,0x78220846,0x10081e10,0x20c0301c,0x1fe0e018,0x4d8487e1,0x409fe7,0xf9007f82,0x11a040,
+ 0x13248902,0x41102418,0xe0081022,0x11320c05,0x402008,0x1000000,0x2409,0x409020,0x81024082,0x412008,0x9240902,0x40902101,0x101022,
+ 0x11321208,0x40102008,0x2000000,0x7e0c8000,0xfc000003,0xf0fc0018,0x43802047,0x8c8040c8,0x32008300,0x44240000,0x0,0x4000048,
+ 0x8c801050,0x20440,0x40221dc0,0x808c0028,0x11d0667f,0x8009c400,0x1fc180,0x4001023,0xc8300002,0x1e0ccfb,0x3ec7b020,0x12048120,
+ 0x48120482,0x79007f9f,0xe7f9fe08,0x2008020,0xf0922409,0x2409024,0x8504490,0x24090240,0x85040920,0x802008,0x2008020,0x89004090,
+ 0x24090208,0x2008020,0x40902409,0x2409024,0x8304390,0x24090240,0x88440884,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000,
+ 0x481c0606,0xc8001001,0x802000,0x20,0x4c810020,0x4220024,0x8102108,0x60000070,0x3820,0x48884419,0x409004,0x10e4082,0x112040,
+ 0x13244902,0x7e1027e0,0x3c081021,0x21320c02,0x802008,0x1000000,0x7e409,0x409020,0x81024082,0x414008,0x9240902,0x40902101,
+ 0x80101022,0x11320c08,0x40202008,0x2038800,0x200bc000,0x20000000,0x80200003,0x80f04044,0xbc080bc,0x2f000200,0x0,0x0,0x6001048,
+ 0x8bc02020,0x20441,0xf8220200,0x80820028,0x1000cc00,0x80094400,0x201e0,0x78001021,0xc830000f,0x8000663c,0xf03c0c0,0x21084210,
+ 0x84210846,0x41004010,0x4010008,0x2008020,0x40912409,0x2409024,0x8204890,0x24090240,0x82040930,0x1f87e1f8,0x7e1f87e0,0x89004090,
+ 0x24090208,0x2008020,0x40902409,0x2409024,0x8004690,0x24090240,0x88440884,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000,
+ 0x480719c4,0x48001001,0x81fc00,0x7800020,0x40810040,0x2420024,0x8104087,0xa0000070,0x3820,0x48884409,0x409004,0x1024082,0x111040,
+ 0x13244902,0x40102410,0x2081021,0x214a1202,0x1802008,0x1000000,0x182409,0x409fe0,0x81024082,0x41a008,0x9240902,0x40902100,
+ 0xf8101021,0x214a0c04,0x80c0c008,0x1847000,0x7c1ee000,0x20000000,0x8020000c,0x8c044,0x1ee181ee,0x7b800000,0x707,0xf3ff0000,
+ 0x3e0084f,0x9ee0c020,0x20440,0x40221fc0,0xc2002c,0x13f11000,0x87892400,0x20000,0x1020,0x48000000,0x3f011c6,0x31cc6180,0x21084210,
+ 0x84210844,0x41004010,0x4010008,0x2008020,0x40912409,0x2409024,0x8505090,0x24090240,0x8204191c,0x60982609,0x82609823,0xf9007f9f,
+ 0xe7f9fe08,0x2008020,0x40902409,0x2409024,0x9fe4c90,0x24090240,0x84840848,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0xfe048224,
+ 0x28001001,0x2000,0x40,0x40810080,0x27f8024,0x8104080,0x2000001c,0x1fe0e020,0x488fc409,0x409004,0x1024082,0x110840,0x10242902,
+ 0x40102408,0x2081021,0x214a1202,0x1002004,0x1000000,0x102409,0x409000,0x81024082,0x411008,0x9240902,0x40902100,0x6101021,
+ 0x214a0c04,0x81002008,0x2000000,0x201dc000,0x20000000,0x80200000,0x98044,0x1dc101dc,0x77000000,0x700,0x0,0x180448,0x1dc10020,
+ 0x20440,0x403e0200,0x620017,0xa000cc00,0x80052800,0x20000,0x1020,0x48000000,0x6606,0x206100,0x3f0fc3f0,0xfc3f0fc7,0xc1004010,
+ 0x4010008,0x2008020,0x4090a409,0x2409024,0x8886090,0x24090240,0x8207e106,0x40902409,0x2409024,0x81004010,0x4010008,0x2008020,
+ 0x40902409,0x2409024,0x8005890,0x24090240,0x84840848,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x98048224,0x30001001,0x2000,
+ 0x40,0x21010100,0x2020024,0x8204080,0x40000007,0x80078000,0x48884408,0x80411004,0x824082,0x110840,0x10242986,0x40086409,0x2081021,
+ 0xe14a2102,0x2002004,0x1000000,0x106409,0x409000,0x81024082,0x410808,0x9240902,0x40902100,0x2101021,0x214a1202,0x82002008,
+ 0x2000000,0x300f8000,0x20000000,0x80fc001d,0xe4088044,0xf8200f8,0x3e000000,0x300,0x0,0x80c48,0xf820020,0x20640,0x40410200,
+ 0x803c0018,0x60006600,0x61800,0x0,0x1020,0x48000000,0xcc0a,0x20a100,0x21084210,0x84210844,0x40804010,0x4010008,0x2008020,
+ 0x4110a619,0x86619866,0x19046110,0x24090240,0x82040102,0x41906419,0x6419064,0x81004010,0x4010008,0x2008020,0x40902409,0x2409024,
+ 0x8307090,0x24090240,0x82840828,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000,0x90248222,0x30000802,0x200c,0xc080,0x21010301,
+ 0x4021042,0x10202108,0xc0c03000,0x80040020,0x4d902418,0xc6431004,0xc24082,0x6210440,0x10241884,0x40084409,0x86080840,0xc0842102,
+ 0x4002002,0x1000000,0x18e610,0x84218820,0x80864082,0x410408,0x9240884,0x61086101,0x6101860,0xc0842103,0x4002008,0x2000000,
+ 0x10850180,0x20330000,0x80200013,0x26184024,0x5040050,0x14000000,0x0,0x0,0x4180848,0x85040020,0x20350,0x40000200,0x800c0007,
+ 0x80002200,0x1e000,0x0,0x1860,0x48000000,0x880a,0x40a188,0x40902409,0x2409028,0x40c64010,0x4010008,0x2008020,0x43106210,0x84210842,
+ 0x10006108,0x42108421,0x2040102,0x6398e639,0x8e6398e4,0x88842088,0x22088208,0x2008020,0x21102210,0x84210842,0x10306118,0x66198661,
+ 0x83061030,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20001,0x901f01c1,0xe8000802,0xc,0xc080,0x1e07c7f8,0xf8020f81,0xe0401e07,
+ 0x80c03000,0x20,0x279027e0,0x3c7c1fe4,0x3c408f,0x83c1027f,0x90241878,0x4007c404,0xf8080780,0xc0844082,0x7f82002,0x1000000,
+ 0xfa5e0,0x781e87c0,0x807a409f,0xc0410207,0x9240878,0x5e07a100,0xf80e0fa0,0xc0846183,0x7f82008,0x2000000,0xf020100,0x40321360,
+ 0x80200014,0xa3e0201f,0x8207f820,0x8000000,0x0,0x0,0x3e01037,0x207f820,0x201e1,0xfc000200,0x80040000,0x0,0x0,0x1fc000,0x17b0,
+ 0x48000000,0x12,0xc120f0,0x40902409,0x2409028,0x783c7f9f,0xe7f9fe3e,0xf83e0f8,0x7c1061e0,0x781e0781,0xe000be07,0x81e0781e,
+ 0x204017c,0x3e8fa3e8,0xfa3e8fa3,0x70781f07,0xc1f07c7f,0x1fc7f1fc,0x1e1021e0,0x781e0781,0xe0007e0f,0xa3e8fa3e,0x8305e030,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40000,0xc06,0xc,0x100,0x0,0x0,0x0,0x3000,0x0,0x20000000,0x0,0x0,0x0,0x0,0xc000,
+ 0x0,0x0,0x2001,0x1000000,0x0,0x0,0x20000,0x400000,0x0,0x40002000,0x0,0x1,0x2008,0x2000000,0x100,0x40240000,0x80200008,0x40000000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x40,0x0,0x80040000,0x0,0x0,0x0,0x1000,0x48000000,0x1f,0x181f000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1040010,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40000,0x60c,0x18,0x0,
+ 0x0,0x0,0x0,0x6000,0x0,0x10000000,0x0,0x0,0x0,0x0,0x4000,0x0,0x0,0x3800,0x7000000,0x0,0x0,0x840000,0x400000,0x0,0x40002000,
+ 0x0,0x2,0x2008,0x2000000,0x200,0x40440000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40,0x0,0x80780000,0x0,0x0,0x0,0x1000,0x48000400,
+ 0x2,0x1e02000,0x0,0x0,0x80000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80000,0x0,0x0,0x0,0x0,0x0,0x0,0x2040020,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x0,0x4000,0x0,0xf000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x780000,0x3800000,0x0,0x40002000,0x0,0xe,0x1808,0xc000000,0x3,0x80000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80000000,
+ 0x0,0x0,0x0,0x1000,0x1c00,0x0,0x0,0x0,0x0,0x380000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x380000,0x0,0x0,0x0,0x0,0x0,0x0,0xe0400e0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3fc,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 };
+
+
+ // Definition of a 12x24 font
+ const unsigned int font12x24[12*24*256/32] = {
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x19,0x80000000,0x198000,0x0,0x0,0x0,0x0,
+ 0x0,0x198,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc001806,0xc81980,0x60000000,0xc001806,0x1980c00,0x18060198,0xc80c,
+ 0x180600,0xc8198000,0xc001,0x80601980,0x18000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0x0,0xf0000,0x0,0x0,0x0,0x0,0x0,0x198,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x600300f,0x1301980,0x90000000,0x600300f,0x1980600,0x300f0198,0x13006,0x300f01,0x30198000,0x6003,
+ 0xf01980,0x30000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x6,0x0,0x60000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7007,0x3c0000,0x3006019,
+ 0x80000000,0x90000000,0x3006019,0x80000300,0x60198000,0x3,0x601980,0x0,0x3006,0x1980000,0x60000000,0x0,0x0,0xe0000000,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000000,
+ 0x0,0x0,0x0,0x0,0x0,0xc800019,0x80000000,0x198000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc0,0x0,0x0,0x1001,0x420000,0x0,0x0,0x90000000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18000c06,0xc80001,0x10000000,0x18000c06,0x1800,0xc060000,0xc818,0xc0600,0xc8000000,
+ 0x18000,0xc0600000,0xc000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6019,0x80660207,0x800f8060,0x300c004,0x0,0x6,
+ 0xe00703f,0x3f00383,0xf80f07fc,0x1f01f000,0x0,0xf8,0x607f,0x7c7e07,0xfe7fe0f8,0x6063fc1f,0x86066007,0xe7060f0,0x7f80f07f,
+ 0x81f8fff6,0x6606c03,0x70ee077f,0xe0786000,0xf0070000,0xc000060,0xc0,0x3e000,0x60006003,0x600fc00,0x0,0x0,0x0,0x0,0x0,0x3c0603,
+ 0xc0000000,0x7800000,0xf0000,0x0,0xf00001f,0x80001fe0,0x7fe000,0x0,0x0,0x0,0x168fe609,0x0,0x90e07,0x6000,0x3c000e,0x70000f8,
+ 0x1980001f,0x0,0x1f8,0xf00000f,0xf00180,0xfe000,0xe00e,0x1001,0x20060,0x6006006,0x600600,0x600fe07c,0x7fe7fe7f,0xe7fe3fc3,
+ 0xfc3fc3fc,0x7e07060f,0xf00f00,0xf00f0000,0xf360660,0x6606606e,0x76001e0,0xc00180f,0x1681981,0x10000000,0xc00180f,0x1980c00,
+ 0x180f0198,0x3801680c,0x180f01,0x68198000,0xc001,0x80f01980,0x18600198,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6019,
+ 0x8044020c,0xc01f8060,0x2004004,0x0,0xc,0x3f81f07f,0x87f80383,0xf81f87fc,0x3f83f800,0x0,0x1fc,0x780607f,0x81fe7f87,0xfe7fe1fc,
+ 0x6063fc1f,0x860c6007,0xe7061f8,0x7fc1f87f,0xc3fcfff6,0x6606c03,0x30c6067f,0xe0783000,0xf00d8000,0x6000060,0xc0,0x7e000,0x60006003,
+ 0x600fc00,0x0,0x0,0xc00,0x0,0x0,0x7c0603,0xe0000000,0xfc00000,0x1f0000,0x0,0x900003f,0xc0003fe0,0x7fe000,0x0,0x0,0x0,0x1302660f,
+ 0x0,0xf0606,0x6004,0x7e0006,0x60601f8,0x19800001,0x80000000,0x1f8,0x19800010,0x81080300,0x3f2000,0x2011,0x1001,0x1c0060,0x6006006,
+ 0x600600,0x601fe1fe,0x7fe7fe7f,0xe7fe3fc3,0xfc3fc3fc,0x7f87061f,0x81f81f81,0xf81f8000,0x3fa60660,0x66066066,0x66003f0,0x6003009,
+ 0x1301981,0x10000000,0x6003009,0x1980600,0x30090198,0x1f013006,0x300901,0x30198000,0x6003,0x901980,0x30600198,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6019,0x80cc0f8c,0xc0180060,0x6006044,0x40000000,0xc,0x3181b041,0xc41c0783,0x388018,
+ 0x71c71800,0x0,0x106,0x18c0f061,0xc38261c6,0x600384,0x60606001,0x86186007,0xe78630c,0x60e30c60,0xe7040606,0x630cc03,0x39c30c00,
+ 0xc0603000,0x3018c000,0x3000060,0xc0,0x60000,0x60000000,0x6000c00,0x0,0x0,0xc00,0x0,0x0,0x600600,0x60000000,0x18400000,0x180000,
+ 0x0,0x19800070,0x40003600,0xc000,0x0,0x0,0x0,0x25a06,0x0,0x6030c,0x4,0xe20007,0xe060180,0xf000,0x80000000,0xf0000,0x10800000,
+ 0x80080600,0x7f2000,0x2020,0x80001001,0x20000,0xf00f00f,0xf00f00,0x601b0382,0x60060060,0x6000600,0x60060060,0x61c78630,0xc30c30c3,
+ 0xc30c000,0x30e60660,0x66066063,0xc600738,0x3006019,0x80000000,0xe0000000,0x3006019,0x80000300,0x60198000,0x3e000003,0x601980,
+ 0x0,0x3006,0x1980000,0x60600000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6019,0x80cc1fcc,0xc0180060,0x6006035,0x80000000,
+ 0x18,0x71c03000,0xc00c0583,0x300018,0x60c60c00,0x0,0x6,0x3060f060,0xc30060c6,0x600300,0x60606001,0x86306007,0x9e78670e,0x60670e60,
+ 0x66000606,0x630c606,0x19830c01,0xc0601800,0x30306000,0x60,0xc0,0x60000,0x60000000,0x6000c00,0x0,0x0,0xc00,0x0,0x0,0x600600,
+ 0x60000000,0x18000000,0x300000,0x0,0x78060,0x6600,0x1c000,0x300c,0x39819c0,0x0,0x25a00,0x0,0x30c,0x4,0xc00003,0xc060180,0x30c1f,
+ 0x80000000,0x30c000,0x10800001,0x80700000,0x7f2000,0x2020,0x80001001,0x20060,0xf00f00f,0xf00f00,0xf01b0300,0x60060060,0x6000600,
+ 0x60060060,0x60c78670,0xe70e70e7,0xe70e000,0x70c60660,0x66066063,0xc7f8618,0x0,0x0,0x0,0x0,0x0,0x0,0x7000000,0x0,0x0,0x0,
+ 0x0,0x600000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6019,0x87ff3a4c,0xc0180060,0x400600e,0x600000,0x18,0x60c03000,
+ 0xc00c0d83,0x700018,0x60c60c00,0x20,0x400006,0x3060f060,0xc6006066,0x600600,0x60606001,0x86606006,0x966c6606,0x60660660,0x66000606,
+ 0x630c666,0xf019801,0x80601800,0x30603000,0x1f06f,0xf01ec0,0xf03fe1ec,0x6703e01f,0x61c0c06,0xdc6701f0,0x6f01ec0c,0xe1f87fc6,
+ 0xc60cc03,0x71c60c7f,0xc0600600,0x60000000,0x30000000,0x300000,0x40040,0x88060,0x6600,0x18000,0x300c,0x1981980,0x0,0x2421f,
+ 0x80003ce0,0x7fc198,0x601f,0xc02021,0x980600c0,0x40230,0x80000000,0x402000,0x19806003,0x80006,0xc7f2000,0x2020,0x80001001,
+ 0x420060,0xf00f00f,0xf00f00,0xf01b0600,0x60060060,0x6000600,0x60060060,0x6066c660,0x66066066,0x6606208,0x60e60660,0x66066061,
+ 0x987fc670,0x1f01f01f,0x1f01f01,0xf039c0f0,0xf00f00f,0xf03e03,0xe03e03e0,0x1f06701f,0x1f01f01,0xf01f0060,0x1e660c60,0xc60c60c6,
+ 0xc6f060c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x7ff3207,0x8c0c0000,0xc00300e,0x600000,0x30,0x60c03000,
+ 0xc01c0983,0xf0600030,0x31860c06,0x6001e0,0x78000e,0x23e1f861,0xc6006066,0x600600,0x60606001,0x86c06006,0x966c6606,0x60660660,
+ 0xe7000606,0x630c666,0xf01f803,0x600c00,0x30000000,0x3f87f,0x83f83fc3,0xf83fe3fc,0x7f83e01f,0x6380c07,0xfe7f83f8,0x7f83fc0d,
+ 0xf3fc7fc6,0xc71cc03,0x3183187f,0xc0600600,0x60000000,0xff806000,0x300000,0x40040,0x88070,0x6600,0x60030060,0x6001818,0x1883180,
+ 0x0,0x2423f,0xc0007ff0,0x607fc1f8,0x603f,0x80c01fc1,0xf80601e0,0x5f220,0x80420000,0x5f2000,0xf006006,0x80006,0xc7f2000,0x2020,
+ 0x82107c07,0xc03c0060,0x1f81f81f,0x81f81f80,0xf03b0600,0x60060060,0x6000600,0x60060060,0x6066c660,0x66066066,0x660671c,0x61660660,
+ 0x66066061,0xf860e6c0,0x3f83f83f,0x83f83f83,0xf87fe3f8,0x3f83f83f,0x83f83e03,0xe03e03e0,0x3f87f83f,0x83f83f83,0xf83f8060,
+ 0x3fc60c60,0xc60c60c3,0x187f8318,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x883200,0x300c0000,0xc003035,0x80600000,
+ 0x30,0x66c03001,0xc0f81983,0xf86f0030,0x1f071c06,0x600787,0xfe1e001c,0x6261987f,0x86006067,0xfe7fc600,0x7fe06001,0x87c06006,
+ 0xf6646606,0x60e6067f,0xc3e00606,0x61986f6,0x600f007,0x600c00,0x30000000,0x21c71,0x830831c3,0x1c06031c,0x71c06003,0x6700c06,
+ 0x6671c318,0x71831c0f,0x16040c06,0xc318606,0x1b031803,0x80600600,0x60000000,0x30009000,0x300000,0x40040,0x7003e,0x67e0,0x90070090,
+ 0x9001818,0x8c3100,0x0,0x60,0x4000e730,0x900380f0,0x6034,0x80c018c7,0xfe060338,0xb0121,0x80c60000,0x909000,0x6008,0x1080006,
+ 0xc3f2000,0x2011,0x3180060,0x60060e0,0x19819819,0x81981981,0x9833c600,0x7fe7fe7f,0xe7fe0600,0x60060060,0x60664660,0x66066066,
+ 0x66063b8,0x62660660,0x66066060,0xf06066c0,0x21c21c21,0xc21c21c2,0x1c466308,0x31c31c31,0xc31c0600,0x60060060,0x31871c31,0x83183183,
+ 0x18318000,0x71860c60,0xc60c60c3,0x18718318,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x1981a00,0xe03e0000,0xc003044,
+ 0x40600000,0x60,0x66c03001,0x80f03182,0x1c7f8030,0x3f83fc06,0x601e07,0xfe078038,0x6661987f,0x86006067,0xfe7fc61e,0x7fe06001,
+ 0x87e06006,0x66666606,0x7fc6067f,0x81f80606,0x61986f6,0x6006006,0x600600,0x30000000,0xc60,0xc60060c6,0xc06060c,0x60c06003,
+ 0x6e00c06,0x6660c60c,0x60c60c0e,0x6000c06,0xc318666,0x1f031803,0x600600,0x603c2000,0x30016800,0x1fe0000,0x1f81f8,0x1c1f,0x804067e1,
+ 0x68060168,0x16800810,0xc42300,0x0,0x60,0x20c331,0x68030060,0x6064,0x3fc1040,0xf006031c,0xa011e,0x818c7fe0,0x909000,0x7fe1f,
+ 0x80f00006,0xc0f2060,0xf80e,0x18c0780,0x780781c0,0x19819819,0x81981981,0x9833c600,0x7fe7fe7f,0xe7fe0600,0x60060060,0xfc666660,
+ 0x66066066,0x66061f0,0x66660660,0x66066060,0x606066e0,0xc00c00,0xc00c00c0,0xc066600,0x60c60c60,0xc60c0600,0x60060060,0x60c60c60,
+ 0xc60c60c6,0xc60c000,0x61c60c60,0xc60c60c3,0x1860c318,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x1980f81,0x80373000,
+ 0xc003004,0x7fe0001,0xf0000060,0x60c03003,0x183180,0xc71c060,0x3181ec00,0x7000,0xe070,0x66619860,0xc6006066,0x60061e,0x60606001,
+ 0x87606006,0x66626606,0x7f860661,0xc01c0606,0x6198696,0xf00600e,0x600600,0x30000000,0x1fc60,0xc60060c7,0xfc06060c,0x60c06003,
+ 0x7c00c06,0x6660c60c,0x60c60c0c,0x7f00c06,0xc3b8666,0xe01b007,0x3c00600,0x3c7fe000,0xff03ec00,0x1fe0000,0x40040,0xe001,0xc0806603,
+ 0xec0e03ec,0x3ec00010,0x0,0x60000000,0x7f,0x10c3f3,0xec070060,0x6064,0x3fc1040,0x6000030c,0xa0100,0x3187fe1,0xf09f1000,0x7fe00,
+ 0x6,0xc012060,0x0,0xc63c03,0xc03c0380,0x19819819,0x81981981,0x98330600,0x60060060,0x6000600,0x60060060,0xfc662660,0x66066066,
+ 0x66060e0,0x6c660660,0x66066060,0x6060e630,0x1fc1fc1f,0xc1fc1fc1,0xfc3fe600,0x7fc7fc7f,0xc7fc0600,0x60060060,0x60c60c60,0xc60c60c6,
+ 0xc60c7fe,0x62c60c60,0xc60c60c1,0xb060c1b0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0xffe02c6,0x3c633000,0xc003004,
+ 0x7fe0001,0xf00000c0,0x60c03006,0xc6180,0xc60c060,0x60c00c00,0x7000,0xe060,0x66639c60,0x66006066,0x600606,0x60606001,0x86306006,
+ 0x66636606,0x60060660,0xc0060606,0x61f8696,0xf00600c,0x600300,0x30000000,0x3fc60,0xc60060c7,0xfc06060c,0x60c06003,0x7c00c06,
+ 0x6660c60c,0x60c60c0c,0x1f80c06,0xc1b0666,0xe01b00e,0x3c00600,0x3c43c000,0x3007de00,0x600000,0x40040,0x30000,0x61006607,0xde0c07de,
+ 0x7de00000,0x0,0xf07fefff,0x1f,0x8008c3f7,0xde0e0060,0x6064,0xc01047,0xfe00018c,0xb013f,0x86300061,0xf0911000,0x6000,0x6,
+ 0xc012060,0x3f,0x8063c0cc,0x3cc0c700,0x39c39c39,0xc39c39c1,0x98630600,0x60060060,0x6000600,0x60060060,0x60663660,0x66066066,
+ 0x66061f0,0x78660660,0x66066060,0x607fc618,0x3fc3fc3f,0xc3fc3fc3,0xfc7fe600,0x7fc7fc7f,0xc7fc0600,0x60060060,0x60c60c60,0xc60c60c6,
+ 0xc60c7fe,0x64c60c60,0xc60c60c1,0xb060c1b0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0xffe0260,0x6661b000,0xc003000,
+ 0x600000,0xc0,0x60c0300c,0xc7fe0,0xc60c060,0x60c01c00,0x1e07,0xfe078060,0x6663fc60,0x66006066,0x600606,0x60606001,0x86386006,
+ 0x6636606,0x60060660,0xe0060606,0x60f039c,0x1b806018,0x600300,0x30000000,0x70c60,0xc60060c6,0x6060c,0x60c06003,0x7600c06,
+ 0x6660c60c,0x60c60c0c,0x1c0c06,0xc1b03fc,0xe01f01c,0xe00600,0x70000000,0x3007fc00,0x600000,0x40040,0x0,0x62006607,0xfc1807fc,
+ 0x7fc00000,0x0,0xf0000000,0x1,0xc004c307,0xfc1c0060,0x6064,0xc018c0,0x600000d8,0x5f200,0x3180060,0x50a000,0x6000,0x6,0xc012000,
+ 0x0,0xc601c0,0x4201c600,0x3fc3fc3f,0xc3fc3fc3,0xfc7f0600,0x60060060,0x6000600,0x60060060,0x60663660,0x66066066,0x66063b8,
+ 0x70660660,0x66066060,0x607f860c,0x70c70c70,0xc70c70c7,0xcc60600,0x60060060,0x6000600,0x60060060,0x60c60c60,0xc60c60c6,0xc60c000,
+ 0x68c60c60,0xc60c60c1,0xf060c1f0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3300260,0x6661e000,0xc003000,0x600000,
+ 0x180,0x71c03018,0xc7fe0,0xc60c0c0,0x60c01800,0x787,0xfe1e0060,0x6663fc60,0x630060c6,0x600306,0x60606001,0x86186006,0x661e70e,
+ 0x60070c60,0x60060606,0x60f039c,0x19806038,0x600180,0x30000000,0x60c60,0xc60060c6,0x6060c,0x60c06003,0x6700c06,0x6660c60c,
+ 0x60c60c0c,0xc0c06,0xc1b039c,0x1f00e018,0x600600,0x60000000,0x1803f800,0x600000,0x40040,0x39e00,0x63006603,0xf83803f8,0x3f800000,
+ 0x0,0x60000000,0x0,0xc00cc303,0xf8180060,0x6064,0xc01fc0,0x60060070,0x40200,0x18c0060,0x402000,0x6000,0x6,0xc012000,0x0,0x18c0140,
+ 0x2014600,0x3fc3fc3f,0xc3fc3fc3,0xfc7f0300,0x60060060,0x6000600,0x60060060,0x60c61e70,0xe70e70e7,0xe70e71c,0x60e60660,0x66066060,
+ 0x6060060c,0x60c60c60,0xc60c60c6,0xcc60600,0x60060060,0x6000600,0x60060060,0x60c60c60,0xc60c60c6,0xc60c000,0x70c60c60,0xc60c60c0,
+ 0xe060c0e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x33022e0,0x6670c000,0xc003000,0x600600,0x60180,0x31803030,
+ 0x41c0184,0x1831c0c0,0x71c23806,0x6001e0,0x780000,0x62630c60,0xe38261c6,0x600386,0x60606043,0x860c6006,0x661e30c,0x60030c60,
+ 0x740e0607,0xe0f039c,0x31c06030,0x600180,0x30000000,0x61c71,0x830831c3,0x406031c,0x60c06003,0x6300c06,0x6660c318,0x71831c0c,
+ 0x41c0c07,0x1c0e039c,0x1b00e030,0x600600,0x60000000,0x1c41b00e,0x601cc0,0x401f8,0x45240,0xe1803601,0xb03001b0,0x1b000000,
+ 0x0,0x0,0x41,0xc008e711,0xb0300060,0x6034,0x80c02020,0x60060030,0x30c00,0xc60000,0x30c000,0x0,0x7,0x1c012000,0x0,0x3180240,
+ 0x6024608,0x30c30c30,0xc30c30c3,0xc630382,0x60060060,0x6000600,0x60060060,0x61c61e30,0xc30c30c3,0xc30c208,0x70c70e70,0xe70e70e0,
+ 0x6060068c,0x61c61c61,0xc61c61c6,0x1cc62308,0x30430430,0x43040600,0x60060060,0x31860c31,0x83183183,0x18318060,0x31c71c71,
+ 0xc71c71c0,0xe07180e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x2203fc0,0x663f6000,0x6006000,0x600600,0x60300,
+ 0x3f81fe7f,0xc7f80187,0xf83f80c0,0x3f83f006,0x600020,0x400060,0x33e6067f,0xc1fe7f87,0xfe6001fe,0x6063fc7f,0x60e7fe6,0x660e3f8,
+ 0x6001f860,0x37fc0603,0xfc06030c,0x30c0607f,0xe06000c0,0x30000000,0x7fc7f,0x83f83fc3,0xfc0603fc,0x60c7fe03,0x61807c6,0x6660c3f8,
+ 0x7f83fc0c,0x7f80fc3,0xfc0e039c,0x3180607f,0xc0600600,0x60000000,0xfc0e00c,0x601986,0x66040040,0x4527f,0xc0803fe0,0xe07fe0e0,
+ 0xe000000,0x0,0x0,0x7f,0x80107ff0,0xe07fc060,0x603f,0x83fe0000,0x60060018,0xf000,0x420000,0xf0000,0x7fe00,0x7,0xfe012000,
+ 0x0,0x2100640,0xc0643f8,0x60660660,0x66066067,0xec3e1fe,0x7fe7fe7f,0xe7fe3fc3,0xfc3fc3fc,0x7f860e3f,0x83f83f83,0xf83f8000,
+ 0x5fc3fc3f,0xc3fc3fc0,0x606006fc,0x7fc7fc7f,0xc7fc7fc7,0xfcffe3f8,0x3fc3fc3f,0xc3fc7fe7,0xfe7fe7fe,0x3f860c3f,0x83f83f83,
+ 0xf83f8060,0x7f83fc3f,0xc3fc3fc0,0x607f8060,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x2201f80,0x3c1e7000,0x6006000,
+ 0x600,0x60300,0xe01fe7f,0xc3f00183,0xe01f0180,0x1f01e006,0x600000,0x60,0x3006067f,0x807c7e07,0xfe6000f8,0x6063fc3e,0x6067fe6,
+ 0x660e0f0,0x6000f060,0x3bf80601,0xf806030c,0x60e0607f,0xe06000c0,0x30000000,0x1ec6f,0xf01ec0,0xf80601ec,0x60c7fe03,0x61c03c6,
+ 0x6660c1f0,0x6f01ec0c,0x3f007c1,0xcc0e030c,0x71c0c07f,0xc0600600,0x60000000,0x7804018,0xe01186,0x66040040,0x39e3f,0x80401fe0,
+ 0x407fe040,0x4000000,0x0,0x0,0x3f,0x203ce0,0x407fc060,0x601f,0x3fe0000,0x60060018,0x0,0x0,0x0,0x7fe00,0x6,0xe6012000,0x0,
+ 0x7e0,0x1807e1f0,0x60660660,0x66066066,0x6c3e07c,0x7fe7fe7f,0xe7fe3fc3,0xfc3fc3fc,0x7e060e0f,0xf00f00,0xf00f0000,0x8f01f81f,
+ 0x81f81f80,0x60600670,0x1ec1ec1e,0xc1ec1ec1,0xec79c0f0,0xf80f80f,0x80f87fe7,0xfe7fe7fe,0x1f060c1f,0x1f01f01,0xf01f0000,0x4f01cc1c,
+ 0xc1cc1cc0,0xc06f00c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x200,0x0,0x6006000,0x600,0x600,0x0,0x0,0x0,0x0,
+ 0x600000,0x0,0x18000000,0x0,0x0,0x0,0x0,0x0,0x1800,0x0,0x0,0x0,0x600060,0x30000000,0x0,0x0,0xc,0x3,0x0,0x0,0x60000c00,0x0,
+ 0x0,0xc000,0x600600,0x60000000,0x18,0xc03100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x601f8,0x0,0x0,0x0,0x0,0x6,
+ 0x12000,0x2000000,0x40,0x20004000,0x0,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0xc06000c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x200,0x0,0x2004000,0xc00,0x0,0x0,0x0,0x0,0x0,0xc00000,
+ 0x0,0x1c000000,0x0,0x0,0x0,0x0,0x0,0xc00,0x0,0x0,0x0,0x780000,0xf0000000,0x0,0x0,0x21c,0x3,0x0,0x0,0x60000c00,0x0,0x0,0xc000,
+ 0x7c0603,0xe0000000,0x10,0xc02300,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x601f0,0x0,0x0,0x0,0x0,0x6,0x12000,0x1000000,
+ 0x40,0x7e004000,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc06000c0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x200,0x0,0x300c000,0xc00,0x0,0x0,0x0,0x0,0x0,0xc00000,0x0,0x7800000,0x0,
+ 0x0,0x0,0x0,0x0,0x800,0x0,0x0,0x0,0x780000,0xf0000000,0x0,0x0,0x3f8,0x3e,0x0,0x0,0x60000c00,0x0,0x0,0x38000,0x3c0603,0xc0000000,
+ 0x10,0xfc00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x60000,0x0,0x0,0x0,0x0,0x6,0x0,0x1000000,0x0,0x0,0x0,0x0,
+ 0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x80600380,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffc,0x0,
+ 0x0,0x1f0,0x3c,0x0,0x0,0x60000c00,0x0,0x0,0x38000,0x600,0x0,0x0,0xf000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x6,0x0,0xe000000,0x0,0x0,0x0,0x0,0x70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x70,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x3,0x80600380,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xffc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 };
+
+ // Definition of a 16x32
+ const unsigned int font16x32[16*32*256/32] = {
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc300000,0x0,0xc300000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x70000e0,0x3c00730,0xe7001c0,0x0,0x70000e0,0x3c00e70,0x70000e0,0x3c00e70,0x730,0x70000e0,0x3c00730,
+ 0xe700000,0x700,0xe003c0,0xe7000e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x6600000,0x0,0x6600000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x18001c0,0x6600ff0,0xe7003e0,0x0,0x18001c0,0x6600e70,0x18001c0,0x6600e70,0xff0,0x18001c0,0x6600ff0,0xe700000,0x180,
+ 0x1c00660,0xe7001c0,0x0,0x0,0x0,0x380,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,
+ 0x0,0x3c00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c00380,
+ 0xc300ce0,0xe700630,0x0,0x1c00380,0xc300e70,0x1c00380,0xc300e70,0xce0,0x1c00380,0xc300ce0,0xe700000,0x1c0,0x3800c30,0xe700380,
+ 0x0,0x0,0x0,0x7c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0xe000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1800000,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0xc300000,0x0,0xc300000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x700000,0x0,0x0,0x0,0x7c007c00,0x3e000000,
+ 0x0,0x0,0x630,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe000070,0x1800000,0xc60,0x0,0xe000070,0x1800000,0xe000070,
+ 0x1800000,0x0,0xe000070,0x1800000,0x0,0xe00,0x700180,0x70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x800000,0x0,0x600600,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x3f0,0xfc0,0x0,0x7000000,0x38000000,0x1c0000,0xfc0000,0x380001c0,0xe01c00,0x7f800000,0x0,0x0,0x0,0x0,0x0,0x0,0x7c,
+ 0x1801f00,0x0,0x0,0x1c,0x0,0x0,0x3c00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7300000,0x6600000,0x0,0x6600000,0x0,0x0,0x0,0x0,0xe700000,
+ 0x0,0x0,0x0,0x0,0x0,0xe00000,0x0,0x0,0x0,0xc000c00,0x43800000,0x0,0x0,0x630,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0xf80,0x70000e0,0x3c00730,0xe700c60,0x0,0x70000e0,0x3c00e70,0x70000e0,0x3c00e70,0xe000730,0x70000e0,0x3c00730,0xe700000,0x700,
+ 0xe003c0,0xe7000e0,0x38000e70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x6300000,0x803c00,0x7c00180,
+ 0xc00300,0x1000000,0x0,0x1c,0x3c007c0,0xfc007e0,0xe01ff8,0x3f03ffc,0x7e007c0,0x0,0x0,0x7c0,0x1c0,0x7f8003f0,0x7f007ff8,0x7ff803f0,
+ 0x70381ffc,0xff0700e,0x7000783c,0x783807c0,0x7fc007c0,0x7fc00fc0,0x7fff7038,0x700ee007,0x780f780f,0x7ffc03f0,0x70000fc0,0x3c00000,
+ 0x3000000,0x38000000,0x1c0000,0x1fc0000,0x380001c0,0xe01c00,0x7f800000,0x0,0x0,0x0,0x0,0x0,0x0,0xfc,0x1801f80,0x0,0x1f80000,
+ 0x7e,0x0,0x0,0x2400000,0xfc00000,0x7ff0000,0x7ffc0000,0x0,0x0,0x0,0x0,0xf30fb0c,0x2400000,0x0,0x240780f,0x1c0,0xfc,0x780f,
+ 0x18003f0,0xe700000,0x7c00000,0x0,0xff0,0x3c00000,0x78007c0,0xc00000,0xff80000,0xf80,0x7c00000,0xc000c00,0x18001c0,0x1c001c0,
+ 0x1c001c0,0x1c003e0,0x7fe03f0,0x7ff87ff8,0x7ff87ff8,0x1ffc1ffc,0x1ffc1ffc,0x7f007838,0x7c007c0,0x7c007c0,0x7c00000,0x7c67038,
+ 0x70387038,0x7038780f,0x70001fe0,0x30000c0,0x2400f30,0xe700c60,0x0,0x30000c0,0x2400e70,0x30000c0,0x2400e70,0xf700f30,0x30000c0,
+ 0x2400f30,0xe700000,0x300,0xc00240,0xe7000c0,0x38000e70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,
+ 0x630018c,0x807e00,0xfe00180,0xc00300,0x1000000,0x0,0x38,0xff01fc0,0x3ff01ff0,0x1e01ff8,0x7f83ffc,0x1ff80ff0,0x0,0x0,0xff0,
+ 0x1f003e0,0x7fe00ff8,0x7fc07ff8,0x7ff80ff8,0x70381ffc,0xff0701c,0x7000783c,0x78381ff0,0x7fe01ff0,0x7fe01ff0,0x7fff7038,0x781ee007,
+ 0x3c1e380e,0x7ffc0380,0x380001c0,0x3c00000,0x1800000,0x38000000,0x1c0000,0x3c00000,0x380001c0,0xe01c00,0x3800000,0x0,0x0,
+ 0x0,0x7000000,0x0,0x0,0x1e0,0x18003c0,0x0,0x3fc0000,0x70,0x0,0x0,0x6600000,0x1ff00000,0x1fff0000,0x7ffc0000,0x0,0x0,0x0,0x0,
+ 0xcf0239c,0x3c00000,0x0,0x3c0380e,0x1c0,0x2001fe,0x380e,0x18007f8,0xe700000,0x8600000,0x0,0xff0,0x7e00000,0x8c00870,0x1800000,
+ 0x1ff80000,0x180,0xc600000,0xc000c00,0x38001c0,0x3e003e0,0x3e003e0,0x3e001c0,0x7fe0ff8,0x7ff87ff8,0x7ff87ff8,0x1ffc1ffc,0x1ffc1ffc,
+ 0x7fc07838,0x1ff01ff0,0x1ff01ff0,0x1ff00000,0x1fec7038,0x70387038,0x7038380e,0x70003ce0,0x1800180,0x6600cf0,0xe7007c0,0x0,
+ 0x1800180,0x6600e70,0x1800180,0x6600e70,0x7c00cf0,0x1800180,0x6600cf0,0xe700000,0x180,0x1800660,0xe700180,0x38000e70,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x630030c,0x3f0e700,0x1e200180,0x1800180,0x21100000,0x0,
+ 0x38,0x1e7819c0,0x38781038,0x1e01c00,0xf080038,0x1c381c38,0x0,0x0,0x1878,0x7fc03e0,0x70e01e18,0x70e07000,0x70001e18,0x703801c0,
+ 0x707038,0x70007c7c,0x7c381c70,0x70701c70,0x70703830,0x1c07038,0x381ce007,0x1c1c3c1e,0x3c0380,0x380001c0,0x7e00000,0xc00000,
+ 0x38000000,0x1c0000,0x3800000,0x38000000,0x1c00,0x3800000,0x0,0x0,0x0,0x7000000,0x0,0x0,0x1c0,0x18001c0,0x0,0x70c0000,0xe0,
+ 0x0,0x0,0xc300000,0x38300000,0x3c700000,0x3c0000,0x0,0x0,0x0,0x0,0xce022f4,0x1800000,0x0,0x1803c1e,0x1c0,0x2003c2,0x3c1e,
+ 0x1800e08,0x7e0,0x300000,0x0,0x7e00000,0xe700000,0x600030,0x3000000,0x3f980000,0x180,0x18200000,0xc000c00,0x1e0001c0,0x3e003e0,
+ 0x3e003e0,0x3e003e0,0xfe01e18,0x70007000,0x70007000,0x1c001c0,0x1c001c0,0x70e07c38,0x1c701c70,0x1c701c70,0x1c700000,0x3c787038,
+ 0x70387038,0x70383c1e,0x70003870,0xc00300,0xc300ce0,0x380,0x0,0xc00300,0xc300000,0xc00300,0xc300000,0xfc00ce0,0xc00300,0xc300ce0,
+ 0x0,0xc0,0x3000c30,0x300,0x38000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x630031c,0xff8c300,
+ 0x1c000180,0x1800180,0x39380000,0x0,0x70,0x1c3801c0,0x203c001c,0x3e01c00,0x1c000038,0x381c3838,0x0,0x0,0x1038,0xe0e03e0,0x70703c08,
+ 0x70707000,0x70003808,0x703801c0,0x707070,0x70007c7c,0x7c383838,0x70383838,0x70387010,0x1c07038,0x381c700e,0x1e3c1c1c,0x780380,
+ 0x1c0001c0,0xe700000,0x0,0x38000000,0x1c0000,0x3800000,0x38000000,0x1c00,0x3800000,0x0,0x0,0x0,0x7000000,0x0,0x0,0x1c0,0x18001c0,
+ 0x0,0xe000000,0xe0,0x0,0x1000100,0x3800,0x70100000,0x38700000,0x780000,0x1c0,0x7801ce0,0xe380000,0x0,0x2264,0x0,0x0,0x1c1c,
+ 0x0,0x200780,0x1c1c,0x1800c00,0x1818,0x7f00000,0x0,0x18180000,0xc300000,0x600070,0x0,0x7f980000,0x180,0x18300000,0xc000c00,
+ 0x3000000,0x3e003e0,0x3e003e0,0x3e003e0,0xee03c08,0x70007000,0x70007000,0x1c001c0,0x1c001c0,0x70707c38,0x38383838,0x38383838,
+ 0x38380000,0x38387038,0x70387038,0x70381c1c,0x7fc03870,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xbc00000,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x38000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x6300318,0xe88c300,0x1c000180,0x38001c0,
+ 0xfe00180,0x0,0x70,0x1c3801c0,0x1c001c,0x6e01c00,0x1c000078,0x381c3818,0x0,0x40000,0x40000038,0x1c0607e0,0x70703800,0x70707000,
+ 0x70003800,0x703801c0,0x7070e0,0x70007c7c,0x7c383838,0x70383838,0x70387000,0x1c07038,0x381c700e,0xf780e38,0x700380,0x1c0001c0,
+ 0x1c380000,0x0,0x38000000,0x1c0000,0x3800000,0x38000000,0x1c00,0x3800000,0x0,0x0,0x0,0x7000000,0x0,0x0,0x1c0,0x18001c0,0x0,
+ 0xe000000,0xe0,0x0,0x1000100,0x4400,0x70000000,0x38700000,0x700000,0xe0,0x7001c70,0xe380000,0x0,0x2264,0x0,0x0,0xe38,0x0,
+ 0x200700,0xe38,0x1800c00,0x300c,0xc300000,0x0,0x300c0000,0xc300180,0x6003c0,0x0,0x7f980000,0x180,0x18300000,0xc000c00,0x1800000,
+ 0x7e007e0,0x7e007e0,0x7e003e0,0xee03800,0x70007000,0x70007000,0x1c001c0,0x1c001c0,0x70707c38,0x38383838,0x38383838,0x38380000,
+ 0x38387038,0x70387038,0x70380e38,0x7ff039f0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1e00000,0x0,0x0,0x0,0x40000,0x0,0x0,0x38000000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x6300318,0x1c80e700,0x1c000180,0x38001c0,0x3800180,
+ 0x0,0xe0,0x381c01c0,0x1c001c,0x6e01c00,0x38000070,0x381c381c,0x0,0x3c0000,0x78000078,0x38030770,0x70707800,0x70387000,0x70007000,
+ 0x703801c0,0x7071c0,0x7000745c,0x7638701c,0x7038701c,0x70387000,0x1c07038,0x1c38718e,0x7700f78,0xf00380,0xe0001c0,0x381c0000,
+ 0x7e0,0x39e003e0,0x79c03f0,0x3ffc079c,0x39e01fc0,0xfe01c1e,0x3807778,0x39e007e0,0x39e0079c,0x73c07e0,0x7ff83838,0x701ce007,
+ 0x783c701c,0x1ffc01c0,0x18001c0,0x0,0x1c000100,0xe0,0x0,0x1000100,0x4200,0x70000000,0x70700100,0xf00100,0x10000e0,0x7000c70,
+ 0xc700000,0x0,0x2204,0x7e00000,0x1e380100,0x1ffc0f78,0x0,0xf80700,0xf78,0x1800e00,0x63e6,0x18300000,0x0,0x6fe60000,0xe700180,
+ 0xc00060,0x3838,0x7f980000,0x180,0x18300000,0xc000c00,0x18001c0,0x7700770,0x7700770,0x77007f0,0xee07800,0x70007000,0x70007000,
+ 0x1c001c0,0x1c001c0,0x70387638,0x701c701c,0x701c701c,0x701c1008,0x707c7038,0x70387038,0x70380f78,0x707039c0,0x7e007e0,0x7e007e0,
+ 0x7e007e0,0x1f3c03e0,0x3f003f0,0x3f003f0,0x1fc01fc0,0x1fc01fc0,0x7f039e0,0x7e007e0,0x7e007e0,0x7e00380,0x7ce3838,0x38383838,
+ 0x3838701c,0x39e0701c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x6307fff,0x1c807e0c,0xe000180,
+ 0x30000c0,0x3800180,0x0,0xe0,0x381c01c0,0x1c001c,0xce01fe0,0x38000070,0x381c381c,0x3800380,0xfc0000,0x7e0000f0,0x30030770,
+ 0x70707000,0x70387000,0x70007000,0x703801c0,0x707380,0x700076dc,0x7638701c,0x7038701c,0x70387800,0x1c07038,0x1c3873ce,0x7f00770,
+ 0xe00380,0xe0001c0,0x700e0000,0x1ff8,0x3ff00ff0,0xffc0ff8,0x3ffc0ffc,0x3bf01fc0,0xfe01c3c,0x3807f78,0x3bf00ff0,0x3ff00ffc,
+ 0x77e0ff0,0x7ff83838,0x3838e007,0x3c783838,0x1ffc01c0,0x18001c0,0x0,0x7ff00380,0x1e0,0x0,0x1000100,0x4200,0x78000000,0x70700380,
+ 0xe00380,0x3800060,0xe000e30,0x1c600000,0x0,0x2204,0xff00000,0x7f7c0380,0x1ffc0770,0x1c0,0x3fc0700,0x18040770,0x1800780,0x4e12,
+ 0x18300104,0x0,0x4c320000,0x7e00180,0x1c00030,0x3838,0x7f980000,0x180,0x18302080,0xc000c00,0x18001c0,0x7700770,0x7700770,
+ 0x7700770,0x1ee07000,0x70007000,0x70007000,0x1c001c0,0x1c001c0,0x70387638,0x701c701c,0x701c701c,0x701c381c,0x705c7038,0x70387038,
+ 0x70380770,0x70383b80,0x1ff81ff8,0x1ff81ff8,0x1ff81ff8,0x3fbe0ff0,0xff80ff8,0xff80ff8,0x1fc01fc0,0x1fc01fc0,0xff83bf0,0xff00ff0,
+ 0xff00ff0,0xff00380,0xffc3838,0x38383838,0x38383838,0x3ff03838,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x1c0,0x7fff,0x1c803c38,0xf000000,0x70000e0,0xfe00180,0x0,0x1c0,0x381c01c0,0x3c0078,0xce01ff0,0x39e000f0,0x1c38381c,0x3800380,
+ 0x3e07ffc,0xf8001f0,0x307b0770,0x70e07000,0x70387000,0x70007000,0x703801c0,0x707700,0x700076dc,0x7638701c,0x7038701c,0x70387e00,
+ 0x1c07038,0x1c3873ce,0x3e007f0,0x1e00380,0x70001c0,0x0,0x1038,0x3c381e18,0x1c7c1e3c,0x3801e3c,0x3c7801c0,0xe01c78,0x380739c,
+ 0x3c781c38,0x3c381c3c,0x7c21e10,0x7003838,0x3838700e,0x1ef03838,0x3c01c0,0x18001c0,0x0,0x7fe007c0,0x1c0,0x0,0x1000100,0x6400,
+ 0x7e000000,0x707007c0,0x1e007c0,0x7c00070,0xe000638,0x18600000,0x0,0x0,0x1e100000,0x73ce07c0,0x3c07f0,0x1c0,0x7240700,0x1ddc3ffe,
+ 0x1800de0,0x8c01,0x1870030c,0x0,0x8c310000,0x3c00180,0x3800030,0x3838,0x7f980000,0x180,0x183030c0,0xc000c00,0x430001c0,0x7700770,
+ 0x7700770,0x7700770,0x1ce07000,0x70007000,0x70007000,0x1c001c0,0x1c001c0,0x70387638,0x701c701c,0x701c701c,0x701c1c38,0x70dc7038,
+ 0x70387038,0x703807f0,0x70383b80,0x10381038,0x10381038,0x10381038,0x21e71e18,0x1e3c1e3c,0x1e3c1e3c,0x1c001c0,0x1c001c0,0x1e383c78,
+ 0x1c381c38,0x1c381c38,0x1c380380,0x1c383838,0x38383838,0x38383838,0x3c383838,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x1c0,0x630,0x1e8000e0,0x1f000000,0x70000e0,0x39380180,0x0,0x1c0,0x3b9c01c0,0x3c07f0,0x18e01078,0x3bf800e0,
+ 0x7e0383c,0x3800380,0x1f807ffc,0x3f001c0,0x61ff0e38,0x7fc07000,0x70387ff0,0x7ff07000,0x7ff801c0,0x707f00,0x7000729c,0x7338701c,
+ 0x7070701c,0x70703fc0,0x1c07038,0x1e7873ce,0x1c003e0,0x3c00380,0x70001c0,0x0,0x1c,0x3c381c00,0x1c3c1c1c,0x3801c3c,0x383801c0,
+ 0xe01cf0,0x380739c,0x38381c38,0x3c381c3c,0x7801c00,0x7003838,0x3838700e,0xfe03c78,0x7801c0,0x18001c0,0x0,0x1c000c20,0xff8,
+ 0x0,0x1ff01ff0,0x3818,0x3fc00100,0x707e0c20,0x3c00c20,0xc200030,0xc000618,0x18c00000,0x0,0x0,0x1c000080,0xe1ce0c20,0x7803e0,
+ 0x1c0,0xe200700,0xff83ffe,0x1801878,0x9801,0x1cf0071c,0x7ffc0000,0x8c310000,0x7ffe,0x7000030,0x3838,0x3f980380,0x180,0xc6038e0,
+ 0x7f9c7f9c,0x3e1c01c0,0xe380e38,0xe380e38,0xe380f78,0x1cfc7000,0x7ff07ff0,0x7ff07ff0,0x1c001c0,0x1c001c0,0xfe387338,0x701c701c,
+ 0x701c701c,0x701c0e70,0x719c7038,0x70387038,0x703803e0,0x70383b80,0x1c001c,0x1c001c,0x1c001c,0xe71c00,0x1c1c1c1c,0x1c1c1c1c,
+ 0x1c001c0,0x1c001c0,0x1c383838,0x1c381c38,0x1c381c38,0x1c380000,0x3c383838,0x38383838,0x38383c78,0x3c383c78,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x630,0xf800380,0x3f830000,0x70000e0,0x31080180,0x0,0x380,0x3b9c01c0,
+ 0x7807e0,0x38e00038,0x3c3800e0,0xff01c3c,0x3800380,0x7c000000,0x7c03c0,0x61870e38,0x7fc07000,0x70387ff0,0x7ff070fc,0x7ff801c0,
+ 0x707f80,0x7000739c,0x7338701c,0x7ff0701c,0x7fe00ff0,0x1c07038,0xe7073ce,0x1c003e0,0x3800380,0x38001c0,0x0,0x1c,0x381c3800,
+ 0x381c380e,0x380381c,0x383801c0,0xe01de0,0x380739c,0x3838381c,0x381c381c,0x7001e00,0x7003838,0x1c70718e,0x7e01c70,0xf00380,
+ 0x18001e0,0x1e000000,0x1c001bb0,0xff8,0x0,0x1000100,0xe0,0xff00300,0x707e1bb0,0x3801bb0,0x1bb00010,0x8000308,0x30c00000,0x0,
+ 0x0,0x1e0000c0,0xe1ce1bb0,0xf003e0,0x1c0,0x1c203ff8,0x63003e0,0x180181c,0x9801,0xfb00e38,0x7ffc0000,0x8fc10000,0x7ffe,0xe000860,
+ 0x3838,0x1f980380,0x180,0x7c01c70,0x1f001f0,0x1f003c0,0xe380e38,0xe380e38,0xe380e38,0x1cfc7000,0x7ff07ff0,0x7ff07ff0,0x1c001c0,
+ 0x1c001c0,0xfe387338,0x701c701c,0x701c701c,0x701c07e0,0x731c7038,0x70387038,0x703803e0,0x70383980,0x1c001c,0x1c001c,0x1c001c,
+ 0xe73800,0x380e380e,0x380e380e,0x1c001c0,0x1c001c0,0x381c3838,0x381c381c,0x381c381c,0x381c0000,0x387c3838,0x38383838,0x38381c70,
+ 0x381c1c70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0xc30,0x7f00e00,0x33c30000,0x70000e0,0x1007ffe,
+ 0x0,0x380,0x3b9c01c0,0xf00078,0x30e0001c,0x3c1c01c0,0x1c381fdc,0x0,0x70000000,0x1c0380,0x63030e38,0x70707000,0x70387000,0x700070fc,
+ 0x703801c0,0x707b80,0x7000739c,0x7338701c,0x7fc0701c,0x7fc001f0,0x1c07038,0xe703e5c,0x3e001c0,0x7800380,0x38001c0,0x0,0x7fc,
+ 0x381c3800,0x381c380e,0x380381c,0x383801c0,0xe01fe0,0x380739c,0x3838381c,0x381c381c,0x7001fc0,0x7003838,0x1c70718e,0x7c01c70,
+ 0xe01f00,0x180007c,0x7f8c0000,0x7fc03fb8,0x1c0,0x0,0x1000100,0x700,0x1f00600,0x70703fb8,0x7803fb8,0x3fb80000,0x8000000,0x180,
+ 0x0,0x0,0x1fc00060,0xe1ce3fb8,0xe001c0,0x1c0,0x1c203ff8,0xc1801c0,0x180c,0x9801,0x1c70,0xc0000,0x8cc10000,0x180,0xfe007c0,
+ 0x3838,0x7980380,0xff0,0xe38,0x3e003e00,0x3e000380,0xe380e38,0xe380e38,0xe380e38,0x38e07000,0x70007000,0x70007000,0x1c001c0,
+ 0x1c001c0,0x70387338,0x701c701c,0x701c701c,0x701c03c0,0x731c7038,0x70387038,0x703801c0,0x703838e0,0x7fc07fc,0x7fc07fc,0x7fc07fc,
+ 0xe73800,0x380e380e,0x380e380e,0x1c001c0,0x1c001c0,0x381c3838,0x381c381c,0x381c381c,0x381c7ffc,0x38dc3838,0x38383838,0x38381c70,
+ 0x381c1c70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0xc60,0xf83878,0x71e30000,0x70000e0,0x1007ffe,
+ 0x7f0,0x380,0x381c01c0,0x1e0003c,0x60e0001c,0x381c01c0,0x381c079c,0x0,0x7c000000,0x7c0380,0x63031c1c,0x70307000,0x70387000,
+ 0x7000701c,0x703801c0,0x7071c0,0x7000739c,0x71b8701c,0x7000701c,0x71e00078,0x1c07038,0xe703e7c,0x7e001c0,0xf000380,0x38001c0,
+ 0x0,0x1ffc,0x381c3800,0x381c3ffe,0x380381c,0x383801c0,0xe01fc0,0x380739c,0x3838381c,0x381c381c,0x7000ff0,0x7003838,0x1ef03bdc,
+ 0x3800ee0,0x1e01f00,0x180007c,0x61fc0000,0x7fc07f3c,0x1c0,0x0,0x1000100,0x1800,0x780c00,0x70707f3c,0xf007f3c,0x7f3c0000,0x0,
+ 0x3c0,0x3ffcffff,0x0,0xff00030,0xe1fe7f3c,0x1e001c0,0x1c0,0x1c200700,0xc183ffe,0xe0c,0x9801,0x1ff038e0,0xc07f0,0x8c610000,
+ 0x180,0x0,0x3838,0x1980380,0x0,0x1ff0071c,0xe000e000,0xe0000f80,0x1c1c1c1c,0x1c1c1c1c,0x1c1c1e38,0x38e07000,0x70007000,0x70007000,
+ 0x1c001c0,0x1c001c0,0x703871b8,0x701c701c,0x701c701c,0x701c03c0,0x761c7038,0x70387038,0x703801c0,0x70703870,0x1ffc1ffc,0x1ffc1ffc,
+ 0x1ffc1ffc,0xfff3800,0x3ffe3ffe,0x3ffe3ffe,0x1c001c0,0x1c001c0,0x381c3838,0x381c381c,0x381c381c,0x381c7ffc,0x389c3838,0x38383838,
+ 0x38380ee0,0x381c0ee0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0xfffc,0xbc60fc,0x70e30000,0x70000e0,
+ 0x180,0x7f0,0x700,0x381c01c0,0x3e0001c,0x7ffc001c,0x381c03c0,0x381c001c,0x0,0x1f807ffc,0x3f00380,0x63031ffc,0x70387000,0x70387000,
+ 0x7000701c,0x703801c0,0x7071e0,0x7000701c,0x71b8701c,0x7000701c,0x70f00038,0x1c07038,0x7e03e7c,0x77001c0,0xe000380,0x1c001c0,
+ 0x0,0x3c1c,0x381c3800,0x381c3ffe,0x380381c,0x383801c0,0xe01fe0,0x380739c,0x3838381c,0x381c381c,0x70003f8,0x7003838,0xee03bdc,
+ 0x3c00ee0,0x3c00380,0x18000e0,0xf00000,0x1c007e7c,0x3c0,0x0,0x1000100,0x0,0x381800,0x70707e7c,0xe007e7c,0x7e7c0000,0x0,0x7c0,
+ 0x0,0x0,0x3f80018,0xe1fe7e7c,0x3c001c0,0x1c0,0x1c200700,0xc183ffe,0xf0c,0x8c01,0x38e0,0xc07f0,0x8c710000,0x180,0x0,0x3838,
+ 0x1980000,0x0,0x71c,0x7000f0,0x700f00,0x1ffc1ffc,0x1ffc1ffc,0x1ffc1ffc,0x3fe07000,0x70007000,0x70007000,0x1c001c0,0x1c001c0,
+ 0x703871b8,0x701c701c,0x701c701c,0x701c07e0,0x7c1c7038,0x70387038,0x703801c0,0x7ff03838,0x3c1c3c1c,0x3c1c3c1c,0x3c1c3c1c,
+ 0x3fff3800,0x3ffe3ffe,0x3ffe3ffe,0x1c001c0,0x1c001c0,0x381c3838,0x381c381c,0x381c381c,0x381c0000,0x391c3838,0x38383838,0x38380ee0,
+ 0x381c0ee0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfffc,0x9c01ce,0x70f60000,0x70000e0,0x180,
+ 0x0,0x700,0x381c01c0,0x780001c,0x7ffc001c,0x381c0380,0x381c003c,0x0,0x3e07ffc,0xf800380,0x63031ffc,0x70387000,0x70387000,
+ 0x7000701c,0x703801c0,0x7070f0,0x7000701c,0x71b8701c,0x7000701c,0x70700038,0x1c07038,0x7e03e7c,0xf7801c0,0x1e000380,0x1c001c0,
+ 0x0,0x381c,0x381c3800,0x381c3800,0x380381c,0x383801c0,0xe01fe0,0x380739c,0x3838381c,0x381c381c,0x7000078,0x7003838,0xee03a5c,
+ 0x7c00fe0,0x78001c0,0x18001c0,0x0,0x1c003ef8,0x380,0x0,0x1000100,0x810,0x383000,0x70703ef8,0x1e003ef8,0x3ef80000,0x0,0x7c0,
+ 0x0,0x0,0x78000c,0xe1c03ef8,0x78001c0,0x1c0,0x1c200700,0x63001c0,0x18003f8,0x4e12,0x1c70,0xc0000,0x4c320000,0x180,0x0,0x3838,
+ 0x1980000,0x0,0xe38,0x700118,0x701e00,0x1ffc1ffc,0x1ffc1ffc,0x1ffc1ffc,0x7fe07000,0x70007000,0x70007000,0x1c001c0,0x1c001c0,
+ 0x703871b8,0x701c701c,0x701c701c,0x701c0e70,0x7c1c7038,0x70387038,0x703801c0,0x7fc0381c,0x381c381c,0x381c381c,0x381c381c,
+ 0x78e03800,0x38003800,0x38003800,0x1c001c0,0x1c001c0,0x381c3838,0x381c381c,0x381c381c,0x381c0000,0x3b1c3838,0x38383838,0x38380fe0,
+ 0x381c0fe0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1860,0x9c0186,0x707e0000,0x30000c0,0x180,
+ 0x0,0xe00,0x183801c0,0xf00001c,0xe0001c,0x181c0380,0x381c0038,0x0,0xfc0000,0x7e000000,0x61873c1e,0x70383800,0x70707000,0x7000381c,
+ 0x703801c0,0x707070,0x7000701c,0x70f83838,0x70003838,0x70780038,0x1c07038,0x7e03c3c,0xe3801c0,0x1c000380,0xe001c0,0x0,0x381c,
+ 0x381c3800,0x381c3800,0x380381c,0x383801c0,0xe01ef0,0x380739c,0x3838381c,0x381c381c,0x7000038,0x7003838,0xfe03e7c,0xfe007c0,
+ 0x70001c0,0x18001c0,0x0,0xe001ff0,0x380,0x0,0x1000100,0x162c,0x381800,0x30701ff0,0x1c001ff0,0x1ff00000,0x0,0x3c0,0x0,0x0,
+ 0x380018,0xe1c01ff0,0x70001c0,0x1c0,0x1c200700,0xff801c0,0x18000f0,0x63e6,0xe38,0x0,0x6c3e0000,0x0,0x0,0x3838,0x1980000,0x0,
+ 0x1c70,0xf0000c,0xf01c00,0x3c1e3c1e,0x3c1e3c1e,0x3c1e3c1c,0x70e03800,0x70007000,0x70007000,0x1c001c0,0x1c001c0,0x707070f8,
+ 0x38383838,0x38383838,0x38381c38,0x38387038,0x70387038,0x703801c0,0x7000381c,0x381c381c,0x381c381c,0x381c381c,0x70e03800,
+ 0x38003800,0x38003800,0x1c001c0,0x1c001c0,0x381c3838,0x381c381c,0x381c381c,0x381c0380,0x3e1c3838,0x38383838,0x383807c0,0x381c07c0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x18c0,0x9c0186,0x783c0000,0x38001c0,0x180,0x3800000,
+ 0x3800e00,0x1c3801c0,0x1e00003c,0xe00038,0x1c1c0780,0x381c0038,0x3800380,0x3c0000,0x78000000,0x61ff380e,0x70383808,0x70707000,
+ 0x7000381c,0x703801c0,0x40707078,0x7000701c,0x70f83838,0x70003838,0x70384038,0x1c07038,0x7e03c3c,0x1e3c01c0,0x3c000380,0xe001c0,
+ 0x0,0x383c,0x3c381c00,0x1c3c1c00,0x3801c3c,0x383801c0,0xe01c78,0x380739c,0x38381c38,0x3c381c3c,0x7000038,0x7003878,0x7c01e78,
+ 0x1ef007c0,0xf0001c0,0x18001c0,0x0,0xe000ee0,0x7800380,0xe380000,0x1001ff0,0x2242,0x40380c00,0x38700ee0,0x3c000ee0,0xee00000,
+ 0x0,0x0,0x0,0x0,0x380030,0xe1c00ee0,0xf0001c0,0x1c0,0xe200700,0xdd801c0,0x1800038,0x300c,0x71c,0x0,0x300c0000,0x0,0x0,0x3838,
+ 0x1980000,0x0,0x38e0,0xb0000c,0xb01c08,0x380e380e,0x380e380e,0x380e380e,0x70e03808,0x70007000,0x70007000,0x1c001c0,0x1c001c0,
+ 0x707070f8,0x38383838,0x38383838,0x3838381c,0x38387038,0x70387038,0x703801c0,0x7000381c,0x383c383c,0x383c383c,0x383c383c,
+ 0x70e01c00,0x1c001c00,0x1c001c00,0x1c001c0,0x1c001c0,0x1c383838,0x1c381c38,0x1c381c38,0x1c380380,0x1c383878,0x38783878,0x387807c0,
+ 0x3c3807c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x18c0,0x10b801ce,0x3c3e0000,0x38001c0,0x180,
+ 0x3800000,0x3801c00,0x1e7801c0,0x3c002078,0xe02078,0x1c380700,0x1c3810f0,0x3800380,0x40000,0x40000380,0x307b380e,0x70701e18,
+ 0x70e07000,0x70001c1c,0x703801c0,0x60e0703c,0x7000701c,0x70f83c78,0x70003c70,0x703c70f0,0x1c03870,0x3c01c3c,0x3c1c01c0,0x78000380,
+ 0x7001c0,0x0,0x3c7c,0x3c381e18,0x1c7c1e0c,0x3801c3c,0x383801c0,0xe01c38,0x3c0739c,0x38381c38,0x3c381c3c,0x7001078,0x7803c78,
+ 0x7c01c38,0x1c780380,0x1e0001c0,0x18001c0,0x0,0x70c06c0,0x7000380,0xe300000,0x1000100,0x2142,0x70f00600,0x3c7006c0,0x780006c0,
+ 0x6c00000,0x0,0x0,0x0,0x0,0x10780060,0x73e206c0,0x1e0001c0,0x1c0,0x7240700,0x180c01c0,0x1800018,0x1818,0x30c,0x0,0x18180000,
+ 0x0,0x0,0x3c78,0x1980000,0x0,0x30c0,0x130000c,0x1301c18,0x380e380e,0x380e380e,0x380e380e,0x70e01e18,0x70007000,0x70007000,
+ 0x1c001c0,0x1c001c0,0x70e070f8,0x3c783c78,0x3c783c78,0x3c781008,0x7c783870,0x38703870,0x387001c0,0x70003a3c,0x3c7c3c7c,0x3c7c3c7c,
+ 0x3c7c3c7c,0x79f11e18,0x1e0c1e0c,0x1e0c1e0c,0x1c001c0,0x1c001c0,0x1c783838,0x1c381c38,0x1c381c38,0x1c380380,0x1c383c78,0x3c783c78,
+ 0x3c780380,0x3c380380,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x38c0,0x1ff800fc,0x1fee0000,
+ 0x1800180,0x180,0x3800000,0x3801c00,0xff01ffc,0x3ffc3ff0,0xe03ff0,0xff00700,0x1ff81fe0,0x3800380,0x0,0x380,0x3000780f,0x7ff00ff8,
+ 0x7fc07ff8,0x70000ffc,0x70381ffc,0x7fe0701c,0x7ff8701c,0x70781ff0,0x70001ff0,0x701c7ff0,0x1c01fe0,0x3c01c38,0x380e01c0,0x7ffc0380,
+ 0x7001c0,0x0,0x1fdc,0x3ff00ff0,0xffc0ffc,0x3800fdc,0x38383ffe,0xe01c3c,0x1fc739c,0x38380ff0,0x3ff00ffc,0x7001ff0,0x3f81fb8,
+ 0x7c01c38,0x3c3c0380,0x1ffc01c0,0x18001c0,0x0,0x3fc0380,0x7000380,0xc70718c,0x1000100,0x2244,0x7ff00200,0x1fff0380,0x7ffc0380,
+ 0x3800000,0x0,0x0,0x0,0x0,0x1ff000c0,0x7f7e0380,0x1ffc01c0,0x1c0,0x3fc3ffe,0x1c0,0x1800018,0x7e0,0x104,0x0,0x7e00000,0x7ffe,
+ 0x0,0x3fde,0x1980000,0x0,0x2080,0x3300018,0x3300ff0,0x780f780f,0x780f780f,0x780f780e,0xf0fe0ff8,0x7ff87ff8,0x7ff87ff8,0x1ffc1ffc,
+ 0x1ffc1ffc,0x7fc07078,0x1ff01ff0,0x1ff01ff0,0x1ff00000,0x7ff01fe0,0x1fe01fe0,0x1fe001c0,0x70003bf8,0x1fdc1fdc,0x1fdc1fdc,
+ 0x1fdc1fdc,0x3fbf0ff0,0xffc0ffc,0xffc0ffc,0x3ffe3ffe,0x3ffe3ffe,0xff03838,0xff00ff0,0xff00ff0,0xff00000,0x3ff01fb8,0x1fb81fb8,
+ 0x1fb80380,0x3ff00380,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0,0x31c0,0x7e00078,0x7cf0000,0x1800180,
+ 0x0,0x3800000,0x3803800,0x3c01ffc,0x3ffc0fe0,0xe01fc0,0x3e00e00,0x7e00f80,0x3800380,0x0,0x380,0x18007007,0x7fc003f0,0x7f007ff8,
+ 0x700003f0,0x70381ffc,0x3f80701e,0x7ff8701c,0x707807c0,0x700007c0,0x701e1fc0,0x1c00fc0,0x3c01818,0x780f01c0,0x7ffc0380,0x3801c0,
+ 0x0,0xf9c,0x39e003e0,0x79c03f0,0x380079c,0x38383ffe,0xe01c1e,0x7c739c,0x383807e0,0x39e0079c,0x7000fc0,0x1f80f38,0x3801c38,
+ 0x781e0380,0x1ffc01c0,0x18001c0,0x0,0x1f80100,0xe000700,0x1c60718c,0x1000100,0x1e3c,0x1fc00100,0x7ff0100,0x7ffc0100,0x1000000,
+ 0x0,0x0,0x0,0x0,0xfc00080,0x3e3c0100,0x1ffc01c0,0x1c0,0xf83ffe,0x1c0,0x1800838,0x0,0x0,0x0,0x0,0x7ffe,0x0,0x3b9e,0x1980000,
+ 0x0,0x0,0x2300038,0x23003e0,0x70077007,0x70077007,0x70077007,0xe0fe03f0,0x7ff87ff8,0x7ff87ff8,0x1ffc1ffc,0x1ffc1ffc,0x7f007078,
+ 0x7c007c0,0x7c007c0,0x7c00000,0xc7c00fc0,0xfc00fc0,0xfc001c0,0x700039f0,0xf9c0f9c,0xf9c0f9c,0xf9c0f9c,0x1f1e03e0,0x3f003f0,
+ 0x3f003f0,0x3ffe3ffe,0x3ffe3ffe,0x7e03838,0x7e007e0,0x7e007e0,0x7e00000,0x63e00f38,0xf380f38,0xf380380,0x39e00380,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x800000,0x0,0xc00300,0x0,0x3000000,0x3800,0x0,0x0,0x0,0x0,
+ 0x0,0x300,0x0,0x0,0x1c000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe0,0x0,0x0,0x0,0x0,0x380,0x3801c0,0x0,0x0,0x0,0x0,0x1c,0x0,0xe00000,
+ 0x0,0x0,0x3800001c,0x0,0x0,0x0,0x700,0x1c0,0x18001c0,0x0,0x0,0xe000700,0x18600000,0x1000100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x200000,0x0,0x1800ff0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x1980000,0x1800000,0x0,0x6300070,0x6300000,0x0,
+ 0x0,0x0,0xc0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x40000000,
+ 0x0,0x700,0x38000700,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x800000,0x0,0xc00300,0x0,0x7000000,
+ 0x7000,0x0,0x0,0x0,0x0,0x0,0x700,0x0,0x0,0xf040000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x78,0x0,0x0,0x0,0x0,0x3f0,0x1c0fc0,0x0,0x0,
+ 0x0,0x0,0x1c,0x0,0xe00000,0x0,0x0,0x3800001c,0x0,0x0,0x0,0x700,0x1e0,0x18003c0,0x0,0x0,0xc000700,0x18c00000,0x1000000,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x200000,0x0,0x18007e0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x1980000,0xc00000,
+ 0x0,0x7f800e0,0x7f80000,0x0,0x0,0x0,0x60,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x60,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x700,0x38000700,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x800000,
+ 0x0,0x600600,0x0,0x6000000,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x7fc0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30,0x0,0x0,0x0,0x0,
+ 0x3f0,0xfc0,0x0,0x0,0x0,0x0,0x838,0x0,0x1e00000,0x0,0x0,0x3800001c,0x0,0x0,0x0,0xf00,0xfc,0x1801f80,0x0,0x0,0x8008e00,0x30c00000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x200000,0x0,0x1800000,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x1980000,0xc00000,
+ 0x0,0x3001c0,0x300000,0x0,0x0,0x0,0x60,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x60,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0xf00,0x38000f00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x800000,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfc0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0xff0,0x0,0x1fc00000,0x0,0x0,0x3800001c,0x0,0x0,0x0,0x3e00,0x7c,0x1801f00,0x0,0x0,0x800fe00,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x200000,0x0,0x1800000,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x0,0x7c00000,0x0,0x3001fc,0x300000,
+ 0x0,0x0,0x0,0x3e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x3e00,0x38003e00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfff8,0x0,0x0,0x0,0x7e0,0x0,0x1f000000,
+ 0x0,0x0,0x3800001c,0x0,0x0,0x0,0x3c00,0x0,0x1800000,0x0,0x0,0x7800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x0,0x7800000,0x0,0x0,0x0,0x0,0x0,0x0,0x3c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00,0x38003c00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfff8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1800000,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0 };
+
+ // Definition of a 19x38 font
+ const unsigned int font19x38[19*38*256/32] = {
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c380000,0x0,0x1c380,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800007,0x3c003,0x86000000,
+ 0x1e00000,0x3,0x80000700,0x3c00000,0x380000,0x70003c00,0x0,0xe1800e,0x1c00,0xf000e18,0x0,0x0,0x700000e0,0x780000,0x7000,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe700000,0x0,0xe700,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x38e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c0000e,0x7e003,0xe60071c0,0x7f80000,0x1,0xc0000e00,0x7e0038e,0x1c0000,
+ 0xe0007e00,0x38e00000,0xf98007,0x3800,0x1f800f98,0x1c70000,0x0,0x380001c0,0xfc0071,0xc000e000,0x0,0x0,0x0,0x0,0x3e00000,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x7e00000,0x0,0x7e00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x38e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe0001c,0xe7006,0x7c0071c0,0xe180000,0x0,0xe0001c00,0xe70038e,0xe0001,0xc000e700,0x38e00000,
+ 0x19f0003,0x80007000,0x39c019f0,0x1c70000,0x0,0x1c000380,0x1ce0071,0xc001c000,0x0,0x0,0x0,0x0,0x7f00000,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,
+ 0x0,0x3c00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x38e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x700038,0x1c3806,0x3c0071c0,0xc0c0000,0x0,0x70003800,0x1c38038e,0x70003,0x8001c380,0x38e00000,0x18f0001,0xc000e000,
+ 0x70e018f0,0x1c70000,0x0,0xe000700,0x3870071,0xc0038000,0x0,0x0,0x0,0x0,0xe380000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0xe000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x60000000,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c38,0x0,0x1,0xc3800000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c00000,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0xc0c0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe000003,0x80018000,0x0,0xc180000,
+ 0xe,0x380,0x1800000,0xe00000,0x38001800,0x0,0x38,0xe00,0x6000000,0x0,0x1,0xc0000070,0x300000,0x3800,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7000000,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x78c00,0xc30,
+ 0x0,0x0,0xc3000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800000,0x0,0x0,0x0,0xe0,0x1c000f,0xc0000000,0x0,0x0,
+ 0x0,0xc0c0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7000007,0x3c003,0xc6000000,0xc180000,0x7,0x700,
+ 0x3c00000,0x700000,0x70003c00,0x0,0xf1801c,0x1c00,0xf000f18,0x0,0x0,0xe00000e0,0x780000,0x7000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x1c007000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfe0000,0xfe000,0x0,0x3800000,0x700000,0x38,
+ 0x7,0xe000001c,0x1c00,0x1c00700,0x7fc0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf800e,0x3e0000,0x0,0x0,0x0,0x1e00000,0x0,0x1,
+ 0xf8000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7cc00,0x660,0x0,0x0,0x66000000,0x0,0x0,0x0,0x0,0x7,0x1c000000,0x0,0x0,0x0,0x3fe00000,
+ 0x0,0x0,0x7000000,0x0,0x0,0x0,0x3e0,0x7c001f,0xe0000000,0x0,0x0,0x0,0xe1c0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x1f80,0x380000e,0x7e007,0xe60071c0,0xc180000,0x3,0x80000e00,0x7e0038e,0x380000,0xe0007e00,0x38e00f00,0x1f9800e,
+ 0x3800,0x1f801f98,0x1c70000,0x0,0x700001c0,0xfc0071,0xc000e007,0x38e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x1c7000,0x61c00600,0x1e00007e,0x70000,0x18003000,0x1800000,0x0,0x0,0x1c01f0,0x7e003f,0xc003f800,
+ 0x1e03ffc,0x7f01ff,0xfc03f000,0x7e000000,0x0,0x0,0xfc0,0x1e,0x7fe000,0x7e03fe00,0x3fff07ff,0xe007e038,0x383ffe0,0xff81c01,
+ 0xe1c000f8,0xf8f00e0,0xfc01ffc,0x3f00ff,0xc000fe07,0xfffc7007,0x1c007700,0x73c01ef,0x78ffff,0xfe0380,0xfe000,0x38000000,0x1800000,
+ 0x700000,0x38,0x1f,0xe000001c,0x1c00,0x1c00700,0x7fc0000,0x0,0x0,0x0,0x0,0x1c000000,0x0,0x0,0x0,0x3f800e,0x3f8000,0x0,0xfc0000,
+ 0x0,0x7f00000,0x0,0x1,0x98000000,0x7f00000,0x3ffe00,0xffff0,0x0,0x0,0x0,0x0,0x0,0xcf81f,0xee3807e0,0x0,0x0,0x7e03c01e,0x1c,
+ 0x0,0x1f800000,0xf0078038,0xfc007,0x1c000000,0xfe00000,0x0,0x0,0x3fe000f0,0xf,0xc001f800,0x6000000,0xffc000,0x0,0x1c0007e0,
+ 0x360,0x6c0010,0x70000700,0xf0001e,0x3c000,0x78000f00,0x7f800ff,0xf007e01f,0xff83fff0,0x7ffe0fff,0xc1fff03f,0xfe07ffc0,0xfff83fc0,
+ 0x7807007,0xe000fc00,0x1f8003f0,0x7e0000,0x1f867,0x70e00e,0x1c01c380,0x38f00787,0x3fe0,0x180000c,0x66006,0x7c0071c0,0xe380000,
+ 0x1,0x80000c00,0x660038e,0x180000,0xc0006600,0x38e0078e,0x19f0006,0x3000,0x198019f0,0x1c70000,0x0,0x30000180,0xcc0071,0xc000c007,
+ 0x38e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x1c7000,0x61800600,0x7f8001ff,0x70000,
+ 0x38003800,0x1800000,0x0,0x0,0x3807fc,0x1fe00ff,0xf00ffe00,0x3e03ffc,0xff81ff,0xfc07fc01,0xff800000,0x0,0x0,0x3fe0,0xfe001e,
+ 0x7ff801,0xff83ff80,0x3fff07ff,0xe01ff838,0x383ffe0,0xff81c03,0xc1c000f8,0xf8f80e0,0x3ff01fff,0xffc0ff,0xf003ff87,0xfffc7007,
+ 0x1e00f700,0x71c03c7,0x70ffff,0xfe01c0,0xfe000,0x7c000000,0xc00000,0x700000,0x38,0x3f,0xe000001c,0x1c00,0x1c00700,0x7fc0000,
+ 0x0,0x0,0x0,0x0,0x1c000000,0x0,0x0,0x0,0x3f800e,0x3f8000,0x0,0x3fe0000,0x0,0xff00000,0x0,0x3,0xc000000,0x1ffc0000,0xfffe00,
+ 0xffff0,0x0,0x0,0x0,0x0,0x0,0xc781f,0xee3803c0,0x0,0x0,0x3c01c01c,0x1c,0xc000,0x7fc00000,0x70070038,0x3fe007,0x1c000000,0x1ff80000,
+ 0x0,0x0,0x3fe003fc,0x1f,0xe003fc00,0xc000000,0x3ffc000,0x0,0x7c000ff0,0x60,0xc0000,0x30000700,0xf0001e,0x3c000,0x78000f00,
+ 0x3f000ff,0xf01ff81f,0xff83fff0,0x7ffe0fff,0xc1fff03f,0xfe07ffc0,0xfff83ff8,0x7c0701f,0xf803ff00,0x7fe00ffc,0x1ff8000,0x7fe67,
+ 0x70e00e,0x1c01c380,0x38700707,0x7ff0,0xc00018,0xc3006,0x3c0071c0,0x7f00000,0x0,0xc0001800,0xc30038e,0xc0001,0x8000c300,0x38e003fc,
+ 0x18f0003,0x6000,0x30c018f0,0x1c70000,0x0,0x18000300,0x1860071,0xc0018007,0x38e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x1c7000,0xe1801fc0,0x618001ff,0x70000,0x30001800,0x21840000,0x0,0x0,0x380ffe,0x1fe00ff,
+ 0xfc0fff00,0x3e03ffc,0x1ff81ff,0xfc0ffe03,0xffc00000,0x0,0x0,0x7ff0,0x3ff803f,0x7ffc03,0xffc3ffc0,0x3fff07ff,0xe03ffc38,0x383ffe0,
+ 0xff81c07,0x81c000f8,0xf8f80e0,0x7ff81fff,0x81ffe0ff,0xf80fff87,0xfffc7007,0xe00e700,0x70e0387,0x80f0ffff,0xe001c0,0xe000,
+ 0xfe000000,0xe00000,0x700000,0x38,0x3c,0x1c,0x1c00,0x1c00700,0x1c0000,0x0,0x0,0x0,0x0,0x1c000000,0x0,0x0,0x0,0x78000e,0x3c000,
+ 0x0,0x7ff0000,0x0,0xf100000,0x0,0x7,0xe000000,0x7ffc0000,0x1fffe00,0xffff0,0x0,0x0,0x0,0x0,0x0,0x3,0xf780180,0x0,0x0,0x1801e03c,
+ 0x1c,0xc000,0xffc00000,0x780f0038,0x786000,0x7f00,0x18380000,0x0,0xfe00,0x30c,0x10,0x70020e00,0x1c000000,0x7f8c000,0x0,0x6c001c38,
+ 0x60,0xc0000,0x70000700,0x1f8003f,0x7e000,0xfc001f80,0x3f000ff,0xf03ffc1f,0xff83fff0,0x7ffe0fff,0xc1fff03f,0xfe07ffc0,0xfff83ffc,
+ 0x7c0703f,0xfc07ff80,0xfff01ffe,0x3ffc000,0xffec7,0x70e00e,0x1c01c380,0x38780f07,0xf070,0xe00038,0x1c3800,0x0,0x3e00000,0x0,
+ 0xe0003800,0x1c380000,0xe0003,0x8001c380,0x3e0,0x3,0x8000e000,0x70e00000,0x0,0x0,0x1c000700,0x3870000,0x38007,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x1c7000,0xe3807ff0,0xc0c003c1,0x70000,0x70001c00,
+ 0x718e0000,0x0,0x0,0x700f1e,0x1ce00c0,0x3c0c0f80,0x7e03800,0x3e08000,0x381e0f03,0xc1e00000,0x0,0x0,0x7078,0x783c03f,0x701e07,
+ 0xc1c383e0,0x38000700,0x7c1c38,0x3801c00,0x381c0f,0x1c000fc,0x1f8f80e0,0x78781c07,0x81e1e0e0,0x780f0180,0xe007007,0xe00e380,
+ 0xe0f0783,0x80e0000e,0xe000e0,0xe001,0xef000000,0x0,0x700000,0x38,0x38,0x1c,0x0,0x700,0x1c0000,0x0,0x0,0x0,0x0,0x1c000000,
+ 0x0,0x0,0x0,0x70000e,0x1c000,0x0,0xf830000,0x0,0x1e000000,0x0,0x0,0x10000,0x780c0000,0x3e38000,0xe0,0x0,0x0,0x0,0x0,0x0,0x3,
+ 0xd580000,0x0,0x0,0xe038,0x1c,0xc000,0xf0400000,0x380e0038,0x702000,0x1ffc0,0xc0000,0x0,0x3ff80,0x606,0x0,0x30000600,0x0,
+ 0x7f8c000,0x0,0xc001818,0x60,0xc0003,0xe0000700,0x1f8003f,0x7e000,0xfc001f80,0x73801ee,0x7c1c1c,0x38000,0x70000e00,0xe0001,
+ 0xc0003800,0x700383e,0x7c0703c,0x3c078780,0xf0f01e1e,0x3c3c000,0xf0f87,0x70e00e,0x1c01c380,0x38380e07,0xe038,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0xff0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x1c,0x1c7000,0xc380fff0,0xc0c00380,0x70000,0x70001c00,0x3dbc0070,0x0,0x0,0x701e0f,0xe0000,0x1e000380,
+ 0x6e03800,0x7800000,0x781c0707,0x80e00000,0x0,0x0,0x4038,0xe00c03f,0x700e07,0x4380f0,0x38000700,0x700438,0x3801c00,0x381c0e,
+ 0x1c000ec,0x1b8fc0e0,0xf03c1c03,0xc3c0f0e0,0x3c1e0000,0xe007007,0xe00e380,0xe070703,0xc1e0001e,0xe000e0,0xe001,0xc7000000,
+ 0x0,0x700000,0x38,0x38,0x1c,0x0,0x700,0x1c0000,0x0,0x0,0x0,0x0,0x1c000000,0x0,0x0,0x0,0x70000e,0x1c000,0x0,0xe010000,0x0,
+ 0x1c000000,0x10,0x20000,0x6c000,0xf0000000,0x3838000,0x1e0,0x0,0xf000f,0xf1e00,0x78f00000,0x0,0x3,0xdd80000,0x0,0x0,0xf078,
+ 0x0,0xc001,0xe0000000,0x1c1c0038,0x700000,0x3c1e0,0xc0000,0x0,0x783c0,0x606,0x0,0x30000e00,0x0,0xff8c000,0x0,0xc00300c,0x60,
+ 0xc0003,0xe0000000,0x1f8003f,0x7e000,0xfc001f80,0x73801ce,0x70041c,0x38000,0x70000e00,0xe0001,0xc0003800,0x700380f,0x7e07078,
+ 0x1e0f03c1,0xe0783c0f,0x781e000,0x1c0787,0x70e00e,0x1c01c380,0x383c1e07,0xff00e038,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x878,
+ 0x0,0x0,0x0,0x7,0x80000080,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,
+ 0x1c7000,0xc301e630,0xc0c00380,0x70000,0xe0000e00,0xff00070,0x0,0x0,0xe01c07,0xe0000,0xe000380,0xce03800,0x7000000,0x701c0707,
+ 0x600000,0x0,0x4000010,0x38,0x1c00e07f,0x80700e0e,0x38070,0x38000700,0xe00038,0x3801c00,0x381c1c,0x1c000ec,0x1b8ec0e0,0xe01c1c01,
+ 0xc38070e0,0x1c1c0000,0xe007007,0x701c380,0xe078e01,0xc1c0003c,0xe00070,0xe003,0x83800000,0x7f,0x71f000,0x3e003e38,0x3f007ff,
+ 0xe01f1c1c,0x7801fc00,0x3fc00701,0xe01c0077,0x8f071e00,0xf801c7c,0x7c700e,0x3e01fc03,0xfff8380e,0xe007700,0x73c0787,0x387ffc,
+ 0x70000e,0x1c000,0x0,0xe000000,0x0,0x1c000000,0x10,0x20000,0xc2000,0xe0000000,0x3838000,0x3c0,0x0,0xf000f,0x78e00,0x70e00000,
+ 0x0,0x3,0xc980fe0,0x1f0,0xf8000007,0xffc07070,0x0,0x3f801,0xc0000000,0x1e3c0038,0x700000,0x70070,0x7fc0000,0x0,0xe00e0,0x606,
+ 0x1c0000,0x70007c00,0x380e,0xff8c000,0x0,0xc00300c,0x60,0xc0000,0x70000000,0x3fc007f,0x800ff001,0xfe003fc0,0x73801ce,0xe0001c,
+ 0x38000,0x70000e00,0xe0001,0xc0003800,0x7003807,0x7607070,0xe0e01c1,0xc0383807,0x700e000,0x1c0387,0x70e00e,0x1c01c380,0x381c1c07,
+ 0xffc0e0f8,0x3f8007f,0xfe001,0xfc003f80,0x7f007e3,0xe003e001,0xf8003f00,0x7e000fc,0xfe001f,0xc003f800,0x7f00003c,0x38f0007,
+ 0xc000f800,0x1f0003e0,0x7c0007,0x8003f0c3,0x80e0701c,0xe0381c0,0x70700387,0x1f01c00e,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x1c701f,0xfff1c600,0xc0c00380,0x70000,0xe0000e00,0x3c00070,0x0,0x0,0xe03c07,
+ 0x800e0000,0xe000380,0x1ce03800,0x7000000,0x701c0707,0x7003c0,0x780000,0x3c00001e,0x38,0x18006073,0x80700e0e,0x38070,0x38000700,
+ 0xe00038,0x3801c00,0x381c38,0x1c000ee,0x3b8ee0e1,0xe01e1c01,0xc78078e0,0x1c1c0000,0xe007007,0x701c387,0xe03de00,0xe3800038,
+ 0xe00070,0xe007,0x1c00000,0x1ff,0xc077f801,0xff807fb8,0xff807ff,0xe03fdc1d,0xfc01fc00,0x3fc00703,0xc01c007f,0xdf877f00,0x3fe01dfe,
+ 0xff700e,0xff07ff03,0xfff8380e,0x700f700,0x71e0f03,0x80707ffc,0x70000e,0x1c000,0x0,0x1c000008,0x0,0x1c000000,0x10,0x20000,
+ 0x82000,0xe0000000,0x7038000,0x80000380,0x2000040,0x7000e,0x38700,0xf1e00000,0x0,0x3,0xc183ff8,0x3fd,0xfc008007,0xffc038e0,
+ 0x0,0xffc01,0xc0008008,0xe380038,0x380000,0xe3e38,0x1ffc0040,0x80000000,0x1cfc70,0x606,0x1c0000,0xe0007c00,0x380e,0xff8c000,
+ 0x0,0xc00300c,0x8100060,0xc0000,0x30000700,0x39c0073,0x800e7001,0xce0039c0,0x73801ce,0xe0001c,0x38000,0x70000e00,0xe0001,
+ 0xc0003800,0x7003807,0x77070f0,0xf1e01e3,0xc03c7807,0x8f00f080,0x83c0787,0x70e00e,0x1c01c380,0x380e3807,0xffe0e1c0,0xffe01ff,
+ 0xc03ff807,0xff00ffe0,0x1ffc0ff7,0xf01ff807,0xfc00ff80,0x1ff003fe,0xfe001f,0xc003f800,0x7f0003fc,0x3bf801f,0xf003fe00,0x7fc00ff8,
+ 0x1ff0007,0x8007fd83,0x80e0701c,0xe0381c0,0x70380707,0x7f80e01c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x1c,0x1c701f,0xfff1c600,0x618081c0,0x70000,0xe0000e00,0x3c00070,0x0,0x0,0xe03803,0x800e0000,0xe000380,0x18e03800,
+ 0xf000000,0xf01c0707,0x7003c0,0x780000,0xfc00001f,0x80000078,0x301e6073,0x80700e1c,0x38038,0x38000700,0x1c00038,0x3801c00,
+ 0x381c70,0x1c000e6,0x338ee0e1,0xc00e1c01,0xc70038e0,0x1c1c0000,0xe007007,0x701c387,0xe01dc00,0xf7800078,0xe00070,0xe00e,0xe00000,
+ 0x3ff,0xe07ffc03,0xffc0fff8,0x1ffc07ff,0xe07ffc1d,0xfe01fc00,0x3fc00707,0x801c007f,0xdf877f80,0x7ff01fff,0x1fff00e,0xff07ff03,
+ 0xfff8380e,0x700e380,0xe0e0e03,0x80707ffc,0x70000e,0x1c000,0x0,0x7ffc001c,0x0,0x1c000000,0x10,0x20000,0x82000,0xe0000000,
+ 0x7038001,0xc0000780,0x70000e0,0x3800e,0x38700,0xe1c00000,0x0,0x3,0xc183ff8,0x7ff,0xfc01c007,0xffc03de0,0x0,0x1ffc01,0xc001c01c,
+ 0xf780038,0x3c0000,0xcff18,0x380c00c1,0x80000000,0x18fe30,0x30c,0x1c0001,0xc0000e00,0x380e,0xff8c000,0x0,0xc00300c,0xc180060,
+ 0xc0000,0x30000700,0x39c0073,0x800e7001,0xce0039c0,0xe1c038e,0x1c0001c,0x38000,0x70000e00,0xe0001,0xc0003800,0x7003803,0x877070e0,
+ 0x71c00e3,0x801c7003,0x8e0071c0,0x1c380fc7,0x70e00e,0x1c01c380,0x380f7807,0x1e0e380,0x1fff03ff,0xe07ffc0f,0xff81fff0,0x3ffe0fff,
+ 0xf03ffc0f,0xfe01ffc0,0x3ff807ff,0xfe001f,0xc003f800,0x7f0007fe,0x3bfc03f,0xf807ff00,0xffe01ffc,0x3ff8007,0x800fff83,0x80e0701c,
+ 0xe0381c0,0x70380707,0xffc0e01c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x1c701f,
+ 0xfff1c600,0x7f8381e0,0x70000,0xc0000600,0xff00070,0x0,0x0,0x1c03803,0x800e0000,0xe000f00,0x38e03fe0,0xe000000,0xe00e0e07,
+ 0x7003c0,0x780007,0xf0ffff87,0xf00000f0,0x307fe0f3,0xc0703c1c,0x38038,0x38000700,0x1c00038,0x3801c00,0x381ce0,0x1c000e6,0x338e70e1,
+ 0xc00e1c01,0xc70038e0,0x3c1e0000,0xe007007,0x783c38f,0x8e01fc00,0x770000f0,0xe00038,0xe01c,0x700000,0x381,0xe07c1e07,0xc0c1e0f8,
+ 0x3c1e0038,0xf07c1f,0xe001c00,0x1c0070f,0x1c0079,0xf3c7c380,0xf0781f07,0x83c1f00f,0xc10f0300,0x1c00380e,0x700e380,0xe0f1e03,
+ 0xc0f00078,0x70000e,0x1c000,0x0,0xfff8003e,0x0,0x3c000000,0x10,0x20000,0xc6000,0xf0000000,0x7038003,0xe0000f00,0xf8001f0,
+ 0x3801c,0x18300,0xe1800000,0x0,0x3,0xc187818,0x70f,0x9e03e000,0x7801dc0,0x1c,0x3cc401,0xc000efb8,0x7f7f0038,0x3f0000,0x1ce11c,
+ 0x300c01c3,0x80000000,0x38c638,0x3fc,0x1c0003,0x80000600,0x380e,0xff8c000,0x0,0xc00300c,0xe1c0060,0xc0010,0x70000700,0x79e00f3,
+ 0xc01e7803,0xcf0079e0,0xe1c038e,0x1c0001c,0x38000,0x70000e00,0xe0001,0xc0003800,0x7003803,0x873870e0,0x71c00e3,0x801c7003,
+ 0x8e0070e0,0x38381dc7,0x70e00e,0x1c01c380,0x38077007,0xf0e700,0x1c0f0381,0xe0703c0e,0x781c0f0,0x381e083e,0x787c0c1e,0xf03c1e0,
+ 0x783c0f07,0x800e0001,0xc0003800,0x7000fff,0x3e1c078,0x3c0f0781,0xe0f03c1e,0x783c000,0x1e0f03,0x80e0701c,0xe0381c0,0x70380f07,
+ 0xc1e0e03c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x1,0x8701c600,0x1e0f01e0,0x1,
+ 0xc0000700,0x3dbc0070,0x0,0x0,0x1c03803,0x800e0000,0x1e01fe00,0x70e03ff8,0xe3e0001,0xe007fc07,0x80f003c0,0x78001f,0xc0ffff81,
+ 0xfc0001e0,0x30e1e0e1,0xc07ff81c,0x38038,0x3ffe07ff,0xc1c0003f,0xff801c00,0x381de0,0x1c000e7,0x738e70e1,0xc00e1c03,0xc70038e0,
+ 0x780f8000,0xe007007,0x383838d,0x8e00f800,0x7f0000e0,0xe00038,0xe000,0x0,0x200,0xf0780e07,0x8041c078,0x380e0038,0xe03c1e,
+ 0xf001c00,0x1c0071e,0x1c0070,0xe1c783c0,0xe0381e03,0x8380f00f,0xe0000,0x1c00380e,0x381c380,0xe07bc01,0xc0e00078,0x70000e,
+ 0x1c000,0x0,0x1c000061,0x0,0x38000000,0x10,0x20000,0x7c000,0x7c000000,0x703fc06,0x10000e00,0x18400308,0x1801c,0x1c381,0xc3800000,
+ 0x0,0x0,0x7000,0xe0f,0xe061000,0x7801fc0,0x1c,0x38c001,0xc0007ff0,0x7fff0038,0x77c000,0x19c00c,0x301c0387,0x0,0x30c618,0xf0,
+ 0x1c0007,0x600,0x380e,0x7f8c007,0x80000000,0xc001818,0x70e03fc,0x387f871f,0xe0e00700,0x70e00e1,0xc01c3803,0x870070e0,0xe1c038f,
+ 0xe1c0001f,0xff03ffe0,0x7ffc0fff,0x800e0001,0xc0003800,0x7003803,0x873870e0,0x71c00e3,0x801c7003,0x8e007070,0x703839c7,0x70e00e,
+ 0x1c01c380,0x3807f007,0x70e700,0x10078200,0xf0401e08,0x3c10078,0x200f001c,0x3878041c,0x70380e0,0x701c0e03,0x800e0001,0xc0003800,
+ 0x7001e0f,0x3c1e070,0x1c0e0381,0xc070380e,0x701c000,0x1c0f03,0x80e0701c,0xe0381c0,0x701c0e07,0x80e07038,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x3,0x8600e600,0x7803f0,0x1,0xc0000700,0x718e0070,0x0,0x0,0x38038c3,
+ 0x800e0000,0x3c01f800,0x60e03ffc,0xeff8001,0xc001f003,0xc1f003c0,0x7800fe,0xffff80,0x3f8003c0,0x60c0e0e1,0xc07fe01c,0x38038,
+ 0x3ffe07ff,0xc1c07e3f,0xff801c00,0x381fe0,0x1c000e3,0x638e30e1,0xc00e1c07,0x870038ff,0xf00ff800,0xe007007,0x38381cd,0x9c007000,
+ 0x3e0001e0,0xe0001c,0xe000,0x0,0x0,0x70780f0f,0x3c078,0x70070038,0x1e03c1c,0x7001c00,0x1c0073c,0x1c0070,0xe1c701c1,0xe03c1e03,
+ 0xc780f00f,0xe0000,0x1c00380e,0x381c387,0xe03f801,0xc0e000f0,0x70000e,0x1c007,0xe0100000,0x1c0000cd,0x80000003,0xffc00000,
+ 0x3ff,0x807ff000,0xe0,0x7fc00060,0x703fc0c,0xd8001e00,0x3360066c,0x1c018,0xc181,0x83000000,0x0,0x0,0x7000,0x300e07,0xe0cd800,
+ 0xf000f80,0x1c,0x78c00f,0xff0038e0,0x3e00038,0xe1e000,0x19800c,0x383c070e,0x7fffc00,0x30fc18,0x0,0xffff80e,0x20e00,0x380e,
+ 0x7f8c007,0x80000000,0xc001c38,0x38703ff,0xf87fff0f,0xcfe00f00,0x70e00e1,0xc01c3803,0x870070e0,0x1e1e078f,0xe1c0001f,0xff03ffe0,
+ 0x7ffc0fff,0x800e0001,0xc0003800,0x700ff83,0x871870e0,0x71c00e3,0x801c7003,0x8e007038,0xe03871c7,0x70e00e,0x1c01c380,0x3803e007,
+ 0x70e700,0x38000,0x70000e00,0x1c00038,0x7001c,0x38f00038,0x3870070,0xe00e1c01,0xc00e0001,0xc0003800,0x7001c07,0x380e0f0,0x1e1e03c3,
+ 0xc078780f,0xf01e000,0x3c0f03,0x80e0701c,0xe0381c0,0x701c0e07,0x80f07038,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x3,0x8600ff00,0x1e00778,0x38000001,0xc0000700,0x21843fff,0xe0000000,0x0,0x38039e3,0x800e0000,
+ 0x7c01fe00,0xe0e0203e,0xeffc001,0xc00ffe03,0xff700000,0x7f0,0x0,0x7f00380,0x618060e1,0xc07ffc1c,0x38038,0x3ffe07ff,0xc1c07e3f,
+ 0xff801c00,0x381ff0,0x1c000e3,0x638e38e1,0xc00e1fff,0x870038ff,0xc003fe00,0xe007007,0x38381cd,0x9c00f800,0x3e0003c0,0xe0001c,
+ 0xe000,0x0,0x0,0x7070070e,0x38038,0x70070038,0x1c01c1c,0x7001c00,0x1c00778,0x1c0070,0xe1c701c1,0xc01c1c01,0xc700700e,0xfc000,
+ 0x1c00380e,0x381c3c7,0x1e01f001,0xe1e001e0,0xf0000e,0x1e01f,0xf8300000,0x1c00019c,0xc0000003,0xffc00000,0x10,0x20000,0x700,
+ 0x1ff000c0,0x703fc19,0xcc003c00,0x67300ce6,0xc038,0xc181,0x83000000,0x0,0x0,0x7e00,0x180e07,0xe19cc00,0x1e000f80,0x1c,0x70c00f,
+ 0xff007070,0x3e00038,0xe0f000,0x19800c,0x1fec0e1c,0x7fffc00,0x30f818,0x0,0xffff81f,0xf003fc00,0x380e,0x3f8c007,0x80000000,
+ 0x7f800ff0,0x1c3803f,0xe007fc00,0xff800e00,0x70e00e1,0xc01c3803,0x870070e0,0x1c0e070f,0xe1c0001f,0xff03ffe0,0x7ffc0fff,0x800e0001,
+ 0xc0003800,0x700ff83,0x871c70e0,0x71c00e3,0x801c7003,0x8e00701d,0xc038e1c7,0x70e00e,0x1c01c380,0x3803e007,0x70e3c0,0x38000,
+ 0x70000e00,0x1c00038,0x7001c,0x38e00038,0x3870070,0xe00e1c01,0xc00e0001,0xc0003800,0x7003c07,0x8380e0e0,0xe1c01c3,0x80387007,
+ 0xe00e1ff,0xfe381b83,0x80e0701c,0xe0381c0,0x701e1e07,0x707878,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x1c,0x3,0xe007fe0,0x7800e3c,0x38000001,0xc0000700,0x1803fff,0xe0000000,0x0,0x70039c3,0x800e0000,0xf8000f80,
+ 0xc0e0000e,0xf83c003,0xc01e0f01,0xff700000,0x7c0,0x0,0x1f00780,0x618061c0,0xe0701e1c,0x38038,0x38000700,0x1c07e38,0x3801c00,
+ 0x381e78,0x1c000e3,0xe38e18e1,0xc00e1fff,0x70038ff,0xe0007f80,0xe007007,0x1c701dd,0x9c00f800,0x1c000780,0xe0000e,0xe000,0x0,
+ 0x7f,0xf070070e,0x38038,0x7fff0038,0x1c01c1c,0x7001c00,0x1c007f8,0x1c0070,0xe1c701c1,0xc01c1c01,0xc700700e,0x7fc00,0x1c00380e,
+ 0x1c381c7,0x1c01f000,0xe1c001c0,0xfe0000e,0xfe1f,0xfff00000,0x7ff003fc,0xe0000003,0xffc00000,0x10,0x20000,0x3800,0x3fc0180,
+ 0x703803f,0xce007800,0xff381fe7,0x30,0x0,0xc0,0x0,0x0,0x3fe0,0xc0e07,0xfe3fce00,0x1c000700,0x1c,0x70c00f,0xff006030,0x1c00000,
+ 0xe07800,0x19800c,0xfcc1c38,0x7fffc00,0x30d818,0x0,0xffff81f,0xf001f800,0x380e,0xf8c007,0x80000000,0x7f8007e0,0xe1c3fe,0x7fc00f,
+ 0xf8001e00,0xe0701c0,0xe0381c07,0x380e070,0x1c0e070e,0x1c0001c,0x38000,0x70000e00,0xe0001,0xc0003800,0x700ff83,0x870c70e0,
+ 0x71c00e3,0x801c7003,0x8e00700f,0x8038c1c7,0x70e00e,0x1c01c380,0x3801c007,0xf0e3e0,0x3ff807f,0xf00ffe01,0xffc03ff8,0x7ff03ff,
+ 0xf8e0003f,0xff87fff0,0xfffe1fff,0xc00e0001,0xc0003800,0x7003803,0x8380e0e0,0xe1c01c3,0x80387007,0xe00e1ff,0xfe383383,0x80e0701c,
+ 0xe0381c0,0x700e1c07,0x703870,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x3,0xc000ff0,
+ 0x3c1e1c1c,0x38000001,0xc0000700,0x1803fff,0xe0000007,0xf8000000,0x7003803,0x800e0001,0xf0000381,0xc0e00007,0xf01e003,0x801c0700,
+ 0x7c700000,0x7c0,0x0,0x1f00700,0x618061c0,0xe0700e1c,0x38038,0x38000700,0x1c00e38,0x3801c00,0x381e38,0x1c000e1,0xc38e1ce1,
+ 0xc00e1ffc,0x70038e0,0xf0000780,0xe007007,0x1c701dd,0xdc01fc00,0x1c000780,0xe0000e,0xe000,0x0,0x1ff,0xf070070e,0x38038,0x7fff0038,
+ 0x1c01c1c,0x7001c00,0x1c007f8,0x1c0070,0xe1c701c1,0xc01c1c01,0xc700700e,0x3ff00,0x1c00380e,0x1c381cd,0x9c00e000,0xe1c003c0,
+ 0xf80000e,0x3e18,0x3ff00000,0xffe007fd,0xf0000000,0x38000000,0x10,0x20000,0x1c000,0x3c0300,0x703807f,0xdf007801,0xff7c3fef,
+ 0x80000000,0x0,0x3e0,0x7ffe7ff,0xff000000,0x1ff8,0x60e07,0xfe7fdf00,0x3c000700,0x1c,0x70c001,0xc0006030,0x7fff0000,0xf03800,
+ 0x19800c,0x1c38,0x1c07,0xf830cc18,0x0,0x1c0000,0x0,0x380e,0x18c007,0x80000000,0x0,0xe1cfe0,0x1fc003f,0x80003c00,0xe0701c0,
+ 0xe0381c07,0x380e070,0x1c0e070e,0x1c0001c,0x38000,0x70000e00,0xe0001,0xc0003800,0x7003803,0x870e70e0,0x71c00e3,0x801c7003,
+ 0x8e007007,0x3981c7,0x70e00e,0x1c01c380,0x3801c007,0x1e0e0f8,0xfff81ff,0xf03ffe07,0xffc0fff8,0x1fff07ff,0xf8e0003f,0xff87fff0,
+ 0xfffe1fff,0xc00e0001,0xc0003800,0x7003803,0x8380e0e0,0xe1c01c3,0x80387007,0xe00e1ff,0xfe386383,0x80e0701c,0xe0381c0,0x700e1c07,
+ 0x703870,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0x7f,0xffc00678,0x707f9c1e,0x38000001,
+ 0xc0000700,0x70,0x7,0xf8000000,0xe003803,0x800e0003,0xe00001c3,0x80e00007,0xe00e007,0x80380380,0x700000,0x7f0,0x0,0x7f00700,
+ 0x618061ff,0xe070071c,0x38038,0x38000700,0x1c00e38,0x3801c00,0x381c3c,0x1c000e1,0xc38e1ce1,0xc00e1c00,0x70038e0,0x700003c0,
+ 0xe007007,0x1c701d8,0xdc03dc00,0x1c000f00,0xe00007,0xe000,0x0,0x3ff,0xf070070e,0x38038,0x7fff0038,0x1c01c1c,0x7001c00,0x1c007fc,
+ 0x1c0070,0xe1c701c1,0xc01c1c01,0xc700700e,0x3f00,0x1c00380e,0x1c381cd,0x9c01f000,0x73800780,0xfe0000e,0xfe10,0x7c00000,0x1c000ffb,
+ 0xf8000000,0x38000000,0x10,0x20000,0x20000,0x1e0700,0x70380ff,0xbf80f003,0xfefe7fdf,0xc0000000,0x0,0x3f0,0x7ffe7ff,0xff000000,
+ 0x1f8,0x30e07,0xfeffbf80,0x78000700,0x1c,0x70c001,0xc0006030,0x7fff0000,0x783800,0x1ce11c,0xe1c,0x1c07,0xf838ce38,0x0,0x1c0000,
+ 0x0,0x380e,0x18c000,0x0,0x0,0x1c38c00,0x1800030,0x7800,0xfff01ff,0xe03ffc07,0xff80fff0,0x3fff0ffe,0x1c0001c,0x38000,0x70000e00,
+ 0xe0001,0xc0003800,0x7003803,0x870e70e0,0x71c00e3,0x801c7003,0x8e00700f,0x803b81c7,0x70e00e,0x1c01c380,0x3801c007,0xffe0e03c,
+ 0x1fff83ff,0xf07ffe0f,0xffc1fff8,0x3fff0fff,0xf8e0003f,0xff87fff0,0xfffe1fff,0xc00e0001,0xc0003800,0x7003803,0x8380e0e0,0xe1c01c3,
+ 0x80387007,0xe00e000,0x38c383,0x80e0701c,0xe0381c0,0x70073807,0x701ce0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f,0xffc0063c,0x40619c0f,0x30000001,0xc0000700,0x70,0x7,0xf8000000,0xe003803,0x800e0007,0xc00001c3,
+ 0xfffc0007,0xe00e007,0x380380,0xf00000,0xfe,0xffff80,0x3f800700,0x618063ff,0xf070071c,0x38038,0x38000700,0x1c00e38,0x3801c00,
+ 0x381c1e,0x1c000e0,0x38e0ee1,0xc00e1c00,0x70038e0,0x380001c0,0xe007007,0x1ef01d8,0xdc038e00,0x1c001e00,0xe00007,0xe000,0x0,
+ 0x7c0,0x7070070e,0x38038,0x70000038,0x1c01c1c,0x7001c00,0x1c0079e,0x1c0070,0xe1c701c1,0xc01c1c01,0xc700700e,0x780,0x1c00380e,
+ 0xe701cd,0x9c01f000,0x73800f00,0xe0000e,0xe000,0x0,0x1c0007f7,0xf0000000,0x70000000,0x10,0x20000,0x0,0xe0e00,0x703807f,0x7f01e001,
+ 0xfdfc3fbf,0x80000000,0x0,0x7f0,0x0,0x0,0x3c,0x18e07,0x7f7f00,0xf0000700,0x1c,0x70c001,0xc0007070,0x1c00000,0x3e7000,0xcff18,
+ 0x3ffc070e,0x1c07,0xf818c630,0x0,0x1c0000,0x0,0x380e,0x18c000,0x0,0x3ffc,0x3870000,0xe000fc00,0x380f000,0x1fff83ff,0xf07ffe0f,
+ 0xffc1fff8,0x3fff0ffe,0x1c0001c,0x38000,0x70000e00,0xe0001,0xc0003800,0x7003803,0x870770e0,0x71c00e3,0x801c7003,0x8e00701d,
+ 0xc03f01c7,0x70e00e,0x1c01c380,0x3801c007,0xffc0e01c,0x3e0387c0,0x70f80e1f,0x1c3e038,0x7c071e1c,0xe00038,0x70000,0xe0001c00,
+ 0xe0001,0xc0003800,0x7003803,0x8380e0e0,0xe1c01c3,0x80387007,0xe00e000,0x398383,0x80e0701c,0xe0381c0,0x70073807,0x701ce0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f,0xffc0061c,0xc0dc07,0xf0000001,0xc0000700,
+ 0x70,0x0,0x0,0x1c003c07,0x800e000f,0x1c3,0xfffc0007,0xe00e007,0x380380,0xe00000,0x1f,0xc0ffff81,0xfc000700,0x618063ff,0xf070070e,
+ 0x38070,0x38000700,0xe00e38,0x3801c00,0x381c0e,0x1c000e0,0x38e0ee1,0xe01e1c00,0x78078e0,0x380001c0,0xe007007,0xee01f8,0xfc078f00,
+ 0x1c001c00,0xe00003,0x8000e000,0x0,0x700,0x7070070e,0x38038,0x70000038,0x1c01c1c,0x7001c00,0x1c0070e,0x1c0070,0xe1c701c1,
+ 0xc01c1c01,0xc700700e,0x380,0x1c00380e,0xe700ed,0xb803f800,0x77800f00,0x70000e,0x1c000,0x0,0xe0003f7,0xe0000000,0x70000000,
+ 0x10,0x20000,0x1c0e0,0xe1c00,0x703803f,0x7e01c000,0xfdf81fbf,0x0,0x0,0x3f0,0x0,0x0,0x1c,0x1ce07,0x3f7e00,0xf0000700,0x1c,
+ 0x70c001,0xc00038e0,0x1c00038,0xf7000,0xe3e38,0x3ffc0387,0x1c00,0x1cc770,0x0,0x1c0000,0x0,0x380e,0x18c000,0x0,0x3ffc,0x70e0001,
+ 0xe001fe00,0x780e000,0x1fff83ff,0xf07ffe0f,0xffc1fff8,0x3fff0ffe,0xe0001c,0x38000,0x70000e00,0xe0001,0xc0003800,0x7003807,
+ 0x70770f0,0xf1e01e3,0xc03c7807,0x8f00f038,0xe03e03c7,0x70e00e,0x1c01c380,0x3801c007,0xff00e00e,0x38038700,0x70e00e1c,0x1c38038,
+ 0x70071c1c,0xe00038,0x70000,0xe0001c00,0xe0001,0xc0003800,0x7003803,0x8380e0e0,0xe1c01c3,0x80387007,0xe00e000,0x3b0383,0x80e0701c,
+ 0xe0381c0,0x70077807,0x701de0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6,0x1c00061c,
+ 0xc0de03,0xe0000001,0xc0000700,0x70,0x0,0x0,0x1c001c07,0xe001e,0x1c3,0xfffc0007,0x600e00e,0x380380,0xe00000,0x7,0xf0ffff87,
+ 0xf0000000,0x60c0e380,0x7070070e,0x38070,0x38000700,0xe00e38,0x3801c00,0x381c0f,0x1c000e0,0x38e06e0,0xe01c1c00,0x38070e0,
+ 0x1c0001c0,0xe007007,0xee00f8,0xf80f0700,0x1c003c00,0xe00003,0x8000e000,0x0,0x700,0x70780f0f,0x3c078,0x70000038,0x1e03c1c,
+ 0x7001c00,0x1c0070f,0x1c0070,0xe1c701c1,0xe03c1e03,0xc780f00e,0x380,0x1c00380e,0xe700f8,0xf807bc00,0x3f001e00,0x70000e,0x1c000,
+ 0x0,0xe0001ff,0xc0000000,0x70000000,0x10,0x20000,0x33110,0xe0e00,0x383801f,0xfc03c000,0x7ff00ffe,0x0,0x0,0x3e0,0x0,0x0,0x1c,
+ 0x38e07,0x1ffc01,0xe0000700,0x1c,0x78c001,0xc0007ff0,0x1c00038,0x7c000,0x70070,0x1c3,0x80001c00,0xe00e0,0x0,0x1c0000,0x0,
+ 0x380e,0x18c000,0x0,0x0,0xe1c0001,0xe0010700,0x780e000,0x1c038380,0x70700e0e,0x1c1c038,0x78070e0e,0xe0001c,0x38000,0x70000e00,
+ 0xe0001,0xc0003800,0x7003807,0x7037070,0xe0e01c1,0xc0383807,0x700e070,0x701c0387,0x70e00e,0x1c01c380,0x3801c007,0xe00e,0x38038700,
+ 0x70e00e1c,0x1c38038,0x70071c1c,0xf00038,0x70000,0xe0001c00,0xe0001,0xc0003800,0x7003c07,0x8380e0f0,0x1e1e03c3,0xc078780f,
+ 0xf01e007,0x803e0783,0x80e0701c,0xe0381c0,0x7003f007,0x80f00fc0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x6,0x1800061c,0xc0de01,0xc0000000,0xc0000e00,0x70,0xf0000,0x3c00,0x38001c0f,0xe003c,0x3c0,0xe0000e,0x701e00e,
+ 0x3c0780,0x1e003c0,0x780000,0xfc00001f,0x80000000,0x60e1e780,0x78700f07,0x4380f0,0x38000700,0xf00e38,0x3801c00,0xc0781c07,
+ 0x81c000e0,0x38e07e0,0xe03c1c00,0x380f0e0,0x1e0003c0,0xe00780f,0xee00f0,0x780e0780,0x1c007800,0xe00001,0xc000e000,0x0,0x700,
+ 0xf0780e07,0x8041c078,0x38020038,0xe03c1c,0x7001c00,0x1c00707,0x801c0070,0xe1c701c0,0xe0381e03,0x8380f00e,0x80380,0x1c003c1e,
+ 0x7e00f8,0xf80f1e00,0x3f003c00,0x70000e,0x1c000,0x0,0xf0100f7,0x80078000,0x700078f0,0x10,0x7ff000,0x61208,0x1e0700,0x383800f,
+ 0x78078000,0x3de007bc,0x0,0x0,0x0,0x0,0x0,0x401c,0x70e0f,0xf7803,0xc0000700,0x1c,0x38c001,0xc000efb8,0x1c00038,0x1e000,0x3c1e0,
+ 0xc1,0x80000000,0x783c0,0x0,0x0,0x0,0x3c1e,0x18c000,0x0,0x0,0xc180003,0x60000300,0xd80e010,0x3c03c780,0x78f00f1e,0x1e3c03c,
+ 0x70039c0e,0x70041c,0x38000,0x70000e00,0xe0001,0xc0003800,0x700380f,0x703f070,0x1e0e03c1,0xc078380f,0x701e0e0,0x381c0787,
+ 0x80f0f01e,0x1e03c3c0,0x7801c007,0xe00e,0x38078700,0xf0e01e1c,0x3c38078,0x700f1c1c,0x78041c,0x1038020,0x70040e00,0x800e0001,
+ 0xc0003800,0x7001c07,0x380e070,0x1c0e0381,0xc070380e,0x701c007,0x801e0703,0xc1e0783c,0xf0781e0,0xf003f007,0x80e00fc0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0xe,0x1801867c,0xc0cf83,0xe0000000,0xe0000e00,
+ 0x70,0xf0000,0x3c00,0x38000f1e,0xe0070,0x180780,0xe0603e,0x783c01e,0x1e0f01,0x7c003c0,0x780000,0x3c00001e,0x700,0x307fe700,
+ 0x38701e07,0xc1c383e0,0x38000700,0x7c1e38,0x3801c00,0xe0f01c03,0x81c000e0,0x38e03e0,0x78781c00,0x1e1e0e0,0xe180780,0xe003c1e,
+ 0x7c00f0,0x781e03c0,0x1c007000,0xe00001,0xc000e000,0x0,0x783,0xf07c1e07,0xc0c1e0f8,0x3e0e0038,0xf07c1c,0x7001c00,0x1c00703,
+ 0xc01e0070,0xe1c701c0,0xf0781f07,0x83c1f00e,0xe0f80,0x1e003c3e,0x7e00f8,0xf80e0e00,0x3f003800,0x70000e,0x1c000,0x0,0x7830077,
+ 0xf0000,0x700078f0,0x10,0x20000,0x41208,0xc03c0380,0x3c38007,0x70070000,0x1dc003b8,0x0,0x0,0x0,0x0,0x0,0x707c,0x6070f,0x86077003,
+ 0x80000700,0x1c,0x3ec401,0xc001c01c,0x1c00038,0xf000,0x1ffc0,0x40,0x80000000,0x3ff80,0x0,0x0,0x0,0x3e3e,0x18c000,0x0,0x0,
+ 0x8100006,0x60000300,0x1980f070,0x3801c700,0x38e0071c,0xe3801c,0x70039c0e,0x7c1c1c,0x38000,0x70000e00,0xe0001,0xc0003800,
+ 0x700383e,0x701f03c,0x3c078780,0xf0f01e1e,0x3c3c1c0,0x1c3f0f03,0xc1e0783c,0xf0781e0,0xf001c007,0xe81e,0x3c1f8783,0xf0f07e1e,
+ 0xfc3c1f8,0x783f1e3e,0x187c0c1f,0x703e0e0,0x7c1c0f83,0x800e0001,0xc0003800,0x7001e0f,0x380e078,0x3c0f0781,0xe0f03c1e,0x783c007,
+ 0x801e0f03,0xc3e0787c,0xf0f81e1,0xf003f007,0xc1e00fc0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x1c,0xe,0x3801fff8,0x6187ff,0xe0000000,0xe0000e00,0x70,0xf0000,0x3c00,0x38000ffe,0x1fff0ff,0xfe1fff80,0xe07ffc,0x3ffc01c,
+ 0x1fff01,0xff8003c0,0x780000,0x4000010,0x700,0x301e6700,0x387ffe03,0xffc3ffc0,0x3fff0700,0x3ffe38,0x383ffe0,0xfff01c03,0xc1fff8e0,
+ 0x38e03e0,0x7ff81c00,0x1ffe0e0,0xf1fff80,0xe003ffe,0x7c00f0,0x781c01c0,0x1c00ffff,0xe00001,0xc000e000,0x0,0x3ff,0x707ffc03,
+ 0xffc0fff8,0x1ffe0038,0x7ffc1c,0x707fff0,0x1c00701,0xc00ff070,0xe1c701c0,0x7ff01fff,0x1fff00e,0xfff00,0xff81fee,0x7e00f0,
+ 0x781e0f00,0x1e007ffc,0x70000e,0x1c000,0x0,0x3ff003e,0xf0000,0xe00070e0,0x60830010,0x20000,0x41208,0xfffc01c0,0x1fffe03,0xe00ffff0,
+ 0xf8001f0,0x0,0x0,0x0,0x0,0x0,0x7ff8,0xc07fd,0xfe03e007,0xffc00700,0x1c,0x1ffc1f,0xffc08008,0x1c00038,0x7000,0x7f00,0x0,0x0,
+ 0xfe00,0x0,0xffff800,0x0,0x3ff7,0x8018c000,0x0,0x0,0x6,0x60000700,0x19807ff0,0x3801c700,0x38e0071c,0xe3801c,0x70039c0f,0xf03ffc1f,
+ 0xff83fff0,0x7ffe0fff,0xc1fff03f,0xfe07ffc0,0xfff83ffc,0x701f03f,0xfc07ff80,0xfff01ffe,0x3ffc080,0x83fff03,0xffe07ffc,0xfff81ff,
+ 0xf001c007,0xeffc,0x1ffb83ff,0x707fee0f,0xfdc1ffb8,0x3ff70ff7,0xf83ffc0f,0xff01ffe0,0x3ffc07ff,0x83fff87f,0xff0fffe1,0xfffc0ffe,
+ 0x380e03f,0xf807ff00,0xffe01ffc,0x3ff8007,0x803ffe01,0xfee03fdc,0x7fb80ff,0x7001e007,0xffc00780,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0xc,0x3801fff0,0x7f83fe,0x70000000,0xe0000e00,0x0,0xf0000,0x3c00,0x700007fc,
+ 0x1fff0ff,0xfe1ffe00,0xe07ff8,0x1ff801c,0xffe01,0xff0003c0,0x780000,0x0,0x700,0x38000f00,0x3c7ffc01,0xff83ff80,0x3fff0700,
+ 0x1ffc38,0x383ffe0,0x7fe01c01,0xe1fff8e0,0x38e03e0,0x3ff01c00,0xffc0e0,0x71fff00,0xe001ffc,0x7c00f0,0x783c01e0,0x1c00ffff,
+ 0xe00000,0xe000e000,0x0,0x1ff,0x7077f801,0xff807fb8,0xffc0038,0x3fdc1c,0x707fff0,0x1c00701,0xe007f070,0xe1c701c0,0x3fe01dfe,
+ 0xff700e,0x7fe00,0xff80fee,0x3c0070,0x703c0780,0x1e007ffc,0x70000e,0x1c000,0x0,0x1fe001c,0xe0000,0xe000e1c0,0x71c78010,0x20000,
+ 0x21318,0xfff800c0,0xfffe01,0xc00ffff0,0x70000e0,0x0,0x0,0x0,0x0,0x0,0x3ff0,0x1803fd,0xfe01c007,0xffc00700,0x1c,0xffc1f,0xffc00000,
+ 0x1c00038,0x7000,0x0,0x0,0x0,0x0,0x0,0xffff800,0x0,0x3ff7,0x8018c000,0x0,0x0,0xc,0x60000e00,0x31803fe0,0x7801ef00,0x3de007bc,
+ 0xf7801e,0xf003fc0f,0xf01ff81f,0xff83fff0,0x7ffe0fff,0xc1fff03f,0xfe07ffc0,0xfff83ff8,0x701f01f,0xf803ff00,0x7fe00ffc,0x1ff8000,
+ 0x67fe01,0xffc03ff8,0x7ff00ff,0xe001c007,0xeff8,0xffb81ff,0x703fee07,0xfdc0ffb8,0x1ff70ff7,0xf81ff807,0xfe00ffc0,0x1ff803ff,
+ 0x3fff87f,0xff0fffe1,0xfffc07fc,0x380e01f,0xf003fe00,0x7fc00ff8,0x1ff0000,0x37fc00,0xfee01fdc,0x3fb807f,0x7001e007,0x7f800780,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1c,0xc,0x30007fc0,0x1e00f8,0x78000000,0x70001c00,
+ 0x0,0xe0000,0x3c00,0x700001f0,0x1fff0ff,0xfe07f800,0xe01fe0,0x7e0038,0x3f800,0xfc0003c0,0x700000,0x0,0x700,0x18000e00,0x1c7ff000,
+ 0x7e03fe00,0x3fff0700,0x7f038,0x383ffe0,0x1f801c00,0xf1fff8e0,0x38e01e0,0xfc01c00,0x3f80e0,0x787fc00,0xe0007f0,0x7c00f0,0x387800f0,
+ 0x1c00ffff,0xe00000,0xe000e000,0x0,0xfc,0x7071f000,0x3f003e38,0x3f00038,0x1f1c1c,0x707fff0,0x1c00700,0xf003f070,0xe1c701c0,
+ 0x1f801c7c,0x7c700e,0x1f800,0x3f8078e,0x3c0070,0x707803c0,0x1c007ffc,0x70000e,0x1c000,0x0,0x7c0008,0x1e0000,0xe000e1c0,0x71c30010,
+ 0x20000,0x1e1f0,0x3fe00020,0x3ffe00,0x800ffff0,0x2000040,0x0,0x0,0x0,0x0,0x0,0xfc0,0x3001f0,0x78008007,0xffc00700,0x1c,0x3f81f,
+ 0xffc00000,0x1c00038,0x407000,0x0,0x0,0x0,0x0,0x0,0xffff800,0x0,0x39c7,0x18c000,0x0,0x0,0x18,0x60001c00,0x61801f80,0x7000ee00,
+ 0x1dc003b8,0x77000e,0xe001f80f,0xf007e01f,0xff83fff0,0x7ffe0fff,0xc1fff03f,0xfe07ffc0,0xfff83fc0,0x700f007,0xe000fc00,0x1f8003f0,
+ 0x7e0000,0xe1f800,0x7f000fe0,0x1fc003f,0x8001c007,0xe7f0,0x7e380fc,0x701f8e03,0xf1c07e38,0xfc703c1,0xe003f001,0xf8003f00,
+ 0x7e000fc,0x3fff87f,0xff0fffe1,0xfffc03f8,0x380e00f,0xc001f800,0x3f0007e0,0xfc0000,0x61f800,0x78e00f1c,0x1e3803c,0x7001c007,
+ 0x1f000700,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x70001c00,0x0,
+ 0x1c0000,0x0,0xe0000000,0x0,0x0,0x0,0x0,0x0,0x0,0xe00000,0x0,0x0,0xc000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c000,0x0,
+ 0x0,0x0,0x0,0x0,0xe00000,0x7000e000,0x0,0x0,0x0,0x0,0x0,0x1c00,0x0,0x1c00000,0x0,0x0,0x1c00,0x7000,0x0,0x0,0x0,0x0,0x1c000000,
+ 0x70000e,0x1c000,0x0,0x0,0x1c0000,0xe000c180,0x10,0x20000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc000,
+ 0x0,0x38,0x70e000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x18c000,0x2000,0x0,0x1f,0xf8003800,0x7fe00000,0x0,0x0,0x0,0x0,0x4000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x400000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x400000,
+ 0x0,0x0,0x1c007,0x700,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x30001800,
+ 0x0,0x1c0000,0x0,0xe0000000,0x0,0x0,0x0,0x0,0x0,0x0,0xe00000,0x0,0x0,0xe000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1e000,
+ 0x0,0x0,0x0,0x0,0x0,0xe00000,0x7000e000,0x0,0x0,0x0,0x0,0x0,0x1c00,0x0,0x1c00000,0x0,0x0,0x1c00,0x7000,0x0,0x0,0x0,0x0,0x1c000000,
+ 0x70000e,0x1c000,0x0,0x0,0x1c0001,0xe001c380,0x10,0x20000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc000,
+ 0x0,0x38,0x7fe000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x18c000,0x3000,0x0,0x1f,0xf8007000,0x7fe00000,0x0,0x0,0x0,0x0,0x6000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x6000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x1c007,0x700,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x38003800,
+ 0x0,0x380000,0x1,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x1c00000,0x0,0x0,0x3c18000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf000,
+ 0x0,0x0,0x0,0x0,0x0,0xfe0000,0x380fe000,0x0,0x0,0x0,0x0,0x0,0x3800,0x0,0x1c00000,0x0,0x0,0x1c00,0x7000,0x0,0x0,0x0,0x0,0x38000000,
+ 0x78000e,0x3c000,0x0,0x0,0x180001,0xc0018300,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc000,0x0,
+ 0x38,0x1f8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x18c000,0x1800,0x0,0x0,0x6000e000,0x1800000,0x0,0x0,0x0,0x0,0x3000,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x38007,0xe00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x18003000,
+ 0x0,0x300000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1800000,0x0,0x0,0x1ff8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4000,0x0,0x0,
+ 0x0,0x0,0x0,0xfe0000,0xfe000,0x0,0x0,0x0,0x0,0x0,0x607800,0x0,0x3c00000,0x0,0x0,0x1c00,0x7000,0x0,0x0,0x0,0x0,0x78000000,
+ 0x3f800e,0x3f8000,0x0,0x0,0x300043,0xc0018200,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc000,
+ 0x0,0x38,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x0,0x11800,0x0,0x0,0x6001ff00,0x1800000,0x0,0x0,0x0,0x0,0x23000,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x23000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x78007,
+ 0x1e00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x600,0x0,0x0,0x1c007000,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfe0000,
+ 0xfe000,0x0,0x0,0x0,0x0,0x0,0x7ff000,0x0,0x7f800000,0x0,0x0,0x1c00,0x7000,0x0,0x0,0x0,0x3,0xf8000000,0x3f800e,0x3f8000,0x0,
+ 0x0,0x10007f,0x80000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xc000,0x0,0x38,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x3800,0x0,0x1f800,0x0,0x0,0x6001ff00,0x1800000,0x0,0x0,0x0,0x0,0x3f000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3f000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3f8007,0xfe00,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7fff8,0x0,0x0,0x0,0x0,0x7fe000,0x0,
+ 0x7f000000,0x0,0x0,0x1c00,0x7000,0x0,0x0,0x0,0x3,0xf0000000,0xf800e,0x3e0000,0x0,0x0,0x7f,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3800,0x0,0x1f000,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x3e000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3e000,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x3f0007,0xfc00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x7fff8,0x0,0x0,0x0,0x0,0x1fc000,0x0,0x7e000000,0x0,0x0,0x1c00,0x7000,0x0,0x0,0x0,0x3,0xc0000000,0xe,0x0,
+ 0x0,0x0,0x3e,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x3800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c0007,0xf000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7fff8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 };
+
+ // Definition of a 29x57 font
+ const unsigned int font29x57[29*57*256/32] = {
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x781e00,0x0,0x0,0x7,0x81e00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7c0000,0xf8000,0x7e00000,0x0,0x7,
+ 0xc0000000,0x0,0x7c00,0xf80,0x7e000,0x0,0x7c00000,0xf80000,0x7e000000,0x0,0x0,0x1f00,0x3e0,0x1f800,0x0,0x0,0x0,0x3,0xe0000000,
+ 0x7c00003f,0x0,0xf8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x3c3c00,0x0,0x0,0x3,0xc3c00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3e1f00,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3e0000,
+ 0x1f0000,0x7e00000,0xf838001f,0xf80001f,0xf0000000,0x0,0x3e00,0x1f00,0x7e000,0x3e1f000,0x3e00000,0x1f00000,0x7e00003e,0x1f000000,
+ 0x3e0,0xe0000f80,0x7c0,0x1f800,0x3e0e00,0x7c3e000,0x0,0x1,0xf0000000,0xf800003f,0x1f0f,0x800001f0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1e7800,0x0,0x0,
+ 0x1,0xe7800000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3e1f00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1e0000,0x1e0000,0xff00001,0xfe38001f,0xf80003f,
+ 0xf8000000,0x0,0x1e00,0x1e00,0xff000,0x3e1f000,0x1e00000,0x1e00000,0xff00003e,0x1f000000,0x7f8,0xe0000780,0x780,0x3fc00,0x7f8e00,
+ 0x7c3e000,0x0,0x0,0xf0000000,0xf000007f,0x80001f0f,0x800001e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xef000,0x0,0x0,0x0,0xef000000,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3e1f00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf0000,0x3c0000,0x1e780003,0xfff8001f,0xf80003c,0x78000000,0x0,0xf00,0x3c00,0x1e7800,
+ 0x3e1f000,0xf00000,0x3c00001,0xe780003e,0x1f000000,0xfff,0xe00003c0,0xf00,0x79e00,0xfffe00,0x7c3e000,0x0,0x0,0x78000001,0xe00000f3,
+ 0xc0001f0f,0x800003c0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7e000,0x0,0x0,0x0,0x7e000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x3e1f00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x78000,0x780000,0x3c3c0003,0x8ff0001f,0xf800078,0x3c000000,0x0,0x780,0x7800,0x3c3c00,0x3e1f000,0x780000,0x7800003,0xc3c0003e,
+ 0x1f000000,0xe3f,0xc00001e0,0x1e00,0xf0f00,0xe3fc00,0x7c3e000,0x0,0x0,0x3c000003,0xc00001e1,0xe0001f0f,0x80000780,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x1f,0xf0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x7e000,0x0,0x0,0x0,0x7e000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3e1f00,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfc00,0x7e000,0xfe000,0x0,0x3c000,0xf00000,0x781e0003,
+ 0x83e0001f,0xf800070,0x1c000000,0x0,0x3c0,0xf000,0x781e00,0x3e1f000,0x3c0000,0xf000007,0x81e0003e,0x1f000000,0xe0f,0x800000f0,
+ 0x3c00,0x1e0780,0xe0f800,0x7c3e000,0x0,0x0,0x1e000007,0x800003c0,0xf0001f0f,0x80000f00,0x0,0x0,0x0,0x0,0x0,0x0,0x3f,0xf8000000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3fc00,0x1fe000,0x3ff800,0x0,0x0,0x0,0x0,0x0,0x70,0x1c000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c,0x78000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1f00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x78,0xf000000,0x0,0x0,0x780f0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7c0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x3fc00,0x1fe000,0x3ffc00,0x0,0x0,0x0,0x0,0x0,0x70,0x1c000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1f00000,0x3e000,0x3e00000,0x0,0x78,0x3c000000,0x0,0x1f000,0x3e0,
+ 0x3e000,0x0,0x1f000000,0x3e0000,0x3e000000,0x0,0x0,0x7c00,0xf8,0xf800,0x0,0x0,0x0,0xf,0x80000000,0x1f00001f,0x0,0x3e,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x30000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf80000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0xf80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x781c0000,0x38,0xe000000,0x0,0x0,0x380e0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf80,0x0,0x0,0x0,0x0,0x0,0x0,0x39c00,0x1ce000,0x303e00,
+ 0x0,0x0,0x0,0x0,0x0,0x78,0x3c000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4000,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0xf80000,0x7c000,0x3e00000,0xf0380000,0x70,0x1c000000,0x0,0xf800,0x7c0,0x3e000,0x0,0xf800000,0x7c0000,0x3e000000,
+ 0x0,0x3c0,0xe0003e00,0x1f0,0xf800,0x3c0e00,0x0,0x0,0x7,0xc0000000,0x3e00001f,0x0,0x7c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000000,0xff,0x0,
+ 0xf8,0xf8000,0x1c000,0x0,0x0,0x0,0x0,0x1f,0xc0000000,0x1ff8,0xff00,0x0,0x0,0x3fe000,0x0,0x1fc00001,0xfe000000,0x0,0x0,0x0,
+ 0x0,0x7f800,0x0,0x0,0x0,0xff00000,0x0,0x0,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0xf8000000,0xfe,0x0,0x7f80,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x3f,0xf0000000,0x7fe0,0x0,0x0,0x780000,0x1,0xe0000000,0x0,0x780000,0x3,0xfe000000,0x78000,0x3c00,0xf000,0x7800003,0xffe00000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfc0000f0,0x3f000,0x0,0x0,0x3fc00,0x0,0x0,0x1fc000,0x0,0x0,0x0,0x1fc0,
+ 0x0,0xff000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xfe1c0000,0x1c,0x1c000000,0x0,0x0,0x1c1c0,0x0,0x0,0x0,0x0,0x1fe0000,
+ 0x0,0x0,0x1ff,0x1f0f8,0x0,0xff000,0x0,0x0,0x0,0x3f,0xff00000f,0x80000000,0xfe0,0x3f80,0xf00,0x0,0x0,0x0,0x1,0xf8000003,0xe0000000,
+ 0x1c00,0xe000,0xe00,0x0,0x0,0x0,0x0,0x0,0x3c,0x78000000,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f0,0x3f80,0x1fc00,0xfe000,
+ 0x7f0000,0x0,0x1fc07000,0x0,0x0,0x0,0x0,0x0,0x3f800,0x780000,0x78000,0x7f00001,0xfc38001f,0xf800070,0x1c000000,0x0,0x7800,
+ 0x780,0x7f000,0x3e1f000,0x7800000,0x780000,0x7f00003e,0x1f0003f0,0x7f0,0xe0001e00,0x1e0,0x1fc00,0x7f0e00,0x7c3e000,0x0,0x3,
+ 0xc0000000,0x3c00003f,0x80001f0f,0x80000078,0x1e0000,0x3e1f00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x3c1e0000,0x1e078000,0x30000000,0x3ff,0xc00001e0,0xf0,
+ 0x78000,0x1c000,0x0,0x0,0x0,0x0,0x1e0007f,0xf000007e,0x1ffff,0x7ffe0,0x1f80,0x3ffff80,0xfff803,0xfffff800,0xfff80007,0xff800000,
+ 0x0,0x0,0x0,0x0,0x1ffe00,0x0,0xfe0003,0xfff80000,0x3ffe01ff,0xe00003ff,0xffe01fff,0xff0003ff,0xe01e0007,0x803ffff0,0xfff80,
+ 0x3c000fc0,0x7800001f,0x8003f07e,0x1e000f,0xfe0007ff,0xf00003ff,0x8007ffe0,0x1fff8,0x7fffffe,0xf0003c1,0xe000079e,0xf1f,0x1f3e0,
+ 0x1f01ff,0xfff8003f,0xf003c000,0x7fe0,0x3f00,0x0,0x3c0000,0x1,0xe0000000,0x0,0x780000,0xf,0xfe000000,0x78000,0x3c00,0xf000,
+ 0x7800003,0xffe00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xfc0000f0,0x3fe00,0x0,0x0,0xfff00,0x0,0x0,0x3fe000,
+ 0x0,0x0,0x0,0x1dc0,0x0,0x3fff00,0x0,0x3ffff80,0x1f,0xffff8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xff1c07ff,0x3c0f001e,0x3c000000,
+ 0x0,0x0,0x1e3c0,0xf80007c,0x0,0x780000,0x0,0xfff8000,0x3e00,0x1f00000,0x7ff,0xc001f0f8,0x0,0x3ffc00,0x0,0x0,0x0,0x3f,0xff00003f,
+ 0xe0000000,0x3ff8,0xffe0,0x1e00,0x0,0xfffc00,0x0,0x7,0xf800000f,0xf8000000,0x1c00,0xe000,0xe00,0xf000,0x1fc000,0xfe0000,0x7f00000,
+ 0x3f800001,0xfc00003f,0xf80000ff,0xffc003ff,0xe007ffff,0xc03ffffe,0x1fffff0,0xfffff80,0x7fffe003,0xffff001f,0xfff800ff,0xffc01ffc,
+ 0xfc00,0x3c001ffc,0xffe0,0x7ff00,0x3ff800,0x1ffc000,0x0,0x7ff8f0f0,0x3c0780,0x1e03c00,0xf01e000,0x783e0001,0xf01e0000,0xffe00,
+ 0x3c0000,0xf0000,0x7700001,0xfe38001f,0xf800070,0x1c000000,0x0,0x3c00,0xf00,0x77000,0x3e1f000,0x3c00000,0xf00000,0x7700003e,
+ 0x1f0000f8,0xc0007f8,0xe0000f00,0x3c0,0x1dc00,0x7f8e00,0x7c3e000,0x0,0x1,0xe0000000,0x7800003b,0x80001f0f,0x800000f0,0x1e0000,
+ 0x3e1f00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x780000,0x3c1e0000,0x1e070000,0x300001f0,0x7ff,0xc00001e0,0x1e0,0x7c000,0x1c000,0x0,0x0,0x0,0x0,0x3c000ff,0xf80007fe,
+ 0x3ffff,0x801ffff8,0x1f80,0x3ffff80,0x3fff803,0xfffff801,0xfffc000f,0xffc00000,0x0,0x0,0x0,0x0,0x7fff80,0x0,0xfe0003,0xffff0000,
+ 0xffff01ff,0xfc0003ff,0xffe01fff,0xff000fff,0xf01e0007,0x803ffff0,0xfff80,0x3c001f80,0x7800001f,0xc007f07e,0x1e001f,0xff0007ff,
+ 0xfc0007ff,0xc007fffc,0x3fffc,0x7fffffe,0xf0003c1,0xf0000f9e,0xf0f,0x8003e1e0,0x1e01ff,0xfff8003f,0xf001e000,0x7fe0,0x3f00,
+ 0x0,0x1e0000,0x1,0xe0000000,0x0,0x780000,0x1f,0xfe000000,0x78000,0x3c00,0xf000,0x7800003,0xffe00000,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xfc0000f0,0x3ff00,0x0,0x0,0x1fff80,0x0,0x0,0xffe000,0x0,0x0,0x0,0x3de0,0x0,0x7fff80,0x0,0xfffff80,
+ 0x1f,0xffff8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xe7bc07ff,0x3e1f000f,0x78000000,0x0,0x0,0xf780,0x7800078,0x0,0x780000,0x180000,
+ 0x1fff8000,0x1e00,0x1e0003c,0xfff,0xc001f0f8,0x0,0x7ffe00,0x0,0x0,0x0,0x3f,0xff00007f,0xf0000000,0x3ffc,0xfff0,0x3c00,0x0,
+ 0x7fffc00,0x0,0x7,0xf800003f,0xfe000000,0x1c00,0xe000,0xe00,0xf000,0x1fc000,0xfe0000,0x7f00000,0x3f800001,0xfc00001f,0xe00001ff,
+ 0xffc00fff,0xf007ffff,0xc03ffffe,0x1fffff0,0xfffff80,0x7fffe003,0xffff001f,0xfff800ff,0xffc01fff,0xc000fc00,0x3c003ffe,0x1fff0,
+ 0xfff80,0x7ffc00,0x3ffe000,0x0,0xfffce0f0,0x3c0780,0x1e03c00,0xf01e000,0x781e0001,0xe01e0000,0x3fff00,0x1e0000,0x1e0000,0xf780003,
+ 0xcf78001f,0xf800078,0x3c000000,0x0,0x1e00,0x1e00,0xf7800,0x3e1f000,0x1e00000,0x1e00000,0xf780003e,0x1f0000fc,0x7c000f3d,
+ 0xe0000780,0x780,0x3de00,0xf3de00,0x7c3e000,0x0,0x0,0xf0000000,0xf000007b,0xc0001f0f,0x800001e0,0x1e0000,0x3e1f00,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,
+ 0x3c1e0000,0x1e0f0000,0x300007fc,0xfff,0xc00001e0,0x1e0,0x3c000,0x1c000,0x0,0x0,0x0,0x0,0x3c001ff,0xfc001ffe,0x3ffff,0xc01ffffc,
+ 0x3f80,0x3ffff80,0x7fff803,0xfffff803,0xfffe001f,0xffe00000,0x0,0x0,0x0,0x0,0xffff80,0x7f800,0xfe0003,0xffff8001,0xffff01ff,
+ 0xff0003ff,0xffe01fff,0xff001fff,0xf01e0007,0x803ffff0,0xfff80,0x3c003f00,0x7800001f,0xc007f07f,0x1e003f,0xff8007ff,0xff000fff,
+ 0xe007ffff,0x7fffc,0x7fffffe,0xf0003c0,0xf0000f1e,0xf07,0x8003c1f0,0x3e01ff,0xfff8003f,0xf001e000,0x7fe0,0x7f80,0x0,0xe0000,
+ 0x1,0xe0000000,0x0,0x780000,0x1f,0xfe000000,0x78000,0x3c00,0xf000,0x7800003,0xffe00000,0x0,0x0,0x0,0x0,0x0,0x0,0x3c000,0x0,
+ 0x0,0x0,0x0,0x0,0xf,0xfc0000f0,0x3ff00,0x0,0x0,0x3fff80,0x0,0x0,0xffe000,0x0,0x0,0x0,0x78f0,0x0,0xffff80,0x0,0x3fffff80,0x1f,
+ 0xffff8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xc7f80070,0x3e1f0007,0x70000000,0x0,0x0,0x7700,0x7c000f8,0x0,0x780000,0x180000,
+ 0x3fff8000,0x1f00,0x3e0003c,0x1f03,0xc001f0f8,0x0,0x703f00,0x0,0x0,0x0,0x3f,0xff0000f0,0xf8000000,0x303e,0xc0f8,0x7800,0x0,
+ 0xffffc00,0x0,0x7,0x3800003e,0x3e000000,0x1c00,0xe000,0x3c00,0xf000,0x1fc000,0xfe0000,0x7f00000,0x3f800001,0xfc00000f,0xe00001ff,
+ 0xffc01fff,0xf007ffff,0xc03ffffe,0x1fffff0,0xfffff80,0x7fffe003,0xffff001f,0xfff800ff,0xffc01fff,0xf000fe00,0x3c007fff,0x3fff8,
+ 0x1fffc0,0xfffe00,0x7fff000,0x1,0xffffc0f0,0x3c0780,0x1e03c00,0xf01e000,0x781f0003,0xe01e0000,0x3fff80,0xe0000,0x3c0000,0x1e3c0003,
+ 0x8ff0001f,0xf80003c,0x78000000,0x0,0xe00,0x3c00,0x1e3c00,0x3e1f000,0xe00000,0x3c00001,0xe3c0003e,0x1f00007f,0xf8000e3f,0xc0000380,
+ 0xf00,0x78f00,0xe3fc00,0x7c3e000,0x0,0x0,0x70000001,0xe00000f1,0xe0001f0f,0x800003c0,0x1e0000,0x3e1f00,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x3c1e0000,0x3c0f0000,
+ 0x30000ffe,0xf80,0xc00001e0,0x3c0,0x1e000,0x101c040,0x0,0x0,0x0,0x0,0x78003f0,0x7e001ffe,0x3f807,0xe01f00fe,0x3f80,0x3ffff80,
+ 0x7e01803,0xfffff007,0xe03f003f,0x3f00000,0x0,0x0,0x0,0x0,0xfc0fc0,0x3ffe00,0xfe0003,0xffffc003,0xf81f01ff,0xff8003ff,0xffe01fff,
+ 0xff003f01,0xf01e0007,0x803ffff0,0xfff80,0x3c007e00,0x7800001f,0xc007f07f,0x1e007e,0xfc007ff,0xff801f83,0xf007ffff,0x800fc07c,
+ 0x7fffffe,0xf0003c0,0xf0000f0f,0x1e07,0xc007c0f8,0x7c01ff,0xfff8003c,0xf000,0x1e0,0xffc0,0x0,0xf0000,0x1,0xe0000000,0x0,0x780000,
+ 0x3e,0x0,0x78000,0x3c00,0xf000,0x7800000,0x1e00000,0x0,0x0,0x0,0x0,0x0,0x0,0x3c000,0x0,0x0,0x0,0x0,0x0,0x1f,0x800000f0,0x1f80,
+ 0x0,0x0,0x7e0780,0x0,0x0,0x1f82000,0x0,0x0,0x0,0x7070,0x0,0x1f80f80,0x0,0x7fffff80,0x1f,0xffff8000,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x1,0xc3f80070,0x3f3f0007,0xf0000000,0x0,0x0,0x7f00,0x3e001f0,0x0,0x780000,0x180000,0x7f018000,0xf80,0x7c0003c,0x3e00,
+ 0x4001f0f8,0xfe00,0x400f00,0x0,0x0,0x0,0x7f000000,0xe0,0x38000000,0x1e,0x38,0x7800,0x0,0x1ffe1c00,0x0,0x0,0x38000078,0xf000000,
+ 0x1c00,0xe000,0x7f800,0xf000,0x1fc000,0xfe0000,0x7f00000,0x3f800001,0xfc00001f,0xf00001ff,0xffc03f81,0xf007ffff,0xc03ffffe,
+ 0x1fffff0,0xfffff80,0x7fffe003,0xffff001f,0xfff800ff,0xffc01fff,0xf800fe00,0x3c00fc1f,0x8007e0fc,0x3f07e0,0x1f83f00,0xfc1f800,
+ 0x3,0xf07fc0f0,0x3c0780,0x1e03c00,0xf01e000,0x780f8007,0xc01e0000,0x7e0fc0,0xf0000,0x3c0000,0x1c1c0003,0x87f0001f,0xf80003f,
+ 0xf8000000,0x0,0xf00,0x3c00,0x1c1c00,0x3e1f000,0xf00000,0x3c00001,0xc1c0003e,0x1f00003f,0xc0000e1f,0xc00003c0,0xf00,0x70700,
+ 0xe1fc00,0x7c3e000,0x0,0x0,0x78000001,0xe00000e0,0xe0001f0f,0x800003c0,0x1e0000,0x3e1f00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x3c1e0000,0x3c0f0001,0xff801e0f,
+ 0x1f00,0x1e0,0x3c0,0x1e000,0x3c1c1e0,0x0,0x0,0x0,0x0,0x78007c0,0x1f001f9e,0x3c001,0xf010003e,0x7780,0x3c00000,0xf800000,0xf007,
+ 0xc01f007c,0x1f80000,0x0,0x0,0x0,0x0,0xe003e0,0x7fff00,0x1ef0003,0xc007e007,0xc00301e0,0x1fc003c0,0x1e00,0x7c00,0x301e0007,
+ 0x80007800,0x780,0x3c00fc00,0x7800001f,0xe00ff07f,0x1e00f8,0x3e00780,0x1fc03e00,0xf807801f,0xc01f001c,0xf000,0xf0003c0,0xf0000f0f,
+ 0x1e03,0xc00f8078,0x780000,0xf0003c,0xf000,0x1e0,0x1f3e0,0x0,0x78000,0x1,0xe0000000,0x0,0x780000,0x3c,0x0,0x78000,0x0,0x0,
+ 0x7800000,0x1e00000,0x0,0x0,0x0,0x0,0x0,0x0,0x3c000,0x0,0x0,0x0,0x0,0x0,0x1f,0xf0,0xf80,0x0,0x0,0xf80180,0x0,0x0,0x1e00000,
+ 0x0,0x0,0x0,0xe038,0x0,0x3e00380,0x0,0xfe0f0000,0x0,0xf0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xc0f00070,0x3b370003,0xe0000000,
+ 0x0,0x0,0x3e00,0x1e001e0,0x0,0x780000,0x180000,0x7c000000,0x780,0x780003c,0x3c00,0x0,0x7ffc0,0x780,0x0,0x0,0x3,0xffe00000,
+ 0x1c0,0x3c000000,0xe,0x38,0xf000,0x0,0x3ffe1c00,0x0,0x0,0x38000078,0xf000000,0x1c00,0xe000,0x7f000,0xf000,0x3de000,0x1ef0000,
+ 0xf780000,0x7bc00003,0xde00001e,0xf00003e7,0x80007c00,0x30078000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,
+ 0xe0001e03,0xfc00fe00,0x3c01f007,0xc00f803e,0x7c01f0,0x3e00f80,0x1f007c00,0x7,0xc01f80f0,0x3c0780,0x1e03c00,0xf01e000,0x78078007,
+ 0x801e0000,0x7803c0,0x78000,0x780000,0x380e0003,0x81e00000,0x1f,0xf0000000,0x0,0x780,0x7800,0x380e00,0x0,0x780000,0x7800003,
+ 0x80e00000,0x1ff,0x80000e07,0x800001e0,0x1e00,0xe0380,0xe07800,0x0,0x0,0x0,0x3c000003,0xc00001c0,0x70000000,0x780,0x1e0000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x780000,0x3c1e0000,0x3c0e0007,0xfff01c07,0x1e00,0x1e0,0x780,0xf000,0x3e1c3e0,0x0,0x0,0x0,0x0,0xf0007c0,0x1f00181e,0x20000,
+ 0xf000001f,0xf780,0x3c00000,0x1f000000,0x1f00f,0x800f8078,0xf80000,0x0,0x0,0x0,0x0,0x8003e0,0x1fc0f80,0x1ef0003,0xc001e007,
+ 0x800101e0,0x7e003c0,0x1e00,0x7800,0x101e0007,0x80007800,0x780,0x3c00f800,0x7800001e,0xe00ef07f,0x801e00f0,0x1e00780,0x7c03c00,
+ 0x78078007,0xc01e0004,0xf000,0xf0003c0,0x78001e0f,0x1e03,0xe00f807c,0xf80000,0x1f0003c,0x7800,0x1e0,0x3e1f0,0x0,0x3c000,0x1,
+ 0xe0000000,0x0,0x780000,0x3c,0x0,0x78000,0x0,0x0,0x7800000,0x1e00000,0x0,0x0,0x0,0x0,0x0,0x0,0x3c000,0x0,0x0,0x0,0x0,0x0,
+ 0x1e,0xf0,0x780,0x0,0x0,0x1f00080,0x0,0x0,0x3c00000,0x0,0x0,0x0,0x1e03c,0x0,0x3c00080,0x0,0xf80f0000,0x0,0x1f0000,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x70,0x3bf70003,0xe0000000,0x0,0x0,0x3e00,0x1f003e0,0x0,0x780000,0x180000,0x78000000,0x7c0,0xf80003c,
+ 0x3c00,0x0,0x1f01f0,0x780,0x0,0x0,0xf,0x80f80000,0x1c0,0x1c000000,0xe,0x38,0x1e000,0x0,0x7ffe1c00,0x0,0x0,0x380000f0,0x7800000,
+ 0x1c00,0xe000,0x7fc00,0xf000,0x3de000,0x1ef0000,0xf780000,0x7bc00003,0xde00001e,0xf00003c7,0x80007800,0x10078000,0x3c0000,
+ 0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x7e00ff00,0x3c01e003,0xc00f001e,0x7800f0,0x3c00780,0x1e003c00,
+ 0x7,0x800f00f0,0x3c0780,0x1e03c00,0xf01e000,0x7807c00f,0x801e0000,0xf803c0,0x3c000,0xf00000,0x780f0000,0x0,0x7,0xc0000000,
+ 0x0,0x3c0,0xf000,0x780f00,0x0,0x3c0000,0xf000007,0x80f00000,0x7ff,0xc0000000,0xf0,0x3c00,0x1e03c0,0x0,0x0,0x0,0x0,0x1e000007,
+ 0x800003c0,0x78000000,0xf00,0x1e0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x3c1e0000,0x3c1e001f,0xfff03803,0x80001e00,0x1e0,0x780,0xf000,0xf9cf80,
+ 0x0,0x0,0x0,0x0,0xf000780,0xf00001e,0x0,0xf800000f,0xe780,0x3c00000,0x1e000000,0x1e00f,0x78078,0x7c0000,0x0,0x0,0x0,0x0,0x1e0,
+ 0x3f003c0,0x1ef0003,0xc000f00f,0x800001e0,0x1f003c0,0x1e00,0xf000,0x1e0007,0x80007800,0x780,0x3c01f000,0x7800001e,0xe00ef07f,
+ 0x801e01f0,0x1e00780,0x3c07c00,0x78078003,0xc03e0000,0xf000,0xf0003c0,0x78001e0f,0x1e01,0xf01f003c,0xf00000,0x3e0003c,0x7800,
+ 0x1e0,0x7c0f8,0x0,0x0,0x1,0xe0000000,0x0,0x780000,0x3c,0x0,0x78000,0x0,0x0,0x7800000,0x1e00000,0x0,0x0,0x0,0x0,0x0,0x0,0x3c000,
+ 0x0,0x0,0x0,0x0,0x0,0x1e,0xf0,0x780,0x0,0x0,0x1e00000,0x0,0x0,0x3c00000,0x0,0x8,0x40,0x0,0x7e0000,0x7c00000,0x1,0xf00f0000,
+ 0x0,0x3e0000,0x0,0x3f,0xfc0,0xfc3f0,0xfc3f0,0x0,0x0,0x0,0x70,0x39e70000,0x0,0x0,0x0,0x0,0xf003c0,0x0,0x0,0x180000,0xf8000000,
+ 0x3c0,0xf00003c,0x3c00,0x0,0x3c0078,0x7ff80,0x0,0x0,0x1e,0x3c0000,0x1c0,0x1c000000,0xe,0xf0,0x0,0x0,0x7ffe1c00,0x0,0x0,0x380000f0,
+ 0x7800000,0x1c00,0xe000,0x3c00,0x0,0x3de000,0x1ef0000,0xf780000,0x7bc00003,0xde00001e,0xf00003c7,0x8000f800,0x78000,0x3c0000,
+ 0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x1f00ff00,0x3c03e003,0xc01f001e,0xf800f0,0x7c00780,0x3e003c00,
+ 0xf,0x800f80f0,0x3c0780,0x1e03c00,0xf01e000,0x7803c00f,0x1fffc0,0xf001e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x307,0xe0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1e0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x3c1e0000,0x781e003f,0xfff03803,
+ 0x80001e00,0x1e0,0xf80,0xf000,0x3dde00,0x0,0x0,0x0,0x0,0xf000f00,0x780001e,0x0,0x7800000f,0x1e780,0x3c00000,0x3e000000,0x3e00f,
+ 0x780f0,0x7c0000,0x0,0x0,0x0,0x0,0x1e0,0x7c001e0,0x3ef8003,0xc000f00f,0x1e0,0xf003c0,0x1e00,0xf000,0x1e0007,0x80007800,0x780,
+ 0x3c03e000,0x7800001e,0xf01ef07b,0xc01e01e0,0xf00780,0x3e07800,0x3c078003,0xe03c0000,0xf000,0xf0003c0,0x78001e0f,0x1e00,0xf01e003e,
+ 0x1f00000,0x3c0003c,0x7800,0x1e0,0x78078,0x0,0x0,0x1,0xe0000000,0x0,0x780000,0x3c,0x0,0x78000,0x0,0x0,0x7800000,0x1e00000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x3c000,0x0,0x0,0x0,0x0,0x0,0x1e,0xf0,0x780,0x0,0x0,0x1e00000,0x0,0x0,0x3c00000,0x0,0x18,0xc0,0x0,
+ 0xe70000,0x7800000,0x1,0xe00f0000,0x0,0x3c0000,0x0,0x3f,0xfc0,0xfc1f0,0x1f83f0,0x0,0x0,0x0,0x70,0x39e70000,0x0,0x0,0x0,0x0,
+ 0xf807c0,0x0,0x0,0x180000,0xf0000000,0x3e0,0x1f00003c,0x3e00,0x0,0x70001c,0x3fff80,0x0,0x0,0x38,0xe0000,0x1c0,0x1c000078,
+ 0x1c,0x1fe0,0x0,0x0,0xfffe1c00,0x0,0x0,0x380000f0,0x7800000,0x1c00,0xe000,0xe00,0x0,0x7df000,0x3ef8000,0x1f7c0000,0xfbe00007,
+ 0xdf00003c,0x780003c7,0x8000f000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0xf00f780,
+ 0x3c03c001,0xe01e000f,0xf00078,0x78003c0,0x3c001e00,0xf,0xf80f0,0x3c0780,0x1e03c00,0xf01e000,0x7803e01f,0x1ffff8,0xf001e0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0xe0000000,0x0,0x0,0x0,0x0,0x0,0x0,0xc000,0x0,0x0,0x0,0x0,0x1e0000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x780000,0x3c1e0000,0x781e003e,0x30703803,0x80001e00,0x1e0,0xf00,0x7800,0xff800,0x1e0000,0x0,0x0,0x0,0x1e000f00,0x780001e,
+ 0x0,0x7800000f,0x3c780,0x3c00000,0x3c000000,0x3c00f,0x780f0,0x3c0000,0x0,0x0,0x2000000,0x800000,0x1e0,0x78000e0,0x3c78003,
+ 0xc000f01e,0x1e0,0xf803c0,0x1e00,0x1e000,0x1e0007,0x80007800,0x780,0x3c07c000,0x7800001e,0x701cf07b,0xc01e01e0,0xf00780,0x1e07800,
+ 0x3c078001,0xe03c0000,0xf000,0xf0003c0,0x7c003e0f,0x1e00,0xf83e001e,0x1e00000,0x7c0003c,0x3c00,0x1e0,0xf807c,0x0,0x0,0x1fe0001,
+ 0xe1fc0000,0x7f00003,0xf8780007,0xf000003c,0x7f0,0x783f0,0x0,0x0,0x7800000,0x1e00000,0x3e0f8000,0xfc00007,0xf8000007,0xf00001fc,
+ 0xf,0xc0003fc0,0x3c000,0x0,0x0,0x0,0x0,0x0,0x1e,0xf0,0x780,0x0,0x0,0x3c00000,0x0,0x0,0x3c00000,0x0,0x18,0xc0,0x0,0x1818000,
+ 0x7800000,0x1,0xe00f0000,0x0,0x7c0000,0x0,0x1f,0x80001f80,0x7c1f8,0x1f83e0,0x0,0x0,0x0,0x70,0x38c70007,0xf8000000,0x7f03,
+ 0xf0000000,0x0,0x780780,0x0,0x0,0xfe0000,0xf0000000,0x1e0,0x1e00003c,0x3f00,0x0,0xe07f0e,0x7fff80,0x0,0x0,0x70,0x70000,0x1c0,
+ 0x1c000078,0x3c,0x1fc0,0x0,0x0,0xfffe1c00,0x0,0x0,0x380000f0,0x7800000,0x1c00,0xe000,0xe00,0x0,0x78f000,0x3c78000,0x1e3c0000,
+ 0xf1e00007,0x8f00003c,0x78000787,0x8001e000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,
+ 0xf80f780,0x3c03c001,0xe01e000f,0xf00078,0x78003c0,0x3c001e00,0xf,0x1f80f0,0x3c0780,0x1e03c00,0xf01e000,0x7801e01e,0x1ffffc,
+ 0xf007e0,0x3fc000,0x1fe0000,0xff00000,0x7f800003,0xfc00001f,0xe0000fc0,0xfc00007f,0xfe0,0x7f00,0x3f800,0x1fc000,0x0,0x0,0x0,
+ 0x1,0xf000001f,0x80000ff0,0x7f80,0x3fc00,0x1fe000,0xff0000,0x1f80000,0x1fc1e000,0x0,0x0,0x0,0x0,0x1e1fc0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x3c1e0000,
+ 0x781c007c,0x30003803,0x80001f00,0x1e0,0xf00,0x7800,0x7f000,0x1e0000,0x0,0x0,0x0,0x1e000f00,0x780001e,0x0,0x7800000f,0x3c780,
+ 0x3c00000,0x3c000000,0x3c00f,0x780f0,0x3c0000,0x0,0x0,0x1e000000,0xf00000,0x3e0,0xf0000e0,0x3c78003,0xc000f01e,0x1e0,0x7803c0,
+ 0x1e00,0x1e000,0x1e0007,0x80007800,0x780,0x3c0f8000,0x7800001e,0x701cf079,0xe01e01e0,0xf00780,0x1e07800,0x3c078001,0xe03c0000,
+ 0xf000,0xf0003c0,0x3c003c0f,0x3e00,0x787c001f,0x3e00000,0xf80003c,0x3c00,0x1e0,0x1f003e,0x0,0x0,0x1fffc001,0xe7ff0000,0x3ffe000f,
+ 0xfe78003f,0xfc001fff,0xfe001ffc,0xf0078ffc,0x1ffc00,0x7ff000,0x7800f80,0x1e0000f,0x7f1fc01e,0x3ff0001f,0xfe00079f,0xfc0007ff,
+ 0x3c003c7f,0xf001fff8,0x1fffff0,0x3c003c0,0xf0000f1e,0xf1f,0x7c1f0,0x1f00ff,0xffe0001e,0xf0,0x780,0x0,0x0,0x3c00000,0x100000,
+ 0x0,0x7800000,0x0,0x18,0xc0,0x0,0x1818000,0x7800000,0x1,0xe00f0000,0x1000000,0xf80000,0x40000002,0xf,0x80001f00,0x7e0f8,0x1f07c0,
+ 0x0,0x0,0x0,0x70,0x38c7003f,0xff000000,0xff8f,0xf8000100,0xffffe,0x7c0f80,0x0,0x0,0x3ffc000,0xf0000020,0x1001f0,0x3c00003c,
+ 0x1f80,0x0,0x1c3ffc7,0x7c0780,0x0,0x0,0xe3,0xff038000,0xe0,0x38000078,0x78,0x1ff0,0x0,0x3c003c0,0xfffe1c00,0x0,0x0,0x380000f0,
+ 0x7800000,0x1c00,0xe000,0xe00,0xf000,0x78f000,0x3c78000,0x1e3c0000,0xf1e00007,0x8f00003c,0x78000787,0x8001e000,0x78000,0x3c0000,
+ 0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x780f3c0,0x3c03c001,0xe01e000f,0xf00078,0x78003c0,0x3c001e00,
+ 0x4000200f,0x3f80f0,0x3c0780,0x1e03c00,0xf01e000,0x7801f03e,0x1ffffe,0xf01fe0,0x3fff800,0x1fffc000,0xfffe0007,0xfff0003f,
+ 0xff8001ff,0xfc003ff3,0xfe0003ff,0xe0007ff8,0x3ffc0,0x1ffe00,0xfff000,0x3ff80001,0xffc0000f,0xfe00007f,0xf000003f,0xf8003c7f,
+ 0xe0003ffc,0x1ffe0,0xfff00,0x7ff800,0x3ffc000,0x1f80000,0xfff1c03c,0x3c01e0,0x1e00f00,0xf007800,0x781f0001,0xf01e7ff0,0x7c0007c,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,
+ 0x3c1e003f,0xfffff078,0x30003803,0x80000f00,0x1e0,0x1f00,0x7800,0x7f000,0x1e0000,0x0,0x0,0x0,0x3c000f00,0x780001e,0x0,0x7800000f,
+ 0x78780,0x3c00000,0x3c000000,0x7c00f,0x780f0,0x3c0007,0xe000003f,0x0,0xfe000000,0xfe0000,0x3c0,0x1f000070,0x7c7c003,0xc000f01e,
+ 0x1e0,0x7803c0,0x1e00,0x1e000,0x1e0007,0x80007800,0x780,0x3c1f0000,0x7800001e,0x783cf079,0xe01e03c0,0xf00780,0x1e0f000,0x3c078001,
+ 0xe03c0000,0xf000,0xf0003c0,0x3c003c07,0x81f03c00,0x7c7c000f,0x87c00000,0xf00003c,0x1e00,0x1e0,0x3e001f,0x0,0x0,0x3fffe001,
+ 0xefff8000,0x7fff001f,0xff78007f,0xfe001fff,0xfe003ffe,0xf0079ffe,0x1ffc00,0x7ff000,0x7801f00,0x1e0000f,0xffbfe01e,0x7ff8003f,
+ 0xff0007bf,0xfe000fff,0xbc003cff,0xf803fffc,0x1fffff0,0x3c003c0,0x78001e1e,0xf0f,0x800f80f0,0x1e00ff,0xffe0001e,0xf0,0x780,
+ 0x0,0x0,0x3c00000,0x380000,0x0,0x7800000,0x0,0x18,0xc0,0x0,0x1008000,0x7800000,0x3,0xe00f0000,0x3800000,0xf00000,0xe0000007,
+ 0xf,0x80001f00,0x3e0f8,0x1e07c0,0x0,0x0,0x0,0x70,0x3807007f,0xff800000,0x1ffdf,0xfc000380,0xffffe,0x3e1f00,0x0,0x0,0xfffe000,
+ 0xf0000030,0x3800f8,0x7c00003c,0xfc0,0x0,0x18780c3,0xf00780,0x80100,0x0,0xc3,0xffc18000,0xf0,0x78000078,0xf0,0xf0,0x0,0x3c003c0,
+ 0xfffe1c00,0x0,0x0,0x380000f0,0x7800801,0x1c00,0xe000,0x1e00,0xf000,0xf8f800,0x7c7c000,0x3e3e0001,0xf1f0000f,0x8f80007c,0x7c000787,
+ 0x8001e000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x780f3c0,0x3c078001,0xe03c000f,
+ 0x1e00078,0xf0003c0,0x78001e00,0xe000701f,0x3fc0f0,0x3c0780,0x1e03c00,0xf01e000,0x7800f87c,0x1e007f,0xf07e00,0x7fffc00,0x3fffe001,
+ 0xffff000f,0xfff8007f,0xffc003ff,0xfe007ff7,0xff0007ff,0xf000fffc,0x7ffe0,0x3fff00,0x1fff800,0x3ff80001,0xffc0000f,0xfe00007f,
+ 0xf00000ff,0xf8003cff,0xf0007ffe,0x3fff0,0x1fff80,0xfffc00,0x7ffe000,0x1f80001,0xfffb803c,0x3c01e0,0x1e00f00,0xf007800,0x780f0001,
+ 0xe01efff8,0x3c00078,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x780000,0x3c1e003f,0xfffff078,0x30001c07,0xf80,0x1e0,0x1e00,0x3c00,0xff800,0x1e0000,0x0,0x0,0x0,0x3c001e00,
+ 0x3c0001e,0x0,0x7800001e,0x70780,0x3c00000,0x78000000,0x78007,0x800f00f0,0x3e0007,0xe000003f,0x3,0xfe000000,0xff8000,0x7c0,
+ 0x1e000070,0x783c003,0xc001f01e,0x1e0,0x7803c0,0x1e00,0x1e000,0x1e0007,0x80007800,0x780,0x3c3e0000,0x7800001e,0x3838f079,
+ 0xe01e03c0,0x780780,0x1e0f000,0x1e078001,0xe03c0000,0xf000,0xf0003c0,0x3c007c07,0x81f03c00,0x3ef80007,0x87800000,0x1f00003c,
+ 0x1e00,0x1e0,0x7c000f,0x80000000,0x0,0x3ffff001,0xffffc000,0xffff003f,0xff7800ff,0xff001fff,0xfe007ffe,0xf007bffe,0x1ffc00,
+ 0x7ff000,0x7803e00,0x1e0000f,0xffffe01e,0xfff8007f,0xff8007ff,0xff001fff,0xbc003dff,0xf807fffc,0x1fffff0,0x3c003c0,0x78001e0f,
+ 0x1e07,0xc01f00f0,0x1e00ff,0xffe0001e,0xf0,0x780,0x0,0x0,0x7c00000,0x7c0000,0x0,0x7800000,0x0,0x18,0xc0,0x0,0x1018000,0x7800000,
+ 0x3,0xc00f0000,0x7c00000,0x1f00001,0xf000000f,0x80000007,0xc0003e00,0x1e07c,0x3e0780,0x0,0x0,0x0,0x70,0x380700ff,0xff800000,
+ 0x3ffff,0xfe0007c0,0xffffe,0x1e1e00,0x0,0x780000,0x1fffe000,0xf0000078,0x7c0078,0x7800003c,0xff0,0x0,0x38e0003,0x80f00780,
+ 0x180300,0x0,0x1c3,0x81e1c000,0x7f,0xf0000078,0x1e0,0x38,0x0,0x3c003c0,0xfffe1c00,0x0,0x0,0x380000f0,0x7800c01,0x80001c00,
+ 0xe000,0x603e00,0xf000,0xf07800,0x783c000,0x3c1e0001,0xe0f0000f,0x7800078,0x3c000f87,0x8001e000,0x78000,0x3c0000,0x1e00000,
+ 0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x780f3c0,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f01,0xf000f81e,
+ 0x7bc0f0,0x3c0780,0x1e03c00,0xf01e000,0x78007878,0x1e001f,0xf0f800,0x7fffe00,0x3ffff001,0xffff800f,0xfffc007f,0xffe003ff,
+ 0xff007fff,0xff800fff,0xf001fffe,0xffff0,0x7fff80,0x3fffc00,0x3ff80001,0xffc0000f,0xfe00007f,0xf00001ff,0xfc003dff,0xf000ffff,
+ 0x7fff8,0x3fffc0,0x1fffe00,0xffff000,0x1f80003,0xffff803c,0x3c01e0,0x1e00f00,0xf007800,0x780f0001,0xe01ffffc,0x3c00078,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,
+ 0x3c1e003f,0xfffff078,0x30001e0f,0x300780,0x1e0,0x1e00,0x3c00,0x3dde00,0x1e0000,0x0,0x0,0x0,0x78001e00,0x3c0001e,0x0,0xf800003e,
+ 0xf0780,0x3dfc000,0x783f8000,0xf8007,0xc01f00f0,0x3e0007,0xe000003f,0x1f,0xfc000000,0x7ff000,0xf80,0x3e007c70,0x783c003,0xc001e03c,
+ 0x1e0,0x3c03c0,0x1e00,0x3c000,0x1e0007,0x80007800,0x780,0x3c7c0000,0x7800001e,0x3878f078,0xf01e03c0,0x780780,0x1e0f000,0x1e078001,
+ 0xe03e0000,0xf000,0xf0003c0,0x1e007807,0x83f03c00,0x3ef00007,0xcf800000,0x3e00003c,0xf00,0x1e0,0xf80007,0xc0000000,0x0,0x3e01f801,
+ 0xfe07e001,0xf80f007e,0x7f801f8,0x1f801fff,0xfe00fc0f,0xf007f83f,0x1ffc00,0x7ff000,0x7807c00,0x1e0000f,0x87e1e01f,0xe0fc00fc,
+ 0xfc007f8,0x1f803f03,0xfc003df0,0x3807e03c,0x1fffff0,0x3c003c0,0x78003e0f,0x1e03,0xe03e00f8,0x3e00ff,0xffe0001e,0xf0,0x780,
+ 0x0,0x0,0x7800000,0xfe0000,0x0,0x7800000,0x0,0x18,0xc0,0x0,0x1818000,0x7c00000,0x3,0xc00f0000,0xfe00000,0x3e00003,0xf800001f,
+ 0xc0000007,0xc0003e00,0x1e03c,0x3c0f80,0x0,0x0,0x0,0x70,0x380700fc,0x7800000,0x7c1fe,0x3e000fe0,0xffffe,0x1f3e00,0x0,0x780000,
+ 0x3f98e000,0xf000003c,0xfcf8007c,0xf800003c,0x3ffc,0x0,0x31c0001,0x80f00f80,0x380700,0x0,0x183,0x80e0c000,0x3f,0xe0000078,
+ 0x3c0,0x38,0x0,0x3c003c0,0xfffe1c00,0x0,0x0,0x38000078,0xf000e01,0xc003ffe0,0x1fff00,0x7ffc00,0xf000,0xf07800,0x783c000,0x3c1e0001,
+ 0xe0f0000f,0x7800078,0x3c000f07,0x8003c000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,
+ 0x3c0f1e0,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0xf801f01e,0xf3c0f0,0x3c0780,0x1e03c00,0xf01e000,0x78007cf8,
+ 0x1e000f,0x80f0f000,0x7c03f00,0x3e01f801,0xf00fc00f,0x807e007c,0x3f003e0,0x1f80707f,0x8f801f80,0xf003f03f,0x1f81f8,0xfc0fc0,
+ 0x7e07e00,0x3ff80001,0xffc0000f,0xfe00007f,0xf00003ff,0xfc003fc1,0xf801f81f,0x800fc0fc,0x7e07e0,0x3f03f00,0x1f81f800,0x1f80007,
+ 0xe07f003c,0x3c01e0,0x1e00f00,0xf007800,0x780f8003,0xe01fe07e,0x3e000f8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x3f,0xfffff078,0x30000ffe,0x1f007c0,0x0,0x1e00,
+ 0x3c00,0xf9cf80,0x1e0000,0x0,0x0,0x0,0x78001e00,0x3c0001e,0x0,0xf00000fc,0x1e0780,0x3fff800,0x78ffe000,0xf0003,0xe03e00f0,
+ 0x3e0007,0xe000003f,0x7f,0xe01fffff,0xf00ffc00,0x1f80,0x3c01ff70,0x783c003,0xc007e03c,0x1e0,0x3c03c0,0x1e00,0x3c000,0x1e0007,
+ 0x80007800,0x780,0x3cfc0000,0x7800001e,0x3c78f078,0xf01e03c0,0x780780,0x3e0f000,0x1e078003,0xc01f0000,0xf000,0xf0003c0,0x1e007807,
+ 0x83f83c00,0x1ff00003,0xcf000000,0x3e00003c,0xf00,0x1e0,0x0,0x0,0x0,0x20007801,0xfc03e003,0xe003007c,0x3f803e0,0x7c0003c,
+ 0xf807,0xf007e00f,0x3c00,0xf000,0x780f800,0x1e0000f,0x87e1f01f,0x803c00f8,0x7c007f0,0xf803e01,0xfc003f80,0x80f8004,0x3c000,
+ 0x3c003c0,0x3c003c0f,0x1e03,0xe03e0078,0x3c0000,0x7c0001e,0xf0,0x780,0x0,0x0,0x3ffff800,0x1ff0000,0x0,0x7800000,0x0,0x18,
+ 0xc0,0x0,0x1818000,0x3e00000,0x3,0xc00f0000,0x1ff00000,0x3e00007,0xfc00003f,0xe0000003,0xc0003c00,0xf03c,0x3c0f00,0x0,0x0,
+ 0x0,0x70,0x380701f0,0x800000,0x780fc,0x1e001ff0,0x7c,0xf3c00,0x0,0x780000,0x7e182000,0xf000001f,0xfff00ffc,0xffc0003c,0x3cfe,
+ 0x0,0x31c0001,0x80f01f80,0x780f00,0x0,0x183,0x80e0c000,0xf,0x80000078,0x780,0x38,0x0,0x3c003c0,0x7ffe1c00,0x0,0x0,0x38000078,
+ 0xf000f01,0xe003ffe0,0x1fff00,0x7ff800,0xf000,0xf07800,0x783c000,0x3c1e0001,0xe0f0000f,0x78000f8,0x3e000f07,0x8003c000,0x78000,
+ 0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x3c0f1e0,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,
+ 0x78000f00,0x7c03e01e,0x1e3c0f0,0x3c0780,0x1e03c00,0xf01e000,0x78003cf0,0x1e0007,0x80f1e000,0x4000f00,0x20007801,0x3c008,
+ 0x1e0040,0xf00200,0x780403f,0x7803e00,0x3007c00f,0x803e007c,0x1f003e0,0xf801f00,0x780000,0x3c00000,0x1e000000,0xf00007f0,
+ 0x3e003f00,0x7801f00f,0x800f807c,0x7c03e0,0x3e01f00,0x1f00f800,0x1f80007,0xc03e003c,0x3c01e0,0x1e00f00,0xf007800,0x78078003,
+ 0xc01fc03e,0x1e000f0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x780000,0x0,0xf078007c,0x300007fc,0x7e00fe0,0x0,0x1e00,0x3c00,0x3e1c3e0,0x1e0000,0x0,0x0,0x0,0xf0001e00,
+ 0x3c0001e,0x1,0xf000fff8,0x1e0780,0x3fffe00,0x79fff000,0x1f0001,0xfffc00f0,0x7e0007,0xe000003f,0x3ff,0x801fffff,0xf003ff80,
+ 0x3f00,0x3c03fff0,0xf01e003,0xffffc03c,0x1e0,0x3c03ff,0xffc01fff,0xfe03c000,0x1fffff,0x80007800,0x780,0x3df80000,0x7800001e,
+ 0x1c70f078,0x781e03c0,0x780780,0x3c0f000,0x1e078007,0xc01f8000,0xf000,0xf0003c0,0x1e007807,0x83f83c00,0xfe00003,0xff000000,
+ 0x7c00003c,0x780,0x1e0,0x0,0x0,0x0,0x7c01,0xf801f007,0xc00100f8,0x1f803c0,0x3c0003c,0x1f003,0xf007c00f,0x80003c00,0xf000,
+ 0x783f000,0x1e0000f,0x3c0f01f,0x3e01f0,0x3e007e0,0x7c07c00,0xfc003f00,0xf0000,0x3c000,0x3c003c0,0x3c003c0f,0x1e01,0xf07c007c,
+ 0x7c0000,0xfc0001e,0xf0,0x780,0x0,0x0,0x3ffff000,0x3838000,0x0,0x7800000,0x0,0x18,0xc0,0x0,0xff0000,0x3f00000,0x3,0xc00fff00,
+ 0x38380000,0x7c0000e,0xe000070,0x70000001,0xe0003c00,0xf01e,0x780e00,0x0,0x0,0x0,0x0,0x1e0,0x0,0x780f8,0xf003838,0xfc,0xffc00,
+ 0x0,0x780000,0x7c180000,0xf000000f,0xffe00fff,0xffc0003c,0x783f,0x80000000,0x6380000,0xc0f83f80,0xf81f00,0x0,0x303,0x80e06000,
+ 0x0,0x78,0xf00,0x78,0x0,0x3c003c0,0x7ffe1c00,0x0,0x0,0x3800003c,0x3e000f81,0xf003ffe0,0x1fff00,0x1fc000,0xf000,0x1e03c00,
+ 0xf01e000,0x780f0003,0xc078001e,0x3c000f0,0x1e000f07,0xff83c000,0x7ffff,0x803ffffc,0x1ffffe0,0xfffff00,0xf00000,0x7800000,
+ 0x3c000001,0xe0001e00,0x3c0f0f0,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0x3e07c01e,0x1e3c0f0,0x3c0780,0x1e03c00,
+ 0xf01e000,0x78003ff0,0x1e0007,0x80f1e000,0xf80,0x7c00,0x3e000,0x1f0000,0xf80000,0x7c0001e,0x3c07c00,0x10078007,0x803c003c,
+ 0x1e001e0,0xf000f00,0x780000,0x3c00000,0x1e000000,0xf00007c0,0x1e003e00,0x7c03e007,0xc01f003e,0xf801f0,0x7c00f80,0x3e007c00,
+ 0xf,0x801f003c,0x3c01e0,0x1e00f00,0xf007800,0x7807c007,0xc01f801f,0x1f001f0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x0,0xe078003c,0x300001f0,0x3f801ff0,0x0,
+ 0x3c00,0x1e00,0x3c1c1e0,0x1e0000,0x0,0x0,0x0,0xf0001e0f,0x3c0001e,0x3,0xe000fff0,0x3c0780,0x3ffff00,0x7bfff800,0x1e0000,0x7ff00078,
+ 0x7e0007,0xe000003f,0x1ffc,0x1fffff,0xf0007ff0,0x7e00,0x3c07c3f0,0xf01e003,0xffff003c,0x1e0,0x3c03ff,0xffc01fff,0xfe03c000,
+ 0x1fffff,0x80007800,0x780,0x3ffc0000,0x7800001e,0x1ef0f078,0x781e03c0,0x780780,0x7c0f000,0x1e07801f,0x800ff000,0xf000,0xf0003c0,
+ 0xf00f807,0x83b83c00,0xfc00001,0xfe000000,0xf800003c,0x780,0x1e0,0x0,0x0,0x0,0x3c01,0xf000f007,0xc00000f0,0xf80780,0x3c0003c,
+ 0x1e001,0xf007c007,0x80003c00,0xf000,0x787e000,0x1e0000f,0x3c0f01f,0x1e01e0,0x1e007c0,0x3c07800,0x7c003f00,0xf0000,0x3c000,
+ 0x3c003c0,0x3e007c07,0x80003c00,0xf8f8003c,0x780000,0xf80001e,0xf0,0x780,0x0,0x0,0x7ffff000,0x601c000,0x3,0xffff0000,0x0,
+ 0xfff,0xf8007fff,0xc0000000,0x7e003c,0x1fe0000,0xc0003,0xc00fff00,0x601c0000,0xf800018,0x70000c0,0x38000001,0xe0007800,0x701e,
+ 0x701e00,0x0,0x0,0x0,0x0,0x1e0,0x6,0x700f8,0xf00601c,0xf8,0x7f800,0x0,0x780000,0xf8180000,0xf000000f,0x87c00fff,0xffc0003c,
+ 0xf01f,0xc0000000,0x6380000,0xc07ff780,0x1f03e03,0xfffffe00,0x303,0x81c06000,0x0,0x1ffff,0xfe001e00,0x180f8,0x0,0x3c003c0,
+ 0x3ffe1c00,0x3f00000,0x0,0x3800003f,0xfe0007c0,0xf8000000,0x18000000,0xc0000006,0x1f000,0x1e03c00,0xf01e000,0x780f0003,0xc078001e,
+ 0x3c000f0,0x1e001f07,0xff83c000,0x7ffff,0x803ffffc,0x1ffffe0,0xfffff00,0xf00000,0x7800000,0x3c000001,0xe000fff8,0x3c0f0f0,
+ 0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0x1f0f801e,0x3c3c0f0,0x3c0780,0x1e03c00,0xf01e000,0x78001fe0,0x1e0007,
+ 0x80f1e000,0x780,0x3c00,0x1e000,0xf0000,0x780000,0x3c0001e,0x3c07c00,0xf0007,0x8078003c,0x3c001e0,0x1e000f00,0x780000,0x3c00000,
+ 0x1e000000,0xf0000f80,0x1f003e00,0x3c03c003,0xc01e001e,0xf000f0,0x7800780,0x3c003c00,0xf,0x3f003c,0x3c01e0,0x1e00f00,0xf007800,
+ 0x7803c007,0x801f000f,0xf001e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1,0xe078003f,0xb0000000,0xfc003cf0,0x0,0x3c00,0x1e00,0x101c040,0x1e0000,0x0,0x0,0x1,
+ 0xe0001e1f,0x83c0001e,0x7,0xe000fff0,0x3c0780,0x3c03f80,0x7fc0fc00,0x1e0000,0xfff80078,0xfe0007,0xe000003f,0x7fe0,0x1fffff,
+ 0xf0000ffc,0xfc00,0x780f81f0,0xf01e003,0xffff003c,0x1e0,0x3c03ff,0xffc01fff,0xfe03c000,0x1fffff,0x80007800,0x780,0x3ffc0000,
+ 0x7800001e,0x1ef0f078,0x3c1e03c0,0x780780,0x1fc0f000,0x1e07ffff,0x7ff00,0xf000,0xf0003c0,0xf00f007,0xc3b87c00,0x7c00001,0xfe000000,
+ 0xf800003c,0x3c0,0x1e0,0x0,0x0,0x0,0x3c01,0xf000f007,0x800000f0,0xf80780,0x1e0003c,0x1e001,0xf0078007,0x80003c00,0xf000,0x78fc000,
+ 0x1e0000f,0x3c0f01e,0x1e01e0,0x1e007c0,0x3c07800,0x7c003e00,0xf0000,0x3c000,0x3c003c0,0x1e007807,0x80003c00,0x7df0003c,0x780000,
+ 0x1f00001e,0xf0,0x780,0x0,0x0,0x7800000,0xe7ce000,0x3,0xffff0000,0x0,0xfff,0xf8007fff,0xc0000000,0x1f0,0xffe000,0x1c0003,
+ 0xc00fff00,0xe7ce0000,0xf800039,0xf38001cf,0x9c000000,0xe0007800,0x780e,0x701c00,0x0,0x0,0x0,0x0,0x1e0,0x7,0xf0078,0xf00e7ce,
+ 0x1f0,0x7f800,0x0,0x780000,0xf0180000,0xf000000e,0x1c0001f,0xe000003c,0xf007,0xe0000000,0x6380000,0xc03fe780,0x3e07c03,0xfffffe00,
+ 0x303,0xffc06000,0x0,0x1ffff,0xfe003ffe,0x1fff0,0x0,0x3c003c0,0x1ffe1c00,0x3f00000,0x7,0xffc0001f,0xfc0003e0,0x7c000001,0xfc00000f,
+ 0xe000007f,0x1e000,0x1e03c00,0xf01e000,0x780f0003,0xc078001e,0x3c000f0,0x1e001e07,0xff83c000,0x7ffff,0x803ffffc,0x1ffffe0,
+ 0xfffff00,0xf00000,0x7800000,0x3c000001,0xe000fff8,0x3c0f078,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0xf9f001e,
+ 0x783c0f0,0x3c0780,0x1e03c00,0xf01e000,0x78001fe0,0x1e0007,0x80f1e000,0x780,0x3c00,0x1e000,0xf0000,0x780000,0x3c0001e,0x3c07800,
+ 0xf0003,0xc078001e,0x3c000f0,0x1e000780,0x780000,0x3c00000,0x1e000000,0xf0000f00,0xf003c00,0x3c03c003,0xc01e001e,0xf000f0,
+ 0x7800780,0x3c003c00,0xf,0x7f003c,0x3c01e0,0x1e00f00,0xf007800,0x7803c007,0x801f000f,0xf001e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1,0xe070001f,0xf8000007,
+ 0xf0007cf8,0x7800000,0x3c00,0x1e00,0x1c000,0x1e0000,0x0,0x0,0x1,0xe0001e1f,0x83c0001e,0xf,0xc000fff8,0x780780,0x2000f80,0x7f803e00,
+ 0x3e0003,0xfffe007c,0x1fe0000,0x0,0x3ff00,0x0,0x1ff,0x8001f000,0x780f00f0,0x1f00f003,0xffffc03c,0x1e0,0x3c03ff,0xffc01fff,
+ 0xfe03c00f,0xf81fffff,0x80007800,0x780,0x3ffe0000,0x7800001e,0xee0f078,0x3c1e03c0,0x7807ff,0xff80f000,0x1e07fffe,0x3ffe0,
+ 0xf000,0xf0003c0,0xf00f003,0xc7bc7800,0xfc00000,0xfc000001,0xf000003c,0x3c0,0x1e0,0x0,0x0,0x0,0x3c01,0xe000f80f,0x800001e0,
+ 0xf80f00,0x1e0003c,0x3c000,0xf0078007,0x80003c00,0xf000,0x79f8000,0x1e0000f,0x3c0f01e,0x1e03c0,0x1f00780,0x3e0f000,0x7c003e00,
+ 0xf0000,0x3c000,0x3c003c0,0x1e007807,0x81e03c00,0x7df0003e,0xf80000,0x3e00003e,0xf0,0x7c0,0xfc000,0x80000000,0x7800000,0x1e7cf000,
+ 0x3,0xffff0000,0x0,0x18,0xc0,0x0,0xf80,0x7ffc00,0x380003,0xc00fff01,0xe7cf0000,0x1f000079,0xf3c003cf,0x9e000000,0xe0007000,
+ 0x380e,0xe01c00,0x0,0x0,0x0,0x0,0x1e0,0x3,0x800f0078,0xf01e7cf,0x3e0,0x3f000,0x0,0x780000,0xf018001f,0xfff8001e,0x1e0000f,
+ 0xc000003c,0xf003,0xe0000000,0x6380000,0xc00fc780,0x7c0f803,0xfffffe00,0x303,0xfe006000,0x0,0x1ffff,0xfe003ffe,0x1ffe0,0x0,
+ 0x3c003c0,0xffe1c00,0x3f00000,0x7,0xffc00007,0xf00001f0,0x3e00001f,0xfc0000ff,0xe00007ff,0x3e000,0x3e01e00,0x1f00f000,0xf8078007,
+ 0xc03c003e,0x1e001e0,0xf001e07,0xff83c000,0x7ffff,0x803ffffc,0x1ffffe0,0xfffff00,0xf00000,0x7800000,0x3c000001,0xe000fff8,
+ 0x3c0f078,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0x7fe001e,0xf03c0f0,0x3c0780,0x1e03c00,0xf01e000,0x78000fc0,
+ 0x1e0007,0x80f1f000,0x780,0x3c00,0x1e000,0xf0000,0x780000,0x3c0001e,0x3c0f800,0x1e0003,0xc0f0001e,0x78000f0,0x3c000780,0x780000,
+ 0x3c00000,0x1e000000,0xf0000f00,0xf003c00,0x3c078003,0xe03c001f,0x1e000f8,0xf0007c0,0x78003e00,0x1e,0xf7803c,0x3c01e0,0x1e00f00,
+ 0xf007800,0x7803e00f,0x801e000f,0x80f803e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1,0xe0f0000f,0xff00001f,0x8000f87c,0x7800000,0x3c00,0x1e00,0x1c000,0x7fffff80,
+ 0x0,0x0,0x3,0xc0001e1f,0x83c0001e,0x1f,0x800000fe,0xf00780,0x7c0,0x7f001e00,0x3c0007,0xe03f003f,0x3fe0000,0x0,0x3fc00,0x0,
+ 0x7f,0x8001e000,0x781f00f0,0x1e00f003,0xc007e03c,0x1e0,0x3c03c0,0x1e00,0x3c00f,0xf81e0007,0x80007800,0x780,0x3f9f0000,0x7800001e,
+ 0xfe0f078,0x3c1e03c0,0x7807ff,0xff00f000,0x1e07fff8,0xfff8,0xf000,0xf0003c0,0xf81f003,0xc7bc7800,0xfe00000,0x78000003,0xe000003c,
+ 0x1e0,0x1e0,0x0,0x0,0x0,0x1fffc01,0xe000780f,0x1e0,0x780f00,0x1e0003c,0x3c000,0xf0078007,0x80003c00,0xf000,0x7bf0000,0x1e0000f,
+ 0x3c0f01e,0x1e03c0,0xf00780,0x1e0f000,0x3c003c00,0xf8000,0x3c000,0x3c003c0,0x1f00f807,0x81f03c00,0x3fe0001e,0xf00000,0x7c00007c,
+ 0xf0,0x3e0,0x3ff801,0x80000000,0x7800000,0x3cfcf800,0x3,0xffff0000,0x0,0x18,0xc0,0x0,0x7c00,0x1fff00,0x700003,0xc00f0003,
+ 0xcfcf8000,0x3e0000f3,0xf3e0079f,0x9f000000,0xf000,0x1000,0x0,0x0,0x0,0x0,0x0,0x1f0,0x1,0xc00f0078,0xf03cfcf,0x800007c0,0x1e000,
+ 0x0,0x780001,0xe018001f,0xfff8001c,0xe00007,0x8000003c,0xf001,0xf0000000,0x6380000,0xc0000000,0xf81f003,0xfffffe00,0x303,
+ 0x87006000,0x0,0x1ffff,0xfe003ffe,0x7f00,0x0,0x3c003c0,0x3fe1c00,0x3f00000,0x7,0xffc00000,0xf8,0x1f0001ff,0xf0000fff,0x80007ffc,
+ 0xfc000,0x3c01e00,0x1e00f000,0xf0078007,0x803c003c,0x1e001e0,0xf001e07,0x8003c000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,
+ 0x7800000,0x3c000001,0xe000fff8,0x3c0f078,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0x3fc001e,0x1e03c0f0,0x3c0780,
+ 0x1e03c00,0xf01e000,0x78000780,0x1e0007,0x80f0fc00,0x3fff80,0x1fffc00,0xfffe000,0x7fff0003,0xfff8001f,0xffc0001e,0x3c0f000,
+ 0x1e0003,0xc0f0001e,0x78000f0,0x3c000780,0x780000,0x3c00000,0x1e000000,0xf0001e00,0xf803c00,0x3c078001,0xe03c000f,0x1e00078,
+ 0xf0003c0,0x78001e07,0xfffffe1e,0x1e7803c,0x3c01e0,0x1e00f00,0xf007800,0x7801e00f,0x1e0007,0x807803c0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x3,0xc0f00007,
+ 0xffc0007e,0xf03e,0x7800000,0x3c00,0x1e00,0x1c000,0x7fffff80,0x0,0x0,0x3,0xc0001e1f,0x83c0001e,0x3f,0x3e,0xf00780,0x3c0,0x7e001e00,
+ 0x7c000f,0x800f001f,0xffde0000,0x0,0x3e000,0x0,0xf,0x8003e000,0x781e0070,0x1e00f003,0xc001f03c,0x1e0,0x3c03c0,0x1e00,0x3c00f,
+ 0xf81e0007,0x80007800,0x780,0x3f1f0000,0x7800001e,0x7c0f078,0x1e1e03c0,0x7807ff,0xfc00f000,0x1e07fffe,0xffc,0xf000,0xf0003c0,
+ 0x781e003,0xc71c7800,0x1ff00000,0x78000003,0xe000003c,0x1e0,0x1e0,0x0,0x0,0x0,0xffffc01,0xe000780f,0x1e0,0x780fff,0xffe0003c,
+ 0x3c000,0xf0078007,0x80003c00,0xf000,0x7ff0000,0x1e0000f,0x3c0f01e,0x1e03c0,0xf00780,0x1e0f000,0x3c003c00,0x7f000,0x3c000,
+ 0x3c003c0,0xf00f007,0xc1f07c00,0x1fc0001f,0x1f00000,0xfc000ff8,0xf0,0x1ff,0xfffe07,0x80000000,0x7800000,0x7ffcfc00,0x0,0xf000000,
+ 0x0,0x18,0xc0,0x0,0x3e000,0x1ff80,0xe00003,0xc00f0007,0xffcfc000,0x3e0001ff,0xf3f00fff,0x9f800000,0x6000,0x0,0x0,0x7c000,
+ 0x0,0x0,0x0,0xfe,0x0,0xe00f007f,0xff07ffcf,0xc0000fc0,0x1e000,0x0,0x780001,0xe018001f,0xfff8001c,0xe00007,0x80000000,0xf800,
+ 0xf0000000,0x6380000,0xc0000000,0x1f03c000,0x1e00,0x303,0x83806000,0x0,0x78,0x0,0x0,0x0,0x3c003c0,0xfe1c00,0x3f00000,0x0,
+ 0x0,0x3c,0xf801fff,0xfff8,0x7ffc0,0x1f8000,0x3c01e00,0x1e00f000,0xf0078007,0x803c003c,0x1e001e0,0xf003c07,0x8003c000,0x78000,
+ 0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x3c0f03c,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,
+ 0x78000f00,0x1f8001e,0x1e03c0f0,0x3c0780,0x1e03c00,0xf01e000,0x78000780,0x1e000f,0x80f0ff00,0x1ffff80,0xffffc00,0x7fffe003,
+ 0xffff001f,0xfff800ff,0xffc007ff,0xffc0f000,0x1fffff,0xc0fffffe,0x7fffff0,0x3fffff80,0x780000,0x3c00000,0x1e000000,0xf0001e00,
+ 0x7803c00,0x3c078001,0xe03c000f,0x1e00078,0xf0003c0,0x78001e07,0xfffffe1e,0x3c7803c,0x3c01e0,0x1e00f00,0xf007800,0x7801f01f,
+ 0x1e0007,0x807c07c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x780000,0x3,0xc0f00000,0xfff003f0,0x1f00f03e,0x7800000,0x3c00,0x1e00,0x1c000,0x7fffff80,0x0,0x7ff80000,0x3,
+ 0xc0001e0f,0x3c0001e,0x7e,0x1f,0x1e00780,0x3e0,0x7e000f00,0x78000f,0x7800f,0xff9e0000,0x0,0x3fc00,0x0,0x7f,0x8003c000,0x781e0070,
+ 0x3e00f803,0xc000f03c,0x1e0,0x3c03c0,0x1e00,0x3c00f,0xf81e0007,0x80007800,0x780,0x3e0f8000,0x7800001e,0x7c0f078,0x1e1e03c0,
+ 0x7807ff,0xf000f000,0x1e07807f,0xfe,0xf000,0xf0003c0,0x781e003,0xc71c7800,0x3ef00000,0x78000007,0xc000003c,0x1e0,0x1e0,0x0,
+ 0x0,0x0,0x1ffffc01,0xe000780f,0x1e0,0x780fff,0xffe0003c,0x3c000,0xf0078007,0x80003c00,0xf000,0x7ff0000,0x1e0000f,0x3c0f01e,
+ 0x1e03c0,0xf00780,0x1e0f000,0x3c003c00,0x7ff80,0x3c000,0x3c003c0,0xf00f003,0xc1f07800,0x1fc0000f,0x1e00000,0xf8000ff0,0xf0,
+ 0xff,0xffffff,0x80000000,0x3fffc000,0xfff9fe00,0x0,0xf000000,0x0,0x18,0xc0,0x0,0x1f0000,0x1fc0,0x1c00003,0xc00f000f,0xff9fe000,
+ 0x7c0003ff,0xe7f81fff,0x3fc00000,0x0,0x0,0x0,0xfe000,0x1ffffc0f,0xfffffc00,0x0,0xff,0xf0000000,0x700f007f,0xff0fff9f,0xe0000f80,
+ 0x1e000,0x0,0x780001,0xe018001f,0xfff8001c,0xe00fff,0xffc00000,0xf800,0xf0000000,0x6380000,0xc0ffff80,0x3e078000,0x1e00,0x7ff80303,
+ 0x83c06000,0x0,0x78,0x0,0x0,0x0,0x3c003c0,0xe1c00,0x3f00000,0x0,0x7f,0xff00001e,0x7c1fff0,0xfff80,0x7ffc00,0x3f0000,0x7c01f00,
+ 0x3e00f801,0xf007c00f,0x803e007c,0x1f003e0,0xf803c07,0x8003c000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,
+ 0xe0001e00,0x3c0f03c,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0x1f8001e,0x3c03c0f0,0x3c0780,0x1e03c00,0xf01e000,
+ 0x78000780,0x1e001f,0xf07f80,0x3ffff80,0x1ffffc00,0xffffe007,0xffff003f,0xfff801ff,0xffc03fff,0xffc0f000,0x1fffff,0xc0fffffe,
+ 0x7fffff0,0x3fffff80,0x780000,0x3c00000,0x1e000000,0xf0001e00,0x7803c00,0x3c078001,0xe03c000f,0x1e00078,0xf0003c0,0x78001e07,
+ 0xfffffe1e,0x787803c,0x3c01e0,0x1e00f00,0xf007800,0x7800f01e,0x1e0007,0x803c0780,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1ff,0xffff8000,0x3ff80fc0,0x7fc1e01f,
+ 0x7800000,0x3c00,0x1e00,0x0,0x7fffff80,0x0,0x7ff80000,0x7,0x80001e00,0x3c0001e,0xfc,0xf,0x1e00780,0x1e0,0x7c000f00,0x78000f,
+ 0x78007,0xff1e0000,0x0,0x3ff00,0x0,0x1ff,0x8003c000,0x781e0070,0x3c007803,0xc000f03c,0x1e0,0x3c03c0,0x1e00,0x3c000,0x781e0007,
+ 0x80007800,0x780,0x3c07c000,0x7800001e,0x7c0f078,0xf1e03c0,0x780780,0xf000,0x1e07801f,0x3e,0xf000,0xf0003c0,0x781e003,0xcf1c7800,
+ 0x3cf80000,0x7800000f,0x8000003c,0xf0,0x1e0,0x0,0x0,0x0,0x3ffffc01,0xe000780f,0x1e0,0x780fff,0xffe0003c,0x3c000,0xf0078007,
+ 0x80003c00,0xf000,0x7ff8000,0x1e0000f,0x3c0f01e,0x1e03c0,0xf00780,0x1e0f000,0x3c003c00,0x3fff0,0x3c000,0x3c003c0,0xf81f003,
+ 0xc3b87800,0xf80000f,0x1e00001,0xf0000ff0,0xf0,0xff,0xf03fff,0x80000000,0x3fff8001,0xfff1ff00,0x0,0xf000000,0x0,0x18,0xc0,
+ 0x0,0x380000,0x7c0,0x3c00003,0xc00f001f,0xff1ff000,0xf80007ff,0xc7fc3ffe,0x3fe00000,0x0,0x0,0x0,0x1ff000,0x7ffffe1f,0xffffff00,
+ 0x0,0x7f,0xfe000000,0x780f007f,0xff1fff1f,0xf0001f00,0x1e000,0x0,0x780001,0xe0180000,0xf000001c,0xe00fff,0xffc00000,0x7c00,
+ 0xf0000000,0x31c0001,0x80ffff80,0x3e078000,0x1e00,0x7ff80183,0x81c0c000,0x0,0x78,0x0,0x0,0x0,0x3c003c0,0xe1c00,0x3f00000,
+ 0x0,0x7f,0xff00001e,0x7c7ff03,0xc03ff8fe,0x1ffc0f0,0x7e0000,0x7800f00,0x3c007801,0xe003c00f,0x1e0078,0xf003c0,0x7803c07,0x8003c000,
+ 0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x3c0f01e,0x3c078000,0xf03c0007,0x81e0003c,
+ 0xf0001e0,0x78000f00,0x3fc001e,0x7803c0f0,0x3c0780,0x1e03c00,0xf01e000,0x78000780,0x1e007f,0xf03fe0,0x7ffff80,0x3ffffc01,
+ 0xffffe00f,0xffff007f,0xfff803ff,0xffc07fff,0xffc0f000,0x1fffff,0xc0fffffe,0x7fffff0,0x3fffff80,0x780000,0x3c00000,0x1e000000,
+ 0xf0001e00,0x7803c00,0x3c078001,0xe03c000f,0x1e00078,0xf0003c0,0x78001e07,0xfffffe1e,0x707803c,0x3c01e0,0x1e00f00,0xf007800,
+ 0x7800f01e,0x1e0007,0x803c0780,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1ff,0xffff8000,0x30f81f00,0xffe1e00f,0x87800000,0x3c00,0x1e00,0x0,0x1e0000,0x0,0x7ff80000,
+ 0x7,0x80001e00,0x3c0001e,0x1f8,0x7,0x83c00780,0x1e0,0x7c000f00,0xf8001e,0x3c001,0xfc1e0000,0x0,0x7fe0,0x0,0xffc,0x3c000,0x781e0070,
+ 0x3ffff803,0xc000783c,0x1e0,0x3c03c0,0x1e00,0x3c000,0x781e0007,0x80007800,0x780,0x3c07c000,0x7800001e,0x380f078,0xf1e03c0,
+ 0x780780,0xf000,0x1e07800f,0x8000001e,0xf000,0xf0003c0,0x3c3c003,0xcf1e7800,0x7c780000,0x7800000f,0x8000003c,0xf0,0x1e0,0x0,
+ 0x0,0x0,0x7f003c01,0xe000780f,0x1e0,0x780fff,0xffe0003c,0x3c000,0xf0078007,0x80003c00,0xf000,0x7f7c000,0x1e0000f,0x3c0f01e,
+ 0x1e03c0,0xf00780,0x1e0f000,0x3c003c00,0xfff8,0x3c000,0x3c003c0,0x781e003,0xc3b87800,0x1fc00007,0x83e00003,0xe0000ff8,0xf0,
+ 0x1ff,0xc007fe,0x0,0x7fff8001,0xffe3ff00,0x0,0x1e000000,0x0,0x18,0xc0,0x0,0x0,0x3c0,0x7800003,0xc00f001f,0xfe3ff000,0xf80007ff,
+ 0x8ffc3ffc,0x7fe00000,0x0,0x0,0x0,0x1ff000,0x0,0x0,0x0,0x1f,0xff000000,0x3c0f007f,0xff1ffe3f,0xf0003e00,0x1e000,0x0,0x780001,
+ 0xe0180000,0xf000001e,0x1e00fff,0xffc00000,0x3f00,0xf0000000,0x31c0001,0x80ffff80,0x1f03c000,0x1e00,0x7ff80183,0x81c0c000,
+ 0x0,0x78,0x0,0x0,0x0,0x3c003c0,0xe1c00,0x0,0x0,0x7f,0xff00003c,0xf87f007,0xc03f83ff,0x81fc01f0,0x7c0000,0x7ffff00,0x3ffff801,
+ 0xffffc00f,0xfffe007f,0xfff003ff,0xff807fff,0x8003c000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,
+ 0xe0001e00,0x3c0f01e,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0x7fe001e,0xf003c0f0,0x3c0780,0x1e03c00,0xf01e000,
+ 0x78000780,0x1ffffe,0xf00ff0,0xfe00780,0x7f003c03,0xf801e01f,0xc00f00fe,0x7807f0,0x3c0ffff,0xffc0f000,0x1fffff,0xc0fffffe,
+ 0x7fffff0,0x3fffff80,0x780000,0x3c00000,0x1e000000,0xf0001e00,0x7803c00,0x3c078001,0xe03c000f,0x1e00078,0xf0003c0,0x78001e00,
+ 0x1e,0xf07803c,0x3c01e0,0x1e00f00,0xf007800,0x7800783e,0x1e0007,0x801e0f80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1ff,0xffff8000,0x307c0801,0xe1f1e00f,0x87000000,
+ 0x3c00,0x1e00,0x0,0x1e0000,0x0,0x7ff80000,0xf,0x1e00,0x3c0001e,0x3f0,0x7,0x83fffffc,0x1e0,0x7c000f00,0xf0001e,0x3c000,0x3e0000,
+ 0x0,0x1ffc,0x1fffff,0xf0007ff0,0x3c000,0x781e0070,0x7ffffc03,0xc000781e,0x1e0,0x7803c0,0x1e00,0x3c000,0x781e0007,0x80007800,
+ 0x780,0x3c03e000,0x7800001e,0xf078,0x79e03c0,0x780780,0xf000,0x1e078007,0x8000000f,0xf000,0xf0003c0,0x3c3c001,0xee0ef000,
+ 0xf87c0000,0x7800001f,0x3c,0x78,0x1e0,0x0,0x0,0x0,0x7c003c01,0xe000780f,0x1e0,0x780f00,0x3c,0x3c000,0xf0078007,0x80003c00,
+ 0xf000,0x7e3e000,0x1e0000f,0x3c0f01e,0x1e03c0,0xf00780,0x1e0f000,0x3c003c00,0x1ffc,0x3c000,0x3c003c0,0x781e003,0xe3b8f800,
+ 0x1fc00007,0x83c00007,0xc00000fc,0xf0,0x3e0,0x8001f8,0x0,0x7800000,0xffc7fe00,0x0,0x1e000000,0x0,0x18,0xc0,0x0,0x0,0x1e0,
+ 0xf000003,0xc00f000f,0xfc7fe001,0xf00003ff,0x1ff81ff8,0xffc00000,0x0,0x0,0x0,0x1ff000,0x0,0x0,0x0,0x3,0xff800000,0x1e0f0078,
+ 0xffc7f,0xe0007c00,0x1e000,0x0,0x780001,0xe0180000,0xf000000e,0x1c00007,0x80000000,0x1f81,0xe0000000,0x38e0003,0x80000000,
+ 0xf81f000,0x1e00,0x7ff801c3,0x80e1c000,0x0,0x78,0x0,0x0,0x0,0x3c003c0,0xe1c00,0x0,0x0,0x0,0xf8,0x1f070007,0xc03803ff,0xc1c001f0,
+ 0xf80000,0xfffff00,0x7ffff803,0xffffc01f,0xfffe00ff,0xfff007ff,0xffc07fff,0x8001e000,0x78000,0x3c0000,0x1e00000,0xf000000,
+ 0xf00000,0x7800000,0x3c000001,0xe0001e00,0x780f00f,0x3c078000,0xf03c0007,0x81e0003c,0xf0001e0,0x78000f00,0xf9f001e,0xf003c0f0,
+ 0x3c0780,0x1e03c00,0xf01e000,0x78000780,0x1ffffc,0xf003f8,0xf800780,0x7c003c03,0xe001e01f,0xf00f8,0x7807c0,0x3c0fc1e,0xf000,
+ 0x1e0000,0xf00000,0x7800000,0x3c000000,0x780000,0x3c00000,0x1e000000,0xf0001e00,0x7803c00,0x3c078001,0xe03c000f,0x1e00078,
+ 0xf0003c0,0x78001e00,0x1e,0x1e07803c,0x3c01e0,0x1e00f00,0xf007800,0x7800783c,0x1e0007,0x801e0f00,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1ff,0xffff8000,0x303c0001,
+ 0xc071e007,0xcf000000,0x3c00,0x1e00,0x0,0x1e0000,0x0,0x0,0xf,0xf00,0x780001e,0x7e0,0x7,0x83fffffc,0x1e0,0x7c000f00,0x1f0001e,
+ 0x3c000,0x3c0000,0x0,0x3ff,0x801fffff,0xf003ff80,0x3c000,0x781e0070,0x7ffffc03,0xc000781e,0x1e0,0x7803c0,0x1e00,0x1e000,0x781e0007,
+ 0x80007800,0x780,0x3c01f000,0x7800001e,0xf078,0x79e03c0,0xf00780,0xf000,0x3e078007,0xc000000f,0xf000,0xf0003c0,0x3c3c001,
+ 0xee0ef000,0xf03e0000,0x7800003e,0x3c,0x78,0x1e0,0x0,0x0,0x0,0xf8003c01,0xe000780f,0x1e0,0x780f00,0x3c,0x3c000,0xf0078007,
+ 0x80003c00,0xf000,0x7c3e000,0x1e0000f,0x3c0f01e,0x1e03c0,0xf00780,0x1e0f000,0x3c003c00,0xfc,0x3c000,0x3c003c0,0x3c3e001,0xe7b8f000,
+ 0x3fe00007,0xc7c0000f,0xc000003e,0xf0,0x7c0,0x0,0x0,0x7c00000,0x7fcffc00,0x0,0x1e000000,0x0,0x18,0xc0,0x0,0x0,0x1e0,0x1e000003,
+ 0xc00f0007,0xfcffc003,0xe00001ff,0x3ff00ff9,0xff800000,0x0,0x0,0x0,0x1ff000,0x0,0x0,0x0,0x0,0x1f800000,0xf0f0078,0x7fcff,
+ 0xc000fc00,0x1e000,0x0,0x780001,0xe0180000,0xf000000f,0x87c00007,0x80000000,0xfe3,0xe0000000,0x18780c3,0x0,0x7c0f800,0x1e00,
+ 0xc3,0x80e18000,0x0,0x78,0x0,0x0,0x0,0x3c003c0,0xe1c00,0x0,0x0,0x0,0x1f0,0x3e00000f,0xc0000303,0xe00003f0,0xf00000,0xfffff80,
+ 0x7ffffc03,0xffffe01f,0xffff00ff,0xfff807ff,0xffc07fff,0x8001e000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,
+ 0x3c000001,0xe0001e00,0x780f00f,0x3c078001,0xe03c000f,0x1e00078,0xf0003c0,0x78001e00,0x1f0f801f,0xe00780f0,0x3c0780,0x1e03c00,
+ 0xf01e000,0x78000780,0x1ffff8,0xf000f8,0x1f000780,0xf8003c07,0xc001e03e,0xf01f0,0x780f80,0x3c1f01e,0xf000,0x1e0000,0xf00000,
+ 0x7800000,0x3c000000,0x780000,0x3c00000,0x1e000000,0xf0001e00,0x7803c00,0x3c078001,0xe03c000f,0x1e00078,0xf0003c0,0x78001e00,
+ 0x1e,0x3c07803c,0x3c01e0,0x1e00f00,0xf007800,0x78007c7c,0x1e0007,0x801f1f00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x81c00000,0x303c0003,0x8039e003,0xef000000,
+ 0x3c00,0x1e00,0x0,0x1e0000,0x0,0x0,0x1e,0xf00,0x780001e,0xfc0,0x7,0x83fffffc,0x1e0,0x3c000f00,0x1e0001e,0x3c000,0x3c0000,
+ 0x0,0x7f,0xe01fffff,0xf00ffc00,0x3c000,0x781f00f0,0x7ffffc03,0xc000781e,0x1e0,0x7803c0,0x1e00,0x1e000,0x781e0007,0x80007800,
+ 0x780,0x3c01f000,0x7800001e,0xf078,0x7de01e0,0xf00780,0x7800,0x3c078003,0xc000000f,0xf000,0xf0003c0,0x3e7c001,0xee0ef001,
+ 0xf01e0000,0x7800003e,0x3c,0x3c,0x1e0,0x0,0x0,0x0,0xf0003c01,0xe000780f,0x1e0,0x780f00,0x3c,0x3c000,0xf0078007,0x80003c00,
+ 0xf000,0x781f000,0x1e0000f,0x3c0f01e,0x1e03c0,0xf00780,0x1e0f000,0x3c003c00,0x3e,0x3c000,0x3c003c0,0x3c3c001,0xe71cf000,0x7df00003,
+ 0xc780000f,0x8000003e,0xf0,0x780,0x0,0x0,0x3c00000,0x3fcff800,0x0,0x1e000000,0x0,0x18,0xc0,0x0,0x1f00fc,0x1e0,0x1e000001,
+ 0xe00f0003,0xfcff8003,0xe00000ff,0x3fe007f9,0xff000000,0x0,0x0,0x0,0x1ff000,0x0,0x0,0x0,0x0,0x7c00000,0xf0f0078,0x3fcff,0x8000f800,
+ 0x1e000,0x0,0x780001,0xe0180000,0xf000001f,0xffe00007,0x8000003c,0x7ff,0xc0000000,0x1c3ffc7,0x0,0x3e07c00,0x1e00,0xe3,0x80738000,
+ 0x0,0x78,0x0,0x0,0x0,0x3c003c0,0xe1c00,0x0,0x0,0x0,0x3e0,0x7c00001d,0xc0000001,0xe0000770,0x1f00000,0xfffff80,0x7ffffc03,
+ 0xffffe01f,0xffff00ff,0xfff807ff,0xffc07fff,0x8001e000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,
+ 0xe0001e00,0x780f00f,0x3c03c001,0xe01e000f,0xf00078,0x78003c0,0x3c001e00,0x3e07c01f,0xc00780f0,0x3c0780,0x1e03c00,0xf01e000,
+ 0x78000780,0x1fffc0,0xf0007c,0x1e000780,0xf0003c07,0x8001e03c,0xf01e0,0x780f00,0x3c1e01e,0xf000,0x1e0000,0xf00000,0x7800000,
+ 0x3c000000,0x780000,0x3c00000,0x1e000000,0xf0001e00,0x7803c00,0x3c078001,0xe03c000f,0x1e00078,0xf0003c0,0x78001e00,0x1e,0x7807803c,
+ 0x3c01e0,0x1e00f00,0xf007800,0x78003c78,0x1e0007,0x800f1e00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x83c00000,0x303c0003,0x8039e001,0xee000000,0x1e00,0x3c00,
+ 0x0,0x1e0000,0x0,0x0,0x1e,0xf00,0x780001e,0x1f80,0x7,0x83fffffc,0x1e0,0x3c000f00,0x1e0001e,0x3c000,0x3c0000,0x0,0x1f,0xfc1fffff,
+ 0xf07ff000,0x0,0x780f00f0,0x78003c03,0xc000781e,0x1e0,0xf803c0,0x1e00,0x1e000,0x781e0007,0x80007800,0x780,0x3c00f800,0x7800001e,
+ 0xf078,0x3de01e0,0xf00780,0x7800,0x3c078003,0xe000000f,0xf000,0xf0003c0,0x1e78001,0xfe0ff003,0xe01f0000,0x7800007c,0x3c,0x3c,
+ 0x1e0,0x0,0x0,0x0,0xf0007c01,0xe000f80f,0x800001e0,0xf80f00,0x3c,0x1e001,0xf0078007,0x80003c00,0xf000,0x780f800,0x1e0000f,
+ 0x3c0f01e,0x1e03c0,0x1f00780,0x3e0f000,0x7c003c00,0x1e,0x3c000,0x3c003c0,0x3c3c001,0xe71cf000,0xf8f80003,0xe780001f,0x1e,
+ 0xf0,0x780,0x0,0x0,0x3c00000,0x1ffff000,0x0,0x1e000000,0x0,0x18,0xc0,0x0,0x3bc1de,0x1e0,0xf000001,0xe00f0001,0xffff0007,0xc000007f,
+ 0xffc003ff,0xfe000000,0x0,0x0,0x0,0xfe000,0x0,0x0,0x0,0x0,0x3c00000,0x1e0f0078,0x1ffff,0x1f000,0x1e000,0x0,0x780000,0xf0180000,
+ 0xf000001f,0xfff00007,0x8000003c,0x1ff,0x80000000,0xe0ff0e,0x0,0x1f03e00,0x1e00,0x70,0x70000,0x0,0x78,0x0,0x0,0x0,0x3c003c0,
+ 0xe1c00,0x0,0x0,0x0,0x7c0,0xf8000019,0xc0000000,0xe0000670,0x1e00000,0xf000780,0x78003c03,0xc001e01e,0xf00f0,0x780780,0x3c0f807,
+ 0x8001e000,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0xf80f007,0xbc03c001,0xe01e000f,
+ 0xf00078,0x78003c0,0x3c001e00,0x7c03e00f,0x800780f0,0x3c0780,0x1e03c00,0xf01e000,0x78000780,0x1e0000,0xf0003c,0x1e000f80,
+ 0xf0007c07,0x8003e03c,0x1f01e0,0xf80f00,0x7c1e01e,0xf800,0x1e0000,0xf00000,0x7800000,0x3c000000,0x780000,0x3c00000,0x1e000000,
+ 0xf0001e00,0x7803c00,0x3c078003,0xe03c001f,0x1e000f8,0xf0007c0,0x78003e00,0x1f8001f,0xf00f803c,0x3c01e0,0x1e00f00,0xf007800,
+ 0x78003e78,0x1e000f,0x800f9e00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0x3c00000,0x303c0003,0x8039f001,0xfe000000,0x1e00,0x3c00,0x0,0x1e0000,0x0,0x0,0x3c,0xf00,
+ 0x780001e,0x3f00,0x7,0x80000780,0x3e0,0x3e000f00,0x3c0001e,0x3c000,0x7c0000,0x0,0x3,0xfe000000,0xff8000,0x0,0x3c0f81f0,0xf0001e03,
+ 0xc000780f,0x1e0,0xf003c0,0x1e00,0xf000,0x781e0007,0x80007800,0x780,0x3c007c00,0x7800001e,0xf078,0x3de01e0,0xf00780,0x7800,
+ 0x3c078001,0xe000000f,0xf000,0xf0003c0,0x1e78001,0xfc07f003,0xe00f0000,0x78000078,0x3c,0x1e,0x1e0,0x0,0x0,0x0,0xf0007c01,
+ 0xf000f007,0x800000f0,0xf80780,0x3c,0x1e001,0xf0078007,0x80003c00,0xf000,0x7807c00,0x1e0000f,0x3c0f01e,0x1e01e0,0x1e007c0,
+ 0x3c07800,0x7c003c00,0x1e,0x3c000,0x3c007c0,0x1e78001,0xe71df000,0xf8f80001,0xef80003e,0x1e,0xf0,0x780,0x0,0x0,0x3c00000,
+ 0xfffe000,0x0,0x3e000000,0x0,0x18,0x7fff,0xc0000000,0x60c306,0x1e0,0x7800001,0xe00f0000,0xfffe0007,0x8000003f,0xff8001ff,
+ 0xfc000000,0x0,0x0,0x0,0x7c000,0x0,0x0,0x0,0x0,0x3c00000,0x3c0f0078,0xfffe,0x3e000,0x1e000,0x0,0x780000,0xf0180000,0xf000003c,
+ 0xfcf80007,0x8000003c,0x7f,0x0,0x70001c,0x0,0xf81f00,0x0,0x38,0xe0000,0x0,0x0,0x0,0x0,0x0,0x3c003c0,0xe1c00,0x0,0x0,0x0,0xf81,
+ 0xf0000039,0xc0000000,0xe0000e70,0x1e00000,0x1e0003c0,0xf0001e07,0x8000f03c,0x781e0,0x3c0f00,0x1e0f007,0x8000f000,0x78000,
+ 0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0xf00f007,0xbc03c001,0xe01e000f,0xf00078,0x78003c0,
+ 0x3c001e00,0xf801f00f,0x800780f0,0x3c0780,0x1e03c00,0xf01e000,0x78000780,0x1e0000,0xf0003c,0x1e000f80,0xf0007c07,0x8003e03c,
+ 0x1f01e0,0xf80f00,0x7c1e01e,0x7800,0xf0000,0x780000,0x3c00000,0x1e000000,0x780000,0x3c00000,0x1e000000,0xf0000f00,0xf003c00,
+ 0x3c03c003,0xc01e001e,0xf000f0,0x7800780,0x3c003c00,0x1f8000f,0xe00f003c,0x7c01e0,0x3e00f00,0x1f007800,0xf8001ef8,0x1f000f,
+ 0x7be00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0xf,0x3c00000,0x307c0003,0x8038f000,0xfc000000,0x1e00,0x3c00,0x0,0x1e0000,0xfc0000,0x0,0x7e00003c,0x780,0xf00001e,
+ 0x7e00,0xf,0x80000780,0x3c0,0x3e001e00,0x3c0001f,0x7c000,0x780007,0xe000003f,0x0,0xfe000000,0xfe0000,0x0,0x3c07c3f0,0xf0001e03,
+ 0xc000f80f,0x800001e0,0x1f003c0,0x1e00,0xf000,0x781e0007,0x80007800,0x4000f80,0x3c003c00,0x7800001e,0xf078,0x1fe01f0,0x1f00780,
+ 0x7c00,0x7c078001,0xf000001f,0xf000,0xf0003c0,0x1e78001,0xfc07f007,0xc00f8000,0x780000f8,0x3c,0x1e,0x1e0,0x0,0x0,0x0,0xf0007c01,
+ 0xf000f007,0xc00000f0,0xf80780,0x3c,0x1f003,0xf0078007,0x80003c00,0xf000,0x7807c00,0x1e0000f,0x3c0f01e,0x1e01e0,0x1e007c0,
+ 0x3c07800,0x7c003c00,0x1e,0x3c000,0x3c007c0,0x1e78000,0xfe0fe001,0xf07c0001,0xef00007c,0x1e,0xf0,0x780,0x0,0x0,0x1e00000,
+ 0x7cfc000,0xfc00000,0x3c00000f,0xc3f00000,0x18,0x7fff,0xc0000000,0x406303,0x3e0,0x3c00001,0xf00f0000,0x7cfc000f,0x8000001f,
+ 0x3f0000f9,0xf8000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0x780700f8,0x7cfc,0x7c000,0x1e000,0x0,0x780000,0xf8180000,
+ 0xf0000070,0x3c0007,0x8000003c,0x3f,0x80000000,0x3c0078,0x0,0x780f00,0x0,0x1e,0x3c0000,0x0,0x0,0x0,0x0,0x0,0x3e007c0,0xe1c00,
+ 0x0,0x0,0x0,0xf01,0xe0000071,0xc0000000,0xe0001c70,0x1e00000,0x1e0003c0,0xf0001e07,0x8000f03c,0x781e0,0x3c0f00,0x1e0f007,
+ 0x8000f800,0x78000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x1f00f003,0xfc03e003,0xe01f001f,
+ 0xf800f8,0x7c007c0,0x3e003e01,0xf000f80f,0xf00f0,0x3c0780,0x1e03c00,0xf01e000,0x78000780,0x1e0000,0xf0003c,0x1e000f80,0xf0007c07,
+ 0x8003e03c,0x1f01e0,0xf80f00,0x7c1e01e,0x7c00,0xf0000,0x780000,0x3c00000,0x1e000000,0x780000,0x3c00000,0x1e000000,0xf0000f00,
+ 0xf003c00,0x3c03c003,0xc01e001e,0xf000f0,0x7800780,0x3c003c00,0x1f8000f,0xc00f003c,0x7c01e0,0x3e00f00,0x1f007800,0xf8001ef0,
+ 0x1f000f,0x7bc00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x780000,0xf,0x3800040,0x30780003,0x8038f800,0x78000000,0x1e00,0x3c00,0x0,0x1e0000,0xfc0000,0x0,0x7e000078,
+ 0x780,0x1f00001e,0xfc00,0x20001f,0x780,0x80007c0,0x1f001e00,0x7c0000f,0x78000,0xf80007,0xe000003f,0x0,0x1e000000,0xf00000,
+ 0x3c000,0x3c03fff0,0xf0001e03,0xc001f007,0x800101e0,0x7e003c0,0x1e00,0x7800,0x781e0007,0x80007800,0x6000f00,0x3c003e00,0x7800001e,
+ 0xf078,0x1fe00f0,0x1e00780,0x3c00,0x78078000,0xf020001e,0xf000,0x7800780,0xff0001,0xfc07f00f,0x8007c000,0x780001f0,0x3c,0xf,
+ 0x1e0,0x0,0x0,0x0,0xf800fc01,0xf801f007,0xc00100f8,0x1f807c0,0x40003c,0xf807,0xf0078007,0x80003c00,0xf000,0x7803e00,0x1f0000f,
+ 0x3c0f01e,0x1e01f0,0x3e007e0,0x7c07c00,0xfc003c00,0x1e,0x3e000,0x3e007c0,0x1ff8000,0xfe0fe003,0xe03e0001,0xff0000fc,0x1e,
+ 0xf0,0x780,0x0,0x0,0x1f00080,0x3cf8000,0xfc00000,0x3c00001f,0x83f00000,0x18,0xc0,0x0,0xc06203,0x40003c0,0x1c00000,0xf80f0000,
+ 0x3cf8001f,0xf,0x3e000079,0xf0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0x700780fc,0x3cf8,0xfc000,0x1e000,0x0,0x780000,
+ 0x7c180000,0xf0000020,0x100007,0x8000003c,0xf,0x80000000,0x1f01f0,0x0,0x380700,0x0,0xf,0x80f80000,0x0,0x0,0x0,0x0,0x0,0x3e007c0,
+ 0xe1c00,0x0,0x0,0x0,0xe01,0xc0000071,0xc0000001,0xc0001c70,0x1e00040,0x1e0003c0,0xf0001e07,0x8000f03c,0x781e0,0x3c0f00,0x1e0f007,
+ 0x80007800,0x10078000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e00,0x7e00f003,0xfc01e003,0xc00f001e,
+ 0x7800f0,0x3c00780,0x1e003c00,0xe000700f,0x800f0078,0x7803c0,0x3c01e00,0x1e00f000,0xf0000780,0x1e0000,0xf0003c,0x1f001f80,
+ 0xf800fc07,0xc007e03e,0x3f01f0,0x1f80f80,0xfc1e01f,0x7c00,0x100f8000,0x807c0004,0x3e00020,0x1f000100,0x780000,0x3c00000,0x1e000000,
+ 0xf0000f80,0x1f003c00,0x3c03e007,0xc01f003e,0xf801f0,0x7c00f80,0x3e007c00,0x1f8000f,0x801f003e,0x7c01f0,0x3e00f80,0x1f007c00,
+ 0xf8001ff0,0x1f801f,0x7fc00,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0xf,0x7800078,0x31f80001,0xc070fc00,0xfc000000,0x1e00,0x7c00,0x0,0x1e0000,0xfc0000,0x0,0x7e000078,
+ 0x7c0,0x1f00001e,0x1f000,0x38003f,0x780,0xe000f80,0x1f803e00,0x780000f,0x800f8000,0x1f00007,0xe000003f,0x0,0x2000000,0x800000,
+ 0x3c000,0x3e01ff71,0xf0001f03,0xc007f007,0xc00301e0,0x1fc003c0,0x1e00,0x7c00,0x781e0007,0x80007800,0x7801f00,0x3c001f00,0x7800001e,
+ 0xf078,0xfe00f8,0x3e00780,0x3e00,0xf8078000,0xf838003e,0xf000,0x7c00f80,0xff0000,0xfc07e00f,0x8003c000,0x780001e0,0x3c,0xf,
+ 0x1e0,0x0,0x0,0x0,0xf801fc01,0xfc03e003,0xe003007c,0x3f803e0,0x1c0003c,0xfc0f,0xf0078007,0x80003c00,0xf000,0x7801f00,0xf8000f,
+ 0x3c0f01e,0x1e00f8,0x7c007f0,0xf803e01,0xfc003c00,0x8003e,0x1f000,0x1e00fc0,0xff0000,0xfe0fe007,0xc01f0000,0xfe0000f8,0x1e,
+ 0xf0,0x780,0x0,0x0,0xf80180,0x1cf0000,0x1f800000,0x3c00001f,0x83e00000,0x18,0xc0,0x0,0xc06203,0x70007c0,0xe00000,0x7e0f0000,
+ 0x1cf0001e,0x7,0x3c000039,0xe0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x100,0x7c00000,0xe00780fc,0x2001cf0,0xf8000,0x1e000,0x0,
+ 0x780000,0x7e182000,0xf0000000,0x7,0x8000003c,0x7,0xc0000000,0x7ffc0,0x0,0x180300,0x0,0x3,0xffe00000,0x0,0x0,0x0,0x0,0x0,
+ 0x3f00fc0,0xe1c00,0x0,0x0,0x0,0xc01,0x800000e1,0xc0000003,0xc0003870,0x1f001c0,0x3e0003e1,0xf0001f0f,0x8000f87c,0x7c3e0,0x3e1f00,
+ 0x1f1e007,0x80007c00,0x30078000,0x3c0000,0x1e00000,0xf000000,0xf00000,0x7800000,0x3c000001,0xe0001e03,0xfc00f001,0xfc01f007,
+ 0xc00f803e,0x7c01f0,0x3e00f80,0x1f007c00,0x4000201f,0xc01f007c,0xf803e0,0x7c01f00,0x3e00f801,0xf0000780,0x1e0000,0xf0007c,
+ 0x1f003f80,0xf801fc07,0xc00fe03e,0x7f01f0,0x3f80f80,0x1fc1f03f,0x803e00,0x3007c003,0x803e001c,0x1f000e0,0xf800700,0x780000,
+ 0x3c00000,0x1e000000,0xf00007c0,0x3e003c00,0x3c01f00f,0x800f807c,0x7c03e0,0x3e01f00,0x1f00f800,0x1f80007,0xc03e001e,0xfc00f0,
+ 0x7e00780,0x3f003c01,0xf8000fe0,0x1fc03e,0x3f800,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1e,0x780007f,0xfff00001,0xe0f07f03,0xfe000000,0xf00,0x7800,0x0,
+ 0x1e0000,0xfc0000,0x0,0x7e0000f0,0x3f0,0x7e000fff,0xfc03ffff,0xf83f00fe,0x780,0xfc03f80,0xfc0fc00,0xf800007,0xe03f0018,0x7e00007,
+ 0xe000003f,0x0,0x0,0x0,0x3c000,0x1e007c71,0xe0000f03,0xffffe003,0xf01f01ff,0xff8003ff,0xffe01e00,0x3f01,0xf81e0007,0x803ffff0,
+ 0x7e03f00,0x3c000f00,0x7ffffe1e,0xf078,0xfe007e,0xfc00780,0x1f83,0xf0078000,0x783f00fe,0xf000,0x3f03f00,0xff0000,0xfc07e01f,
+ 0x3e000,0x780003ff,0xfffc003c,0x7,0x800001e0,0x0,0x0,0x0,0x7e07fc01,0xfe07e001,0xf80f007e,0x7f801f8,0xfc0003c,0x7ffe,0xf0078007,
+ 0x807ffffe,0xf000,0x7801f00,0xfff00f,0x3c0f01e,0x1e00fc,0xfc007f8,0x1f803f03,0xfc003c00,0xf80fc,0x1fff0,0x1f83fc0,0xff0000,
+ 0xfc07e007,0xc01f0000,0xfe0001ff,0xffe0001e,0xf0,0x780,0x0,0x0,0xfe0780,0xfe0000,0x1f000000,0x3c00001f,0x7c00e03,0x81c00018,
+ 0xc0,0x0,0x406203,0x7e01fc0,0x700000,0x7fffff80,0xfe0003f,0xffffc003,0xf800001f,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1f0,
+ 0x1f800001,0xc007c1fe,0x6000fe0,0x1ffffe,0x1e000,0x0,0x780000,0x3f98e03f,0xffff8000,0x7,0x8000003c,0x7,0xc0000000,0xfe00,
+ 0x0,0x80100,0x0,0x0,0x7f000000,0x0,0x1ffff,0xfe000000,0x0,0x0,0x3f83fe8,0xe1c00,0x0,0x0,0x0,0x801,0xc1,0xc0000007,0x80003070,
+ 0xfc0fc0,0x3c0001e1,0xe0000f0f,0x7878,0x3c3c0,0x1e1e00,0xf1e007,0xffc03f01,0xf007ffff,0xc03ffffe,0x1fffff0,0xfffff80,0x7fffe003,
+ 0xffff001f,0xfff800ff,0xffc01fff,0xf800f001,0xfc00fc1f,0x8007e0fc,0x3f07e0,0x1f83f00,0xfc1f800,0x1f,0xf07e003f,0x3f001f8,
+ 0x1f800fc0,0xfc007e07,0xe0000780,0x1e0000,0xf301f8,0xfc0ff80,0x7e07fc03,0xf03fe01f,0x81ff00fc,0xff807e0,0x7fc0f87f,0x81801f80,
+ 0xf003f01f,0x801f80fc,0xfc07e0,0x7e03f00,0xfffffc07,0xffffe03f,0xffff01ff,0xfff807e0,0x7e003c00,0x3c01f81f,0x800fc0fc,0x7e07e0,
+ 0x3f03f00,0x1f81f800,0x1f8000f,0xe07e001f,0x83fc00fc,0x1fe007e0,0xff003f07,0xf8000fe0,0x1fe07e,0x3f800,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1e,0x780007f,
+ 0xffe00000,0xffe03fff,0xdf000000,0xf00,0x7800,0x0,0x0,0xfc0000,0x0,0x7e0000f0,0x1ff,0xfc000fff,0xfc03ffff,0xf83ffffc,0x780,
+ 0xfffff00,0x7fff800,0xf000007,0xffff001f,0xffe00007,0xe000003f,0x0,0x0,0x0,0x3c000,0x1e000001,0xe0000f03,0xffffc001,0xffff01ff,
+ 0xff0003ff,0xffe01e00,0x1fff,0xf81e0007,0x803ffff0,0x7fffe00,0x3c000f80,0x7ffffe1e,0xf078,0xfe003f,0xff800780,0xfff,0xf0078000,
+ 0x7c3ffffc,0xf000,0x3ffff00,0xff0000,0xf803e01e,0x1e000,0x780003ff,0xfffc003c,0x7,0x800001e0,0x0,0x0,0x0,0x7fffbc01,0xffffc000,
+ 0xffff003f,0xfff800ff,0xffc0003c,0x3ffe,0xf0078007,0x807ffffe,0xf000,0x7800f80,0x7ff00f,0x3c0f01e,0x1e007f,0xff8007ff,0xff001fff,
+ 0xbc003c00,0xffffc,0x1fff0,0x1fffbc0,0xff0000,0x7c07c00f,0x800f8000,0x7e0001ff,0xffe0001e,0xf0,0x780,0x0,0x0,0x7fff80,0x7c0000,
+ 0x1f000000,0x3c00001e,0x7c00f07,0xc1e00018,0xc0,0x0,0x60e303,0x7ffff80,0x380000,0x3fffff80,0x7c0003f,0xffffc001,0xf000000f,
+ 0x80000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1ff,0xff800003,0x8003ffff,0xfe0007c0,0x1ffffe,0x1e000,0x0,0x780000,0x1fffe03f,0xffff8000,
+ 0x7,0x8000003c,0x3,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1ffff,0xfe000000,0x0,0x0,0x3fffdf8,0xe1c00,0x0,0x0,0x0,0x0,0x1c1,
+ 0xc000000f,0x7070,0x7fffc0,0x3c0001e1,0xe0000f0f,0x7878,0x3c3c0,0x1e1e00,0xf1e007,0xffc01fff,0xf007ffff,0xc03ffffe,0x1fffff0,
+ 0xfffff80,0x7fffe003,0xffff001f,0xfff800ff,0xffc01fff,0xf000f001,0xfc007fff,0x3fff8,0x1fffc0,0xfffe00,0x7fff000,0x3b,0xfffc003f,
+ 0xfff001ff,0xff800fff,0xfc007fff,0xe0000780,0x1e0000,0xf3fff8,0xffff780,0x7fffbc03,0xfffde01f,0xffef00ff,0xff7807ff,0xfbc0ffff,
+ 0xff800fff,0xf001ffff,0x800ffffc,0x7fffe0,0x3ffff00,0xfffffc07,0xffffe03f,0xffff01ff,0xfff803ff,0xfc003c00,0x3c00ffff,0x7fff8,
+ 0x3fffc0,0x1fffe00,0xffff000,0x1f,0xfffc001f,0xffbc00ff,0xfde007ff,0xef003fff,0x780007e0,0x1ffffc,0x1f800,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1e,0x700003f,
+ 0xffc00000,0x7fc01fff,0x9f800000,0xf80,0xf800,0x0,0x0,0xfc0000,0x0,0x7e0000f0,0xff,0xf8000fff,0xfc03ffff,0xf83ffff8,0x780,
+ 0xffffe00,0x7fff000,0xf000003,0xfffe001f,0xffc00007,0xe000003f,0x0,0x0,0x0,0x3c000,0xf000003,0xe0000f83,0xffff0000,0xffff01ff,
+ 0xfc0003ff,0xffe01e00,0xfff,0xf01e0007,0x803ffff0,0x7fffc00,0x3c0007c0,0x7ffffe1e,0xf078,0x7e003f,0xff000780,0x7ff,0xe0078000,
+ 0x3c3ffff8,0xf000,0x1fffe00,0x7e0000,0xf803e03e,0x1f000,0x780003ff,0xfffc003c,0x7,0x800001e0,0x0,0x0,0x0,0x3fff3c01,0xefff8000,
+ 0x7ffe001f,0xff78007f,0xff80003c,0x1ffc,0xf0078007,0x807ffffe,0xf000,0x78007c0,0x3ff00f,0x3c0f01e,0x1e003f,0xff0007bf,0xfe000fff,
+ 0xbc003c00,0xffff8,0xfff0,0xfff3c0,0x7e0000,0x7c07c01f,0x7c000,0x7c0001ff,0xffe0001e,0xf0,0x780,0x0,0x0,0x3fff80,0x380000,
+ 0x3e000000,0x7c00003e,0x7801f07,0xc1e00018,0xc0,0x0,0x39c1ce,0x7ffff00,0x1c0000,0xfffff80,0x380003f,0xffffc000,0xe0000007,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1ff,0xff000007,0x1ffcf,0xfe000380,0x1ffffe,0x1e000,0x0,0x780000,0xfffe03f,0xffff8000,0x7,
+ 0x8000003c,0x3,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1ffff,0xfe000000,0x0,0x0,0x3dffdf8,0xe1c00,0x0,0x0,0x0,0x0,0x381,
+ 0xc000001e,0xe070,0x7fff80,0x7c0001f3,0xe0000f9f,0x7cf8,0x3e7c0,0x1f3e00,0xfbe007,0xffc00fff,0xf007ffff,0xc03ffffe,0x1fffff0,
+ 0xfffff80,0x7fffe003,0xffff001f,0xfff800ff,0xffc01fff,0xc000f000,0xfc007ffe,0x3fff0,0x1fff80,0xfffc00,0x7ffe000,0x79,0xfff8001f,
+ 0xffe000ff,0xff0007ff,0xf8003fff,0xc0000780,0x1e0000,0xf3fff0,0x7ffe780,0x3fff3c01,0xfff9e00f,0xffcf007f,0xfe7803ff,0xf3c07ff3,
+ 0xff8007ff,0xe000ffff,0x7fff8,0x3fffc0,0x1fffe00,0xfffffc07,0xffffe03f,0xffff01ff,0xfff801ff,0xf8003c00,0x3c007ffe,0x3fff0,
+ 0x1fff80,0xfffc00,0x7ffe000,0x1d,0xfff8000f,0xff3c007f,0xf9e003ff,0xcf001ffe,0x780007c0,0x1efff8,0x1f000,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780000,0x1e,0xf000003,
+ 0xfe000000,0x1f000fff,0xfc00000,0x780,0xf000,0x0,0x0,0xf80000,0x0,0x7e0001e0,0x7f,0xf0000fff,0xfc03ffff,0xf81ffff0,0x780,
+ 0x7fff800,0x1ffe000,0x1f000000,0xfff8001f,0xff000007,0xe000003e,0x0,0x0,0x0,0x3c000,0xf800003,0xc0000783,0xfff80000,0x3ffe01ff,
+ 0xe00003ff,0xffe01e00,0x7ff,0xc01e0007,0x803ffff0,0x3fff800,0x3c0003c0,0x7ffffe1e,0xf078,0x7e000f,0xfe000780,0x3ff,0xc0078000,
+ 0x3e1fffe0,0xf000,0x7ff800,0x7e0000,0xf803e07c,0xf800,0x780003ff,0xfffc003c,0x3,0xc00001e0,0x0,0x0,0x0,0xffe3c01,0xe7ff0000,
+ 0x3ffc000f,0xfe78003f,0xfe00003c,0x7f0,0xf0078007,0x807ffffe,0xf000,0x78003e0,0xff00f,0x3c0f01e,0x1e001f,0xfe00079f,0xfc0007ff,
+ 0x3c003c00,0x7ffe0,0x1ff0,0x7fe3c0,0x7e0000,0x7c07c03e,0x3e000,0x7c0001ff,0xffe0001e,0xf0,0x780,0x0,0x0,0xfff00,0x100000,
+ 0x3e000000,0x7800003c,0xf800f07,0xc1e00018,0xc0,0x0,0x1f80fc,0x3fffc00,0xc0000,0x3ffff80,0x100003f,0xffffc000,0x40000002,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xff,0xfc000006,0xff87,0xfc000100,0x1ffffe,0x1e000,0x0,0x780000,0x3ffc03f,0xffff8000,0x7,
+ 0x8000003c,0x3,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1ffff,0xfe000000,0x0,0x0,0x3dff9f8,0xe1c00,0x0,0x0,0x0,0x0,0x3ff,
+ 0xf800003c,0xfffe,0x1ffe00,0x780000f3,0xc000079e,0x3cf0,0x1e780,0xf3c00,0x7bc007,0xffc003ff,0xe007ffff,0xc03ffffe,0x1fffff0,
+ 0xfffff80,0x7fffe003,0xffff001f,0xfff800ff,0xffc01ffc,0xf000,0xfc001ffc,0xffe0,0x7ff00,0x3ff800,0x1ffc000,0x70,0xfff00007,
+ 0xff80003f,0xfc0001ff,0xe0000fff,0x780,0x1e0000,0xf3ffe0,0x1ffc780,0xffe3c00,0x7ff1e003,0xff8f001f,0xfc7800ff,0xe3c03fe1,
+ 0xff0003ff,0xc0007ffc,0x3ffe0,0x1fff00,0xfff800,0xfffffc07,0xffffe03f,0xffff01ff,0xfff800ff,0xf0003c00,0x3c003ffc,0x1ffe0,
+ 0xfff00,0x7ff800,0x3ffc000,0x38,0xfff00007,0xfe3c003f,0xf1e001ff,0x8f000ffc,0x780007c0,0x1e7ff0,0x1f000,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000000,
+ 0x1fc,0x0,0x780,0xf000,0x0,0x0,0x1f80000,0x0,0x1e0,0x1f,0xc0000000,0x0,0x1ff80,0x0,0xffc000,0x7f8000,0x0,0x3fe00007,0xfc000000,
+ 0x7e,0x0,0x0,0x0,0x0,0x7c00000,0x0,0x0,0xff00000,0x0,0x0,0xfe,0x0,0x0,0x3fc000,0x0,0x0,0x0,0x3,0xf8000000,0xff,0xc0000000,
+ 0x1ff00,0x0,0x1fe000,0x0,0x0,0x0,0x0,0x3c,0x3,0xc00001e0,0x0,0x0,0x0,0x3f80000,0x1fc0000,0x7f00003,0xf8000007,0xf0000000,
+ 0x0,0xf0000000,0x0,0xf000,0x0,0x0,0x0,0x7,0xf8000787,0xf00001fc,0x3c000000,0x7f80,0x0,0x1f8000,0x0,0x0,0x0,0x7c000000,0x1e,
+ 0xf0,0x780,0x0,0x0,0x3fc00,0x0,0x3c000000,0x7800003c,0xf000601,0xc00018,0xc0,0x0,0x0,0x3fe000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xf0000000,0x7e03,0xf0000000,0x0,0x0,0x0,0x0,0xfe0000,0x0,0x0,0x3c,0x2007,0x80000000,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c7e0f0,0xe1c00,0x0,0x3800000,0x0,0x0,0x3ff,0xf8000078,0xfffe,0x7f800,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0xff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f0,0x3f80,0x1fc00,0xfe000,0x7f0000,0x70,0x3fc00001,0xfe00000f,0xf000007f,
+ 0x800003fc,0x0,0x0,0xff00,0x7f0000,0x3f80000,0x1fc00000,0xfe000007,0xf000003f,0x80001f80,0xfc00007f,0xfe0,0x7f00,0x3f800,
+ 0x1fc000,0x0,0x0,0x0,0x3f,0xc0000000,0xff0,0x7f80,0x3fc00,0x1fe000,0xff0000,0x78,0x3fc00001,0xf800000f,0xc000007e,0x3f0,0x7c0,
+ 0x1e1fc0,0x1f000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000000,0x0,0x0,0x3c0,0x1e000,0x0,0x0,0x1f00000,0x0,0x3c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x7c,0x0,0x0,0x0,0x0,0x3e00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xe0000000,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x3c,0x1,0xe00001e0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf0000000,0x0,0xf000,0x0,0x0,0x0,0x0,0x780,0x0,0x3c000000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x78000000,0x1e,0xf0,0x780,0x0,0x0,0x0,0x0,0x3c000000,0x78000078,0xf000000,0x18,0xc0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x180000,0x0,0x0,0x3c,0x3c0f,0x80000000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0xe1c00,0x0,0x1800000,0x0,0x0,0x3ff,0xf80000f0,0xfffe,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30,0x0,0x0,0x0,0x0,0x780,0x1e0000,0x1e000,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000000,
+ 0x0,0x0,0x3c0,0x1e000,0x0,0x0,0x1f00000,0x0,0x3c0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7c,0x0,0x0,0x0,0x0,0x1f80000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0xf0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c,0x1,0xe00001e0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xe0000000,0x0,0xf000,0x0,0x0,0x0,0x0,0x780,0x0,0x3c000000,0x0,0x0,0x0,0x0,0x0,0x0,0xf8000000,
+ 0x1f,0xf0,0xf80,0x0,0x0,0x0,0x0,0x78000000,0xf8000078,0x1e000000,0x8,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x180000,0x0,0x0,0x3c,0x3fff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x3c00000,0xe1c00,0x0,0x1c00000,0x0,0x0,0x1,0xc00001e0,0x70,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf80,0x1e0000,0x3e000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000000,0x0,0x0,0x1e0,0x3c000,0x0,0x0,0x1f00000,
+ 0x0,0x780,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7c,0x0,0x0,0x0,0x0,0xfe0100,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0xf8000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3f,0xf0000000,0xf0007fe0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1,0xe0000000,
+ 0x0,0xf000,0x0,0x0,0x0,0x0,0x780,0x0,0x3c000000,0x0,0x0,0x0,0x0,0x0,0x0,0xf0000000,0x1f,0x800000f0,0x1f80,0x0,0x0,0x0,0x0,
+ 0x78000000,0xf0000070,0x1c000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x180000,0x0,0x0,0x3c,0x3ffe,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0xe1c00,0x0,0xe00000,
+ 0x0,0x0,0x1,0xc00003ff,0xe0000070,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0xf00,0x1e0000,0x3c000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000000,0x0,0x0,0x1e0,0x7c000,0x0,0x0,0x1e00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x78,0x0,0x0,0x0,0x0,0x7fff80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x78000000,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3f,0xf0000000,0x7fe0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4003,0xe0000000,0x0,0x1f000,0x0,0x0,
+ 0x0,0x0,0x780,0x0,0x3c000000,0x0,0x0,0x0,0x0,0x0,0x1,0xf0000000,0xf,0xfc0000f0,0x3ff00,0x0,0x0,0x0,0x0,0x70000001,0xf00000e0,
+ 0x1c000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x180000,
+ 0x0,0x0,0x3c,0xff8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0xe1c00,0x0,0xe00000,0x0,0x0,0x1,0xc00003ff,
+ 0xe0000070,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1f00,0x1e0000,
+ 0x7c000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x30000000,0x0,0x0,0xf0,0x78000,0x0,0x0,0x3e00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf8,0x0,
+ 0x0,0x0,0x0,0x1fff80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x20000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3f,
+ 0xf0000000,0x7fe0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x780f,0xc0000000,0x0,0x3e000,0x0,0x0,0x0,0x0,0x780,0x0,0x3c000000,0x0,
+ 0x0,0x0,0x0,0x0,0x3,0xe0000000,0xf,0xfc0000f0,0x3ff00,0x0,0x0,0x0,0x0,0xf0000103,0xe0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x180000,0x0,0x0,0x3c,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0x0,0x0,0x21e00000,0x0,0x0,0x1,0xc00003ff,0xe0000070,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10f,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x10f,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3e00,0x1e0000,0xf8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x30000000,0x0,0x0,
+ 0xf8,0xf8000,0x0,0x0,0x3c00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf0,0x0,0x0,0x0,0x0,0x1fe00,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3f,0xf0000000,0x7fe0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x7fff,0xc0000000,0x0,0x3ffe000,0x0,0x0,0x0,0x0,0x780,0x0,0x3c000000,0x0,0x0,0x0,0x0,0x0,0x7f,0xe0000000,0x7,0xfc0000f0,
+ 0x3fe00,0x0,0x0,0x0,0x0,0x600001ff,0xe0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x180000,0x0,0x0,0x3c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0x0,0x0,
+ 0x3fe00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1ff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1ff,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x7fe00,0x1e0000,0x1ff8000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x1fffffe0,0x0,0x0,0x0,0x0,0x0,0x0,0x7fff,0x80000000,0x0,0x3ffc000,0x0,0x0,0x0,0x0,0x780,0x0,0x3c000000,0x0,
+ 0x0,0x0,0x0,0x0,0x7f,0xc0000000,0x0,0xfc0000f0,0x3f000,0x0,0x0,0x0,0x0,0x1ff,0xc0000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x3c00000,0x0,0x0,0x3fc00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1fe,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1fe,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7fc00,0x1e0000,0x1ff0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1fffffe0,0x0,0x0,0x0,0x0,0x0,0x0,0x3ffe,0x0,0x0,0x3ff8000,0x0,0x0,0x0,
+ 0x0,0x780,0x0,0x3c000000,0x0,0x0,0x0,0x0,0x0,0x7f,0x80000000,0x0,0xf0,0x0,0x0,0x0,0x0,0x0,0x1ff,0x80000000,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0x0,0x0,0x3f800000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1fc,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1fc,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f800,0x1e0000,0x1fe0000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1fffffe0,0x0,0x0,0x0,0x0,0x0,0x0,0x7f8,0x0,0x0,0x3fe0000,
+ 0x0,0x0,0x0,0x0,0x780,0x0,0x3c000000,0x0,0x0,0x0,0x0,0x0,0x7e,0x0,0x0,0xf0,0x0,0x0,0x0,0x0,0x0,0xfe,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3c00000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7e000,0x1e0000,0x1f80000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1fffffe0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 };
+
+ // Definition of a 40x38 'danger' color logo
+ const unsigned char logo40x38[4576] = {
+ 177,200,200,200,3,123,123,0,36,200,200,200,1,123,123,0,2,255,255,0,1,189,189,189,1,0,0,0,34,200,200,200,
+ 1,123,123,0,4,255,255,0,1,189,189,189,1,0,0,0,1,123,123,123,32,200,200,200,1,123,123,0,5,255,255,0,1,0,0,
+ 0,2,123,123,123,30,200,200,200,1,123,123,0,6,255,255,0,1,189,189,189,1,0,0,0,2,123,123,123,29,200,200,200,
+ 1,123,123,0,7,255,255,0,1,0,0,0,2,123,123,123,28,200,200,200,1,123,123,0,8,255,255,0,1,189,189,189,1,0,0,0,
+ 2,123,123,123,27,200,200,200,1,123,123,0,9,255,255,0,1,0,0,0,2,123,123,123,26,200,200,200,1,123,123,0,10,255,
+ 255,0,1,189,189,189,1,0,0,0,2,123,123,123,25,200,200,200,1,123,123,0,3,255,255,0,1,189,189,189,3,0,0,0,1,189,
+ 189,189,3,255,255,0,1,0,0,0,2,123,123,123,24,200,200,200,1,123,123,0,4,255,255,0,5,0,0,0,3,255,255,0,1,189,
+ 189,189,1,0,0,0,2,123,123,123,23,200,200,200,1,123,123,0,4,255,255,0,5,0,0,0,4,255,255,0,1,0,0,0,2,123,123,123,
+ 22,200,200,200,1,123,123,0,5,255,255,0,5,0,0,0,4,255,255,0,1,189,189,189,1,0,0,0,2,123,123,123,21,200,200,200,
+ 1,123,123,0,5,255,255,0,5,0,0,0,5,255,255,0,1,0,0,0,2,123,123,123,20,200,200,200,1,123,123,0,6,255,255,0,5,0,0,
+ 0,5,255,255,0,1,189,189,189,1,0,0,0,2,123,123,123,19,200,200,200,1,123,123,0,6,255,255,0,1,123,123,0,3,0,0,0,1,
+ 123,123,0,6,255,255,0,1,0,0,0,2,123,123,123,18,200,200,200,1,123,123,0,7,255,255,0,1,189,189,189,3,0,0,0,1,189,
+ 189,189,6,255,255,0,1,189,189,189,1,0,0,0,2,123,123,123,17,200,200,200,1,123,123,0,8,255,255,0,3,0,0,0,8,255,255,
+ 0,1,0,0,0,2,123,123,123,16,200,200,200,1,123,123,0,9,255,255,0,1,123,123,0,1,0,0,0,1,123,123,0,8,255,255,0,1,189,
+ 189,189,1,0,0,0,2,123,123,123,15,200,200,200,1,123,123,0,9,255,255,0,1,189,189,189,1,0,0,0,1,189,189,189,9,255,255,
+ 0,1,0,0,0,2,123,123,123,14,200,200,200,1,123,123,0,11,255,255,0,1,0,0,0,10,255,255,0,1,189,189,189,1,0,0,0,2,123,
+ 123,123,13,200,200,200,1,123,123,0,23,255,255,0,1,0,0,0,2,123,123,123,12,200,200,200,1,123,123,0,11,255,255,0,1,189,
+ 189,189,2,0,0,0,1,189,189,189,9,255,255,0,1,189,189,189,1,0,0,0,2,123,123,123,11,200,200,200,1,123,123,0,11,255,255,
+ 0,4,0,0,0,10,255,255,0,1,0,0,0,2,123,123,123,10,200,200,200,1,123,123,0,12,255,255,0,4,0,0,0,10,255,255,0,1,189,189,
+ 189,1,0,0,0,2,123,123,123,9,200,200,200,1,123,123,0,12,255,255,0,1,189,189,189,2,0,0,0,1,189,189,189,11,255,255,0,1,
+ 0,0,0,2,123,123,123,9,200,200,200,1,123,123,0,27,255,255,0,1,0,0,0,3,123,123,123,8,200,200,200,1,123,123,0,26,255,
+ 255,0,1,189,189,189,1,0,0,0,3,123,123,123,9,200,200,200,1,123,123,0,24,255,255,0,1,189,189,189,1,0,0,0,4,123,123,
+ 123,10,200,200,200,1,123,123,0,24,0,0,0,5,123,123,123,12,200,200,200,27,123,123,123,14,200,200,200,25,123,123,123,86,
+ 200,200,200,91,49,124,118,124,71,32,124,95,49,56,114,52,82,121,0};
+
+ // Return a 'stringification' of standard integral types.
+ const char* const bool_st = "bool";
+ const char* const uchar_st = "unsigned char";
+ const char* const char_st = "char";
+ const char* const ushort_st = "unsigned short";
+ const char* const short_st = "short";
+ const char* const uint_st = "unsigned int";
+ const char* const int_st = "int";
+ const char* const ulong_st = "unsigned long";
+ const char* const long_st = "long";
+ const char* const float_st = "float";
+ const char* const double_st = "double";
+ const char* const unknown_st = "unknown";
+ template<typename t> inline const char* get_type(const t&) { return cimg::unknown_st; }
+ inline const char* get_type(const bool& ) { return cimg::bool_st; }
+ inline const char* get_type(const unsigned char& ) { return cimg::uchar_st; }
+ inline const char* get_type(const char& ) { return cimg::char_st; }
+ inline const char* get_type(const unsigned short&) { return cimg::ushort_st; }
+ inline const char* get_type(const short& ) { return cimg::short_st; }
+ inline const char* get_type(const unsigned int& ) { return cimg::uint_st; }
+ inline const char* get_type(const int& ) { return cimg::int_st; }
+ inline const char* get_type(const unsigned long& ) { return cimg::ulong_st; }
+ inline const char* get_type(const long& ) { return cimg::long_st; }
+ inline const char* get_type(const float& ) { return cimg::float_st; }
+ inline const char* get_type(const double& ) { return cimg::double_st; }
+
+ // Return an approximation of the minimum value of a type.
+ // (Necessary because of buggy <limits> on VC++ 6.0)
+ template<typename t> inline t get_type_min(const t&) {
+ static const double p = std::pow(2.0,8.0*sizeof(t)-1.0);
+ static const t res = (t)(((t)-1)>=0?0:(-p));
+ return res;
+ }
+ inline float get_type_min(const float&) { return -(float)cimg::infinity; }
+ inline double get_type_min(const double&) { return -cimg::infinity; }
+
+ // Return an approximation of the maximum value of a type.
+ // (Necessary because of buggy <limits> on VC++ 6.0)
+ template<typename t> inline t get_type_max(const t&) {
+ static const double p = std::pow(2.0,8.0*sizeof(t)-1.0);
+ static const t res = (t)(((t)-1)>=0?(2*p-1):(p-1));
+ return res;
+ }
+ inline float get_type_max(const float&) { return (float)cimg::infinity; }
+ inline double get_type_max(const double&) { return cimg::infinity; }
+
+ // Display a warning message if parameter 'cond' is true.
+#if cimg_debug>=1
+ inline void warn(const bool cond,const char *format,...) {
+ if (cond) {
+ std::va_list ap;
+ va_start(ap,format);
+ std::fprintf(stderr,"<CImg Warning> ");
+ std::vfprintf(stderr,format,ap);
+ std::fputc('\n',stderr);
+ va_end(ap);
+ }
+ }
+#else
+ inline void warn(const bool cond,const char *format,...) {}
+#endif
+
+ inline int xln(const int x) { return x>0?(int)(1+std::log10((double)x)):1; }
+ inline char uncase(const char x) { return (char)((x<'A'||x>'Z')?x:x-'A'+'a'); }
+ inline float atof(const char *str) {
+ float x=0,y=1;
+ if (!str) return 0; else { std::sscanf(str,"%g/%g",&x,&y); return x/y; }
+ }
+ inline int strlen(const char *s) { if (s) { int k; for (k=0; s[k]; k++) ; return k; } return -1; }
+ inline int strncmp(const char *s1,const char *s2,const int l) {
+ if (s1 && s2) { int n=0; for (int k=0; k<l; k++) n+=std::abs(s1[k] - s2[k]); return n; }
+ return 0;
+ }
+ inline int strncasecmp(const char *s1,const char *s2,const int l) {
+ if (s1 && s2) { int n=0; for (int k=0; k<l; k++) n+=std::abs(uncase(s1[k])-uncase(s2[k])); return n; }
+ return 0;
+ }
+ inline int strcmp(const char *s1,const char *s2) {
+ const int l1 = cimg::strlen(s1), l2 = cimg::strlen(s2);
+ return cimg::strncmp(s1,s2,1+(l1<l2?l1:l2));
+ }
+ inline int strcasecmp(const char *s1,const char *s2) {
+ const int l1 = cimg::strlen(s1), l2 = cimg::strlen(s2);
+ return cimg::strncasecmp(s1,s2,1+(l1<l2?l1:l2));
+ }
+ inline int strfind(const char *s,const char c) {
+ if (s) {
+ int l; for (l=cimg::strlen(s); l>=0 && s[l]!=c; l--) ;
+ return l;
+ }
+ return -1;
+ }
+ inline const char* basename(const char *s) {
+ return (cimg_OS!=2)?(s?s+1+cimg::strfind(s,'/'):NULL):(s?s+1+cimg::strfind(s,'\\'):NULL);
+ }
+ inline void system(const char *command) {
+#if cimg_OS==2
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+ GetStartupInfo(&si);
+ si.wShowWindow = SW_HIDE;
+ si.dwFlags |= SW_HIDE;
+ BOOL res = CreateProcess(NULL,(LPTSTR)command,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
+ if (res) {
+ WaitForSingleObject(pi.hProcess, INFINITE);
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+ }
+#else
+ std::system(command);
+#endif
+ }
+
+ //! Return path of the ImageMagick's \c convert tool.
+ /**
+ If you have installed the <a href="http://www.imagemagick.org">ImageMagick package</a>
+ in a standard directory, this function should return the correct path of the \c convert tool
+ used by the %CImg Library to load and save compressed image formats.
+ Conversely, if the \c convert executable is not auto-detected by the function,
+ you can define the macro \c cimg_convert_path with the correct path
+ of the \c convert executable, before including <tt>CImg.h</tt> in your program :
+ \code
+ #define cimg_convert_path "/users/thatsme/local/bin/convert"
+ #include "CImg.h"
+
+ int main() {
+ CImg<> img("my_image.jpg"); // Read a JPEG image file.
+ return 0;
+ }
+ \endcode
+
+ Note that non compressed image formats can be read without installing ImageMagick.
+
+ \sa temporary_path(), get_load_convert(), load_convert(), save_convert().
+ **/
+ inline const char* convert_path() {
+ static char *st_convert_path = NULL;
+ if (!st_convert_path) {
+ st_convert_path = new char[1024];
+ bool path_found = false;
+#ifdef cimg_convert_path
+ {
+ std::FILE *file = NULL;
+ std::strcpy(st_convert_path,cimg_convert_path);
+ if ((file=std::fopen(st_convert_path,"r"))!=NULL) { std::fclose(file); path_found = true; }
+ }
+#endif
+#if cimg_OS==2
+ {
+ std::FILE *file = NULL;
+ for (unsigned int k=0; k<=9 && !path_found; k++) {
+ std::sprintf(st_convert_path,"C:\\PROGRA~1\\IMAGEM~1.%u-Q\\convert.exe",k);
+ if ((file=std::fopen(st_convert_path,"r"))!=NULL) { std::fclose(file); path_found = true; }
+ }
+ { for (unsigned int k=0; k<=9 && !path_found; k++) {
+ std::sprintf(st_convert_path,"C:\\PROGRA~1\\IMAGEM~1.%u\\convert.exe",k);
+ if ((file=std::fopen(st_convert_path,"r"))!=NULL) { std::fclose(file); path_found = true; }
+ }}
+ { for (unsigned int k=0; k<=9 && !path_found; k++) {
+ std::sprintf(st_convert_path,"C:\\PROGRA~1\\IMAGEM~1.%u-Q\\VISUA~1\\BIN\\convert.exe",k);
+ if ((file=std::fopen(st_convert_path,"r"))!=NULL) { std::fclose(file); path_found = true; }
+ }}
+ { for (unsigned int k=0; k<=9 && !path_found; k++) {
+ std::sprintf(st_convert_path,"C:\\PROGRA~1\\IMAGEM~1.%u\\VISUA~1\\BIN\\convert.exe",k);
+ if ((file=std::fopen(st_convert_path,"r"))!=NULL) { std::fclose(file); path_found = true; }
+ }}
+ if (!path_found) std::strcpy(st_convert_path,"convert.exe");
+ }
+#else
+ {
+ if (!path_found) std::strcpy(st_convert_path,"convert");
+ }
+#endif
+ }
+ return st_convert_path;
+ }
+
+ //! Return path of the \c XMedcon tool.
+ /**
+ If you have installed the <a href="http://xmedcon.sourceforge.net/">XMedcon package</a>
+ in a standard directory, this function should return the correct path of the \c medcon tool
+ used by the %CIg Library to load DICOM image formats.
+ Conversely, if the \c medcon executable is not auto-detected by the function,
+ you can define the macro \c cimg_medcon_path with the correct path
+ of the \c medcon executable, before including <tt>CImg.h</tt> in your program :
+ \code
+ #define cimg_medcon_path "/users/thatsme/local/bin/medcon"
+ #include "CImg.h"
+
+ int main() {
+ CImg<> img("my_image.dcm"); // Read a DICOM image file.
+ return 0;
+ }
+ \endcode
+
+ Note that \c medcon is only needed if you want to read DICOM image formats.
+
+ \sa temporary_path(), get_load_dicom(), load_dicom().
+ **/
+ inline const char* medcon_path() {
+ static char *st_medcon_path = NULL;
+ if (!st_medcon_path) {
+ st_medcon_path = new char[1024];
+ bool path_found = false;
+#ifdef cimg_medcon_path
+ {
+ std::FILE *file = NULL;
+ std::strcpy(st_medcon_path,cimg_medcon_path);
+ if ((file=std::fopen(st_medcon_path,"r"))!=NULL) { std::fclose(file); path_found = true; }
+ }
+#endif
+#if cimg_OS==2
+ {
+ std::FILE *file = NULL;
+ if (!path_found) {
+ std::sprintf(st_medcon_path,"C:\\PROGRA~1\\XMedCon\\bin\\medcon.bat");
+ if ((file=std::fopen(st_medcon_path,"r"))!=NULL) { std::fclose(file); path_found = true; }
+ }
+ if (!path_found) std::strcpy(st_medcon_path,"medcon.bat");
+ }
+#else
+ {
+ if (!path_found) std::strcpy(st_medcon_path,"medcon");
+ }
+#endif
+ }
+ return st_medcon_path;
+ }
+
+ //! Return path to store temporary files.
+ /**
+ If you are running on a standard Unix or Windows system, this function should return a correct path
+ where temporary files can be stored. If such a path is not auto-detected by this function,
+ you can define the macro \c cimg_temporary_path with a correct path, before including <tt>CImg.h</tt>
+ in your program :
+ \code
+ #define cimg_temporary_path "/users/thatsme/tmp"
+ #include "CImg.h"
+
+ int main() {
+ CImg<> img("my_image.jpg"); // Read a JPEG image file (using the defined temporay path).
+ return 0;
+ }
+ \endcode
+
+ A temporary path is necessary to load and save compressed image formats, using \c convert
+ or \c medcon.
+
+ \sa convert_path(), get_load_convert(), load_convert(), save_convert(), get_load_dicom(), load_dicom().
+ **/
+ inline const char* temporary_path() {
+ static char *st_temporary_path = NULL;
+ if (!st_temporary_path) {
+ st_temporary_path = new char[1024];
+#ifdef cimg_temporary_path
+ std::strcpy(st_temporary_path,cimg_temporary_path);
+ const char* testing_path[7] = { st_temporary_path, "/tmp","C:\\WINNT\\Temp", "C:\\WINDOWS\\Temp","","C:",NULL };
+#else
+ const char* testing_path[6] = { "/tmp","C:\\WINNT\\Temp", "C:\\WINDOWS\\Temp","","C:",NULL };
+#endif
+ char filetmp[1024];
+ std::FILE *file=NULL;
+ int i=-1;
+ while (!file && testing_path[++i]) {
+ std::sprintf(filetmp,"%s/CImg%.4d.ppm",testing_path[i],std::rand()%10000);
+ if ((file=std::fopen(filetmp,"w"))!=NULL) { std::fclose(file); std::remove(filetmp); }
+ }
+ if (!file)
+ throw CImgIOException("cimg::temporary_path() : Unable to find a temporary path accessible for writing\n"
+ "you have to set the macro 'cimg_temporary_path' to a valid path where you have writing access :\n"
+ "#define cimg_temporary_path \"path\" (before including 'CImg.h')");
+ std::strcpy(st_temporary_path,testing_path[i]);
+ }
+ return st_temporary_path;
+ }
+
+ inline const char *filename_split(const char *const filename, char *const body=NULL) {
+ if (!filename) { if (body) body[0]='\0'; return NULL; }
+ int l = cimg::strfind(filename,'.');
+ if (l>=0) { if (body) { std::strncpy(body,filename,l); body[l]='\0'; }}
+ else { if (body) std::strcpy(body,filename); l=(int)std::strlen(filename)-1; }
+ return filename+l+1;
+ }
+
+ inline char* filename_number(const char *filename,const int number,const unsigned int n,char *const string) {
+ if (!filename) { if (string) string[0]='\0'; return NULL; }
+ char format[1024],body[1024];
+ const char *ext = cimg::filename_split(filename,body);
+ if (n>0) std::sprintf(format,"%s_%%.%ud.%s",body,n,ext);
+ else std::sprintf(format,"%s_%%d.%s",body,ext);
+ std::sprintf(string,format,number);
+ return string;
+ }
+
+ inline std::FILE *fopen(const char *const path,const char *const mode) {
+ if(!path || !mode) throw CImgArgumentException("cimg::fopen() : Can't open file '%s' with mode '%s'",path,mode);
+ if (path[0]=='-') return (mode[0]=='r')?stdin:stdout;
+ else {
+ std::FILE *dest = std::fopen(path,mode);
+ if(!dest) throw CImgIOException("cimg::fopen() : File '%s' cannot be opened %s",
+ path,mode[0]=='r'?"for reading":(mode[0]=='w'?"for writing":""),path);
+ return dest;
+ }
+ }
+
+ inline int fclose(std::FILE *file) {
+ warn(!file,"cimg::fclose() : Can't close (null) file");
+ if (!file || file==stdin || file==stdout) return 0;
+ const int errn=std::fclose(file);
+ warn(errn!=0,"cimg::fclose() : Error %d during file closing",errn);
+ return errn;
+ }
+ template<typename T> inline int fread(T *ptr,const unsigned int nmemb,std::FILE *stream) {
+ if (!ptr || nmemb<=0 || !stream)
+ throw CImgArgumentException("cimg::fread() : Can't read %u x %u bytes of file pointer '%p' in buffer '%p'",
+ nmemb,sizeof(T),stream,ptr);
+ const unsigned int errn = (unsigned int)std::fread((void*)ptr,sizeof(T),nmemb,stream);
+ cimg::warn(errn!=nmemb,"cimg::fread() : File reading problems, only %u/%u elements read",errn,nmemb);
+ return errn;
+ }
+ template<typename T> inline int fwrite(const T *ptr,const unsigned int nmemb,std::FILE *stream) {
+ if (!ptr || nmemb<=0 || !stream)
+ throw CImgArgumentException("cimg::fwrite() : Can't write %u x %u bytes of file pointer '%p' from buffer '%p'",
+ nmemb,sizeof(T),stream,ptr);
+ const unsigned int errn = (unsigned int)std::fwrite(ptr,sizeof(T),nmemb,stream);
+ if(errn!=nmemb)
+ throw CImgIOException("cimg::fwrite() : File writing problems, only %u/%u elements written",errn,nmemb);
+ return errn;
+ }
+
+ // Exchange the values of variables \p a and \p b
+ template<typename T> inline void swap(T& a,T& b) { T t=a; a=b; b=t; }
+ template<typename T1,typename T2> inline void swap(T1& a1,T1& b1,T2& a2,T2& b2) {
+ cimg::swap(a1,b1); cimg::swap(a2,b2);
+ }
+ template<typename T1,typename T2,typename T3> inline void swap(T1& a1,T1& b1,T2& a2,T2& b2,T3& a3,T3& b3) {
+ cimg::swap(a1,b1,a2,b2); cimg::swap(a3,b3);
+ }
+ template<typename T1,typename T2,typename T3,typename T4>
+ inline void swap(T1& a1,T1& b1,T2& a2,T2& b2,T3& a3,T3& b3,T4& a4,T4& b4) {
+ cimg::swap(a1,b1,a2,b2,a3,b3); cimg::swap(a4,b4);
+ }
+ template<typename T1,typename T2,typename T3,typename T4,typename T5>
+ inline void swap(T1& a1,T1& b1,T2& a2,T2& b2,T3& a3,T3& b3,T4& a4,T4& b4,T5& a5,T5& b5) {
+ cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4); cimg::swap(a5,b5);
+ }
+ template<typename T1,typename T2,typename T3,typename T4,typename T5,typename T6>
+ inline void swap(T1& a1,T1& b1,T2& a2,T2& b2,T3& a3,T3& b3,T4& a4,T4& b4,T5& a5,T5& b5,T6& a6,T6& b6) {
+ cimg::swap(a1,b1,a2,b2,a3,b3,a4,b4,a5,b5); cimg::swap(a6,b6);
+ }
+
+ template<typename T> inline void endian_swap(T* const buffer, const unsigned int size) {
+ switch (sizeof(T)) {
+ case 1: break;
+ case 2: {
+ for (unsigned short *ptr = (unsigned short*)buffer+size; ptr>(unsigned short*)buffer;) {
+ const register unsigned short val = *(--ptr);
+ *ptr = (val>>8)|((val<<8));
+ }
+ } break;
+ case 4: {
+ for (unsigned int *ptr = (unsigned int*)buffer+size; ptr>(unsigned int*)buffer;) {
+ const register unsigned int val = *(--ptr);
+ *ptr = (val>>24)|((val>>8)&0xff00)|((val<<8)&0xff0000)|(val<<24);
+ }
+ } break;
+ default: {
+ for (T* ptr = buffer+size; ptr>buffer; --ptr) {
+ register unsigned char *pb=(unsigned char*)(--ptr), *pe=pb+sizeof(T);
+ for (int i=0; i<(int)sizeof(T)/2; i++) cimg::swap(*(pb++),*(--pe));
+ } break;
+ }
+ }
+ }
+ template<typename T> inline T& endian_swap(T& a) { endian_swap(&a,1); return a; }
+
+ inline const char* option(const char *const name, const int argc, char **argv,
+ const char *defaut, const char *const usage=NULL) {
+ static bool first=true, visu=false;
+ const char *res = NULL;
+ if (first) {
+ first=false;
+ visu = (cimg::option("-h",argc,argv,(const char*)NULL)!=NULL);
+ visu |= (cimg::option("-help",argc,argv,(const char*)NULL)!=NULL);
+ visu |= (cimg::option("--help",argc,argv,(const char*)NULL)!=NULL);
+ }
+ if (!name && visu) {
+ std::fprintf(stderr,"\n %s%s%s",cimg::t_red,cimg::basename(argv[0]),cimg::t_normal);
+ if (usage) std::fprintf(stderr," : %s",usage);
+ std::fprintf(stderr," (%s, %s)\n\n",__DATE__,__TIME__);
+ }
+ if (name) {
+ if (argc>0) {
+ int k=0,i;
+ while (k<argc && cimg::strcmp(argv[k],name)) k++;
+ i=k;
+ res=(k++==argc?defaut:(k==argc?argv[--k]:argv[k]));
+ } else res = defaut;
+ if (visu && usage) std::fprintf(stderr," %s%-8s%s = %-12s : %s%s%s\n",
+ cimg::t_bold,name,cimg::t_normal,res?res:"NULL",cimg::t_purple,usage,cimg::t_normal);
+ }
+ return res;
+ }
+
+ inline bool option(const char *const name, const int argc, char **argv,
+ const bool defaut, const char *const usage=NULL) {
+ const char *s = cimg::option(name,argc,argv,(const char*)NULL);
+ const bool res = s?(cimg::strcasecmp(s,"false") && cimg::strcasecmp(s,"off") && cimg::strcasecmp(s,"0")):defaut;
+ cimg::option(name,0,NULL,res?"true":"false",usage);
+ return res;
+ }
+
+ inline int option(const char *const name, const int argc, char **argv,
+ const int defaut, const char *const usage=NULL) {
+ const char *s = cimg::option(name,argc,argv,(const char*)NULL);
+ const int res = s?std::atoi(s):defaut;
+ char tmp[256];
+ std::sprintf(tmp,"%d",res);
+ cimg::option(name,0,NULL,tmp,usage);
+ return res;
+ }
+
+ inline char option(const char *const name, const int argc, char **argv,
+ const char defaut, const char *const usage=NULL) {
+ const char *s = cimg::option(name,argc,argv,(const char*)NULL);
+ const char res = s?s[0]:defaut;
+ char tmp[8];
+ tmp[0] = res;
+ tmp[1] ='\0';
+ cimg::option(name,0,NULL,tmp,usage);
+ return res;
+ }
+
+ inline float option(const char *const name, const int argc, char **argv,
+ const float defaut, const char *const usage=NULL) {
+ const char *s = cimg::option(name,argc,argv,(const char*)NULL);
+ const float res = s?cimg::atof(s):defaut;
+ char tmp[256];
+ std::sprintf(tmp,"%g",res);
+ cimg::option(name,0,NULL,tmp,usage);
+ return res;
+ }
+
+ inline double option(const char *const name, const int argc, char **argv,
+ const double defaut, const char *const usage=NULL) {
+ const char *s = cimg::option(name,argc,argv,(const char*)NULL);
+ const double res = s?cimg::atof(s):defaut;
+ char tmp[256];
+ std::sprintf(tmp,"%g",res);
+ cimg::option(name,0,NULL,tmp,usage);
+ return res;
+ }
+
+ //! Return \c false for little endian CPUs (Intel), \c true for big endian CPUs (Motorola).
+ inline bool endian() { const int x=1; return ((unsigned char*)&x)[0]?false:true; }
+
+ //! Print informations about %CImg environement variables.
+ /**
+ Printing is done on the standart error output.
+ **/
+ inline void info() {
+ std::fprintf(stderr,"\n %sCImg Library %g%s, compiled %s ( %s ) with the following flags :\n\n",
+ cimg::t_red,cimg_version,cimg::t_normal,__DATE__,__TIME__);
+ std::fprintf(stderr," > Architecture : %s%-12s%s %s(cimg_OS=%d)\n%s",
+ cimg::t_bold,
+ cimg_OS==1?"Unix":(cimg_OS==2?"Windows":"Unknown"),
+ cimg::t_normal,cimg::t_purple,cimg_OS,cimg::t_normal);
+ std::fprintf(stderr," > Display type : %s%-12s%s %s(cimg_display_type=%d)%s\n",
+ cimg::t_bold,cimg_display_type==0?"No":
+ (cimg_display_type==1?"X11":
+ (cimg_display_type==2?"WindowsGDI":
+ "Unknown")),
+ cimg::t_normal,cimg::t_purple,cimg_display_type,cimg::t_normal);
+#ifdef cimg_color_terminal
+ std::fprintf(stderr," > Color terminal : %s%-12s%s %s(cimg_color_terminal defined)%s\n",
+ cimg::t_bold,"Yes",cimg::t_normal,cimg::t_purple,cimg::t_normal);
+#else
+ std::fprintf(stderr," > Color terminal : %-12s (cimg_color_terminal undefined)\n","No");
+#endif
+ std::fprintf(stderr," > Debug messages : %s%-12s%s %s(cimg_debug=%d)%s\n",cimg::t_bold,
+ cimg_debug==2?"High":(cimg_debug==1?"Yes":"No"),
+ cimg::t_normal,cimg::t_purple,cimg_debug,cimg::t_normal);
+ std::fprintf(stderr,"\n");
+ }
+
+ //! Get the value of a system timer with a millisecond precision.
+ inline long time() {
+#if cimg_OS==1
+ struct timeval st_time;
+ gettimeofday(&st_time,NULL);
+ return (long)(st_time.tv_usec/1000 + st_time.tv_sec*1000);
+#elif cimg_OS==2
+ static SYSTEMTIME st_time;
+ GetSystemTime(&st_time);
+ return (long)(st_time.wMilliseconds + 1000*(st_time.wSecond + 60*(st_time.wMinute + 60*st_time.wHour)));
+#else
+ return 0;
+#endif
+ }
+
+ //! Sleep for a certain numbers of milliseconds.
+ /**
+ This function frees the CPU ressources during the sleeping time.
+ It may be used to temporize your program properly, without wasting CPU time.
+ \sa wait(), time().
+ **/
+ inline void sleep(const int milliseconds) {
+#if cimg_OS==1
+ struct timespec tv;
+ tv.tv_sec = milliseconds/1000;
+ tv.tv_nsec = (milliseconds%1000)*1000000;
+ nanosleep(&tv,NULL);
+#elif cimg_OS==2
+ Sleep(milliseconds);
+#endif
+ }
+
+ //! Wait for a certain number of milliseconds since the last call.
+ /**
+ This function is equivalent to sleep() but the waiting time is computed with regard to the last call
+ of wait(). It may be used to temporize your program properly.
+ \sa sleep(), time().
+ **/
+ inline long wait(const int milliseconds=20,long reference_time=-1) {
+ static long latest_time = cimg::time();
+ if (reference_time>=0) latest_time = reference_time;
+ const long current_time = cimg::time(), time_diff = milliseconds + latest_time - current_time;
+ if (time_diff>0) { cimg::sleep(time_diff); return (latest_time = current_time + time_diff); }
+ else return (latest_time = current_time);
+ }
+
+ template<typename T> inline const T rol(const T& a,const unsigned int n=1) { return (T)((a<<n)|(a>>((sizeof(T)<<3)-n))); }
+ template<typename T> inline const T ror(const T& a,const unsigned int n=1) { return (T)((a>>n)|(a<<((sizeof(T)<<3)-n))); }
+
+#if ( !defined(_MSC_VER) || _MSC_VER>1200 )
+ //! Return the absolute value of \p a
+ template<typename T> inline T abs(const T& a) { return a>=0?a:-a; }
+ inline bool abs(const bool a) { return a; }
+ inline unsigned char abs(const unsigned char a) { return a; }
+ inline unsigned short abs(const unsigned short a) { return a; }
+ inline unsigned int abs(const unsigned int a) { return a; }
+ inline unsigned long abs(const unsigned long a) { return a; }
+ inline double abs(const double a) { return std::fabs(a); }
+ inline float abs(const float a) { return (float)std::fabs((double)a); }
+ inline int abs(const int a) { return std::abs(a); }
+
+ //! Return the minimum between \p a and \p b.
+ template<typename T> inline const T& min(const T& a,const T& b) { return a<=b?a:b; }
+
+ //! Return the minimum between \p a,\p b and \a c.
+ template<typename T> inline const T& min(const T& a,const T& b,const T& c) { return cimg::min(cimg::min(a,b),c); }
+
+ //! Return the minimum between \p a,\p b,\p c and \p d.
+ template<typename T> inline const T& min(const T& a,const T& b,const T& c,const T& d) { return cimg::min(cimg::min(a,b,c),d); }
+
+ //! Return the maximum between \p a and \p b.
+ template<typename T> inline const T& max(const T& a,const T& b) { return a>=b?a:b; }
+
+ //! Return the maximum between \p a,\p b and \p c.
+ template<typename T> inline const T& max(const T& a,const T& b,const T& c) { return cimg::max(cimg::max(a,b),c); }
+
+ //! Return the maximum between \p a,\p b,\p c and \p d.
+ template<typename T> inline const T& max(const T& a,const T& b,const T& c,const T& d) { return cimg::max(cimg::max(a,b,c),d); }
+
+ //! Return the sign of \p x.
+ template<typename T> inline T sign(const T& x) { return (x<0)?(T)(-1):(x==0?(T)0:(T)1); }
+#else
+
+ // Special versions due to object reference bug in VisualC++ 6.0.
+ template<typename T> inline const T abs(const T a) { return a>=0?a:-a; }
+ template<typename T> inline const T min(const T a,const T b) { return a<=b?a:b; }
+ template<typename T> inline const T min(const T a,const T b,const T c) { return cimg::min(cimg::min(a,b),c); }
+ template<typename T> inline const T min(const T a,const T b,const T c,const T& d) { return cimg::min(cimg::min(a,b,c),d); }
+ template<typename T> inline const T max(const T a,const T b) { return a>=b?a:b; }
+ template<typename T> inline const T max(const T a,const T b,const T c) { return cimg::max(cimg::max(a,b),c); }
+ template<typename T> inline const T max(const T a,const T b,const T c,const T& d) { return cimg::max(cimg::max(a,b,c),d); }
+ template<typename T> inline char sign(const T x) { return (x<0)?-1:(x==0?0:1); }
+#endif
+
+ //! Return the nearest power of 2 higher than \p x.
+ template<typename T> inline unsigned long nearest_pow2(const T& x) {
+ unsigned long i=1;
+ while (x>i) i<<=1;
+ return i;
+ }
+
+ //! Return \p x modulo \p m (generic modulo).
+ /**
+ This modulo function accepts negative and floating-points modulo numbers \p m.
+ **/
+ inline double mod(const double& x,const double& m) { return x-m*std::floor(x/m); }
+ inline float mod(const float& x,const float& m) { return (float)(x-m*std::floor((double)x/m)); }
+ inline int mod(const int x,const int m) { return x>=0?x%m:(x%m?m+x%m:0); }
+
+ //! Return minmod(\p a,\p b).
+ /**
+ The operator minmod(\p a,\p b) is defined to be :
+ - minmod(\p a,\p b) = min(\p a,\p b), if (\p a * \p b)>0.
+ - minmod(\p a,\p b) = 0, if (\p a * \p b)<=0
+ **/
+ template<typename T> inline T minmod(const T& a,const T& b) { return a*b<=0?0:(a>0?(a<b?a:b):(a<b?b:a)); }
+
+ //! Return a random variable between [0,1], followin a uniform distribution.
+ inline double rand() { return (double)std::rand()/RAND_MAX; }
+
+ //! Return a random variable between [-1,1], following a uniform distribution.
+ inline double crand() { return 1-2*cimg::rand(); }
+
+ //! Return a random variable following a gaussian distribution and a standard deviation of 1.
+ inline double grand() {
+ return std::sqrt(-2*std::log((double)(1e-10 + (1-2e-10)*cimg::rand())))*std::cos((double)(2*PI*cimg::rand()));
+ }
+
+ inline double pythagore(double a, double b) {
+ const double absa = cimg::abs(a), absb = cimg::abs(b);
+ if (absa>absb) { const double tmp = absb/absa; return absa*std::sqrt(1.0+tmp*tmp); }
+ else { const double tmp = absa/absb; return (absb==0?0:absb*std::sqrt(1.0+tmp*tmp)); }
+ }
+
+ // End of the 'cimg' namespace
+ }
+
+ /*
+ #----------------------------------------
+ #
+ #
+ #
+ # Definition of the CImgStats structure
+ #
+ #
+ #
+ #----------------------------------------
+ */
+ //! Class used to compute basic statistics on pixel values of a \ref CImg<T> image.
+ /**
+ Constructing a CImgStats instance from an image CImg<T> or a list CImgl<T>
+ will compute the minimum, maximum and average pixel values of the input object.
+ Optionally, the variance of the pixel values can be computed.
+ Coordinates of the pixels whose values are minimum and maximum are also stored.
+ The example below shows how to use CImgStats objects to retrieve simple statistics of an image :
+ \code
+ const CImg<float> img("my_image.jpg"); // Read JPEG image file.
+ const CImgStats stats(img); // Compute basic statistics on the image.
+ stats.print("My statistics"); // Display statistics.
+ std::printf("Max-Min = %lf",stats.max-stats.min); // Compute the difference between extremum values.
+ \endcode
+
+ Note that statistics are computed by considering the set of \a scalar values of the image pixels.
+ No vector-valued statistics are computed.
+ **/
+ struct CImgStats {
+ double min; //!< Minimum of the pixel values.
+ double max; //!< Maximum of the pixel values.
+ double mean; //!< Mean of the pixel values.
+ double variance; //!< Variance of the pixel values.
+ int xmin; //!< X-coordinate of the pixel with minimum value.
+ int ymin; //!< Y-coordinate of the pixel with minimum value.
+ int zmin; //!< Z-coordinate of the pixel with minimum value.
+ int vmin; //!< V-coordinate of the pixel with minimum value.
+ int lmin; //!< Image number (for a list) containing the minimum pixel.
+ int xmax; //!< X-coordinate of the pixel with maximum value.
+ int ymax; //!< Y-coordinate of the pixel with maximum value.
+ int zmax; //!< Z-coordinate of the pixel with maximum value.
+ int vmax; //!< V-coordinate of the pixel with maximum value.
+ int lmax; //!< Image number (for a list) containing the maximum pixel.
+
+ //! Empty constructor.
+ /**
+ Field values of a CImgStats constructed with the empty constructor have no meaning.
+ **/
+ CImgStats():min(0),max(0),mean(0),variance(0),xmin(-1),ymin(-1),zmin(-1),vmin(-1),lmin(-1),
+ xmax(-1),ymax(-1),zmax(-1),vmax(-1),lmax(-1) {}
+ //! Copy constructor.
+ CImgStats(const CImgStats& stats):min(stats.min),max(stats.max),mean(stats.mean),variance(stats.variance),
+ xmin(stats.xmin),ymin(stats.ymin),zmin(stats.zmin),vmin(stats.vmin),lmin(stats.lmin),
+ xmax(stats.xmax),ymax(stats.ymax),zmax(stats.zmax),vmax(stats.vmax),lmax(stats.lmax) {};
+
+ //! In-place version of the copy constructor.
+ CImgStats& assign(const CImgStats& stats) {
+ return (*this)=stats;
+ }
+
+ //! Constructor that computes statistics of an input image \p img.
+ /**
+ \param img The input image.
+ \param compute_variance If true, the \c variance field is computed, else it is set to 0.
+ **/
+ template<typename T> CImgStats(const CImg<T>& img,const bool compute_variance=true):mean(0),variance(0),lmin(-1),lmax(-1) {
+ if (img.is_empty())
+ throw CImgArgumentException("CImgStats::CImgStats() : Specified input image (%u,%u,%u,%u,%p) is empty.",
+ img.width,img.height,img.depth,img.dim,img.data);
+ T pmin=img[0], pmax=pmin, *ptrmin=img.data, *ptrmax=ptrmin;
+ cimg_map(img,ptr,T) {
+ const T& a=*ptr;
+ mean+=(double)a;
+ if (a<pmin) { pmin=a; ptrmin = ptr; }
+ if (a>pmax) { pmax=a; ptrmax = ptr; }
+ }
+ mean/=img.size();
+ min=(double)pmin;
+ max=(double)pmax;
+ unsigned long offmin = (unsigned long)(ptrmin-img.data), offmax = (unsigned long)(ptrmax-img.data);
+ const unsigned long whz = img.width*img.height*img.depth, wh = img.width*img.height;
+ vmin = offmin/whz; offmin%=whz; zmin = offmin/wh; offmin%=wh; ymin = offmin/img.width; xmin = offmin%img.width;
+ vmax = offmax/whz; offmax%=whz; zmax = offmax/wh; offmax%=wh; ymax = offmax/img.width; xmax = offmax%img.width;
+ if (compute_variance) {
+ cimg_map(img,ptr,T) { const double tmpf=(*ptr)-mean; variance+=tmpf*tmpf; }
+ const unsigned int siz = img.size();
+ if (siz>1) variance/=(siz-1); else variance=0;
+ }
+ }
+
+ //! In-place version of the copy constructor.
+ template<typename T> CImgStats& assign(const CImg<T>& img, const bool compute_variance=true) {
+ return (*this) = CImgStats(img,compute_variance);
+ }
+
+ //! Constructor that computes statistics of an input image list \p list.
+ /**
+ \param list The input list of images.
+ \param compute_variance If true, the \c variance field is computed, else it is set to 0.
+ **/
+ template<typename T> CImgStats(const CImgl<T>& list,const bool compute_variance=true):mean(0),variance(0),lmin(0),lmax(0) {
+ if (list.is_empty())
+ throw CImgArgumentException("CImgStats::CImgStats() : Specified input list (%u,%p) is empty.",
+ list.size,list.data);
+ T pmin=list[0][0], pmax=pmin, *ptrmin=list[0].data, *ptrmax=ptrmin;
+ int psize=0;
+ cimgl_map(list,l) {
+ cimg_map(list[l],ptr,T) {
+ const T& a=*ptr;
+ mean+=(double)a;
+ if (a<pmin) { pmin=a; ptrmin = ptr; lmin = l; }
+ if (a>pmax) { pmax=a; ptrmax = ptr; lmax = l; }
+ }
+ psize+=list[l].size();
+ }
+ mean/=psize;
+ min=(double)pmin;
+ max=(double)pmax;
+ const CImg<T> &imin = list[lmin], &imax = list[lmax];
+ unsigned long offmin = (ptrmin-imin.data), offmax = (ptrmax-imax.data);
+ const unsigned long whz1 = imin.width*imin.height*imin.depth, wh1 = imin.width*imin.height;
+ vmin = offmin/whz1; offmin%=whz1; zmin = offmin/wh1; offmin%=wh1; ymin = offmin/imin.width; xmin = offmin%imin.width;
+ const unsigned long whz2 = imax.width*imax.height*imax.depth, wh2 = imax.width*imax.height;
+ vmax = offmax/whz2; offmax%=whz2; zmax = offmax/wh2; offmax%=wh2; ymax = offmax/imax.width; xmax = offmax%imax.width;
+ if (compute_variance) {
+ cimgl_map(list,l) cimg_map(list[l],ptr,T) { const double tmpf=(*ptr)-mean; variance+=tmpf*tmpf; }
+ if (psize>1) variance/=(psize-1); else variance=0;
+ }
+ }
+
+ //! In-place version of the copy constructor
+ template<typename T> CImgStats& assign(const CImgl<T>& list, const bool compute_variance=true) {
+ return (*this) = CImgStats(list,compute_variance);
+ }
+
+ //! Assignement operator.
+ CImgStats& operator=(const CImgStats& stats) {
+ min = stats.min;
+ max = stats.max;
+ mean = stats.mean;
+ variance = stats.variance;
+ xmin = stats.xmin; ymin = stats.ymin; zmin = stats.zmin; vmin = stats.vmin; lmin = stats.lmin;
+ xmax = stats.xmax; ymax = stats.ymax; zmax = stats.zmax; vmax = stats.vmax; lmax = stats.lmax;
+ return *this;
+ }
+
+ //! Print the current statistics.
+ /**
+ Printing is done on the standart error output.
+ **/
+ const CImgStats& print(const char* title=NULL) const {
+ if (lmin>=0 && lmax>=0)
+ std::fprintf(stderr,"%-8s(this=%p) : { min=%g, mean=%g [var=%g], max=%g, "
+ "pmin=[%d](%d,%d,%d,%d), pmax=[%d](%d,%d,%d,%d) }\n",
+ title?title:"CImgStats",(void*)this,min,mean,variance,max,
+ lmin,xmin,ymin,zmin,vmin,lmax,xmax,ymax,zmax,vmax);
+ else
+ std::fprintf(stderr,"%-8s(this=%p) : { min=%g, mean=%g [var=%g], max=%g, "
+ "pmin=(%d,%d,%d,%d), pmax=(%d,%d,%d,%d) }\n",
+ title?title:"CImgStats",(void*)this,min,mean,variance,max,
+ xmin,ymin,zmin,vmin,xmax,ymax,zmax,vmax);
+ return *this;
+ }
+
+ // Swap fields between two CImgStats
+ CImgStats& swap(CImgStats& stats) {
+ cimg::swap(min,stats.min);
+ cimg::swap(max,stats.max);
+ cimg::swap(mean,stats.mean);
+ cimg::swap(variance,stats.variance);
+ cimg::swap(xmin,stats.xmin); cimg::swap(ymin,stats.ymin); cimg::swap(zmin,stats.zmin); cimg::swap(vmin,stats.vmin);
+ cimg::swap(lmin,stats.lmin);
+ cimg::swap(xmax,stats.xmax); cimg::swap(ymax,stats.ymax); cimg::swap(zmax,stats.zmax); cimg::swap(vmax,stats.vmax);
+ cimg::swap(lmax,stats.lmax);
+ return *this;
+ }
+
+#ifdef cimgstats_plugin
+#include cimgstats_plugin
+#endif
+
+ };
+
+ /*
+ #-------------------------------------------
+ #
+ #
+ #
+ # Definition of the CImgDisplay structure
+ #
+ #
+ #
+ #-------------------------------------------
+ */
+
+ //! This class represents a window which can display \ref CImg<T> images and handles mouse and keyboard events.
+ /**
+ Creating a \c CImgDisplay instance opens a window that can be used to display a \c CImg<T> image
+ of a \c CImgl<T> image list inside. When a display is created, associated window events
+ (such as mouse motion, keyboard and window size changes) are handled and can be easily
+ detected by testing specific \c CImgDisplay data fields.
+ See \ref cimg_displays for a complete tutorial on using the \c CImgDisplay class.
+ **/
+
+ struct CImgDisplay {
+
+ //! Width of the display.
+ /**
+ Prefer using CImgDisplay::dimx() to get the width of the display.
+
+ \note Using CImgDisplay::dimx() instead of \p width is more safe when doing arithmetics
+ involving the value of \p width, since it returns a \e signed int. Arithmetics with
+ \e unsigned types needs a lot of attention.
+
+ \note The variable \c width should be considered as read-only.
+ Setting a new value for \p CImgDisplay::width is done through CImgDisplay::resize().
+ Modifying directly \p width would probably result in a crash.
+
+ \see CImgDisplay::height, CImgDisplay::resize()
+ **/
+ unsigned int width;
+
+ //! Height of the display.
+ /**
+ Prefer using CImgDisplay::dimy() to get the height of the display.
+
+ \note Using CImgDisplay::dimy() instead of \p height is more safe when doing arithmetics
+ involving the value of \p height, since it returns a \e signed int. Artihmetics with
+ \e unsigned types needs a lot of attention.
+
+ \note The variable \c height should be considered as read-only.
+ Setting a new value for \p CImgDisplay::height is done through CImgDisplay::resize().
+ Modifying directly \p height would probably result in a crash.
+
+ \see CImgDisplay::width, CImgDisplay::resize()
+ **/
+ unsigned int height;
+
+ //! Width of the window containing the display.
+ /**
+ \note This is not the width of the display, but the width of the underlying system window.
+ This variable is updated when an user resized the window associated to the display.
+ When it occurs, \c width and \c window_width will be probably different.
+ \see CImgDisplay::window_height, CImgDisplay::resized, CImgDisplay::resize().
+ **/
+ volatile unsigned int window_width;
+
+ //! Height of the window containing the display.
+ /**
+ \note This is not the height of the display, but the height of the underlying system window.
+ This variable is updated when an user resized the window associated to the display.
+ When it occurs, \c height and \c window_height will be probably different.
+ \see CImgDisplay::window_width, CImgDisplay::resized, CImgDisplay::resize().
+ **/
+ volatile unsigned int window_height;
+
+ //! X-coordinate of the display, relative to screen coordinates.
+ volatile int window_x;
+
+ //! Y-coordinate of the display, relative to screen coordinates.
+ volatile int window_y;
+
+ //! Type of pixel normalization done by the display.
+ /**
+ It represents the way the pixel values are normalized for display purposes.
+ Its value can be set to :
+ - \c 0 : No pixel value normalization are performed (fastest). Be sure your image data are bounded in [0,255].
+ - \c 1 : Pixel value renormalization between [0,255] is done at each display request (default).
+ - \c 2 : Pixel value renormalization between [0,255] is done at the first display request. Then the
+ normalization parameters are kept and used for the next image display requests.
+ \note \c normalization is preferably set by invoking constructors CImgDisplay::CImgDisplay().
+ \see CImgDisplay::CImgDisplay(), CImgDisplay::display().
+ **/
+ unsigned int normalization;
+
+ //! Type of events handled by the display.
+ /**
+ It represents what events are handled by the display. Its value can be set to :
+ - \c 0 : No events are handled by the display.
+ - \c 1 : Display closing and resizing are handled by the display.
+ - \c 2 : Display closing, resizing, mouse motion and buttons press, as well as key press are handled by the display.
+ - \c 3 : Display closing, resizing, mouse motion and buttons press/release, as well as key press/release
+ are handled by the display.
+ \note \c events if preferably set by invoking constructors CImgDisplay::CImgDisplay().
+ \see CImgDisplay::CImgDisplay(), CImgDisplay::mouse_x, CImgDisplay::mouse_y, CImgDisplay::key,
+ CImgDisplay::button, CImgDisplay::resized, CImgDisplay::closed.
+ **/
+ unsigned int events;
+
+ //! Flag indicating fullscreen mode.
+ /**
+ If the display has been specified to be fullscreen at the construction, this variable is set to \c true.
+ **/
+ const bool fullscreen;
+
+ //! X-coordinate of the mouse pointer over the display.
+ /**
+ If CImgDisplay::events>=2, \p mouse_x represents the current x-coordinate of the mouse pointer.
+ - If the mouse pointer is outside the display window, \p mouse_x is equal to \p -1.
+ - If the mouse pointer is over the display window, \p mouse_x falls in the range [0,CImgDisplay::width-1],
+ where \p 0 corresponds to the far left coordinate and \p CImgDisplay::width-1 to the far right coordinate.
+ \note \p mouse_x is updated every 25 milliseconds, through an internal thread.
+ \see CImgDisplay::mouse_y, CImgDisplay::button
+ **/
+ volatile int mouse_x;
+
+ //! Y-coordinate of the mouse pointer over the display.
+ /**
+ If CImgDisplay::events>=2, \p mouse_y represents the current y-coordinate of the mouse pointer.
+ - If the mouse pointer is outside the display window, \p mouse_y is equal to \p -1.
+ - If the mouse pointer is over the display window, \p mouse_y falls in the range [0,CImgDisplay::height-1],
+ where \p 0 corresponds to the far top coordinate and \p CImgDisplay::height-1 to the far bottom coordinate.
+ \note \p mouse_y is updated every 25 milliseconds, through an internal thread.
+ \see CImgDisplay::mouse_x, CImgDisplay::button
+ **/
+ volatile int mouse_y;
+
+ //! Variable representing the state of the mouse buttons when the mouse pointer is over the display window.
+ //! (should be considered as read only)
+ /**
+ If CImgDisplay::events>=2, \c button represents the current state of the mouse buttons.
+ - If the mouse pointer is outside the display window, \c button is equal to \c 0.
+ - If the mouse pointer is over the display window, \c button is a combination of the following bits :
+ - bit 0 : State of the left mouse button.
+ - bit 1 : State of the right mouse button.
+ - bit 2 : State of the middle mouse button.
+ - Other bits are unused.
+ \note
+ - \c button is updated every 25 milliseconds, through an internal thread.
+ - If CImgDisplay::events==2, you should re-init \p button to \p 0 after catching the
+ mouse button events, since it will NOT be done automatically (\p Mouse \p button \p Release event is
+ not handled in this case).
+ \see CImgDisplay::mouse_x, CImgDisplay::mouse_y
+ **/
+ volatile unsigned int button;
+
+ //! Variable representing the key pressed when mouse pointer is over the display window.
+ /**
+ If CImgDisplay::events>=2, \c key represents a raw integer value corresponding
+ to the current pressed key.
+ - If no keys are pressed, \c key is equal to \p 0.
+ - If a key is pressed, \p key is a value representing the key. This raw value is \e OS-dependent.
+ Testing the \p key value directly with a raw integer will mostly result in incompabilities
+ between different plateforms.
+ To bypass this problem, \b OS-independent \b keycodes are defined in the \p cimg:: namespace.
+ They are named as \p cimg::key*, where * stands for the key name :
+ \p cimg::keyESC, \p cimg::keyF1, \p cimg::key0, \p cimg::keyA, \p cimg::keySPACE, \p cimg::keySHIFTLEFT, etc...
+ \code
+ CImgDisplay disp(320,200,"Display"); // Create a display window with full events handling
+ ...
+ if (disp.key==cimg::keyESC) std::exit(0); // Exit when pressing the ESC key.
+ ...
+ \endcode
+
+ \note
+ - \p key is updated every 25 milliseconds, through an internal thread.
+ - If CImgDisplay::events==2, You should re-init the \c key variable to \c 0 after catching
+ the \p Key \p Pressed event, since it will NOT be done automatically (Key Release event is handled
+ only when \c CImgDisplay::events>=3).
+
+ \see CImgDisplay::button, CImgDisplay::mouse_x, CImgDisplay::mouse_y
+ **/
+ volatile unsigned int key;
+
+ //! Variable representing the visibility state of the display window (should be read only).
+ /**
+ \p closed can be either true or false :
+ - \p false : The window is visible.
+ - \p true : The window is hidden.
+
+ If CImgDisplay::events>=1, \p closed is set to \p true when the user try to close the display window.
+ The way to set a value for \p closed is to use the functions :
+ - CImgDisplay::show(), to set \p closed to \p false.
+ - CImgDisplay::close(), to set \p closed to \p true.
+
+ Closing a display window DO NOT destroy the instance object. It simply \e hides the display window
+ and set the variable \p closed to true. You are then free to decide what to do
+ when this event occurs. For instance, the following code will re-open the window indefinitely
+ when the user tries to close it :
+ \code
+ CImgDisplay disp(320,200,"Try to close me !");
+ for (;; disp.wait()) if (disp.closed) disp.show();
+ \endcode
+
+ \note - \p closed is updated every 25 milliseconds, through an internal thread.
+
+ \see CImgDisplay::show(), CImgDisplay::close().
+ **/
+ volatile bool closed;
+
+ //! Event-variable
+ volatile bool resized;
+ volatile bool moved;
+
+ // Not documented, internal use only.
+ double min,max;
+
+ //! Return the width of the display window, as a signed integer.
+ /** \note When working with resizing window, \p dimx() does not necessarily return the width of the resized window,
+ but the width of the internal data structure that can be used to display image.
+ Resizing a display window can be done with the function CImgDisplay::resize().
+
+ \see CImgDisplay::width, CImgDisplay::dimy(), CImgDisplay::resize()
+ **/
+ int dimx() const { return (int)width; }
+
+ //! Return the height of the display window, as a signed integer.
+ /** \note When working with resizing window, \p dimy() does not necessarily return the height of the resized window,
+ but the height of the internal data structure that can be used to display image.
+ Resizing a display window can be done with the function CImgDisplay::resize().
+
+ \see CImgDisplay::height, CImgDisplay::dimx(), CImgDisplay::resize()
+ **/
+ int dimy() const { return (int)height; }
+
+ int window_dimx() const { return (int)window_width; }
+ int window_dimy() const { return (int)window_height; }
+
+ // operator=(). It is actually defined to avoid its use, and throw a CImgDisplay exception.
+ private:
+ CImgDisplay& operator=(const CImgDisplay&) {
+ throw CImgDisplayException("CImgDisplay()::operator=() : Assignement of CImgDisplay is not allowed. Use pointers instead !");
+ return *this;
+ }
+ public:
+
+ //! Synchronized waiting function. Same as cimg::wait().
+ /** \see cimg::wait()
+ **/
+ const CImgDisplay& wait(const unsigned int milliseconds) const { cimg::wait(milliseconds); return *this; }
+
+ //! Display an image list CImgl<T> into a display window.
+ /** First, all images of the list are appended into a single image used for visualization,
+ then this image is displayed in the current display window.
+ \param list : The list of images to display.
+ \param axe : The axe used to append the image for visualization. Can be 'x' (default),'y','z' or 'v'.
+ \param align : Defines the relative tqalignment of images when displaying images of different sizes.
+ Can be '\p c' (centered, which is the default), '\p p' (top tqalignment) and '\p n' (bottom aligment).
+
+ \see CImg::get_append()
+ **/
+ template<typename T> CImgDisplay& display(const CImgl<T>& list,const char axe='x',const char align='c') {
+ return display(list.get_append(axe,align));
+ }
+
+ //! Resize a display window with the size of an image.
+ /** \param img : Input image. \p image.width and \p image.height give the new dimensions of the display window.
+ \param redraw : If \p true (default), the current displayed image in the display window will
+ be bloc-interpolated to fit the new dimensions. If \p false, a black image will be drawn in the resized window.
+ \param force : If \p true, the window size is effectively set to the specified dimensions (default).
+ If \p false, only internal data buffer to display images is resized, not the window itself.
+
+ \see CImgDisplay::resized, CImgDisplay::resizedimx(), CImgDisplay::resizedimy()
+ **/
+ template<typename T> CImgDisplay& resize(const CImg<T>& img,const bool redraw=false,const bool force=true) {
+ return resize(img.width,img.height,redraw,force);
+ }
+
+ //! Resize a display window using the size of the given display \p disp
+ CImgDisplay& resize(const CImgDisplay& disp,const bool redraw=false,const bool force=true) {
+ return resize(disp.width,disp.height,redraw,force);
+ }
+
+ //! Force to resize a display window in its current size.
+ CImgDisplay& resize(const bool redraw=false,const bool force=false) {
+ resize(window_width,window_height,redraw,force);
+ return *this;
+ }
+
+ //! Display a 3d object
+ template<typename tp, typename tf, typename T, typename to>
+ CImgDisplay& display_object3d(const tp& points, const CImgl<tf>& primitives,
+ const CImgl<T>& colors, const CImg<to>& opacities,
+ const bool centering=true,
+ const int render_static=4, const int render_motion=1,
+ const bool double_sided=false,
+ const float focale=500.0f, const float ambiant_light=0.05f,
+ const bool display_axes = true, const bool keep_pos = false) {
+ CImg<T>(width,height,1,3,0).display_object3d(points,primitives,colors,opacities,*this,
+ centering,render_static,render_motion,
+ double_sided,focale,ambiant_light,display_axes,keep_pos);
+ return *this;
+ }
+
+ //! Display a 3d object
+ template<typename tp, typename tf, typename T, typename to>
+ CImgDisplay& display_object3d(const tp& points, const CImgl<tf>& primitives,
+ const CImgl<T>& colors, const CImgl<to>& opacities,
+ const bool centering=true,
+ const int render_static=4, const int render_motion=1,
+ const bool double_sided=false,
+ const float focale=500.0f, const float ambiant_light=0.05f,
+ const bool display_axes = true, const bool keep_pos = false) {
+ CImg<T>(width,height,1,3,0).display_object3d(points,primitives,colors,opacities,*this,
+ centering,render_static,render_motion,
+ double_sided,focale,ambiant_light,display_axes,keep_pos);
+ return *this;
+ }
+
+ //! Display a 3D object.
+ template<typename tp, typename tf, typename T>
+ CImgDisplay& display_object3d(const tp& points, const CImgl<tf>& primitives,
+ const CImgl<T>& colors,
+ const bool centering=true,
+ const int render_static=4, const int render_motion=1,
+ const bool double_sided=false,
+ const float focale=500.0f, const float ambiant_light=0.05f,
+ const float opacity=1.0f, const bool display_axes = true, const bool keep_pos = false) {
+ typedef typename cimg::largest<tp,float>::type to;
+ CImg<T>(width,height,1,3,0).display_object3d(points,primitives,colors,
+ CImg<to>(primitives.size)=(to)opacity,*this,
+ centering,render_static,render_motion,
+ double_sided,focale,ambiant_light,display_axes,keep_pos);
+ return *this;
+ }
+
+ // Inner routine used for fast resizing of buffer to display size.
+ template<typename T> static void _render_resize(const T *ptrs, const unsigned int ws, const unsigned int hs,
+ T *ptrd, const unsigned int wd, const unsigned int hd) {
+ unsigned int *const offx = new unsigned int[wd], *const offy = new unsigned int[hd+1], *poffx, *poffy;
+ float s, curr, old;
+ s = (float)ws/wd;
+ poffx = offx; curr=0; for (unsigned int x=0; x<wd; x++) { old=curr; curr+=s; *(poffx++) = (unsigned int)curr-(unsigned int)old; }
+ s = (float)hs/hd;
+ poffy = offy; curr=0; for (unsigned int y=0; y<hd; y++) { old=curr; curr+=s; *(poffy++) = ws*((unsigned int)curr-(unsigned int)old); }
+ *poffy=0;
+ poffy = offy;
+ {for (unsigned int y=0; y<hd; ) {
+ const T *ptr = ptrs;
+ poffx = offx;
+ for (unsigned int x=0; x<wd; x++) { *(ptrd++)=*ptr; ptr+=*(poffx++); }
+ y++;
+ unsigned int dy=*(poffy++);
+ for (;!dy && y<hd; std::memcpy(ptrd, ptrd-wd, sizeof(T)*wd), y++, ptrd+=wd, dy=*(poffy++));
+ ptrs+=dy;
+ }}
+ delete[] offx; delete[] offy;
+ }
+
+ // When no display available
+ //---------------------------
+#if cimg_display_type==0
+ void nodisplay_available() {
+ static bool first = true;
+ if (first) {
+ cimg::warn(true,"CImgDisplay() : Display has been required but is not available (cimg_display_type=0)");
+ first = false;
+ }
+ }
+
+ //! Create a display window with a specified size \p pwidth x \p height.
+ /** \param dimw : Width of the display window.
+ \param dimh : Height of the display window.
+ \param title : Title of the display window.
+ \param normalization_type : Normalization type of the display window (see CImgDisplay::normalize).
+ \param events_type : Type of events handled by the display window.
+ \param fullscreen_flag : Fullscreen mode.
+ \param closed_flag : Initially visible mode.
+ A black image will be initially displayed in the display window.
+ **/
+ CImgDisplay(const unsigned int dimw,const unsigned int dimh,const char *title=NULL,
+ const unsigned int normalization_type=1,const unsigned int events_type=3,
+ const bool fullscreen_flag=false,const bool closed_flag=false):
+ width(0),height(0),window_width(0),window_height(0),window_x(0),window_y(0),normalization(0),
+ events(0),fullscreen(false),mouse_x(0),mouse_y(0),button(0),key(0),closed(true),resized(false),
+ moved(false),min(0),max(0) {
+ nodisplay_available();
+ }
+
+ //! Create a display window from an image.
+ /** \param img : Image that will be used to create the display window.
+ \param title : Title of the display window
+ \param normalization_type : Normalization type of the display window.
+ \param events_type : Type of events handled by the display window.
+ \param fullscreen_flag : Fullscreen mode.
+ \param closed_flag : Initially visible mode.
+ **/
+ template<typename T>
+ CImgDisplay(const CImg<T>& img,const char *title=NULL,
+ const unsigned int normalization_type=1,const unsigned int events_type=3,
+ const bool fullscreen_flag=false,const bool closed_flag=false):
+ width(0),height(0),window_width(0),window_height(0),window_x(0),window_y(0),normalization(0),
+ events(0),fullscreen(false),mouse_x(0),mouse_y(0),button(0),key(0),closed(true),resized(false),
+ moved(false),min(0),max(0) {
+ nodisplay_available();
+ }
+
+ //! Create a display window from an image list.
+ /** \param list : The list of images to display.
+ \param title : Title of the display window
+ \param normalization_type : Normalization type of the display window.
+ \param events_type : Type of events handled by the display window.
+ \param fullscreen_flag : Fullscreen mode.
+ \param closed_flag : Initially visible mode.
+ **/
+ template<typename T>
+ CImgDisplay(const CImgl<T>& list,const char *title=NULL,
+ const unsigned int normalization_type=1,const unsigned int events_type=3,
+ const bool fullscreen_flag=false,const bool closed_flag=false):
+ width(0),height(0),window_width(0),window_height(0),window_x(0),window_y(0),normalization(0),
+ events(0),fullscreen(false),mouse_x(0),mouse_y(0),button(0),key(0),closed(true),resized(false),
+ moved(false),min(0),max(0) {
+ nodisplay_available();
+ }
+
+ //! Create a display window by copying another one.
+ /** \param win : Display window to copy.
+ \param title : Title of the new display window.
+ **/
+ CImgDisplay(const CImgDisplay& win, char *title=NULL):
+ width(0),height(0),window_width(0),window_height(0),window_x(0),window_y(0),normalization(0),
+ events(0),fullscreen(false),mouse_x(0),mouse_y(0),button(0),key(0),closed(true),resized(false),
+ moved(false),min(0),max(0) {
+ nodisplay_available();
+ }
+
+ //! Resize a display window with new dimensions \p width and \p height.
+ CImgDisplay& resize(const int width, const int height,const bool redraw=false,const bool force=true) {
+ return *this;
+ }
+ //! Move a display window at a specific location \p posx, \p posy, and show it on screen.
+ CImgDisplay& move(const int posx,const int posy) { return *this; }
+
+ //! Destructor. Close and destroy a display.
+ ~CImgDisplay() {}
+
+ //! Fill the pixel data of the window buffer according to the image \p pimg.
+ template<typename T> void render(const CImg<T>& img) {}
+
+ //! Display an image in a window.
+ template<typename T> CImgDisplay& display(const CImg<T>& img) { return *this; }
+
+ //! Wait for a window event
+ CImgDisplay& wait() { return *this; }
+
+ //! Show a closed display
+ CImgDisplay& show() { return *this; }
+
+ //! Close a visible display
+ CImgDisplay& close() { return *this; }
+
+ //! Return the width of the screen resolution.
+ static int screen_dimx() { return 0; }
+
+ //! Return the height of the screen resolution.
+ static int screen_dimy() { return 0; }
+
+ //! Set the window title
+ CImgDisplay& title(const char *title,...) { return *this; }
+
+ // X11-based display
+ //-------------------
+#elif cimg_display_type==1
+ void *data;
+ Window window;
+ XImage *image;
+ Colormap colormap;
+ Atom wm_delete_window, wm_delete_protocol;
+#ifdef cimg_use_xshm
+ XShmSegmentInfo *shminfo;
+#else
+ void *shminfo;
+#endif
+
+ CImgDisplay(const unsigned int dimw,const unsigned int dimh,const char *title=NULL,
+ const unsigned int normalization_type=1,const unsigned int events_type=3,
+ const bool fullscreen_flag=false,const bool closed_flag=false):
+ width(dimw),height(dimh),normalization(normalization_type&3),events(events_type&3),
+ fullscreen(fullscreen_flag),closed(closed_flag),min(0),max(-1) {
+ if (!(dimw && dimh)) throw CImgArgumentException("CImgDisplay::CImgDisplay() : Specified window size (%u,%u) is not valid.",
+ dimw,dimh);
+ new_lowlevel(title);
+ std::memset(data,0,
+ (cimg::X11attr().nb_bits==8?sizeof(unsigned char):
+ (cimg::X11attr().nb_bits==16?sizeof(unsigned short):sizeof(unsigned int)))*width*height);
+ _XRefresh();
+ }
+
+ template<typename T>
+ CImgDisplay(const CImg<T>& img,const char *title=NULL,
+ const unsigned int normalization_type=1,const unsigned int events_type=3,
+ const bool fullscreen_flag=false,const bool closed_flag=false):
+ normalization(normalization_type&3),events(events_type&3),
+ fullscreen(fullscreen_flag),closed(closed_flag),min(0),max(0) {
+ if (img.is_empty())
+ throw CImgArgumentException("CImgDisplay::CImgDisplay() : Specified input image (%u,%u,%u,%u,%p) is empty.",
+ img.width,img.height,img.depth,img.dim,img.data);
+ CImg<T> tmp;
+ const CImg<T>& nimg = (img.depth==1)?img:(tmp=img.get_projections2d(img.width/2,img.height/2,img.depth/2));
+ width = nimg.width;
+ height = nimg.height;
+ if (normalization==2) { CImgStats st(img,false); min=st.min; max=st.max; }
+ new_lowlevel(title);
+ render(img);
+ _XRefresh();
+ }
+
+ template<typename T>
+ CImgDisplay(const CImgl<T>& list,const char *title=NULL,
+ const unsigned int normalization_type=1,const unsigned int events_type=3,
+ const bool fullscreen_flag=false,const bool closed_flag=false):
+ normalization(normalization_type&3),events(events_type&3),fullscreen(fullscreen_flag),
+ closed(closed_flag),min(0),max(0) {
+ if (list.is_empty())
+ throw CImgArgumentException("CImgDisplay::CImgDisplay() : Specified input list (%u,%p) is empty.",
+ list.size,list.data);
+ CImg<T> tmp;
+ const CImg<T>
+ img0 = list.get_append('x'),
+ &img = (img0.depth==1)?img0:(tmp=img0.get_projections2d(img0.width/2,img0.height/2,img0.depth/2));
+ width = img.width;
+ height = img.height;
+ if (normalization==2) { CImgStats st(img,false); min=st.min; max=st.max; }
+ new_lowlevel(title);
+ render(list.get_append('x','c'));
+ _XRefresh();
+ }
+
+ CImgDisplay(const CImgDisplay& win, char *title="[Copy]"):
+ width(win.width),height(win.height),normalization(win.normalization&3),events(win.events&3),
+ fullscreen(win.fullscreen),closed(win.closed),min(win.min),max(win.max) {
+ new_lowlevel(title);
+ std::memcpy(data,win.data,
+ (cimg::X11attr().nb_bits==8?sizeof(unsigned char):
+ (cimg::X11attr().nb_bits==16?sizeof(unsigned short):sizeof(unsigned int)))*width*height);
+ _XRefresh();
+ }
+
+ void _XRefresh(const bool wait_expose = true) {
+ if (!closed) {
+ if (wait_expose) {
+ static XEvent event;
+ pthread_mutex_lock(cimg::X11attr().mutex);
+ event.xexpose.type = Expose;
+ event.xexpose.serial = 0;
+ event.xexpose.send_event = True;
+ event.xexpose.display = cimg::X11attr().display;
+ event.xexpose.window = window;
+ event.xexpose.x = 0;
+ event.xexpose.y = 0;
+ event.xexpose.width = (int)width;
+ event.xexpose.height = (int)height;
+ event.xexpose.count = 0;
+ XSendEvent(cimg::X11attr().display, window, False, 0, &event);
+ pthread_mutex_unlock(cimg::X11attr().mutex);
+ } else {
+#if cimg_use_xshm
+ if (shminfo)
+ XShmPutImage(cimg::X11attr().display,window,*cimg::X11attr().gc,image,0,0,0,0,width,height,False);
+ else
+#endif
+ XPutImage(cimg::X11attr().display,window,*cimg::X11attr().gc,image,0,0,0,0,width,height);
+ XSync(cimg::X11attr().display, False);
+ }
+ }
+ }
+
+ template<typename T> void _resize(const T& foo, const unsigned int ndimx, const unsigned int ndimy, const bool redraw) {
+ if (shminfo) {
+#ifdef cimg_use_xshm
+ XShmSegmentInfo *nshminfo = new XShmSegmentInfo;
+ XImage *nimage;
+ nimage = XShmCreateImage(cimg::X11attr().display,DefaultVisual(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)),
+ cimg::X11attr().nb_bits,ZPixmap,0,nshminfo,ndimx,ndimy);
+ nshminfo->shmid = shmget(IPC_PRIVATE, ndimx*ndimy*sizeof(T), IPC_CREAT | 0777);
+ nshminfo->shmaddr = nimage->data = (char*)(data = shmat(nshminfo->shmid,0,0));
+ nshminfo->readOnly = False;
+ XShmAttach(cimg::X11attr().display, nshminfo);
+ T *ndata = (T*)nimage->data;
+ if (redraw) for (unsigned int y=0; y<ndimy; y++) for (unsigned int x=0; x<ndimx; x++)
+ ndata[x+y*ndimx] = ((T*)data)[x*width/ndimx + width*(y*height/ndimy)];
+ else std::memset(ndata,0,sizeof(T)*ndimx*ndimy);
+ XShmDetach(cimg::X11attr().display, shminfo);
+ XDestroyImage(image);
+ shmdt(shminfo->shmaddr);
+ shmctl(shminfo->shmid,IPC_RMID,0);
+ image = nimage;
+ data = (void*)ndata;
+ delete shminfo;
+ shminfo = nshminfo;
+#endif
+ } else {
+ T *ndata = (T*)std::malloc(ndimx*ndimy*sizeof(T));
+ if (redraw) for (unsigned int y=0; y<ndimy; y++) for (unsigned int x=0; x<ndimx; x++)
+ ndata[x+y*ndimx] = ((T*)data)[x*width/ndimx + width*(y*height/ndimy)];
+ else std::memset(ndata,0,sizeof(T)*ndimx*ndimy);
+ data = (void*)ndata;
+ XDestroyImage(image);
+ image = XCreateImage(cimg::X11attr().display,DefaultVisual(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)),
+ cimg::X11attr().nb_bits,ZPixmap,0,(char*)data,ndimx,ndimy,8,0);
+ }
+ }
+
+ CImgDisplay& resize(const int nwidth, const int nheight, const bool redraw = false, const bool force = true) {
+ if (!(nwidth && nheight))
+ throw CImgArgumentException("CImgDisplay::resize() : Specified window size (%d,%d) is not valid.",
+ nwidth,nheight);
+ const unsigned int
+ tmpdimx=(nwidth>0)?nwidth:(-nwidth*width/100),
+ tmpdimy=(nheight>0)?nheight:(-nheight*height/100),
+ dimx = tmpdimx?tmpdimx:1,
+ dimy = tmpdimy?tmpdimy:1;
+ pthread_mutex_lock(cimg::X11attr().mutex);
+ if (dimx!=width || dimy!=height) {
+ switch (cimg::X11attr().nb_bits) {
+ case 8: { unsigned char foo; _resize(foo,dimx,dimy,redraw); } break;
+ case 16: { unsigned short foo; _resize(foo,dimx,dimy,redraw); } break;
+ default: { unsigned int foo; _resize(foo,dimx,dimy,redraw); } break;
+ }
+ }
+ width = dimx;
+ height = dimy;
+ if (force && (window_width!=width || window_height!=height)) {
+ XResizeWindow(cimg::X11attr().display,window,width,height);
+ window_width = width;
+ window_height = height;
+ }
+ resized = false;
+ pthread_mutex_unlock(cimg::X11attr().mutex);
+ _XRefresh();
+ return *this;
+ }
+
+ CImgDisplay& move(const int posx,const int posy) {
+ show();
+ pthread_mutex_lock(cimg::X11attr().mutex);
+ XMoveWindow(cimg::X11attr().display,window,posx,posy);
+ moved = false;
+ window_x = posx;
+ window_y = posy;
+ pthread_mutex_unlock(cimg::X11attr().mutex);
+ _XRefresh();
+ return *this;
+ }
+
+ ~CImgDisplay() {
+ unsigned int i;
+ pthread_mutex_lock(cimg::X11attr().mutex);
+ for (i=0; i<cimg::X11attr().nb_wins && cimg::X11attr().wins[i]!=this; i++) i++;
+ for (; i<cimg::X11attr().nb_wins-1; i++) cimg::X11attr().wins[i]=cimg::X11attr().wins[i+1];
+ cimg::X11attr().nb_wins--;
+ if (fullscreen) XUngrabKeyboard(cimg::X11attr().display,CurrentTime);
+ XDestroyWindow(cimg::X11attr().display,window);
+ if (shminfo) {
+#if cimg_use_xshm
+ XShmDetach(cimg::X11attr().display, shminfo);
+ XDestroyImage(image);
+ shmdt(shminfo->shmaddr);
+ shmctl(shminfo->shmid,IPC_RMID,0);
+ delete shminfo;
+#endif
+ } else XDestroyImage(image);
+ if (cimg::X11attr().nb_bits==8) XFreeColormap(cimg::X11attr().display,colormap);
+ pthread_mutex_unlock(cimg::X11attr().mutex);
+ if (!cimg::X11attr().nb_wins) {
+ pthread_cancel(*cimg::X11attr().event_thread);
+ pthread_join(*cimg::X11attr().event_thread,NULL);
+ pthread_mutex_lock(cimg::X11attr().mutex);
+ XCloseDisplay(cimg::X11attr().display);
+ cimg::X11attr().display=NULL;
+ pthread_mutex_unlock(cimg::X11attr().mutex);
+ pthread_mutex_destroy(cimg::X11attr().mutex);
+ delete cimg::X11attr().event_thread;
+ delete cimg::X11attr().mutex;
+ delete cimg::X11attr().gc;
+ }
+ }
+
+ void set_colormap(Colormap& colormap, const unsigned int dim) {
+ XColor palette[256];
+ switch (dim) {
+ case 1: // palette for greyscale images
+ for (unsigned int index=0; index<256; index++) {
+ palette[index].pixel = index;
+ palette[index].red = palette[index].green = palette[index].blue = index<<8;
+ palette[index].flags = DoRed | DoGreen | DoBlue;
+ }
+ break;
+ case 2: // palette for RG images
+ for (unsigned int index=0, r=8; r<256; r+=16)
+ for (unsigned int g=8; g<256; g+=16) {
+ palette[index].pixel = index;
+ palette[index].red = palette[index].blue = r<<8;
+ palette[index].green = g<<8;
+ palette[index++].flags = DoRed | DoGreen | DoBlue;
+ }
+ break;
+ default: // palette for RGB images
+ for (unsigned int index=0, r=16; r<256; r+=32)
+ for (unsigned int g=16; g<256; g+=32)
+ for (unsigned int b=32; b<256; b+=64) {
+ palette[index].pixel = index;
+ palette[index].red = r<<8;
+ palette[index].green = g<<8;
+ palette[index].blue = b<<8;
+ palette[index++].flags = DoRed | DoGreen | DoBlue;
+ }
+ break;
+ }
+ XStoreColors(cimg::X11attr().display,colormap,palette,256);
+ }
+
+
+ static int _new_lowlevel_shm(Display *dpy, XErrorEvent *error) {
+ cimg::X11attr().shm_enabled = false;
+ return 0;
+ }
+
+ void new_lowlevel(const char *title=NULL) {
+ if (!cimg::X11attr().display) { // Open X11 Display if not already done.
+ cimg::X11attr().nb_wins = 0;
+ cimg::X11attr().thread_finished = false;
+ cimg::X11attr().mutex = new pthread_mutex_t;
+ pthread_mutex_init(cimg::X11attr().mutex,NULL);
+ pthread_mutex_lock(cimg::X11attr().mutex);
+ cimg::X11attr().display = XOpenDisplay((std::getenv("DISPLAY") ? std::getenv("DISPLAY") : ":0.0"));
+ if (!cimg::X11attr().display) throw CImgDisplayException("CImgDisplay::new_lowlevel() : Can't open X11 display");
+ cimg::X11attr().nb_bits = DefaultDepth(cimg::X11attr().display, DefaultScreen(cimg::X11attr().display));
+ if (cimg::X11attr().nb_bits!=8 && cimg::X11attr().nb_bits!=16 && cimg::X11attr().nb_bits!=24)
+ throw CImgDisplayException("CImgDisplay::new_lowlevel() : %u bits mode is not supported "
+ "(only 8, 16 and 24 bits modes are supported)",cimg::X11attr().nb_bits);
+ cimg::X11attr().gc = new GC;
+ *cimg::X11attr().gc = DefaultGC(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display));
+ Visual *visual = DefaultVisual(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display));
+ XVisualInfo vtemplate;
+ vtemplate.visualid = XVisualIDFromVisual(visual);
+ int nb_visuals;
+ XVisualInfo *vinfo = XGetVisualInfo(cimg::X11attr().display,VisualIDMask,&vtemplate,&nb_visuals);
+ if (vinfo && vinfo->red_mask<vinfo->blue_mask) cimg::X11attr().blue_first = true;
+ cimg::X11attr().byte_order = ImageByteOrder(cimg::X11attr().display);
+ cimg::X11attr().event_thread = new pthread_t;
+ pthread_create(cimg::X11attr().event_thread,NULL,thread_lowlevel,NULL);
+ } else pthread_mutex_lock(cimg::X11attr().mutex);
+
+ // Create display window and image data.
+ if (fullscreen) {
+ const unsigned int sx = screen_dimx(), sy = screen_dimy();
+ XSetWindowAttributes winattr;
+ winattr.override_redirect = True;
+ window = XCreateWindow(cimg::X11attr().display,
+ RootWindow(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)),
+ (sx-width)/2,(sy-height)/2,width,height,0,0,InputOutput,CopyFromParent,
+ CWOverrideRedirect,
+ &winattr);
+ } else
+ window = XCreateSimpleWindow(cimg::X11attr().display,
+ RootWindow(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)),
+ 0,0,width,height,2,0,0x0L);
+
+ const unsigned int bufsize = width*height*(cimg::X11attr().nb_bits==8?1:(cimg::X11attr().nb_bits==16?2:4));
+#ifdef cimg_use_xshm
+ if (XShmQueryExtension(cimg::X11attr().display)) shminfo = new XShmSegmentInfo;
+ else
+#endif
+ shminfo = 0;
+ if (shminfo) {
+#ifdef cimg_use_xshm
+ image = XShmCreateImage(cimg::X11attr().display,DefaultVisual(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)),
+ cimg::X11attr().nb_bits,ZPixmap,0,shminfo,width,height);
+ if (!image) { delete shminfo; shminfo = 0; }
+ else {
+ shminfo->shmid = shmget(IPC_PRIVATE, bufsize, IPC_CREAT | 0777);
+ if (shminfo->shmid==-1) { XDestroyImage(image); delete shminfo; shminfo = 0; }
+ else {
+ shminfo->shmaddr = image->data = (char*)(data = shmat(shminfo->shmid,0,0));
+ if (shminfo->shmaddr==(char*)-1) { XDestroyImage(image); shmctl(shminfo->shmid,IPC_RMID,0); delete shminfo; shminfo = 0; }
+ shminfo->readOnly = False;
+ cimg::X11attr().shm_enabled = true;
+ XErrorHandler oldXErrorHandler = XSetErrorHandler(_new_lowlevel_shm);
+ XShmAttach(cimg::X11attr().display, shminfo);
+ XSync(cimg::X11attr().display, False);
+ XSetErrorHandler(oldXErrorHandler);
+ if (!cimg::X11attr().shm_enabled) {
+ XDestroyImage(image);
+ shmdt(shminfo->shmaddr);
+ shmctl(shminfo->shmid,IPC_RMID,0);
+ delete shminfo; shminfo = 0;
+ }
+ }
+ }
+#endif
+ }
+ if (!shminfo) {
+ data = std::malloc(bufsize);
+ image = XCreateImage(cimg::X11attr().display,DefaultVisual(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display)),
+ cimg::X11attr().nb_bits,ZPixmap,0,(char*)data,width,height,8,0);
+ }
+
+ XStoreName(cimg::X11attr().display,window,title?title:" ");
+ if (cimg::X11attr().nb_bits==8) {
+ colormap = XCreateColormap(cimg::X11attr().display,window,
+ DefaultVisual(cimg::X11attr().display,
+ DefaultScreen(cimg::X11attr().display)),AllocAll);
+ set_colormap(colormap,3);
+ XSetWindowColormap(cimg::X11attr().display,window,colormap);
+ }
+ if (!closed) {
+ XEvent event;
+ XSelectInput(cimg::X11attr().display,window,StructureNotifyMask);
+ XMapRaised(cimg::X11attr().display,window);
+ do XWindowEvent(cimg::X11attr().display,window,StructureNotifyMask,&event);
+ while (event.type!=MapNotify);
+ XWindowAttributes attr;
+ XGetWindowAttributes(cimg::X11attr().display, window, &attr);
+ while (attr.map_state != IsViewable) XSync(cimg::X11attr().display, False);
+ XGetWindowAttributes(cimg::X11attr().display,window,&attr);
+ window_x = attr.x;
+ window_y = attr.y;
+ } else {
+ const int foo=0;
+ window_x = window_y = cimg::get_type_min(foo);
+ }
+ if (events) {
+ wm_delete_window = XInternAtom(cimg::X11attr().display, "WM_DELETE_WINDOW", False);
+ wm_delete_protocol = XInternAtom(cimg::X11attr().display, "WM_PROTOCOLS", False);
+ XSetWMProtocols(cimg::X11attr().display, window, &wm_delete_window, 1);
+ if (fullscreen) XGrabKeyboard(cimg::X11attr().display, window, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+ }
+ window_width = width;
+ window_height = height;
+ mouse_x = mouse_y = -1;
+ button = key = 0;
+ resized = moved = false;
+ cimg::X11attr().wins[cimg::X11attr().nb_wins++]=this;
+ pthread_mutex_unlock(cimg::X11attr().mutex);
+ }
+
+ void proc_lowlevel(XEvent *pevent) {
+ const unsigned int buttoncode[3] = { 1,4,2 };
+ XEvent event=*pevent;
+ switch (event.type) {
+ case ClientMessage:
+ if ((int)event.xclient.message_type==(int)wm_delete_protocol &&
+ (int)event.xclient.data.l[0]==(int)wm_delete_window) {
+ XUnmapWindow(cimg::X11attr().display,window);
+ mouse_x=mouse_y=-1;
+ button=key=0;
+ closed=true;
+ }
+ break;
+ case ConfigureNotify: {
+ while (XCheckWindowEvent(cimg::X11attr().display,window,StructureNotifyMask,&event));
+ const unsigned int
+ nw = event.xconfigure.width,
+ nh = event.xconfigure.height;
+ const int
+ nx = event.xconfigure.x,
+ ny = event.xconfigure.y;
+ if (nw && nh && (nw!=window_width || nh!=window_height)) {
+ window_width = nw;
+ window_height = nh;
+ mouse_x = mouse_y = -1;
+ XResizeWindow(cimg::X11attr().display,window,window_width,window_height);
+ resized = true;
+ }
+ if (nx!=window_x || ny!=window_y) {
+ window_x = nx;
+ window_y = ny;
+ moved = true;
+ }
+ } break;
+ case Expose: {
+ while (XCheckWindowEvent(cimg::X11attr().display,window,ExposureMask,&event));
+ _XRefresh(false);
+ if (fullscreen) {
+ XWindowAttributes attr;
+ XGetWindowAttributes(cimg::X11attr().display, window, &attr);
+ while (attr.map_state != IsViewable) XSync(cimg::X11attr().display, False);
+ XSetInputFocus(cimg::X11attr().display, window, RevertToParent, CurrentTime);
+ }
+ } break;
+ case ButtonPress:
+ while (XCheckWindowEvent(cimg::X11attr().display,window,ButtonPressMask,&event));
+ button |= buttoncode[event.xbutton.button-1];
+ break;
+ case ButtonRelease:
+ while (XCheckWindowEvent(cimg::X11attr().display,window,ButtonReleaseMask,&event));
+ button &= ~buttoncode[event.xbutton.button-1];
+ break;
+ case KeyPress: {
+ while (XCheckWindowEvent(cimg::X11attr().display,window,KeyPressMask,&event));
+ char tmp;
+ KeySym ksym;
+ XLookupString(&event.xkey,&tmp,1,&ksym,NULL);
+ key = (unsigned int)ksym;
+ }
+ break;
+ case KeyRelease:
+ while (XCheckWindowEvent(cimg::X11attr().display,window,KeyReleaseMask,&event));
+ key = 0;
+ break;
+ case LeaveNotify:
+ while (XCheckWindowEvent(cimg::X11attr().display,window,LeaveWindowMask,&event));
+ mouse_x = mouse_y =-1;
+ break;
+ case MotionNotify:
+ while (XCheckWindowEvent(cimg::X11attr().display,window,PointerMotionMask,&event));
+ mouse_x = event.xmotion.x;
+ mouse_y = event.xmotion.y;
+ if (mouse_x<0 || mouse_y<0 || mouse_x>=dimx() || mouse_y>=dimy()) mouse_x=mouse_y=-1;
+ break;
+ }
+ }
+
+ static void* thread_lowlevel(void *arg) {
+ XEvent event;
+ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
+ for (;;) {
+ pthread_mutex_lock(cimg::X11attr().mutex);
+ for (unsigned int i=0; i<cimg::X11attr().nb_wins; i++) {
+ const unsigned int xevent_type = (cimg::X11attr().wins[i]->events)&3;
+ const unsigned int etqmask =
+ ((xevent_type>=1)?ExposureMask|StructureNotifyMask:0)|
+ ((xevent_type>=2)?ButtonPressMask|KeyPressMask|PointerMotionMask|LeaveWindowMask:0)|
+ ((xevent_type>=3)?ButtonReleaseMask|KeyReleaseMask:0);
+ XSelectInput(cimg::X11attr().display,cimg::X11attr().wins[i]->window,etqmask);
+ }
+ bool event_flag = XCheckTypedEvent(cimg::X11attr().display, ClientMessage, &event);
+ if (!event_flag) event_flag = XCheckMaskEvent(cimg::X11attr().display,
+ ExposureMask|StructureNotifyMask|ButtonPressMask|
+ KeyPressMask|PointerMotionMask|LeaveWindowMask|ButtonReleaseMask|
+ KeyReleaseMask,&event);
+ if (event_flag) {
+ for (unsigned int i=0; i<cimg::X11attr().nb_wins; i++)
+ if (!cimg::X11attr().wins[i]->closed && event.xany.window==cimg::X11attr().wins[i]->window)
+ cimg::X11attr().wins[i]->proc_lowlevel(&event);
+ cimg::X11attr().thread_finished = true;
+ }
+ pthread_mutex_unlock(cimg::X11attr().mutex);
+ pthread_testcancel();
+ cimg::wait(25);
+ }
+ return NULL;
+ }
+
+ template<typename T> XImage* render(const CImg<T>& img, const bool flag8 = false) {
+ if (img.is_empty())
+ throw CImgArgumentException("CImgDisplay::render() : Specified input image (%u,%u,%u,%u,%p) is empty.",
+ img.width,img.height,img.depth,img.dim,img.data);
+ if (img.depth!=1) return render(img.get_projections2d(img.width/2,img.height/2,img.depth/2));
+ if (cimg::X11attr().nb_bits==8 && (img.width!=width || img.height!=height)) return render(img.get_resize(width,height,1,-100,1));
+ if (cimg::X11attr().nb_bits==8 && !flag8 && img.dim==3) return render(img.get_RGBtoLUT(true),true);
+
+ const unsigned int xymax = img.width*img.height;
+ const T
+ *data1 = img.ptr(),
+ *data2 = (img.dim>=2)?img.ptr(0,0,0,1):data1,
+ *data3 = (img.dim>=3)?img.ptr(0,0,0,2):data1;
+ if (cimg::X11attr().blue_first) cimg::swap(data1,data3);
+ pthread_mutex_lock(cimg::X11attr().mutex);
+
+ if (!normalization) {
+ switch (cimg::X11attr().nb_bits) {
+ case 8: {
+ set_colormap(colormap,img.dim);
+ unsigned char *const ndata = (img.width==width && img.height==height)?(unsigned char*)data:new unsigned char[img.width*img.height];
+ unsigned char *ptrd = (unsigned char*)ndata;
+ switch (img.dim) {
+ case 1: for (unsigned int xy=0; xy<xymax; xy++) (*ptrd++) = (unsigned char)*(data1++);
+ break;
+ case 2: for (unsigned int xy=0; xy<xymax; xy++) {
+ const unsigned char R = (unsigned char)*(data1++), G = (unsigned char)*(data2++);
+ (*ptrd++) = (R&0xf0)|(G>>4);
+ } break;
+ default: for (unsigned int xy=0; xy<xymax; xy++) {
+ const unsigned char R = (unsigned char)*(data1++), G = (unsigned char)*(data2++), B = (unsigned char)*(data3++);
+ (*ptrd++) = (R&0xe0) | ((G>>5)<<2) | (B>>6);
+ } break;
+ }
+ if (ndata!=data) { _render_resize(ndata,img.width,img.height,(unsigned char*)data,width,height); delete[] ndata; }
+ } break;
+ case 16: {
+ unsigned short *const ndata = (img.width==width && img.height==height)?(unsigned short*)data:new unsigned short[img.width*img.height];
+ unsigned char *ptrd = (unsigned char*)ndata;
+ const unsigned int M = 248;
+ if (cimg::X11attr().byte_order) for (unsigned int xy=0; xy<xymax; xy++) {
+ const unsigned char G = (unsigned char)*(data2++)>>2;
+ *(ptrd++) = (unsigned char)*(data1++)&M | (G>>3);
+ *(ptrd++) = (G<<5) | ((unsigned char)*(data3++)>>3);
+ } else for (unsigned int xy=0; xy<xymax; xy++) {
+ const unsigned char G = (unsigned char)*(data2++)>>2;
+ *(ptrd++) = (G<<5) | ((unsigned char)*(data3++)>>3);
+ *(ptrd++) = (unsigned char)*(data1++)&M | (G>>3);
+ }
+ if (ndata!=data) { _render_resize(ndata,img.width,img.height,(unsigned short*)data,width,height); delete[] ndata; }
+ } break;
+ default: {
+ unsigned int *const ndata = (img.width==width && img.height==height)?(unsigned int*)data:new unsigned int[img.width*img.height];
+ unsigned char *ptrd = (unsigned char*)ndata;
+ if (cimg::X11attr().byte_order) for (unsigned int xy=0; xy<xymax; xy++) {
+ *(ptrd++) = 0;
+ *(ptrd++) = (unsigned char)*(data1++);
+ *(ptrd++) = (unsigned char)*(data2++);
+ *(ptrd++) = (unsigned char)*(data3++);
+ } else for (unsigned int xy=0; xy<xymax; xy++) {
+ *(ptrd++) = (unsigned char)*(data3++);
+ *(ptrd++) = (unsigned char)*(data2++);
+ *(ptrd++) = (unsigned char)*(data1++);
+ *(ptrd++) = 0;
+ }
+ if (ndata!=data) { _render_resize(ndata,img.width,img.height,(unsigned int*)data,width,height); delete[] ndata; }
+ } break;
+ };
+ } else {
+ if ((min>max) || normalization==1) { CImgStats st(img,false); min=st.min; max=st.max; }
+ const T nmin = (T)min, delta = (T)max-nmin, mm=delta?delta:(T)1;
+ switch (cimg::X11attr().nb_bits) {
+ case 8: {
+ set_colormap(colormap,img.dim);
+ unsigned char *const ndata = (img.width==width && img.height==height)?(unsigned char*)data:new unsigned char[img.width*img.height];
+ unsigned char *ptrd = (unsigned char*)ndata;
+ switch (img.dim) {
+ case 1: for (unsigned int xy=0; xy<xymax; xy++) {
+ const unsigned char R = (unsigned char)(255*(*(data1++)-nmin)/mm);
+ *(ptrd++) = R;
+ } break;
+ case 2: for (unsigned int xy=0; xy<xymax; xy++) {
+ const unsigned char
+ R = (unsigned char)(255*(*(data1++)-nmin)/mm),
+ G = (unsigned char)(255*(*(data2++)-nmin)/mm);
+ (*ptrd++) = (R&0xf0) | (G>>4);
+ } break;
+ default:
+ for (unsigned int xy=0; xy<xymax; xy++) {
+ const unsigned char
+ R = (unsigned char)(255*(*(data1++)-nmin)/mm),
+ G = (unsigned char)(255*(*(data2++)-nmin)/mm),
+ B = (unsigned char)(255*(*(data3++)-nmin)/mm);
+ *(ptrd++) = (R&0xe0) | ((G>>5)<<2) | (B>>6);
+ } break;
+ }
+ if (ndata!=data) { _render_resize(ndata,img.width,img.height,(unsigned char*)data,width,height); delete[] ndata; }
+ } break;
+ case 16: {
+ unsigned short *const ndata = (img.width==width && img.height==height)?(unsigned short*)data:new unsigned short[img.width*img.height];
+ unsigned char *ptrd = (unsigned char*)ndata;
+ const unsigned int M = 248;
+ if (cimg::X11attr().byte_order) for (unsigned int xy=0; xy<xymax; xy++) {
+ const unsigned char G = (unsigned char)(255*(*(data2++)-nmin)/mm)>>2;
+ *(ptrd++) = (unsigned char)(255*(*(data1++)-nmin)/mm)&M | (G>>3);
+ *(ptrd++) = (G<<5) | ((unsigned char)(255*(*(data3++)-nmin)/mm)>>3);
+ } else for (unsigned int xy=0; xy<xymax; xy++) {
+ const unsigned char G = (unsigned char)(255*(*(data2++)-nmin)/mm)>>2;
+ *(ptrd++) = (G<<5) | ((unsigned char)(255*(*(data3++)-nmin)/mm)>>3);
+ *(ptrd++) = (unsigned char)(255*(*(data1++)-nmin)/mm)&M | (G>>3);
+ }
+ if (ndata!=data) { _render_resize(ndata,img.width,img.height,(unsigned short*)data,width,height); delete[] ndata; }
+ } break;
+ default: {
+ unsigned int *const ndata = (img.width==width && img.height==height)?(unsigned int*)data:new unsigned int[img.width*img.height];
+ unsigned char *ptrd = (unsigned char*)ndata;
+ if (cimg::X11attr().byte_order) for (unsigned int xy=0; xy<xymax; xy++) {
+ (*ptrd++) = 0;
+ (*ptrd++) = (unsigned char)(255*(*(data1++)-nmin)/mm);
+ (*ptrd++) = (unsigned char)(255*(*(data2++)-nmin)/mm);
+ (*ptrd++) = (unsigned char)(255*(*(data3++)-nmin)/mm);
+ } else for (unsigned int xy=0; xy<xymax; xy++) {
+ (*ptrd++) = (unsigned char)(255*(*(data3++)-nmin)/mm);
+ (*ptrd++) = (unsigned char)(255*(*(data2++)-nmin)/mm);
+ (*ptrd++) = (unsigned char)(255*(*(data1++)-nmin)/mm);
+ (*ptrd++) = 0;
+ }
+ if (ndata!=data) { _render_resize(ndata,img.width,img.height,(unsigned int*)data,width,height); delete[] ndata; }
+ } break;
+ }
+ }
+
+ pthread_mutex_unlock(cimg::X11attr().mutex);
+ return image;
+ }
+
+ template<typename T> CImgDisplay& display(const CImg<T>& img) {
+ render(img);
+ pthread_mutex_lock(cimg::X11attr().mutex);
+ _XRefresh(false);
+ pthread_mutex_unlock(cimg::X11attr().mutex);
+ return *this;
+ }
+
+ CImgDisplay& wait() {
+ if (!closed && events) {
+ XEvent event;
+ do {
+ pthread_mutex_lock(cimg::X11attr().mutex);
+ const unsigned int
+ etqmask = ExposureMask|StructureNotifyMask|
+ ((events>=2)?ButtonPressMask|KeyPressMask|PointerMotionMask|LeaveWindowMask:0)|
+ ((events>=3)?ButtonReleaseMask|KeyReleaseMask:0);
+ XSelectInput(cimg::X11attr().display,window,etqmask);
+ XPeekEvent(cimg::X11attr().display,&event);
+ cimg::X11attr().thread_finished = false;
+ pthread_mutex_unlock(cimg::X11attr().mutex);
+ } while (event.xany.window!=window);
+ while (!cimg::X11attr().thread_finished) cimg::wait(25);
+ }
+ return *this;
+ }
+
+ CImgDisplay& show() {
+ if (closed) {
+ closed = false;
+ const int foo=0, tmin = cimg::get_type_min(foo);
+ pthread_mutex_lock(cimg::X11attr().mutex);
+ XEvent event;
+ XSelectInput(cimg::X11attr().display,window,StructureNotifyMask);
+ XMapRaised(cimg::X11attr().display,window);
+ if (window_x!=tmin || window_y!=tmin) XMoveWindow(cimg::X11attr().display,window,window_x,window_y);
+ do XWindowEvent(cimg::X11attr().display,window,StructureNotifyMask,&event);
+ while (event.type!=MapNotify);
+ if (window_x==tmin && window_y==tmin) {
+ XWindowAttributes attr;
+ XGetWindowAttributes(cimg::X11attr().display,window,&attr);
+ window_x = attr.x;
+ window_y = attr.y;
+ }
+ pthread_mutex_unlock(cimg::X11attr().mutex);
+ }
+ _XRefresh();
+ return *this;
+ }
+
+ CImgDisplay& close() {
+ if (!closed) {
+ pthread_mutex_lock(cimg::X11attr().mutex);
+ XUnmapWindow(cimg::X11attr().display,window);
+ closed = true;
+ window_x = window_y = 0;
+ pthread_mutex_unlock(cimg::X11attr().mutex);
+ }
+ return *this;
+ }
+
+ static int screen_dimx() {
+ int res = 0;
+ if (!cimg::X11attr().display) {
+ Display *disp = XOpenDisplay((std::getenv("DISPLAY") ? std::getenv("DISPLAY") : ":0.0"));
+ if (!disp) throw CImgDisplayException("CImgDisplay::screen_dimx() : Can't open X11 display");
+ res = DisplayWidth(disp,DefaultScreen(disp));
+ XCloseDisplay(disp);
+ } else res = DisplayWidth(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display));
+ return res;
+ }
+
+ static int screen_dimy() {
+ int res = 0;
+ if (!cimg::X11attr().display) {
+ Display *disp = XOpenDisplay((std::getenv("DISPLAY") ? std::getenv("DISPLAY") : ":0.0"));
+ if (!disp) throw CImgDisplayException("CImgDisplay::screen_dimy() : Can't open X11 display");
+ res = DisplayHeight(disp,DefaultScreen(disp));
+ XCloseDisplay(disp);
+ } else res = DisplayHeight(cimg::X11attr().display,DefaultScreen(cimg::X11attr().display));
+ return res;
+ }
+
+ CImgDisplay& title(const char *title,...) {
+ char tmp[1024]={0};
+ va_list ap;
+ va_start(ap, title);
+ std::vsprintf(tmp,title,ap);
+ va_end(ap);
+ pthread_mutex_lock(cimg::X11attr().mutex);
+ XStoreName(cimg::X11attr().display,window,tmp);
+ pthread_mutex_unlock(cimg::X11attr().mutex);
+ return *this;
+ }
+
+ // Windows-based display
+ //-----------------------
+#elif cimg_display_type==2
+ CLIENTCREATESTRUCT ccs;
+ BITMAPINFO bmi;
+ unsigned int *data;
+ DEVMODE curr_mode;
+ HWND window;
+ HDC hdc;
+ HANDLE thread;
+ HANDLE wait_disp;
+ HANDLE created;
+ HANDLE mutex;
+
+ CImgDisplay(const unsigned int dimw,const unsigned int dimh,const char *title=NULL,
+ const unsigned int normalization_type=1,const unsigned int events_type=3,
+ const bool fullscreen_flag=false,const bool closed_flag=false):
+ width(dimw),height(dimh),normalization(normalization_type&3),events(events_type&3),
+ fullscreen(fullscreen_flag),closed(closed_flag),min(0),max(-1) {
+ if (!(dimw && dimh)) throw CImgArgumentException("CImgDisplay::CImgDisplay() : Specified window size (%u,%u) is not valid.",
+ dimw,dimh);
+ new_lowlevel(title);
+ std::memset(data,0,sizeof(unsigned int)*width*height);
+ SetDIBitsToDevice(hdc,0,0,width,height,0,0,0,height,data,&bmi,DIB_RGB_COLORS);
+ }
+
+ template<typename T>
+ CImgDisplay(const CImg<T>& img,const char *title=NULL,
+ const unsigned int normalization_type=1,const unsigned int events_type=3,
+ const bool fullscreen_flag=false,const bool closed_flag=false):
+ normalization(normalization_type&3),events(events_type&3),
+ fullscreen(fullscreen_flag),closed(closed_flag),min(0),max(0) {
+ if (img.is_empty())
+ throw CImgArgumentException("CImgDisplay::CImgDisplay() : Specified input image (%u,%u,%u,%u,%p) is empty.",
+ img.width,img.height,img.depth,img.dim,img.data);
+ CImg<T> tmp;
+ const CImg<T>& nimg = (img.depth==1)?img:(tmp=img.get_projections2d(img.width/2,img.height/2,img.depth/2));
+ width = nimg.width;
+ height = nimg.height;
+ if (normalization==2) { CImgStats st(img,false); min=st.min; max=st.max; }
+ new_lowlevel(title);
+ display(nimg);
+ }
+
+ template<typename T>
+ CImgDisplay(const CImgl<T>& list,const char *title=NULL,
+ const unsigned int normalization_type=1,const unsigned int events_type=3,
+ const bool fullscreen_flag=false,const bool closed_flag=false):
+ normalization(normalization_type&3),events(events_type&3),fullscreen(fullscreen_flag),
+ closed(closed_flag),min(0),max(0) {
+ if (list.is_empty())
+ throw CImgArgumentException("CImgDisplay::CImgDisplay() : Specified input list (%u,%p) is empty",
+ list.size,list.data);
+ CImg<T> tmp;
+ const CImg<T>
+ img0 = list.get_append('x'),
+ &img = (img0.depth==1)?img0:(tmp=img0.get_projections2d(img0.width/2,img0.height/2,img0.depth/2));
+ width = img.width;
+ height = img.height;
+ if (normalization==2) { CImgStats st(img,false); min=st.min; max=st.max; }
+ new_lowlevel(title);
+ display(img);
+ }
+
+ CImgDisplay(const CImgDisplay& win, char *title="[Copy]"):
+ width(win.width),height(win.height),normalization(win.normalization&3),events(win.events&3),
+ fullscreen(win.fullscreen),closed(win.closed),min(win.min),max(win.max) {
+ new_lowlevel(title);
+ std::memcpy(data,win.data,sizeof(unsigned int)*width*height);
+ SetDIBitsToDevice(hdc,0,0,width,height,0,0,0,height,data,&bmi,DIB_RGB_COLORS);
+ }
+
+ CImgDisplay& resize(const int nwidth, const int nheight,const bool redraw=false,const bool force=true) {
+ if (!(nwidth && nheight))
+ throw CImgArgumentException("CImgDisplay::resize() : Specified window size (%d,%d) is not valid.",
+ nwidth,nheight);
+ const unsigned int
+ tmpdimx=(nwidth>0)?nwidth:(-nwidth*width/100),
+ tmpdimy=(nheight>0)?nheight:(-nheight*height/100),
+ dimx = tmpdimx?tmpdimx:1,
+ dimy = tmpdimy?tmpdimy:1;
+ if (dimx!=width || dimy!=height) {
+ unsigned int *ndata = new unsigned int[dimx*dimy];
+ if (redraw)
+ for (unsigned int y=0; y<dimy; y++) for (unsigned int x=0; x<dimx; x++)
+ ndata[x+y*dimx] = data[x*width/dimx + width*(y*height/dimy)];
+ else std::memset(ndata,0x80,sizeof(unsigned int)*dimx*dimy);
+ delete[] data;
+ data = ndata;
+ bmi.bmiHeader.biWidth=dimx;
+ bmi.bmiHeader.biHeight=-(int)dimy;
+ }
+ width = dimx;
+ height = dimy;
+ if (force && (window_width!=width || window_height!=height)) {
+ RECT rect; rect.left=rect.top=0; rect.right=width-1; rect.bottom=height-1;
+ AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false);
+ const int cwidth = rect.right-rect.left+1, cheight = rect.bottom-rect.top+1;
+ SetWindowPos(window,0,0,0,cwidth,cheight,SWP_NOMOVE | SWP_NOZORDER | SWP_NOCOPYBITS);
+ window_width = width;
+ window_height = height;
+ }
+ SetDIBitsToDevice(hdc,0,0,width,height,0,0,0,height,data,&bmi,DIB_RGB_COLORS);
+ resized = false;
+ return *this;
+ }
+
+ CImgDisplay& move(const int posx,const int posy) {
+ RECT rect; rect.left=rect.top=0; rect.right=width-1; rect.bottom=height-1;
+ AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false);
+ const int border1 = (rect.right-rect.left+1-width)/2, border2 = rect.bottom-rect.top+1-height-border1;
+ window_x = posx;
+ window_y = posy;
+ SetWindowPos(window,0,window_x-border1,window_y-border2,0,0,SWP_NOSIZE | SWP_NOZORDER);
+ moved = false;
+ return show();
+ }
+
+ ~CImgDisplay() {
+ DestroyWindow(window);
+ if (events) TerminateThread(thread,0);
+ delete[] data;
+ if (curr_mode.dmSize) ChangeDisplaySettings(&curr_mode,0);
+ }
+
+ void new_lowlevel(const char *title=NULL) {
+ unsigned long ThreadID;
+ DEVMODE mode;
+ unsigned int imode=0,ibest=0,bestbpp=0;
+ void *arg = (void*)(new void*[2]);
+ ((void**)arg)[0]=(void*)this;
+ ((void**)arg)[1]=(void*)title;
+ if (fullscreen) {
+ for (mode.dmSize = sizeof(DEVMODE), mode.dmDriverExtra = 0; EnumDisplaySettings(NULL,imode,&mode); imode++)
+ if (mode.dmPelsWidth==width && mode.dmPelsHeight==height && mode.dmBitsPerPel>bestbpp) {
+ bestbpp = mode.dmBitsPerPel;
+ ibest=imode;
+ }
+ //cimg::warn(!bestbpp,"CImgDisplay::new_lowlevel() : Could not initialize fullscreen mode %ux%u\n",width,height);
+ if (bestbpp) {
+ curr_mode.dmSize = sizeof(DEVMODE); curr_mode.dmDriverExtra = 0;
+ EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&curr_mode);
+ EnumDisplaySettings(NULL,ibest,&mode);
+ ChangeDisplaySettings(&mode,0);
+ }
+ else curr_mode.dmSize = 0;
+ }
+ else curr_mode.dmSize = 0;
+ if (events) {
+ mutex = CreateMutex(NULL,FALSE,NULL);
+ created = CreateEvent(NULL,FALSE,FALSE,NULL);
+ wait_disp = CreateEvent(NULL,FALSE,FALSE,NULL);
+ thread = CreateThread(NULL,0,thread_lowlevel,arg,0,&ThreadID);
+ WaitForSingleObject(created,INFINITE);
+ } else thread_lowlevel(arg);
+ }
+
+ static LRESULT APIENTRY proc_lowlevel(HWND window,UINT msg,WPARAM wParam,LPARAM lParam) {
+ CImgDisplay* disp = (CImgDisplay*)GetWindowLong(window,GWL_USERDATA);
+ MSG st_msg;
+
+ switch(msg) {
+ case WM_CLOSE:
+ disp->mouse_x=disp->mouse_y=-1;
+ disp->key=disp->button=disp->window_x=disp->window_y=0;
+ disp->closed=true;
+ ReleaseMutex(disp->mutex);
+ ShowWindow(disp->window,SW_HIDE);
+ return 0;
+ case WM_SIZE: {
+ while (PeekMessage(&st_msg,window,WM_SIZE,WM_SIZE,PM_REMOVE));
+ WaitForSingleObject(disp->mutex,INFINITE);
+ const unsigned int nw = LOWORD(lParam),nh = HIWORD(lParam);
+ if (nw && nh && (nw!=disp->width || nh!=disp->height)) {
+ disp->window_width = nw;
+ disp->window_height = nh;
+ disp->mouse_x = disp->mouse_y = -1;
+ disp->resized = true;
+ }
+ ReleaseMutex(disp->mutex);
+ } break;
+ case WM_MOVE: {
+ while (PeekMessage(&st_msg,window,WM_SIZE,WM_SIZE,PM_REMOVE));
+ WaitForSingleObject(disp->mutex,INFINITE);
+ const int nx = (int)(short)(LOWORD(lParam)), ny = (int)(short)(HIWORD(lParam));
+ if (nx!=disp->window_x || ny!=disp->window_y) {
+ disp->window_x = nx;
+ disp->window_y = ny;
+ disp->moved = true;
+ }
+ ReleaseMutex(disp->mutex);
+ } break;
+ case WM_PAINT:
+ WaitForSingleObject(disp->mutex,INFINITE);
+ SetDIBitsToDevice(disp->hdc,0,0,disp->width,disp->height,0,0,0,disp->height,disp->data,&(disp->bmi),DIB_RGB_COLORS);
+ ReleaseMutex(disp->mutex);
+ break;
+ }
+ if (disp->events>=2) switch(msg) {
+ case WM_KEYDOWN:
+ while (PeekMessage(&st_msg,window,WM_KEYDOWN,WM_KEYDOWN,PM_REMOVE));
+ disp->key=(int)wParam;
+ break;
+ case WM_MOUSEMOVE: {
+ while (PeekMessage(&st_msg,window,WM_MOUSEMOVE,WM_MOUSEMOVE,PM_REMOVE));
+ disp->mouse_x = LOWORD(lParam);
+ disp->mouse_y = HIWORD(lParam);
+ if (disp->mouse_x<0 || disp->mouse_y<0 || disp->mouse_x>=disp->dimx() || disp->mouse_y>=disp->dimy())
+ disp->mouse_x=disp->mouse_y=-1;
+ }
+ break;
+ case WM_LBUTTONDOWN:
+ while (PeekMessage(&st_msg,window,WM_LBUTTONDOWN,WM_LBUTTONDOWN,PM_REMOVE));
+ disp->button |= 1;
+ break;
+ case WM_RBUTTONDOWN:
+ while (PeekMessage(&st_msg,window,WM_RBUTTONDOWN,WM_RBUTTONDOWN,PM_REMOVE));
+ disp->button |= 2;
+ break;
+ case WM_MBUTTONDOWN:
+ while (PeekMessage(&st_msg,window,WM_MBUTTONDOWN,WM_MBUTTONDOWN,PM_REMOVE));
+ disp->button |= 4;
+ break;
+ }
+ if (disp->events>=3) switch(msg) {
+ case WM_KEYUP:
+ while (PeekMessage(&st_msg,window,WM_KEYUP,WM_KEYUP,PM_REMOVE));
+ disp->key=0;
+ break;
+ case WM_LBUTTONUP:
+ while (PeekMessage(&st_msg,window,WM_LBUTTONUP,WM_LBUTTONUP,PM_REMOVE));
+ disp->button &= ~1;
+ break;
+ case WM_RBUTTONUP:
+ while (PeekMessage(&st_msg,window,WM_RBUTTONUP,WM_RBUTTONUP,PM_REMOVE));
+ disp->button &= ~2;
+ break;
+ case WM_MBUTTONUP:
+ while (PeekMessage(&st_msg,window,WM_MBUTTONUP,WM_MBUTTONUP,PM_REMOVE));
+ disp->button &= ~4;
+ break;
+ }
+ return DefWindowProc(window,msg,wParam,lParam);
+ }
+
+ static DWORD WINAPI thread_lowlevel(void* arg) {
+ CImgDisplay *disp = (CImgDisplay*)(((void**)arg)[0]);
+ const char *title = (const char*)(((void**)arg)[1]);
+ MSG msg;
+ delete[] (void**)arg;
+ disp->bmi.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
+ disp->bmi.bmiHeader.biWidth=disp->width;
+ disp->bmi.bmiHeader.biHeight=-(int)disp->height;
+ disp->bmi.bmiHeader.biPlanes=1;
+ disp->bmi.bmiHeader.biBitCount=32;
+ disp->bmi.bmiHeader.biCompression=BI_RGB;
+ disp->bmi.bmiHeader.biSizeImage=0;
+ disp->bmi.bmiHeader.biXPelsPerMeter=1;
+ disp->bmi.bmiHeader.biYPelsPerMeter=1;
+ disp->bmi.bmiHeader.biClrUsed=0;
+ disp->bmi.bmiHeader.biClrImportant=0;
+ disp->data = new unsigned int[disp->width*disp->height];
+ if (!disp->fullscreen) { // Normal window
+ RECT rect;
+ rect.left=rect.top=0; rect.right=disp->width-1; rect.bottom=disp->height-1;
+ AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false);
+ const int border1 = (rect.right-rect.left+1-disp->width)/2, border2 = rect.bottom-rect.top+1-disp->height-border1;
+
+#if defined(_MSC_VER) && _MSC_VER>1200
+ disp->window = CreateWindowA("MDICLIENT",title?title:" ",
+ WS_OVERLAPPEDWINDOW | (disp->closed?0:WS_VISIBLE), CW_USEDEFAULT,CW_USEDEFAULT,
+ disp->width + 2*border1, disp->height + border1 + border2,
+ NULL,NULL,NULL,&(disp->ccs));
+#else
+ disp->window = CreateWindow("MDICLIENT",title?title:" ",
+ WS_OVERLAPPEDWINDOW | (disp->closed?0:WS_VISIBLE), CW_USEDEFAULT,CW_USEDEFAULT,
+ disp->width + 2*border1, disp->height + border1 + border2,
+ NULL,NULL,NULL,&(disp->ccs));
+#endif
+ if (!disp->closed) {
+ GetWindowRect(disp->window,&rect);
+ disp->window_x = rect.left + border1;
+ disp->window_y = rect.top + border2;
+ } else disp->window_x = disp->window_y = 0;
+ } else { // Fullscreen window
+ const unsigned int sx = screen_dimx(), sy = screen_dimy();
+#if defined(_MSC_VER) && _MSC_VER>1200
+ disp->window = CreateWindowA("MDICLIENT",title?title:" ",
+ WS_POPUP | (disp->closed?0:WS_VISIBLE), (sx-disp->width)/2, (sy-disp->height)/2,
+ disp->width,disp->height,NULL,NULL,NULL,&(disp->ccs));
+#else
+ disp->window = CreateWindow("MDICLIENT",title?title:" ",
+ WS_POPUP | (disp->closed?0:WS_VISIBLE), (sx-disp->width)/2, (sy-disp->height)/2,
+ disp->width,disp->height,NULL,NULL,NULL,&(disp->ccs));
+#endif
+ disp->window_x = disp->window_y = 0;
+ }
+ SetForegroundWindow(disp->window);
+ disp->hdc = GetDC(disp->window);
+ disp->window_width = disp->width;
+ disp->window_height = disp->height;
+ disp->mouse_x = disp->mouse_y = -1;
+ disp->button = disp->key = 0;
+ disp->resized = disp->moved = false;
+ if (disp->events) {
+ SetWindowLong(disp->window,GWL_USERDATA,(LONG)disp);
+ SetWindowLong(disp->window,GWL_WNDPROC,(LONG)proc_lowlevel);
+ SetEvent(disp->created);
+ while( GetMessage( &msg, NULL, 0, 0 ) ) { DispatchMessage( &msg ); SetEvent(disp->wait_disp); }
+ }
+ return 0;
+ }
+
+ template<typename T> BITMAPINFO* render(const CImg<T>& img) {
+ if (img.is_empty())
+ throw CImgArgumentException("CImgDisplay::render() : Specified input image (%u,%u,%u,%u,%p) is empty.",
+ img.width,img.height,img.depth,img.dim,img.data);
+ if (img.depth!=1) return render(img.get_projections2d(img.width/2,img.height/2,img.depth/2));
+
+ const T
+ *data1 = img.ptr(),
+ *data2 = (img.dim>=2)?img.ptr(0,0,0,1):data1,
+ *data3 = (img.dim>=3)?img.ptr(0,0,0,2):data1;
+
+ WaitForSingleObject(mutex,INFINITE);
+ unsigned int
+ *const ndata = (img.width==width && img.height==height)?data:new unsigned int[img.width*img.height],
+ *ptrd = ndata;
+
+ if (!normalization) for (unsigned int xy = img.width*img.height; xy>0; xy--)
+ *(ptrd++) = ((unsigned char)*(data1++)<<16) | ((unsigned char)*(data2++)<<8) | (unsigned char)*(data3++);
+ else {
+ if ((min>max) || normalization==1) { CImgStats st(img,false); min=st.min; max=st.max; }
+ const T nmin = (T)min, delta = (T)max-nmin, mm = delta?delta:(T)1;
+ for (unsigned int xy = img.width*img.height; xy>0; xy--) {
+ const unsigned char
+ R = (unsigned char)(255*(*(data1++)-nmin)/mm),
+ G = (unsigned char)(255*(*(data2++)-nmin)/mm),
+ B = (unsigned char)(255*(*(data3++)-nmin)/mm);
+ *(ptrd++) = (R<<16) | (G<<8) | (B);
+ }
+ }
+ if (ndata!=data) { _render_resize(ndata,img.width,img.height,data,width,height); delete[] ndata; }
+ ReleaseMutex(mutex);
+ return &bmi;
+ }
+
+ template<typename T> CImgDisplay& display(const CImg<T>& img) {
+ render(img);
+ if (!closed) {
+ WaitForSingleObject(mutex,INFINITE);
+ SetDIBitsToDevice(hdc,0,0,width,height,0,0,0,height,data,&bmi,DIB_RGB_COLORS);
+ ReleaseMutex(mutex);
+ }
+ return *this;
+ }
+
+ CImgDisplay& wait() {
+ if (!closed && events) WaitForSingleObject(wait_disp,INFINITE);
+ return *this;
+ }
+
+ CImgDisplay& show() {
+ if (closed) {
+ ShowWindow(window,SW_SHOW);
+ SetDIBitsToDevice(hdc,0,0,width,height,0,0,0,height,data,&bmi,DIB_RGB_COLORS);
+ RECT rect;
+ rect.left=rect.top=0; rect.right=width-1; rect.bottom=height-1;
+ AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false);
+ const int border1 = (rect.right-rect.left+1-width)/2, border2 = rect.bottom-rect.top+1-height-border1;
+ GetWindowRect(window,&rect);
+ window_x = rect.left + border1;
+ window_y = rect.top + border2;
+ closed = false;
+ }
+ return *this;
+ }
+
+ CImgDisplay& close() {
+ if (!closed) {
+ ShowWindow(window,SW_HIDE);
+ closed = true;
+ window_x = window_y = 0;
+ }
+ return *this;
+ }
+
+ static int screen_dimx() {
+ DEVMODE mode;
+ mode.dmSize = sizeof(DEVMODE); mode.dmDriverExtra = 0;
+ EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&mode);
+ return mode.dmPelsWidth;
+ }
+
+ static int screen_dimy() {
+ DEVMODE mode;
+ mode.dmSize = sizeof(DEVMODE); mode.dmDriverExtra = 0;
+ EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&mode);
+ return mode.dmPelsHeight;
+ }
+
+ CImgDisplay& title(const char *title,...) {
+ char tmp[1024]={0};
+ va_list ap;
+ va_start(ap, title);
+ std::vsprintf(tmp,title,ap);
+ va_end(ap);
+#if defined(_MSC_VER) && _MSC_VER>1200
+ SetWindowTextA(window, tmp);
+#else
+ SetWindowText(window, tmp);
+#endif
+ return *this;
+ }
+
+#endif
+
+#ifdef cimgdisplay_plugin
+#include cimgdisplay_plugin
+#endif
+
+ };
+
+ /*
+ #--------------------------------------
+ #
+ #
+ #
+ # Definition of the CImg<T> structure
+ #
+ #
+ #
+ #--------------------------------------
+ */
+
+ //! Class representing an image (up to 4 dimensions wide), each pixel being of type \c T.
+ /**
+ This is the main structure of the %CImg Library. It allows the declaration and construction
+ of an image, the access to its pixel values, and the application of various operations on it.
+
+ \par Image representation
+
+ A %CImg image is defined as an instance of the container \ref CImg<T>, which contains a regular grid of pixels,
+ each pixel value being of type \c T. The image grid can have up to 4 dimensions : width, height, depth
+ and number of channels.
+ Usually, the three first dimensions are used to describe spatial coordinates <tt>(x,y,z)</tt>, while the number of channels
+ is rather used as a vector-valued dimension (it may describe the R,G,B color channels for instance).
+ If you need a fifth dimension, you can use image lists \ref CImgl<T> rather than simple images \ref CImg<T>.
+
+ Thus, the \ref CImg<T> class is able to represent volumetric images of vector-valued pixels,
+ as well as images with less dimensions (1D scalar signal, 2D color images, ...).
+ Most member functions of the class CImg<T> are designed to handle this maximum case of (3+1) dimensions.
+
+ Concerning the pixel value type \c T :
+ fully supported template types are the basic C++ types : <tt>unsigned char, char, short, unsigned int, int,
+ unsigned long, long, float, double, ... </tt>.
+ Typically, fast image display can be done using <tt>CImg<unsigned char></tt> images,
+ while complex image processing algorithms may be rather coded using <tt>CImg<float></tt> or <tt>CImg<double></tt>
+ images that have floating-point pixel values. The default value for the template T is \c float.
+ Using your own template types may be possible. However, you will certainly have to define the complete set
+ of arithmetic and logical operators for your class.
+
+ \par Image structure
+
+ The \ref CImg<\c T> structure tqcontains \a five fields :
+ - \ref width defines the number of \a columns of the image (size along the X-axis).
+ - \ref height defines the number of \a rows of the image (size along the Y-axis).
+ - \ref depth defines the number of \a slices of the image (size along the Z-axis).
+ - \ref dim defines the number of \a channels of the image (size along the V-axis).
+ - \ref data defines a \a pointer to the \a pixel \a data (of type \c T).
+
+ You can access these fields publicly although it is recommended to use the dedicated functions
+ dimx(), dimy(), dimz(), dimv() and ptr() to do so.
+ Image dimensions are not limited to a specific range (as long as you got enough available memory).
+ A value of \e 1 usually means that the corresponding dimension is \a flat.
+ If one of the dimensions is \e 0, or if the data pointer is null, the image is considered as \e empty.
+ Empty images should not contain any pixel data and thus, will not be processed by CImg member functions
+ (a CImgInstanceException will be thrown instead).
+ Pixel data are stored in memory, in a non interlaced mode (See \ref cimg_storage).
+
+ \par Image declaration and construction
+
+ Declaring an image can be done by using one of the several available constructors.
+ Here is a list of the most used :
+
+ - Construct images from arbitrary dimensions :
+ - <tt>CImg<char> img;</tt> declares an empty image.
+ - <tt>CImg<unsigned char> img(128,128);</tt> declares a 128x128 greyscale image with
+ \c unsigned \c char pixel values.
+ - <tt>CImg<double> img(3,3);</tt> declares a 3x3 matrix with \c double coefficients.
+ - <tt>CImg<unsigned char> img(256,256,1,3);</tt> declares a 256x256x1x3 (color) image
+ (colors are stored as an image with three channels).
+ - <tt>CImg<double> img(128,128,128);</tt> declares a 128x128x128 volumetric and greyscale image
+ (with \c double pixel values).
+ - <tt>CImg<> img(128,128,128,3);</tt> declares a 128x128x128 volumetric color image
+ (with \c float pixels, which is the default value of the template parameter \c T).
+ - \b Note : images pixels are <b>not automatically initialized to 0</b>. You may use the function \ref fill() to
+ do it, or use the specific constructor taking 5 parameters like this :
+ <tt>CImg<> img(128,128,128,3,0);</tt> declares a 128x128x128 volumetric color image with all pixel values to 0.
+
+ - Construct images from filenames :
+ - <tt>CImg<unsigned char> img("image.jpg");</tt> reads a JPEG color image from the file "image.jpg".
+ - <tt>CImg<float> img("analyze.hdr");</tt> reads a volumetric image (ANALYZE7.5 format) from the file "analyze.hdr".
+ - \b Note : You need to install <a href="http://www.imagemagick.org">ImageMagick</a>
+ to be able to read common compressed image formats (JPG,PNG,...) (See \ref cimg_files_io).
+
+ - Construct images from C-style arrays :
+ - <tt>CImg<int> img(data_buffer,256,256);</tt> constructs a 256x256 greyscale image from a \c int* buffer
+ \c data_buffer (of size 256x256=65536).
+ - <tt>CImg<unsigned char> img(data_buffer,256,256,1,3,false);</tt> constructs a 256x256 color image
+ from a \c unsigned \c char* buffer \c data_buffer (where R,G,B channels follow each others).
+ - <tt>CImg<unsigned char> img(data_buffer,256,256,1,3,true);</tt> constructs a 256x256 color image
+ from a \c unsigned \c char* buffer \c data_buffer (where R,G,B channels are multiplexed).
+
+ The complete list of constructors can be found <a href="#constructors">here</a>.
+
+ \par Most useful functions
+
+ The \ref CImg<T> class contains a lot of functions that operates on images.
+ Some of the most useful are :
+
+ - operator()(), operator[]() : allows to access or write pixel values.
+ - display() : displays the image in a new window.
+
+ \sa CImgl, CImgStats, CImgDisplay, CImgException.
+
+ **/
+ template<typename T> struct CImg {
+
+ //! Number of columns in the instance image (size along the X-axis).
+ /**
+ - Prefer using dimx() to get the width of the instance image.
+ - Should be considered as \a read-only. Modifying directly \c width would probably result in a library crash.
+ - This value can be safely modified by resize().
+ - If width==0, the image is \a empty and contains no pixel data.
+ **/
+ unsigned int width;
+
+ //! Number of rows in the instance image (size along the Y-axis).
+ /**
+ - Prefer using dimy() to get the height of the instance image.
+ - Should be considered as \a read-only. Modifying directly \c height would probably result in a library crash.
+ - This value can be safely modified by resize().
+ - If height==0, the image is \a empty and contains no pixel data.
+ **/
+ unsigned int height;
+
+ //! Number of slices in the instance image (size along the Z-axis).
+ /**
+ - Prefer using dimz() to get the depth of the instance image.
+ - Should be considered as \a read-only. Modifying directly \c depth would probably result in a library crash.
+ - This value can be safely modified by resize().
+ - If depth==0, the image is \a empty and contains no pixel data.
+ **/
+ unsigned int depth;
+
+ //! Number of vector channels in the instance image (size along the V-axis).
+ /**
+ - Prefer using dimv() to get the number of channels of the instance image.
+ - Should be considered as \a read-only. Modifying directly \c dim would probably result in a library crash.
+ - This value can be safely modified by resize().
+ - If dim==0, the image is \a empty and contains no pixel data.
+ **/
+ unsigned int dim;
+
+ //! This variable defines if the instance image uses shared memory.
+ /**
+ \note shared images are retrieved by the functions CImg<>::get_shared_*()
+ **/
+ const bool shared;
+
+ //! Pointer to pixel values (array of elements \c T).
+ /**
+ - Prefer using ptr() to get a pointer to the pixel buffer.
+ - Should be considered as \a read-only. Modifying directly \c data would probably result in a library crash.
+ - If data==0, the image is \a empty and contains no pixel data.
+ **/
+ T *data;
+
+ //! Define the iterator type for any CImg<T>.
+ /**
+ A CImg iterator is only a pointer to an array of T (the pixel buffer).
+ **/
+ typedef T* iterator;
+
+ //! Define the const iterator type for any CImg<T>.
+ /**
+ A CImg const_iterator is only a pointer to an array of const T (the pixel buffer).
+ **/
+ typedef const T* const_iterator;
+
+ //--------------------------------------
+ //
+ //! \name Constructors-Destructor-Copy
+ //@{
+ //--------------------------------------
+
+ //! <a name="constructors"></a>Create an image of size (\c dx,\c dy,\c dz,\c dv) with pixels of type \c T.
+ /**
+ \param dx Number of columns of the created image (size along the X-axis i.e image width).
+ \param dy Number of rows of the created image (size along the Y-axis, i.e image height).
+ \param dz Number of slices of the created image (size along the Z-axis, i.e image depth).
+ \param dv Number of channels of the created image (size along the V-axis).
+
+ - Pixel values are \a not \a initialized by this constructor (this can be done afterwards by fill()).
+ - If invoked without parameters, this constructor creates an \a empty image (default constructor).
+ - The construction of an empty image does not allocate memory.
+
+ \par example:
+ \code
+ CImg<unsigned char> img1(100,100); // Define a 100x100 greyscale image of \c unsigned \c char pixels.
+ CImg<float> img2(256,256,1,3); // Define a 256x256 color image of \c float pixels.
+ CImg<short> img3(128,128,128); // Define a 128x128x128 volumetric image of \c short pixels.
+ CImg<double> img4(10); // Define a 1D array of 10 double values.
+ CImg<unsigned char> img5; // Define an empty image.
+ \endcode
+ **/
+ explicit CImg(const unsigned int dx=0,const unsigned int dy=1,const unsigned int dz=1,const unsigned int dv=1):shared(false) {
+ const unsigned int siz = dx*dy*dz*dv;
+ if (siz) { data = new T[siz]; width = dx; height = dy; depth = dz; dim = dv; }
+ else { width = height = depth = dim = 0; data = 0; }
+ }
+
+ //! In-place version of the previous constructor.
+ CImg& assign(const unsigned int dx=0,const unsigned int dy=1,const unsigned int dz=1,const unsigned int dv=1) {
+ return CImg(dx,dy,dz,dv).swap(*this);
+ }
+
+ //! Create an image of size (\c dx,\c dy,\c dz,\c dv) with pixels of type \c T, and set the value of image pixels to \c val.
+ /**
+ \param dx Number of columns of the created image (size along the X-axis, i.e image width).
+ \param dy Number of rows of the created image (size along the Y-axis, i.e image height).
+ \param dz Number of slices of the created image (size along the Z-axis, i.e image depth).
+ \param dv Number of channels of the created image (size along the V-axis).
+ \param val Initialization value set to all image pixels.
+
+ - Same as previous constructor except that pixel values are now initialized to value \c val.
+
+ \par example:
+ \code
+ CImg<unsigned char> img(100,100,1,3,0); // Define a 100x100 color image with black pixels (all color channels equal to 0).
+ \endcode
+ **/
+ explicit CImg(const unsigned int dx,const unsigned int dy,const unsigned int dz,const unsigned int dv,const T& val):shared(false) {
+ const unsigned int siz = dx*dy*dz*dv;
+ if (siz) { data = new T[siz]; width = dx; height = dy; depth = dz; dim = dv; fill(val); }
+ else { width = height = depth = dim = 0; data = 0; }
+ }
+
+ //! In-place version of the previous constructor.
+ CImg& assign(const unsigned int dx,const unsigned int dy,const unsigned int dz,const unsigned int dv,const T& val) {
+ return CImg<T>(dx,dy,dz,dv,val).swap(*this);
+ }
+
+ //! Copy an image (copy constructor).
+ /**
+ \param img Image to copy.
+
+ - The copy constructor is faster if input and output images have same template types.
+ - Otherwise, pixel values are casted as in C.
+
+ \par example:
+ \code
+ CImg<float> src(100,100,1,1,0); // Define a 100x100 greyscale image with black pixels.
+ CImg<float> dest1(src); // Define a perfect copy of src (fast).
+ CImg<int> dest2(src); // Define a copy with a cast float->int.
+ \endcode
+
+ \sa operator=().
+ **/
+ template<typename t> CImg(const CImg<t>& img):shared(false) {
+ const unsigned int siz = img.size();
+ if (img.data && siz) {
+ data = new T[siz];
+ width = img.width; height = img.height; depth = img.depth; dim = img.dim;
+ const t *ptrs = img.data + siz;
+ cimg_map(*this,ptrd,T) (*ptrd)=(T)*(--ptrs);
+ } else { width = height = depth = dim = 0; data = 0; }
+ }
+
+ //! Copy an image (copy constructor, fast version).
+ CImg(const CImg<T>& img):shared(img.shared) {
+ const unsigned int siz = img.size();
+ if (img.data && siz) {
+ width = img.width; height = img.height; depth = img.depth; dim = img.dim;
+ if (shared) data = img.data;
+ else {
+ data = new T[siz];
+ std::memcpy(data,img.data,siz*sizeof(T));
+ }
+ } else { width = height = depth = dim = 0; data = 0; }
+ }
+
+ //! In-place version of the previous constructor.
+ template<typename t> CImg& assign(const CImg<t>& img) {
+ return CImg<T>(img).swap(*this);
+ }
+
+ //! Copy an image, with or without copying the pixel buffer.
+ template<typename t> CImg(const CImg<t>& img, const bool pixel_copy):shared(false) {
+ const unsigned int siz = img.size();
+ if (img.data && siz) {
+ data = new T[siz];
+ width = img.width; height = img.height; depth = img.depth; dim = img.dim;
+ if (pixel_copy) {
+ const t *ptrs = img.data + siz;
+ cimg_map(*this,ptrd,T) (*ptrd)=(T)*(--ptrs);
+ }
+ } else { data = 0; width = height = depth = dim = 0; }
+ }
+
+ //! Copy an image, with or without copying the pixel buffer (fast version).
+ CImg(const CImg<T>& img, const bool pixel_copy):shared(img.shared) {
+ const unsigned int siz = img.size();
+ if (img.data && siz) {
+ width = img.width; height = img.height; depth = img.depth; dim = img.dim;
+ if (shared) data = img.data;
+ else {
+ data = new T[siz];
+ if (pixel_copy) std::memcpy(data,img.data,siz*sizeof(T));
+ }
+ } else { width = height = depth = dim = 0; data = 0; }
+ }
+
+ //! In-place version of the previous constructor.
+ template<typename t> CImg& assign(const CImg<t>& img, const bool pixel_copy) {
+ if (pixel_copy) return assign(img);
+ return assign(img.width,img.height,img.depth,img.dim);
+ }
+
+ //! Create an image from a filename.
+ /**
+ \param filename Filename of the image file to load as an image.
+
+ - The filename extension implicitely informs CImg about the image format.
+ - Image pixels of the loaded image will be converted as values of the image type \c T.
+
+ \par example:
+ \code
+ CImg<unsigned char> img1("foo.jpg"); // Load JPEG image "foo.jpg" and store RGB colors as three channels of unsigned char pixels.
+ CImg<float> img2("foo.png"); // Load PNG image "foo.png" ans store RGB colors as three channels of float pixels.
+ \endcode
+
+ \sa get_load(), load(), cimg_files_io.
+ **/
+ CImg(const char *const filename):width(0),height(0),depth(0),dim(0),shared(false),data(0) {
+ load(filename);
+ }
+
+ //! In-place version of the previous constructor.
+ CImg& assign(const char *const filename) {
+ return load(filename);
+ }
+
+ //! Create an image from a one-dimensional data buffer.
+ /**
+ \param data_buffer Pointer \c t* to a buffer of pixel values t.
+ \param dx Number of columns of the created image (size along the X-axis, i.e image width).
+ \param dy Number of rows of the created image (size along the Y-axis, i.e image height).
+ \param dz Number of slices of the created image (size along the Z-axis, i.e image depth).
+ \param dv Number of vector channels of the created image (size along the V-axis).
+ **/
+ template<typename t> CImg(const t *const data_buffer,
+ const unsigned int dx,const unsigned int dy=1,
+ const unsigned int dz=1,const unsigned int dv=1):shared(false) {
+ const unsigned int siz = dx*dy*dz*dv;
+ if (data_buffer && siz) {
+ data = new T[siz];
+ width = dx; height = dy; depth = dz; dim = dv;
+ const t *ptrs = data_buffer+siz;
+ cimg_map(*this,ptrd,T) *ptrd = (T)(*(--ptrs));
+ } else { width = height = depth = dim = 0; data=0; }
+ }
+
+ //! In-place version of the previous constructor.
+ template<typename t> CImg& assign(const t *const data_buffer,
+ const unsigned int dx,const unsigned int dy=1,
+ const unsigned int dz=1,const unsigned int dv=1) {
+ return CImg<T>(data_buffer,dx,dy,dz,dv).swap(*this);
+ }
+
+ //! Create an image from a one-dimensional data buffer.
+ /**
+ \param data_buffer Pointer \c T* to a buffer of pixel values t.
+ \param dx Number of columns of the created image (size along the X-axis, i.e image width).
+ \param dy Number of rows of the created image (size along the Y-axis, i.e image height).
+ \param dz Number of slices of the created image (size along the Z-axis, i.e image depth).
+ \param dv Number of vector channels of the created image (size along the V-axis).
+ \param shared_memory Tell if memory must be shared.
+ **/
+ CImg(const T *const data_buffer,
+ const unsigned int dx, const unsigned int dy,
+ const unsigned int dz,const unsigned int dv,
+ const bool shared_memory):shared(shared_memory) {
+ const unsigned int siz = dx*dy*dz*dv;
+ if (data_buffer && siz) {
+ width=dx; height=dy; depth=dz; dim=dv;
+ if (shared) data=const_cast<T*>(data_buffer);
+ else {
+ data = new T[siz];
+ std::memcpy(data,data_buffer,siz*sizeof(T));
+ }
+ } else { width = height = depth = dim = 0; data=0; }
+ }
+
+ //! In-place version of the previous constructor.
+ CImg& assign(const T *const data_buffer,
+ const unsigned int dx,const unsigned int dy,
+ const unsigned int dz,const unsigned int dv, const bool shared_memory=false) {
+ return CImg<T>(data_buffer,dx,dy,dz,dv,shared_memory).swap(*this);
+ }
+
+ //! Destructor.
+ /**
+ - The destructor frees the memory eventually allocated for the image pixels.
+ **/
+ ~CImg() {
+ if (data && !shared) delete[] data;
+ }
+
+ //! Replace the instance image by an empty image.
+ /**
+ This is the in-place version of the destructor.
+ \sa ~CImg()
+ **/
+ CImg& empty() {
+ return CImg<T>().swap(*this);
+ }
+
+ //! Same as empty().
+ /**
+ This function has been added since its name is 'STL-compliant'.
+ \sa empty()
+ **/
+ CImg& clear() {
+ return empty();
+ }
+
+ //! Return an empty image
+ static CImg get_empty() {
+ return CImg<T>();
+ }
+
+ // Swap fields of an image (use it carefully!)
+ // If an image is shared, its content is replaced by the non-shared image (which is unchanged).
+ CImg& swap(CImg& img) {
+ if (img.shared==shared) {
+ cimg::swap(width,img.width);
+ cimg::swap(height,img.height);
+ cimg::swap(depth,img.depth);
+ cimg::swap(dim,img.dim);
+ cimg::swap(data,img.data);
+ } else {
+ if (img.shared) img=*this;
+ if (shared) *this=img;
+ }
+ return img;
+ }
+
+ //@}
+ //-------------------------------------
+ //
+ //! \name Access to image informations
+ //@{
+ //-------------------------------------
+
+ //! Return the type of the pixel values.
+ /**
+ \return a string describing the type of the image pixels (template parameter \p T).
+ - The string returned may contains spaces (<tt>"unsigned char"</tt>).
+ - If the template parameter T does not correspond to a registered type, the string <tt>"unknown"</tt> is returned.
+ **/
+ static const char* pixel_type() {
+ T val;
+ return cimg::get_type(val);
+ }
+
+ //! Return the total number of pixel values in an image.
+ /**
+ - Equivalent to : dimx() * dimy() * dimz() * dimv().
+
+ \par example:
+ \code
+ CImg<> img(100,100,1,3);
+ if (img.size()==100*100*3) std::fprintf(stderr,"This statement is true");
+ \endcode
+ \sa dimx(), dimy(), dimz(), dimv()
+ **/
+ unsigned long size() const {
+ return width*height*depth*dim;
+ }
+
+ //! Return the number of columns of the instance image (size along the X-axis, i.e image width).
+ /**
+ \sa width, dimy(), dimz(), dimv(), size().
+ **/
+ int dimx() const {
+ return (int)width;
+ }
+
+ //! Return the number of rows of the instance image (size along the Y-axis, i.e image height).
+ /**
+ \sa height, dimx(), dimz(), dimv(), size().
+ **/
+ int dimy() const {
+ return (int)height;
+ }
+
+ //! Return the number of slices of the instance image (size along the Z-axis).
+ /**
+ \sa depth, dimx(), dimy(), dimv(), size().
+ **/
+ int dimz() const {
+ return (int)depth;
+ }
+
+ //! Return the number of vector channels of the instance image (size along the V-axis).
+ /**
+ \sa dim, dimx(), dimy(), dimz(), size().
+ **/
+ int dimv() const {
+ return (int)dim;
+ }
+
+ //! Return \c true if images \c (*this) and \c img have same width.
+ template<typename t> bool has_sameX(const CImg<t>& img) const {
+ return (width==img.width);
+ }
+
+ //! Return \c true if images \c (*this) and \c img have same height.
+ template<typename t> bool has_sameY(const CImg<t>& img) const {
+ return (height==img.height);
+ }
+
+ //! Return \c true if images \c (*this) and \c img have same depth.
+ template<typename t> bool has_sameZ(const CImg<t>& img) const {
+ return (depth==img.depth);
+ }
+
+ //! Return \c true if images \c (*this) and \c img have same dim.
+ template<typename t> bool has_sameV(const CImg<t>& img) const {
+ return (dim==img.dim);
+ }
+
+ //! Return \c true if images have same width and same height.
+ template<typename t> bool has_sameXY(const CImg<t>& img) const {
+ return (has_sameX(img) && has_sameY(img));
+ }
+
+ //! Return \c true if images have same width, same height and same depth.
+ template<typename t> bool has_sameXYZ(const CImg<t>& img) const {
+ return (has_sameXY(img) && has_sameZ(img));
+ }
+
+ //! Return \c true if images \c (*this) and \c img have same width, same height, same depth and same number of channels.
+ template<typename t> bool has_sameXYZV(const CImg<t>& img) const {
+ return (has_sameXYZ(img) && has_sameV(img));
+ }
+
+ //! Return \c true if image is empty.
+ bool is_empty() const {
+ return !(data && width && height && depth && dim);
+ }
+
+ //! Return the offset of the pixel coordinates (\p x,\p y,\p z,\p v) with respect to the data pointer \c data.
+ /**
+ \param x X-coordinate of the pixel.
+ \param y Y-coordinate of the pixel.
+ \param z Z-coordinate of the pixel.
+ \param v V-coordinate of the pixel.
+
+ - No checking is done on the validity of the given coordinates.
+
+ \par example:
+ \code
+ CImg<float> img(100,100,1,3,0); // Define a 100x100 color image with float-valued black pixels.
+ long off = img.offset(10,10,0,2); // Get the offset of the blue value of the pixel located at (10,10).
+ float val = img[off]; // Get the blue value of the pixel.
+ \endcode
+ \sa ptr(), operator()(), operator[](), cimg_storage.
+ **/
+ long offset(const int x=0, const int y=0, const int z=0, const int v=0) const {
+ return x+width*(y+height*(z+depth*v));
+ }
+
+ //! Return a pointer to the pixel value located at (\p x,\p y,\p z,\p v).
+ /**
+ \param x X-coordinate of the pixel.
+ \param y Y-coordinate of the pixel.
+ \param z Z-coordinate of the pixel.
+ \param v V-coordinate of the pixel.
+
+ - When called without parameters, ptr() returns a pointer to the begining of the pixel buffer.
+ - If the macro \c cimg_debug == 2, boundary checking is performed and warning messages may appear if
+ given coordinates are outside the image range (but function performances decrease).
+
+ \par example:
+ \code
+ CImg<float> img(100,100,1,1,0); // Define a 100x100 greyscale image with float-valued pixels.
+ float *ptr = ptr(10,10); // Get a pointer to the pixel located at (10,10).
+ float val = *ptr; // Get the pixel value.
+ \endcode
+ \sa data, offset(), operator()(), operator[](), cimg_storage, cimg_environment.
+ **/
+ T* ptr(const unsigned int x=0, const unsigned int y=0, const unsigned int z=0, const unsigned int v=0) {
+ const long off = offset(x,y,z,v);
+#if cimg_debug>1
+ if (off<0 || off>=(long)size()) {
+ cimg::warn(true,"CImg<%s>::ptr() : Asked for a pointer at coordinates (%u,%u,%u,%u) (offset=%u), "
+ "outside image range (%u,%u,%u,%u) (size=%u)",
+ pixel_type(),x,y,z,v,off,width,height,depth,dim,size());
+ return data;
+ }
+#endif
+ return data+off;
+ }
+
+ const T* ptr(const unsigned int x=0, const unsigned int y=0, const unsigned int z=0, const unsigned int v=0) const {
+ const long off = offset(x,y,z,v);
+#if cimg_debug>1
+ if (off<0 || off>=(long)size()) {
+ cimg::warn(true,"CImg<%s>::ptr() : Trying to get a pointer at (%u,%u,%u,%u) (offset=%d) which is"
+ "outside the data of the image (%u,%u,%u,%u) (size=%u)",
+ pixel_type(),x,y,z,v,off,width,height,depth,dim,size());
+ return data;
+ }
+#endif
+ return data+off;
+ }
+
+ //! Return an iterator to the first image pixel
+ iterator begin() { return data; }
+ const_iterator begin() const { return data; }
+
+ //! Return an iterator to the last image pixel
+ iterator end() { return data + size(); }
+ const_iterator end() const { return data + size(); }
+
+ //! Fast access to pixel value for reading or writing.
+ /**
+ \param x X-coordinate of the pixel.
+ \param y Y-coordinate of the pixel.
+ \param z Z-coordinate of the pixel.
+ \param v V-coordinate of the pixel.
+
+ - If one image dimension is equal to 1, it can be omitted in the coordinate list (see example below).
+ - If the macro \c cimg_debug == 2, boundary checking is performed and warning messages may appear
+ (but function performances decrease).
+
+ \par example:
+ \code
+ CImg<float> img(100,100,1,3,0); // Define a 100x100 color image with float-valued black pixels.
+ const float valR = img(10,10,0,0); // Read the red component at coordinates (10,10).
+ const float valG = img(10,10,0,1); // Read the green component at coordinates (10,10)
+ const float valB = img(10,10,2); // Read the blue component at coordinates (10,10) (Z-coordinate omitted here).
+ const float avg = (valR + valG + valB)/3; // Compute average pixel value.
+ img(10,10,0) = img(10,10,1) = img(10,10,2) = avg; // Replace the pixel (10,10) by the average grey value.
+ \endcode
+
+ \sa operator[](), ptr(), offset(), cimg_storage, cimg_environment.
+ **/
+ T& operator()(const unsigned int x,const unsigned int y=0,const unsigned int z=0,const unsigned int v=0) {
+ const long off = offset(x,y,z,v);
+#if cimg_debug>1
+ if (!data || off>=(long)size()) {
+ cimg::warn(true,"CImg<%s>::operator() : Pixel access requested at (%u,%u,%u,%u) (offset=%d) "
+ "outside the image range (%u,%u,%u,%u) (size=%u)",
+ pixel_type(),x,y,z,v,off,width,height,depth,dim,size());
+ return *data;
+ }
+#endif
+ return data[off];
+ }
+
+ const T& operator()(const unsigned int x,const unsigned int y=0,const unsigned int z=0,const unsigned int v=0) const {
+ const long off = offset(x,y,z,v);
+#if cimg_debug>1
+ if (!data || off>=(long)size()) {
+ cimg::warn(true,"CImg<%s>::operator() : Pixel access requested at (%u,%u,%u,%u) (offset=%d) "
+ "outside the image range (%u,%u,%u,%u) (size=%u)",
+ pixel_type(),x,y,z,v,off,width,height,depth,dim,size());
+ return *data;
+ }
+#endif
+ return data[off];
+ }
+
+ //! Return pixel value at a given position. Equivalent to operator().
+ T& at(const unsigned int x,const unsigned int y=0,const unsigned int z=0,const unsigned int v=0) {
+ const long off = offset(x,y,z,v);
+ if (!data || off>=(long)size())
+ throw CImgArgumentException("CImg<%s>::at() : Pixel access requested at (%u,%u,%u,%u) (offset=%d) "
+ "outside the image range (%u,%u,%u,%u) (size=%u)",
+ pixel_type(),x,y,z,v,off,width,height,depth,dim,size());
+ return data[off];
+ }
+
+ const T& at(const unsigned int x,const unsigned int y=0,const unsigned int z=0,const unsigned int v=0) const {
+ const long off = offset(x,y,z,v);
+ if (!data || off>=(long)size())
+ throw CImgArgumentException("CImg<%s>::at() : Pixel access requested at (%u,%u,%u,%u) (offset=%d) "
+ "outside the image range (%u,%u,%u,%u) (size=%u)",
+ pixel_type(),x,y,z,v,off,width,height,depth,dim,size());
+ return data[off];
+ }
+
+ //! Fast access to pixel value for reading or writing, using an offset to the image pixel.
+ /**
+ \param off Offset of the pixel according to the begining of the pixel buffer, given by ptr().
+
+ - If the macro \c cimg_debug==2, boundary checking is performed and warning messages may appear
+ (but function performances decrease).
+ - As pixel values are aligned in memory, this operator can sometime useful to access values easier than
+ with operator()() (see example below).
+
+ \par example:
+ \code
+ CImg<float> vec(1,10); // Define a vector of float values (10 lines, 1 row).
+ const float val1 = vec(0,4); // Get the fifth element using operator()().
+ const float val2 = vec[4]; // Get the fifth element using operator[]. Here, val2==val1.
+ \endcode
+
+ \sa operator()(), ptr(), offset(), cimg_storage, cimg_environment.
+ **/
+ T& operator[](const unsigned long off) {
+ return operator()(off);
+ }
+
+ const T& operator[](const unsigned long off) const {
+ return operator()(off);
+ }
+
+ //! Return a reference to the last image value
+ T& back() {
+ return operator()(size()-1);
+ }
+
+ const T& back() const {
+ return operator()(size()-1);
+ }
+
+ //! Return a reference to the first image value
+ T& front() {
+ return *data;
+ }
+
+ const T& front() const {
+ return *data;
+ }
+
+ //! Read a pixel value with Dirichlet or Neumann boundary conditions.
+ /**
+ \param x X-coordinate of the pixel.
+ \param y Y-coordinate of the pixel.
+ \param z Z-coordinate of the pixel.
+ \param v V-coordinate of the pixel.
+ \param out_val Desired value if pixel coordinates are outside the image range (optional parameter).
+
+ - This function allows to read pixel values with boundary checking on all coordinates.
+ - If given coordinates are outside the image range and the parameter out_val is specified, the value \c out_val is returned.
+ - If given coordinates are outside the image range and the parameter out_val is not specified, the closest pixel value
+ is returned.
+
+ \par example:
+ \code
+ CImg<float> img(100,100,1,1,128); // Define a 100x100 images with all pixel values equal to 128.
+ const float val1 = img.pix4d(10,10,0,0,0); // Equivalent to val1=img(10,10) (but slower).
+ const float val2 = img.pix4d(-4,5,0,0,0); // Return 0, since coordinates are outside the image range.
+ const float val3 = img.pix4d(10,10,5,0,64); // Return 64, since coordinates are outside the image range.
+ \endcode
+
+ \sa operator()(), linear_pix4d(), cubic_pix2d().
+ **/
+ T pix4d(const int x, const int y, const int z, const int v, const T& out_val) const {
+ return (x<0 || y<0 || z<0 || v<0 || x>=dimx() || y>=dimy() || z>=dimz() || v>=dimv())?out_val:(*this)(x,y,z,v);
+ }
+
+ T pix4d(const int x, const int y, const int z, const int v) const {
+ return (*this)(x<0?0:(x>=dimx()?dimx()-1:x), y<0?0:(y>=dimy()?dimy()-1:y),
+ z<0?0:(z>=dimz()?dimz()-1:z), v<0?0:(v>=dimv()?dimv()-1:v));
+ }
+
+ //! Read a pixel value with Dirichlet or Neumann boundary conditions for the three first coordinates (\c x,\c y,\c z).
+ T pix3d(const int x, const int y, const int z, const int v, const T& out_val) const {
+ return (x<0 || y<0 || z<0 || x>=dimx() || y>=dimy() || z>=dimz())?out_val:(*this)(x,y,z,v);
+ }
+
+ const T& pix3d(const int x, const int y, const int z, const int v=0) const {
+ return (*this)(x<0?0:(x>=dimx()?dimx()-1:x), y<0?0:(y>=dimy()?dimy()-1:y),
+ z<0?0:(z>=dimz()?dimz()-1:z),v);
+ }
+
+ //! Read a pixel value with Dirichlet or Neumann boundary conditions for the two first coordinates (\c x,\c y).
+ T pix2d(const int x, const int y, const int z, const int v, const T& out_val) const {
+ return (x<0 || y<0 || x>=dimx() || y>=dimy())?out_val:(*this)(x,y,z,v);
+ }
+
+ const T& pix2d(const int x,const int y,const int z=0,const int v=0) const {
+ return (*this)(x<0?0:(x>=dimx()?dimx()-1:x), y<0?0:(y>=dimy()?dimy()-1:y),z,v);
+ }
+
+ //! Read a pixel value with Dirichlet or Neumann boundary conditions for the first coordinate \c x.
+ T pix1d(const int x, const int y, const int z, const int v, const T& out_val) const {
+ return (x<0 || x>=dimx())?out_val:(*this)(x,y,z,v);
+ }
+
+ const T& pix1d(const int x, const int y=0, const int z=0, const int v=0) const {
+ return (*this)(x<0?0:(x>=dimx()?dimx()-1:x),y,z,v);
+ }
+
+ //! Read a pixel value using linear interpolation.
+ /**
+ \param ffx X-coordinate of the pixel (float-valued).
+ \param ffy Y-coordinate of the pixel (float-valued).
+ \param ffz Z-coordinate of the pixel (float-valued).
+ \param ffv V-coordinate of the pixel (float-valued).
+ \param out_val Out-of-border pixel value
+
+ - This function allows to read pixel values with boundary checking on all coordinates.
+ - If given coordinates are outside the image range, the value of the nearest pixel inside the image is returned
+ (Neumann boundary conditions).
+ - If given coordinates are float-valued, a linear interpolation is performed in order to compute the returned value.
+
+ \par example:
+ \code
+ CImg<float> img(2,2); // Define a greyscale 2x2 image.
+ img(0,0) = 0; // Fill image with specified pixel values.
+ img(1,0) = 1;
+ img(0,1) = 2;
+ img(1,1) = 3;
+ const double val = img.linear_pix4d(0.5,0.5); // Return val=1.5, which is the average intensity of the four pixels values.
+ \endcode
+
+ \sa operator()(), linear_pix3d(), linear_pix2d(), linear_pix1d(), cubic_pix2d().
+ **/
+ typename cimg::largest<T,float>::type linear_pix4d(const float fx,const float fy,const float fz,const float fv,
+ const T& out_val) const {
+ const int x = (int)fx-(fx>=0?0:1), y = (int)fy-(fy>=0?0:1), z = (int)fz-(fz>=0?0:1), v = (int)fv-(fv>=0?0:1),
+ nx = x+1, ny = y+1, nz = z+1, nv = v+1;
+ const float dx = fx-x, dy = fy-y, dz = fz-z, dv = fv-v;
+ const T
+ Icccc = pix4d(x,y,z,v,out_val), Inccc = pix4d(nx,y,z,v,out_val),
+ Icncc = pix4d(x,ny,z,v,out_val), Inncc = pix4d(nx,ny,z,v,out_val),
+ Iccnc = pix4d(x,y,nz,v,out_val), Incnc = pix4d(nx,y,nz,v,out_val),
+ Icnnc = pix4d(x,ny,nz,v,out_val), Innnc = pix4d(nx,ny,nz,v,out_val),
+ Icccn = pix4d(x,y,z,nv,out_val), Inccn = pix4d(nx,y,z,nv,out_val),
+ Icncn = pix4d(x,ny,z,nv,out_val), Inncn = pix4d(nx,ny,z,nv,out_val),
+ Iccnn = pix4d(x,y,nz,nv,out_val), Incnn = pix4d(nx,y,nz,nv,out_val),
+ Icnnn = pix4d(x,ny,nz,nv,out_val), Innnn = pix4d(nx,ny,nz,nv,out_val);
+ return Icccc +
+ dx*(Inccc-Icccc +
+ dy*(Icccc+Inncc-Icncc-Inccc +
+ dz*(Iccnc+Innnc+Icncc+Inccc-Icnnc-Incnc-Icccc-Inncc +
+ dv*(Iccnn+Innnn+Icncn+Inccn+Icnnc+Incnc+Icccc+Inncc-Icnnn-Incnn-Icccn-Inncn-Iccnc-Innnc-Icncc-Inccc)) +
+ dv*(Icccn+Inncn+Icncc+Inccc-Icncn-Inccn-Icccc-Inncc)) +
+ dz*(Icccc+Incnc-Iccnc-Inccc +
+ dv*(Icccn+Incnn+Iccnc+Inccc-Iccnn-Inccn-Icccc-Incnc)) +
+ dv*(Icccc+Inccn-Inccc-Icccn)) +
+ dy*(Icncc-Icccc +
+ dz*(Icccc+Icnnc-Iccnc-Icncc +
+ dv*(Icccn+Icnnn+Iccnc+Icncc-Iccnn-Icncn-Icccc-Icnnc)) +
+ dv*(Icccc+Icncn-Icncc-Icccn)) +
+ dz*(Iccnc-Icccc +
+ dv*(Icccc+Iccnn-Iccnc-Icccn)) +
+ dv*(Icccn-Icccc);
+ }
+
+ typename cimg::largest<T,float>::type linear_pix4d(const float ffx,const float ffy=0,const float ffz=0,const float ffv=0) const {
+ const float
+ fx = ffx<0?0:(ffx>width-1?width-1:ffx), fy = ffy<0?0:(ffy>height-1?height-1:ffy),
+ fz = ffz<0?0:(ffz>depth-1?depth-1:ffz), fv = ffv<0?0:(ffv>dim-1?dim-1:ffv);
+ const unsigned int x = (unsigned int)fx, y = (unsigned int)fy, z = (unsigned int)fz, v = (unsigned int)fv;
+ const float dx = fx-x, dy = fy-y, dz = fz-z, dv = fv-v;
+ const unsigned int nx = dx>0?x+1:x, ny = dy>0?y+1:y, nz = dz>0?z+1:z, nv = dv>0?v+1:v;
+ const T
+ &Icccc = (*this)(x,y,z,v), &Inccc = (*this)(nx,y,z,v), &Icncc = (*this)(x,ny,z,v), &Inncc = (*this)(nx,ny,z,v),
+ &Iccnc = (*this)(x,y,nz,v), &Incnc = (*this)(nx,y,nz,v), &Icnnc = (*this)(x,ny,nz,v), &Innnc = (*this)(nx,ny,nz,v),
+ &Icccn = (*this)(x,y,z,nv), &Inccn = (*this)(nx,y,z,nv), &Icncn = (*this)(x,ny,z,nv), &Inncn = (*this)(nx,ny,z,nv),
+ &Iccnn = (*this)(x,y,nz,nv), &Incnn = (*this)(nx,y,nz,nv), &Icnnn = (*this)(x,ny,nz,nv), &Innnn = (*this)(nx,ny,nz,nv);
+ return Icccc +
+ dx*(Inccc-Icccc +
+ dy*(Icccc+Inncc-Icncc-Inccc +
+ dz*(Iccnc+Innnc+Icncc+Inccc-Icnnc-Incnc-Icccc-Inncc +
+ dv*(Iccnn+Innnn+Icncn+Inccn+Icnnc+Incnc+Icccc+Inncc-Icnnn-Incnn-Icccn-Inncn-Iccnc-Innnc-Icncc-Inccc)) +
+ dv*(Icccn+Inncn+Icncc+Inccc-Icncn-Inccn-Icccc-Inncc)) +
+ dz*(Icccc+Incnc-Iccnc-Inccc +
+ dv*(Icccn+Incnn+Iccnc+Inccc-Iccnn-Inccn-Icccc-Incnc)) +
+ dv*(Icccc+Inccn-Inccc-Icccn)) +
+ dy*(Icncc-Icccc +
+ dz*(Icccc+Icnnc-Iccnc-Icncc +
+ dv*(Icccn+Icnnn+Iccnc+Icncc-Iccnn-Icncn-Icccc-Icnnc)) +
+ dv*(Icccc+Icncn-Icncc-Icccn)) +
+ dz*(Iccnc-Icccc +
+ dv*(Icccc+Iccnn-Iccnc-Icccn)) +
+ dv*(Icccn-Icccc);
+ }
+
+ //! Read a pixel value using linear interpolation for the three first coordinates (\c cx,\c cy,\c cz).
+ /**
+ - Same as linear_pix4d(), except that linear interpolation and boundary checking is performed only on the three first coordinates.
+
+ \sa operator()(), linear_pix4d(), linear_pix2d(), linear_pix1d(), linear_pix3d(), cubic_pix2d().
+ **/
+ typename cimg::largest<T,float>::type linear_pix3d(const float fx,const float fy,const float fz,const int v,
+ const T& out_val) const {
+ const int x = (int)fx-(fx>=0?0:1), y = (int)fy-(fy>=0?0:1), z = (int)fz-(fz>=0?0:1), nx = x+1, ny = y+1, nz = z+1;
+ const float dx = fx-x, dy = fy-y, dz = fz-z;
+ const T
+ Iccc = pix3d(x,y,z,v,out_val), Incc = pix3d(nx,y,z,v,out_val), Icnc = pix3d(x,ny,z,v,out_val), Innc = pix3d(nx,ny,z,v,out_val),
+ Iccn = pix3d(x,y,nz,v,out_val), Incn = pix3d(nx,y,nz,v,out_val), Icnn = pix3d(x,ny,nz,v,out_val), Innn = pix3d(nx,ny,nz,v,out_val);
+ return Iccc +
+ dx*(Incc-Iccc +
+ dy*(Iccc+Innc-Icnc-Incc +
+ dz*(Iccn+Innn+Icnc+Incc-Icnn-Incn-Iccc-Innc)) +
+ dz*(Iccc+Incn-Iccn-Incc)) +
+ dy*(Icnc-Iccc +
+ dz*(Iccc+Icnn-Iccn-Icnc)) +
+ dz*(Iccn-Iccc);
+ }
+
+ typename cimg::largest<T,float>::type linear_pix3d(const float ffx,const float ffy=0,const float ffz=0,const int v=0) const {
+ const float fx = ffx<0?0:(ffx>width-1?width-1:ffx), fy = ffy<0?0:(ffy>height-1?height-1:ffy), fz = ffz<0?0:(ffz>depth-1?depth-1:ffz);
+ const unsigned int x = (unsigned int)fx, y = (unsigned int)fy, z = (unsigned int)fz;
+ const float dx = fx-x, dy = fy-y, dz = fz-z;
+ const unsigned int nx = dx>0?x+1:x, ny = dy>0?y+1:y, nz = dz>0?z+1:z;
+ const T
+ &Iccc = (*this)(x,y,z,v), &Incc = (*this)(nx,y,z,v), &Icnc = (*this)(x,ny,z,v), &Innc = (*this)(nx,ny,z,v),
+ &Iccn = (*this)(x,y,nz,v), &Incn = (*this)(nx,y,nz,v), &Icnn = (*this)(x,ny,nz,v), &Innn = (*this)(nx,ny,nz,v);
+ return Iccc +
+ dx*(Incc-Iccc +
+ dy*(Iccc+Innc-Icnc-Incc +
+ dz*(Iccn+Innn+Icnc+Incc-Icnn-Incn-Iccc-Innc)) +
+ dz*(Iccc+Incn-Iccn-Incc)) +
+ dy*(Icnc-Iccc +
+ dz*(Iccc+Icnn-Iccn-Icnc)) +
+ dz*(Iccn-Iccc);
+ }
+
+ //! Read a pixel value using linear interpolation for the two first coordinates (\c cx,\c cy).
+ /**
+ - Same as linear_pix4d(), except that linear interpolation and boundary checking is performed only on the two first coordinates.
+
+ \sa operator()(), linear_pix4d(), linear_pix3d(), linear_pix1d(), linear_pix2d(), cubic_pix2d().
+ **/
+ typename cimg::largest<T,float>::type linear_pix2d(const float fx, const float fy, const int z, const int v,
+ const T& out_val) const {
+ const int x = (int)fx-(fx>0?0:1), y = (int)fy-(fy>0?0:1), nx = x+1, ny = y+1;
+ const float dx = fx-x, dy = fy-y;
+ const T
+ Icc = pix2d(x,y,z,v,out_val), Inc = pix2d(nx,y,z,v,out_val),
+ Icn = pix2d(x,ny,z,v,out_val), Inn = pix2d(nx,ny,z,v,out_val);
+ return Icc + dx*(Inc-Icc + dy*(Icc+Inn-Icn-Inc)) + dy*(Icn-Icc);
+ }
+
+ typename cimg::largest<T,float>::type linear_pix2d(const float ffx, const float ffy=0, const int z=0, const int v=0) const {
+ const float fx = ffx<0?0:(ffx>width-1?width-1:ffx), fy = ffy<0?0:(ffy>height-1?height-1:ffy);
+ const unsigned int x = (unsigned int)fx, y = (unsigned int)fy;
+ const float dx = fx-x, dy = fy-y;
+ const unsigned int nx = dx>0?x+1:x, ny = dy>0?y+1:y;
+ const T &Icc = (*this)(x,y,z,v), &Inc = (*this)(nx,y,z,v), &Icn = (*this)(x,ny,z,v), &Inn = (*this)(nx,ny,z,v);
+ return Icc + dx*(Inc-Icc + dy*(Icc+Inn-Icn-Inc)) + dy*(Icn-Icc);
+ }
+
+ //! Read a pixel value using linear interpolation for the first coordinate \c cx.
+ /**
+ - Same as linear_pix4d(), except that linear interpolation and boundary checking is performed only on the first coordinate.
+
+ \sa operator()(), linear_pix4d(), linear_pix3d(), linear_pix2d(), linear_pix1d(), cubic_pix1d().
+ **/
+ typename cimg::largest<T,float>::type linear_pix1d(const float fx,const int y,const int z,const int v,
+ const T& out_val) const {
+ const int x = (int)fx-(fx>0?0:1), nx = x+1;
+ const float dx = fx-x;
+ const T Ic = pix1d(x,y,z,v,out_val), In = pix2d(nx,y,z,v,out_val);
+ return Ic + dx*(In-Ic);
+ }
+
+ typename cimg::largest<T,float>::type linear_pix1d(const float ffx,const int y=0,const int z=0,const int v=0) const {
+ const float fx = ffx<0?0:(ffx>width-1?width-1:ffx);
+ const unsigned int x = (unsigned int)fx;
+ const float dx = fx-x;
+ const unsigned int nx = dx>0?x+1:x;
+ const T &Ic = (*this)(x,y,z,v), &In = (*this)(nx,y,z,v);
+ return Ic + dx*(In-Ic);
+ }
+
+ // This function is used as a subroutine for cubic interpolation
+ static float _cubic_R(const float x) {
+ const float xp2 = x+2, xp1 = x+1, xm1 = x-1,
+ nxp2 = xp2>0?xp2:0, nxp1 = xp1>0?xp1:0, nx = x>0?x:0, nxm1 = xm1>0?xm1:0;
+ return (nxp2*nxp2*nxp2 - 4*nxp1*nxp1*nxp1 + 6*nx*nx*nx - 4*nxm1*nxm1*nxm1)/6.0f;
+ }
+
+ //! Read a pixel value using cubic interpolation for the first coordinate \c cx.
+ /**
+ - Same as cubic_pix2d(), except that cubic interpolation and boundary checking is performed only on the first coordinate.
+
+ \sa operator()(), cubic_pix2d(), linear_pix1d().
+ **/
+ typename cimg::largest<T,float>::type cubic_pix1d(const float fx,const int y,const int z,const int v,
+ const T& out_val) const {
+ const int x = (int)fx-(fx>=0?0:1), px = x-1, nx = x+1, ax = nx+1;
+ const float dx = fx-x;
+ const T a = pix2d(px,y,z,v,out_val), b = pix2d(x,y,z,v,out_val), c = pix2d(nx,y,z,v,out_val), d = pix2d(ax,y,z,v,out_val);
+ const float Rxp = _cubic_R(-1-dx), Rxc = _cubic_R(dx), Rxn = _cubic_R(1-dx), Rxa = _cubic_R(2-dx);
+ return Rxp*a + Rxc*b + Rxn*c + Rxa*d;
+ }
+
+ typename cimg::largest<T,float>::type cubic_pix1d(const float pfx,const int y=0,const int z=0,const int v=0) const {
+ const float fx = pfx<0?0:(pfx>width-1?width-1:pfx);
+ const unsigned int x = (unsigned int)fx, px = (int)x-1>=0?x-1:0, nx = x+1<width?x+1:width-1, ax = nx+1<width?nx+1:width-1;
+ const float dx = fx-x;
+ const T& a = (*this)(px,y,z,v), b = (*this)(x,y,z,v), c = (*this)(nx,y,z,v), d = (*this)(ax,y,z,v);
+ const float Rxp = _cubic_R(-1-dx), Rxc = _cubic_R(dx), Rxn = _cubic_R(1-dx), Rxa = _cubic_R(2-dx);
+ return Rxp*a + Rxc*b + Rxn*c + Rxa*d;
+ }
+
+ //! Read a pixel value using bicubic interpolation.
+ /**
+ \param pfx X-coordinate of the pixel (float-valued).
+ \param pfy Y-coordinate of the pixel (float-valued).
+ \param z Z-coordinate of the pixel.
+ \param v V-coordinate of the pixel.
+
+ - This function allows to read pixel values with boundary checking on the two first coordinates.
+ - If given coordinates are outside the image range, the value of the nearest pixel inside the image is returned
+ (Neumann boundary conditions).
+ - If given coordinates are float-valued, a cubic interpolation is performed in order to compute the returned value.
+
+ \sa operator()(), cubic_pix1d(), linear_pix2d().
+ **/
+ typename cimg::largest<T,float>::type cubic_pix2d(const float fx,const float fy,const int z,const int v,
+ const T& out_val) const {
+ const int
+ x = (int)fx-(fx>=0?0:1), y = (int)fy-(fy>=0?0:1),
+ px = x-1, nx = x+1, ax = nx+1, py = y-1, ny = y+1, ay = ny+1;
+ const float dx = fx-x, dy = fy-y;
+ const T
+ a = pix2d(px,py,z,v,out_val), b = pix2d(x,py,z,v,out_val), c = pix2d(nx,py,z,v,out_val), d = pix2d(ax,py,z,v,out_val),
+ e = pix2d(px, y,z,v,out_val), f = pix2d(x, y,z,v,out_val), g = pix2d(nx, y,z,v,out_val), h = pix2d(ax, y,z,v,out_val),
+ i = pix2d(px,ny,z,v,out_val), j = pix2d(x,ny,z,v,out_val), k = pix2d(nx,ny,z,v,out_val), l = pix2d(ax,ny,z,v,out_val),
+ m = pix2d(px,ay,z,v,out_val), n = pix2d(x,ay,z,v,out_val), o = pix2d(nx,ay,z,v,out_val), p = pix2d(ax,ay,z,v,out_val);
+ const float
+ Rxp = _cubic_R(-1-dx), Rxc = _cubic_R(dx), Rxn = _cubic_R(1-dx), Rxa = _cubic_R(2-dx),
+ Ryp = _cubic_R(dy+1), Ryc = _cubic_R(dy), Ryn = _cubic_R(dy-1), Rya = _cubic_R(dy-2);
+ return
+ Rxp*Ryp*a + Rxc*Ryp*b + Rxn*Ryp*c + Rxa*Ryp*d +
+ Rxp*Ryc*e + Rxc*Ryc*f + Rxn*Ryc*g + Rxa*Ryc*h +
+ Rxp*Ryn*i + Rxc*Ryn*j + Rxn*Ryn*k + Rxa*Ryn*l +
+ Rxp*Rya*m + Rxc*Rya*n + Rxn*Rya*o + Rxa*Rya*p;
+ }
+
+ typename cimg::largest<T,float>::type cubic_pix2d(const float pfx,const float pfy=0,const int z=0,const int v=0) const {
+ const float fx = pfx<0?0:(pfx>width-1?width-1:pfx), fy = pfy<0?0:(pfy>height-1?height-1:pfy);
+ const unsigned int
+ x = (unsigned int)fx, px = (int)x-1>=0?x-1:0, nx = x+1<width?x+1:width-1, ax = nx+1<width?nx+1:width-1,
+ y = (unsigned int)fy, py = (int)y-1>=0?y-1:0, ny = y+1<height?y+1:height-1, ay = ny+1<height?ny+1:height-1;
+ const float dx = fx-x, dy = fy-y;
+ const T&
+ a = (*this)(px,py,z,v), b = (*this)(x,py,z,v), c = (*this)(nx,py,z,v), d = (*this)(ax,py,z,v),
+ e = (*this)(px, y,z,v), f = (*this)(x, y,z,v), g = (*this)(nx, y,z,v), h = (*this)(ax, y,z,v),
+ i = (*this)(px,ny,z,v), j = (*this)(x,ny,z,v), k = (*this)(nx,ny,z,v), l = (*this)(ax,ny,z,v),
+ m = (*this)(px,ay,z,v), n = (*this)(x,ay,z,v), o = (*this)(nx,ay,z,v), p = (*this)(ax,ay,z,v);
+ const float
+ Rxp = _cubic_R(-1-dx), Rxc = _cubic_R(dx), Rxn = _cubic_R(1-dx), Rxa = _cubic_R(2-dx),
+ Ryp = _cubic_R(dy+1), Ryc = _cubic_R(dy), Ryn = _cubic_R(dy-1), Rya = _cubic_R(dy-2);
+ return
+ Rxp*Ryp*a + Rxc*Ryp*b + Rxn*Ryp*c + Rxa*Ryp*d +
+ Rxp*Ryc*e + Rxc*Ryc*f + Rxn*Ryc*g + Rxa*Ryc*h +
+ Rxp*Ryn*i + Rxc*Ryn*j + Rxn*Ryn*k + Rxa*Ryn*l +
+ Rxp*Rya*m + Rxc*Rya*n + Rxn*Rya*o + Rxa*Rya*p;
+ }
+
+ //! Display informations about the image on the standard error output.
+ /**
+ \param title Name for the considered image (optional).
+ \param print_flag Level of informations to be printed.
+
+ - The possible values for \c print_flag are :
+ - 0 : print only informations about image size and pixel buffer.
+ - 1 : print also statistics on the image pixels.
+ - 2 : print also the content of the pixel buffer, in a matlab-style.
+
+ \par example:
+ \code
+ CImg<float> img("foo.jpg"); // Load image from a JPEG file.
+ img.print("Image : foo.jpg",1); // Print image informations and statistics.
+ \endcode
+
+ \sa CImgStats
+ **/
+ const CImg& print(const char *title=NULL,const unsigned int print_flag=1) const {
+ std::fprintf(stderr,"%-8s(this=%p): { size=(%u,%u,%u,%u), data=(%s*)%p (%s)",
+ title?title:"CImg",(void*)this,
+ width,height,depth,dim,pixel_type(),(void*)data,
+ shared?"shared":"not shared");
+ if (is_empty()) { std::fprintf(stderr,", [Undefined pixel data] }\n"); return *this; }
+ if (print_flag>=1) {
+ CImgStats st(*this);
+ std::fprintf(stderr,", min=%g, mean=%g [var=%g], max=%g, pmin=(%d,%d,%d,%d), pmax=(%d,%d,%d,%d)",
+ st.min,st.mean,st.variance,st.max,st.xmin,st.ymin,st.zmin,st.vmin,st.xmax,st.ymax,st.zmax,st.vmax);
+ }
+ if (print_flag>=2 || size()<=16) {
+ std::fprintf(stderr," }\n%s = [ ",title?title:"data");
+ cimg_mapXYZV(*this,x,y,z,k)
+ std::fprintf(stderr,"%g%s",(double)(*this)(x,y,z,k),
+ ((x+1)*(y+1)*(z+1)*(k+1)==(int)size()?" ]\n":(((x+1)%width==0)?" ; ":" ")));
+ } else std::fprintf(stderr," }\n");
+ return *this;
+ }
+
+ //! Display informations about the image on the standart output.
+ const CImg& print(const unsigned int print_flag) const { return print(NULL,print_flag); }
+
+ //@}
+ //------------------------------------------
+ //
+ //! \name Arithmetic and Boolean operators
+ //@{
+ //------------------------------------------
+
+ //! Assign an image to the instance image.
+ /**
+ \param img Image to copy.
+
+ - Replace the instance image by a copy of the image \c img.
+ - The assignement is faster if input and output images have same template types.
+ - Otherwise, pixel values are casted as in C.
+
+ \par example:
+ \code
+ CImg<unsigned char> img("foo.jpg"); // Load image from a JPEG file.
+ CImg<unsigned char> dest1; // Define an empty image of unsigned char pixels.
+ CImg<float> dest2; // Define an empty image of float pixels.
+ dest1 = img; // Fast copy of img to dest1.
+ dest2 = img; // Copy of img to dest2, with conversion of pixel to float values.
+ \endcode
+ **/
+ template<typename t> CImg<T>& operator=(const CImg<t>& img) {
+ const unsigned long siz = img.size();
+ if (img.data && siz) {
+ if (shared) {
+ if (siz==size()) {
+ const t* ptrs = img.data + siz;
+ for (T *ptrd = data+siz; ptrd>data; ) *(--ptrd) = (T)*(--ptrs);
+ } else throw CImgArgumentException("CImg<%s>::operator=() : Given image (%u,%u,%u,%u,%p) and instance image (%u,%u,%u,%u,%p) "
+ "must have same dimensions, since instance image has shared memory.",
+ pixel_type(),img.width,img.height,img.depth,img.dim,img.data,width,height,depth,dim,data);
+ } else {
+ if (siz!=size()) { if (data) delete[] data; data = new T[siz]; }
+ width = img.width; height = img.height; depth = img.depth; dim = img.dim;
+ const t* ptrs = img.data + siz;
+ for (T *ptrd = data+siz; ptrd>data; ) *(--ptrd) = (T)*(--ptrs);
+ }
+ } else {
+ if (data) delete[] data;
+ width = height = depth = dim = 0; data = 0;
+ }
+ return *this;
+ }
+
+ // Assignment operator (fast version).
+ CImg& operator=(const CImg& img) {
+ if (&img!=this) {
+ const unsigned int siz = img.size();
+ if (img.data && siz) {
+ if (shared) {
+ if (siz==size()) std::memcpy(data,img.data,siz*sizeof(T));
+ else throw CImgArgumentException("CImg<%s>::operator=() : Given image (%u,%u,%u,%u,%p) and instance image (%u,%u,%u,%u,%p) "
+ "must have same dimensions, since instance image has shared memory.",
+ pixel_type(),img.width,img.height,img.depth,img.dim,img.data,width,height,depth,dim,data);
+ } else {
+ T* xdata = 0;
+ if (siz!=width*height*depth*dim) xdata = new T[siz];
+ width = img.width; height = img.height; depth = img.depth; dim = img.dim;
+ std::memcpy(xdata?xdata:data,img.data,siz*sizeof(T));
+ if (xdata) { delete[] data; data = xdata; }
+ }
+ } else {
+ if (data) delete[] data;
+ width = height = depth = dim = 0; data = 0;
+ }
+ }
+ return *this;
+ }
+
+ //! Assign a value to each image pixel of the instance image.
+ /**
+ \param val Value to assign.
+
+ - Replace all pixel values of the instance image by \c val.
+ - Can be used to easily initialize an image.
+
+ \par example:
+ \code
+ CImg<float> img(100,100); // Define a 100x100 greyscale image.
+ img = 3.14f; // Set all pixel values to 3.14.
+ \endcode
+
+ \sa fill().
+ **/
+ CImg& operator=(const T& val) {
+ return fill(val);
+ }
+
+ //! Assign values of a C-array to the instance image.
+ /**
+ \param buf Pointer to a C-style array having a size of (at least) <tt>this->size()</tt>.
+
+ - Replace pixel values by the content of the array \c buf.
+ - Warning : the value types in the array and in the image must be the same.
+
+ \par example:
+ \code
+ float tab[4*4] = { 1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16 }; // Define a 4x4 matrix in C-style.
+ CImg<float> matrice(4,4); // Define a 4x4 greyscale image.
+ matrice = tab; // Fill the image by the values in tab.
+ \endcode
+ **/
+ CImg& operator=(const T *buf) {
+ if (buf) std::memcpy(data,buf,size()*sizeof(T));
+ else empty();
+ return *this;
+ }
+
+ //! Addition.
+ /**
+ \param val Constant value added to each image pixel of the instance image.
+ **/
+ CImg operator+(const T& val) const {
+ return CImg<T>(*this)+=val;
+ }
+
+ //! Addition.
+ /**
+ \param img Image added to the instance image.
+ **/
+ template<typename t> CImg<typename cimg::largest<T,t>::type> operator+(const CImg<t>& img) const {
+ typedef typename cimg::largest<T,t>::type restype;
+ return CImg<restype>(*this)+=img;
+ }
+
+ //! Addition.
+ friend CImg operator+(const T& val, const CImg<T>& img) {
+ return CImg<T>(img)+=val;
+ }
+
+ //! In-place addition.
+ /** This is the in-place version of operator+(). **/
+ CImg& operator+=(const T& val) {
+ cimg_map(*this,ptr,T) (*ptr)+=val;
+ return *this;
+ }
+
+ //! In-place addition.
+ /** This is the in-place version of operator+(). **/
+ template<typename t> CImg& operator+=(const CImg<t>& img) {
+ const unsigned int smin = cimg::min(size(),img.size());
+ t *ptrs = img.data+smin;
+ for (T *ptrd = data+smin; ptrd>data; --ptrd, (*ptrd)=(T)((*ptrd)+(*(--ptrs))));
+ return *this;
+ }
+
+ //! In-place increment.
+ /** Equivalent to \c operator+=(1). **/
+ CImg& operator++() {
+ return (*this)+=1;
+ }
+
+ //! Substraction.
+ /**
+ \param val Constant value substracted to each image pixel of the instance image.
+ **/
+ CImg operator-(const T& val) const {
+ return CImg<T>(*this)-=val;
+ }
+
+ //! Substraction.
+ /**
+ \param img Image substracted to the instance image.
+ **/
+ template<typename t> CImg<typename cimg::largest<T,t>::type> operator-(const CImg<t>& img) const {
+ typedef typename cimg::largest<T,t>::type restype;
+ return CImg<restype>(*this)-=img;
+ }
+
+ //! Substraction.
+ friend CImg operator-(const T& val, const CImg<T>& img) {
+ return CImg<T>(img.width,img.height,img.depth,img.dim,val)-=img;
+ }
+
+ //! In-place substraction.
+ /** This is the in-place version of operator-(). **/
+ CImg& operator-=(const T& val) {
+ cimg_map(*this,ptr,T) (*ptr)-=val;
+ return *this;
+ }
+
+ //! In-place substraction.
+ /** This is the in-place version of operator-(). **/
+ template<typename t> CImg& operator-=(const CImg<t>& img) {
+ const unsigned int smin = cimg::min(size(),img.size());
+ t *ptrs = img.data+smin;
+ for (T *ptrd = data+smin; ptrd>data; --ptrd, (*ptrd)=(T)((*ptrd)-(*(--ptrs))));
+ return *this;
+ }
+
+ //! In-place decrement.
+ /** Equivalent to \c operator-=(1). **/
+ CImg& operator--() {
+ return (*this)-=1;
+ }
+
+ //! Multiplication.
+ /**
+ \param val Constant value multiplied to each image pixel of the instance image.
+ **/
+ CImg operator*(const double val) const {
+ return CImg<T>(*this)*=val;
+ }
+
+ //! Multiplication.
+ /**
+ Matrix multiplication.
+ **/
+ template<typename t> CImg<typename cimg::largest<T,t>::type> operator*(const CImg<t>& img) const {
+ typedef typename cimg::largest<T,t>::type restype;
+ if (width!=img.height)
+ throw CImgArgumentException("CImg<%s>::operator*() : can't multiply a matrix *this = (%ux%u) by a matrix (%ux%u)",
+ pixel_type(),width,height,img.width,img.height);
+ CImg<restype> res(img.width,height);
+ restype val;
+ cimg_mapXY(res,i,j) { val=0; cimg_mapX(*this,k) val+=(*this)(k,j)*img(i,k); res(i,j) = val; }
+ return res;
+ }
+
+ //! Multiplication.
+ friend CImg operator*(const double val,const CImg &img) {
+ return CImg<T>(img)*=val;
+ }
+
+ //! In-place multiplication.
+ /** This is the in-place version of operator*(). **/
+ CImg& operator*=(const double val) {
+ cimg_map(*this,ptr,T) (*ptr)=(T)((*ptr)*val);
+ return *this;
+ }
+
+ //! In-place multiplication.
+ /** This is the in-place version of operator*(). **/
+ template<typename t> CImg& operator*=(const CImg<t>& img) {
+ return ((*this)*img).swap(*this);
+ }
+
+ //! Division.
+ /**
+ \param val Constant value divided to each image pixel of the instance image.
+ **/
+ CImg operator/(const double val) const {
+ return CImg<T>(*this)/=val;
+ }
+
+ //! In-place division.
+ /** This is the in-place version of operator/(). **/
+ CImg& operator/=(const double val) {
+ cimg_map(*this,ptr,T) (*ptr)=(T)((*ptr)/val);
+ return *this;
+ }
+
+ //! Modulo.
+ /**
+ \param val Constant valued used for a modulo on each image pixel.
+ **/
+ CImg operator%(const T& val) const {
+ return CImg<T>(*this)%=val;
+ }
+
+ //! Modulo.
+ /**
+ \param img Image whose values are used for a modulo.
+ **/
+ CImg operator%(const CImg& img) const { return CImg<T>(*this)%=img; }
+
+ //! In-place modulo.
+ /** This is the in-place version of operator%(). **/
+ CImg& operator%=(const T& val) { cimg_map(*this,ptr,T) (*ptr)%=val; return *this; }
+
+ //! In-place modulo.
+ /** This is the in-place version of operator%(). **/
+ CImg& operator%=(const CImg& img) {
+ const unsigned int smin = cimg::min(size(),img.size());
+ for (T *ptrs=img.data+smin, *ptrd=data+smin; ptrd>data; *(--ptrd)%=*(--ptrs));
+ return *this;
+ }
+
+ //! Bitwise AND.
+ /**
+ \param val Constant valued used for a bitwise AND on each image pixel.
+ **/
+ CImg operator&(const T& val) const { return CImg<T>(*this)&=val; }
+
+ //! Bitwise AND.
+ /**
+ \param img Image whose value are used for the AND.
+ **/
+ CImg operator&(const CImg& img) const { return CImg<T>(*this)&=img; }
+
+ //! In-place bitwise AND.
+ /** This is the in-place version of operator&(). **/
+ CImg& operator&=(const T& val) { cimg_map(*this,ptr,T) (*ptr)&=val; return *this; }
+
+ //! In-place bitwise AND.
+ /** This is the in-place version of operator&=(). **/
+ CImg& operator&=(const CImg& img) {
+ const unsigned int smin = cimg::min(size(),img.size());
+ for (T *ptrs=img.data+smin, *ptrd=data+smin; ptrd>data; *(--ptrd)&=*(--ptrs));
+ return *this;
+ }
+
+ //! Bitwise OR.
+ /**
+ \param val Constant valued used for a bitwise OR on each image pixel.
+ **/
+ CImg operator|(const T& val) const { return CImg<T>(*this)|=val; }
+
+ //! Bitwise OR.
+ /**
+ \param img Image whose values are used for the OR.
+ **/
+ CImg operator|(const CImg& img) const { return CImg<T>(*this)|=img; }
+
+ //! In-place bitwise OR.
+ /** This is the in-place version of operator|(). **/
+ CImg& operator|=(const T& val) { cimg_map(*this,ptr,T) (*ptr)|=val; return *this; }
+
+ //! In-place bitwise OR.
+ /** This is the in-place version of operator|(). **/
+ CImg& operator|=(const CImg& img) {
+ const unsigned int smin = cimg::min(size(),img.size());
+ for (T *ptrs=img.data+smin, *ptrd=data+smin; ptrd>data; *(--ptrd)|=*(--ptrs));
+ return *this;
+ }
+
+ //! Bitwise XOR.
+ /**
+ \param val Constant valued used for a bitwise XOR on each image pixel.
+ **/
+ CImg operator^(const T& val) const { return CImg<T>(*this)^=val; }
+
+ //! Bitwise XOR.
+ /**
+ \param img Image whose values are used for the XOR.
+ **/
+ CImg operator^(const CImg& img) const { return CImg<T>(*this)^=img; }
+
+ //! In-place bitwise XOR.
+ /** This is the in-place version of operator^(). **/
+ CImg& operator^=(const T& val) { cimg_map(*this,ptr,T) (*ptr)^=val; return *this; }
+
+ //! In-place bitwise XOR.
+ /** This is the in-place version of operator^(). **/
+ CImg& operator^=(const CImg& img) {
+ const unsigned int smin = cimg::min(size(),img.size());
+ for (T *ptrs=img.data+smin, *ptrd=data+smin; ptrd>data; *(--ptrd)^=*(--ptrs));
+ return *this;
+ }
+
+ //! Boolean NOT.
+ CImg operator!() const {
+ CImg<T> res(*this,false);
+ const T *ptrs = end();
+ cimg_map(res,ptrd,T) *ptrd=!(*(--ptrs));
+ return res;
+ }
+
+ //! Bitwise NOT.
+ CImg operator~() const {
+ CImg<T> res(*this,false);
+ const T *ptrs = end();
+ cimg_map(res,ptrd,T) *ptrd=~(*(--ptrs));
+ return res;
+ }
+
+ //! Boolean equality.
+ template<typename t> bool operator==(const CImg<t>& img) const {
+ const unsigned int siz = size();
+ bool vequal = true;
+ if (siz!=img.size()) return false;
+ t *ptrs=img.data+siz;
+ for (T *ptrd=data+siz; vequal && ptrd>data; vequal=vequal&&((*(--ptrd))==(*(--ptrs))));
+ return vequal;
+ }
+
+ //! Boolean difference.
+ template<typename t> bool operator!=(const CImg<t>& img) const { return !((*this)==img); }
+
+ //@}
+ //---------------------------------------
+ //
+ //! \name Usual mathematical operations
+ //@{
+ //---------------------------------------
+
+ //! In-place pointwise multiplication between \c *this and \c img.
+ /**
+ This is the in-place version of get_mul().
+ \sa get_mul().
+ **/
+ template<typename t> CImg& mul(const CImg<t>& img) {
+ t *ptrs = img.data;
+ T *ptrf = data + cimg::min(size(),img.size());
+ for (T* ptrd = data; ptrd<ptrf; ptrd++) (*ptrd)=(T)(*ptrd*(*(ptrs++)));
+ return *this;
+ }
+
+ //! Pointwise multiplication between \c *this and \c img.
+ /**
+ \param img Argument of the multiplication.
+ - if \c *this and \c img have different size, the multiplication is applied on the maximum possible range.
+ \sa get_div(),mul(),div()
+ **/
+ template<typename t> CImg<typename cimg::largest<T,t>::type> get_mul(const CImg<t>& img) const {
+ typedef typename cimg::largest<T,t>::type restype;
+ return CImg<restype>(*this).mul(img);
+ }
+
+ //! Replace the image by the pointwise division between \p *this and \p img.
+ /**
+ This is the in-place version of get_div().
+ \see get_div().
+ **/
+ template<typename t> CImg& div(const CImg<t>& img) {
+ t *ptrs = img.data;
+ T *ptrf = data + cimg::min(size(),img.size());
+ for (T* ptrd = data; ptrd<ptrf; ptrd++) (*ptrd)=(T)(*ptrd/(*(ptrs++)));
+ return *this;
+ }
+
+ //! Return an image from a pointwise division between \p *this and \p img.
+ /**
+ \param img = argument of the division.
+ \note if \c *this and \c img have different size, the division is applied
+ only on possible values.
+ \see get_mul(),mul(),div()
+ **/
+ template<typename t> CImg<typename cimg::largest<T,t>::type> get_div(const CImg<t>& img) const {
+ typedef typename cimg::largest<T,t>::type restype;
+ return CImg<restype>(*this).div(img);
+ }
+
+ //! Replace the image by the pointwise max operator between \p *this and \p img
+ /**
+ This is the in-place version of get_max().
+ \see get_max().
+ **/
+ template<typename t> CImg& max(const CImg<t>& img) {
+ t *ptrs = img.data;
+ T *ptrf = data + cimg::min(size(),img.size());
+ for (T* ptrd = data; ptrd<ptrf; ptrd++) (*ptrd)=cimg::max((T)(*(ptrs++)),*ptrd);
+ return *this;
+ }
+
+ //! Return the image corresponding to the max value for each pixel.
+ /**
+ \param img = second argument of the max operator (the first one is *this).
+ \see max(), min(), get_min()
+ **/
+ template<typename t> CImg<typename cimg::largest<T,t>::type> get_max(const CImg<t>& img) const {
+ typedef typename cimg::largest<T,t>::type restype;
+ return CImg<restype>(*this).max(img);
+ }
+
+ //! Replace the image by the pointwise max operator between \p *this and \p val
+ /**
+ This is the in-place version of get_max().
+ \see get_max().
+ **/
+ CImg& max(const T& val) {
+ cimg_map(*this,ptr,T) (*ptr)=cimg::max(*ptr,val);
+ return *this;
+ }
+
+ //! Return the image corresponding to the max value for each pixel.
+ /**
+ \param val = second argument of the max operator (the first one is *this).
+ \see max(), min(), get_min()
+ **/
+ CImg get_max(const T& val) const {
+ return CImg<T>(*this).max(val);
+ }
+
+ //! Replace the image by the pointwise min operator between \p *this and \p img
+ /**
+ This is the in-place version of get_min().
+ \see get_min().
+ **/
+ template<typename t> CImg& min(const CImg<t>& img) {
+ t *ptrs = img.data;
+ T *ptrf = data + cimg::min(size(),img.size());
+ for (T* ptrd = data; ptrd<ptrf; ptrd++) (*ptrd)=cimg::min((T)(*(ptrs++)),*ptrd);
+ return *this;
+ }
+ //! Return the image corresponding to the min value for each pixel.
+ /**
+ \param img = second argument of the min operator (the first one is *this).
+ \see min(), max(), get_max()
+ **/
+ template<typename t> CImg<typename cimg::largest<T,t>::type> get_min(const CImg<t>& img) const {
+ typedef typename cimg::largest<T,t>::type restype;
+ return CImg<restype>(*this).min(img);
+ }
+
+ //! Replace the image by the pointwise min operator between \p *this and \p val
+ /**
+ This is the in-place version of get_min().
+ \see get_min().
+ **/
+ CImg& min(const T& val) {
+ cimg_map(*this,ptr,T) (*ptr)=cimg::min(*ptr,val);
+ return *this;
+ }
+
+ //! Return the image corresponding to the min value for each pixel.
+ /**
+ \param val = second argument of the min operator (the first one is *this).
+ \see min(), max(), get_max()
+ **/
+ CImg get_min(const T& val) const {
+ return CImg<T>(*this).min(val);
+ }
+
+ //! Replace each image pixel by its square root.
+ /**
+ \see get_sqrt()
+ **/
+ CImg& sqrt() {
+ cimg_map(*this,ptr,T) (*ptr)=(T)std::sqrt((double)(*ptr));
+ return *this;
+ }
+
+ //! Return the image of the square root of the pixel values.
+ /**
+ \see sqrt()
+ **/
+ CImg<typename cimg::largest<T,float>::type> get_sqrt() const {
+ typedef typename cimg::largest<T,float>::type restype;
+ return CImg<restype>(*this).sqrt();
+ }
+
+ //! Replace each image pixel by its log.
+ /**
+ \see get_log(), log10(), get_log10()
+ **/
+ CImg& log() {
+ cimg_map(*this,ptr,T) (*ptr)=(T)std::log((double)(*ptr));
+ return *this;
+ }
+
+ //! Return the image of the log of the pixel values.
+ /**
+ \see log(), log10(), get_log10()
+ **/
+ CImg<typename cimg::largest<T,float>::type> get_log() const {
+ typedef typename cimg::largest<T,float>::type restype;
+ return CImg<restype>(*this).log();
+ }
+
+ //! Replace each image pixel by its log10.
+ /**
+ \see get_log10(), log(), get_log()
+ **/
+ CImg& log10() {
+ cimg_map(*this,ptr,T) (*ptr)=(T)std::log10((double)(*ptr));
+ return *this;
+ }
+
+ //! Return the image of the log10 of the pixel values.
+ /**
+ \see log10(), log(), get_log()
+ **/
+ CImg<typename cimg::largest<T,float>::type> get_log10() const {
+ typedef typename cimg::largest<T,float>::type restype;
+ return CImg<restype>(*this).log10();
+ }
+
+ //! Replace each image pixel by its power by \p p.
+ /**
+ \param p = power
+ \see get_pow(), sqrt(), get_sqrt()
+ **/
+ CImg& pow(const double p) {
+ if (p==0) return fill(1);
+ if (p==1) return *this;
+ if (p==2) { cimg_map(*this,ptr,T) { const T& val = *ptr; *ptr=val*val; } return *this; }
+ if (p==3) { cimg_map(*this,ptr,T) { const T& val = *ptr; *ptr=val*val*val; } return *this; }
+ if (p==4) { cimg_map(*this,ptr,T) { const T& val = *ptr; *ptr=val*val*val*val; } return *this; }
+ cimg_map(*this,ptr,T) (*ptr)=(T)std::pow((double)(*ptr),p);
+ return *this;
+ }
+
+ //! Return the image of the square root of the pixel values.
+ /**
+ \param p = power
+ \see pow(), sqrt(), get_sqrt()
+ **/
+ CImg<typename cimg::largest<T,float>::type> get_pow(const double p) const {
+ typedef typename cimg::largest<T,float>::type restype;
+ return CImg<restype>(*this).pow(p);
+ }
+
+ //! Return each image pixel (*this)(x,y,z,k) by its power by \p img(x,y,z,k)
+ /**
+ In-place version
+ **/
+ template<typename t> CImg& pow(const CImg<t>& img) {
+ t *ptrs = img.data;
+ T *ptrf = data + cimg::min(size(),img.size());
+ for (T* ptrd = data; ptrd<ptrf; ptrd++) (*ptrd)=(T)std::pow((double)*ptrd,(double)(*(ptrs++)));
+ return *this;
+ }
+
+ //! Return each image pixel (*this)(x,y,z,k) by its power by \p img(x,y,z,k)
+ template<typename t> CImg<typename cimg::largest<T,float>::type> get_pow(const CImg<t>& img) const {
+ typedef typename cimg::largest<T,float>::type restype;
+ return CImg<restype>(*this).pow(img);
+ }
+
+ //! Replace each pixel value by its absolute value.
+ /**
+ \see get_abs()
+ **/
+ CImg& abs() {
+ cimg_map(*this,ptr,T) (*ptr)=cimg::abs(*ptr);
+ return *this;
+ }
+
+ //! Return the image of the absolute value of the pixel values.
+ /**
+ \see abs()
+ **/
+ CImg<typename cimg::largest<T,float>::type> get_abs() const {
+ typedef typename cimg::largest<T,float>::type restype;
+ return CImg<restype>(*this).abs();
+ }
+
+ //! Replace each image pixel by its cosinus.
+ /**
+ \see get_cos(), sin(), get_sin(), tan(), get_tan()
+ **/
+ CImg& cos() {
+ cimg_map(*this,ptr,T) (*ptr)=(T)std::cos((double)(*ptr));
+ return *this;
+ }
+
+ //! Return the image of the cosinus of the pixel values.
+ /**
+ \see cos(), sin(), get_sin(), tan(), get_tan()
+ **/
+ CImg<typename cimg::largest<T,float>::type> get_cos() const {
+ typedef typename cimg::largest<T,float>::type restype;
+ return CImg<restype>(*this).cos();
+ }
+
+ //! Replace each image pixel by its sinus.
+ /**
+ \see get_sin(), cos(), get_cos(), tan(), get_tan()
+ **/
+ CImg& sin() {
+ cimg_map(*this,ptr,T) (*ptr)=(T)std::sin((double)(*ptr));
+ return *this;
+ }
+
+ //! Return the image of the sinus of the pixel values.
+ /**
+ \see sin(), cos(), get_cos(), tan(), get_tan()
+ **/
+ CImg<typename cimg::largest<T,float>::type> get_sin() const {
+ typedef typename cimg::largest<T,float>::type restype;
+ return CImg<restype>(*this).sin();
+ }
+
+ //! Replace each image pixel by its tangent.
+ /**
+ \see get_tan(), cos(), get_cos(), sin(), get_sin()
+ **/
+ CImg& tan() {
+ cimg_map(*this,ptr,T) (*ptr)=(T)std::tan((double)(*ptr));
+ return *this;
+ }
+
+ //! Return the image of the tangent of the pixel values.
+ /**
+ \see tan(), cos(), get_cos(), sin(), get_sin()
+ **/
+ CImg<typename cimg::largest<T,float>::type> get_tan() const {
+ typedef typename cimg::largest<T,float>::type restype;
+ return CImg<restype>(*this).tan();
+ }
+
+ //! Return the MSE (Mean-Squared Error) between two images.
+ template<typename t> double MSE(const CImg<t>& img) const {
+ if (img.size()!=size())
+ throw CImgArgumentException("CImg<%s>::MSE() : Instance image (%u,%u,%u,%u) and given image (%u,%u,%u,%u) have different dimensions.",
+ pixel_type(),width,height,depth,dim,img.width,img.height,img.depth,img.dim);
+
+ double vMSE = 0;
+ const t* ptr2 = img.end();
+ cimg_map(*this,ptr1,T) {
+ const double diff = (double)*ptr1 - (double)*(--ptr2);
+ vMSE += diff*diff;
+ }
+ vMSE/=img.size();
+ return vMSE;
+ }
+
+ //! Return the PSNR between two images.
+ template<typename t> double PSNR(const CImg<t>& img, const double valmax=255.0) const {
+ const double vMSE = std::sqrt(MSE(img));
+ return (vMSE!=0)?(20*std::log10(valmax/vMSE)):(cimg::infinity);
+ }
+
+ //@}
+ //-----------------------------------
+ //
+ //! \name Usual image transformation
+ //@{
+ //-----------------------------------
+
+ //! Fill an image by a value \p val.
+ /**
+ \param val = fill value
+ \note All pixel values of the instance image will be initialized by \p val.
+ \see operator=().
+ **/
+ CImg& fill(const T& val) {
+ if (!is_empty()) {
+ if (val!=0 && sizeof(T)!=1) cimg_map(*this,ptr,T) *ptr=val;
+ else std::memset(data,(int)val,size()*sizeof(T));
+ }
+ return *this;
+ }
+
+ //! Fill sequentially all pixel values with values \a val0 and \a val1 respectively.
+ /**
+ \param val0 = fill value 1
+ \param val1 = fill value 2
+ **/
+ CImg& fill(const T& val0,const T& val1) {
+ if (!is_empty()) {
+ T *ptr, *ptr_end = end()-1;
+ for (ptr=data; ptr<ptr_end; ) { *(ptr++)=val0; *(ptr++)=val1; }
+ if (ptr!=ptr_end+1) *(ptr++)=val0;
+ }
+ return *this;
+ }
+
+ //! Fill sequentially all pixel values with values \a val0 and \a val1 and \a val2.
+ /**
+ \param val0 = fill value 1
+ \param val1 = fill value 2
+ \param val2 = fill value 3
+ **/
+ CImg& fill(const T& val0,const T& val1,const T& val2) {
+ if (!is_empty()) {
+ T *ptr, *ptr_end = end()-2;
+ for (ptr=data; ptr<ptr_end; ) { *(ptr++)=val0; *(ptr++)=val1; *(ptr++)=val2; }
+ ptr_end+=2;
+ switch (ptr_end-ptr) {
+ case 2: *(--ptr_end)=val1;
+ case 1: *(--ptr_end)=val0;
+ }
+ }
+ return *this;
+ }
+
+ //! Fill sequentially all pixel values with values \a val0 and \a val1 and \a val2 and \a val3.
+ /**
+ \param val0 = fill value 1
+ \param val1 = fill value 2
+ \param val2 = fill value 3
+ \param val3 = fill value 4
+ **/
+ CImg& fill(const T& val0,const T& val1,const T& val2,const T& val3) {
+ if (!is_empty()) {
+ T *ptr, *ptr_end = end()-3;
+ for (ptr=data; ptr<ptr_end; ) { *(ptr++)=val0; *(ptr++)=val1; *(ptr++)=val2; *(ptr++)=val3; }
+ ptr_end+=3;
+ switch (ptr_end-ptr) {
+ case 3: *(--ptr_end)=val2;
+ case 2: *(--ptr_end)=val1;
+ case 1: *(--ptr_end)=val0;
+ }
+ }
+ return *this;
+ }
+
+ //! Fill sequentially all pixel values with values \a val0 and \a val1 and \a val2 and \a val3 and \a val4.
+ /**
+ \param val0 = fill value 1
+ \param val1 = fill value 2
+ \param val2 = fill value 3
+ \param val3 = fill value 4
+ \param val4 = fill value 5
+ **/
+ CImg& fill(const T& val0,const T& val1,const T& val2,const T& val3,const T& val4) {
+ if (!is_empty()) {
+ T *ptr, *ptr_end = end()-4;
+ for (ptr=data; ptr<ptr_end; ) { *(ptr++)=val0; *(ptr++)=val1; *(ptr++)=val2; *(ptr++)=val3; *(ptr++)=val4; }
+ ptr_end+=4;
+ switch (ptr_end-ptr) {
+ case 4: *(--ptr_end)=val3;
+ case 3: *(--ptr_end)=val2;
+ case 2: *(--ptr_end)=val1;
+ case 1: *(--ptr_end)=val0;
+ }
+ }
+ return *this;
+ }
+
+ //! Fill sequentially all pixel values with values \a val0 and \a val1 and \a val2 and \a val3 and \a val4 and \a val5
+ /**
+ \param val0 = fill value 1
+ \param val1 = fill value 2
+ \param val2 = fill value 3
+ \param val3 = fill value 4
+ \param val4 = fill value 5
+ \param val5 = fill value 6
+ **/
+ CImg& fill(const T& val0,const T& val1,const T& val2,const T& val3,const T& val4,const T& val5) {
+ if (!is_empty()) {
+ T *ptr, *ptr_end = end()-5;
+ for (ptr=data; ptr<ptr_end; ) {
+ *(ptr++)=val0; *(ptr++)=val1; *(ptr++)=val2; *(ptr++)=val3; *(ptr++)=val4; *(ptr++)=val5;
+ }
+ ptr_end+=5;
+ switch (ptr_end-ptr) {
+ case 5: *(--ptr_end)=val4;
+ case 4: *(--ptr_end)=val3;
+ case 3: *(--ptr_end)=val2;
+ case 2: *(--ptr_end)=val1;
+ case 1: *(--ptr_end)=val0;
+ }
+ }
+ return *this;
+ }
+
+ //! Fill sequentially all pixel values with values \a val0 and \a val1 and \a val2 and \a val3 and \a val4 and \a val5
+ /**
+ \param val0 = fill value 1
+ \param val1 = fill value 2
+ \param val2 = fill value 3
+ \param val3 = fill value 4
+ \param val4 = fill value 5
+ \param val5 = fill value 6
+ \param val6 = fill value 7
+ **/
+ CImg& fill(const T& val0,const T& val1,const T& val2,const T& val3,
+ const T& val4,const T& val5,const T& val6) {
+ if (!is_empty()) {
+ T *ptr, *ptr_end = end()-6;
+ for (ptr=data; ptr<ptr_end; ) {
+ *(ptr++)=val0; *(ptr++)=val1; *(ptr++)=val2; *(ptr++)=val3; *(ptr++)=val4; *(ptr++)=val5; *(ptr++)=val6;
+ }
+ ptr_end+=6;
+ switch (ptr_end-ptr) {
+ case 6: *(--ptr_end)=val5;
+ case 5: *(--ptr_end)=val4;
+ case 4: *(--ptr_end)=val3;
+ case 3: *(--ptr_end)=val2;
+ case 2: *(--ptr_end)=val1;
+ case 1: *(--ptr_end)=val0;
+ }
+ }
+ return *this;
+ }
+
+ //! Fill sequentially all pixel values with values \a val0 and \a val1 and \a val2 and \a val3 and \a ... and \a val7.
+ /**
+ \param val0 = fill value 1
+ \param val1 = fill value 2
+ \param val2 = fill value 3
+ \param val3 = fill value 4
+ \param val4 = fill value 5
+ \param val5 = fill value 6
+ \param val6 = fill value 7
+ \param val7 = fill value 8
+ **/
+ CImg& fill(const T& val0,const T& val1,const T& val2,const T& val3,
+ const T& val4,const T& val5,const T& val6,const T& val7) {
+ if (!is_empty()) {
+ T *ptr, *ptr_end = end()-7;
+ for (ptr=data; ptr<ptr_end; ) {
+ *(ptr++)=val0; *(ptr++)=val1; *(ptr++)=val2; *(ptr++)=val3;
+ *(ptr++)=val4; *(ptr++)=val5; *(ptr++)=val6; *(ptr++)=val7;
+ }
+ ptr_end+=7;
+ switch (ptr_end-ptr) {
+ case 7: *(--ptr_end)=val6;
+ case 6: *(--ptr_end)=val5;
+ case 5: *(--ptr_end)=val4;
+ case 4: *(--ptr_end)=val3;
+ case 3: *(--ptr_end)=val2;
+ case 2: *(--ptr_end)=val1;
+ case 1: *(--ptr_end)=val0;
+ }
+ }
+ return *this;
+ }
+
+ //! Fill sequentially all pixel values with values \a val0 and \a val1 and \a val2 and \a val3 and \a ... and \a val8.
+ /**
+ \param val0 = fill value 1
+ \param val1 = fill value 2
+ \param val2 = fill value 3
+ \param val3 = fill value 4
+ \param val4 = fill value 5
+ \param val5 = fill value 6
+ \param val6 = fill value 7
+ \param val7 = fill value 8
+ \param val8 = fill value 9
+ **/
+ CImg& fill(const T& val0,const T& val1,const T& val2,
+ const T& val3,const T& val4,const T& val5,
+ const T& val6,const T& val7,const T& val8) {
+ if (!is_empty()) {
+ T *ptr, *ptr_end = end()-8;
+ for (ptr=data; ptr<ptr_end; ) {
+ *(ptr++)=val0; *(ptr++)=val1; *(ptr++)=val2;
+ *(ptr++)=val3; *(ptr++)=val4; *(ptr++)=val5;
+ *(ptr++)=val6; *(ptr++)=val7; *(ptr++)=val8;
+ }
+ ptr_end+=8;
+ switch (ptr_end-ptr) {
+ case 8: *(--ptr_end)=val7;
+ case 7: *(--ptr_end)=val6;
+ case 6: *(--ptr_end)=val5;
+ case 5: *(--ptr_end)=val4;
+ case 4: *(--ptr_end)=val3;
+ case 3: *(--ptr_end)=val2;
+ case 2: *(--ptr_end)=val1;
+ case 1: *(--ptr_end)=val0;
+ }
+ }
+ return *this;
+ }
+
+ //! Fill sequentially all pixel values with values \a val0 and \a val1 and \a val2 and \a val3 and \a ... and \a val9.
+ /**
+ \param val0 = fill value 1
+ \param val1 = fill value 2
+ \param val2 = fill value 3
+ \param val3 = fill value 4
+ \param val4 = fill value 5
+ \param val5 = fill value 6
+ \param val6 = fill value 7
+ \param val7 = fill value 8
+ \param val8 = fill value 9
+ \param val9 = fill value 10
+ **/
+ CImg& fill(const T& val0,const T& val1,const T& val2,const T& val3,const T& val4,
+ const T& val5,const T& val6,const T& val7,const T& val8,const T& val9) {
+ if (!is_empty()) {
+ T *ptr, *ptr_end = end()-9;
+ for (ptr=data; ptr<ptr_end; ) {
+ *(ptr++)=val0; *(ptr++)=val1; *(ptr++)=val2; *(ptr++)=val3; *(ptr++)=val4;
+ *(ptr++)=val5; *(ptr++)=val6; *(ptr++)=val7; *(ptr++)=val8; *(ptr++)=val9;
+ }
+ ptr_end+=9;
+ switch (ptr_end-ptr) {
+ case 9: *(--ptr_end)=val8;
+ case 8: *(--ptr_end)=val7;
+ case 7: *(--ptr_end)=val6;
+ case 6: *(--ptr_end)=val5;
+ case 5: *(--ptr_end)=val4;
+ case 4: *(--ptr_end)=val3;
+ case 3: *(--ptr_end)=val2;
+ case 2: *(--ptr_end)=val1;
+ case 1: *(--ptr_end)=val0;
+ }
+ }
+ return *this;
+ }
+
+ //! Fill sequentially all pixel values with values \a val0 and \a val1 and \a val2 and \a val3 and \a ... and \a val11.
+ /**
+ \param val0 = fill value 1
+ \param val1 = fill value 2
+ \param val2 = fill value 3
+ \param val3 = fill value 4
+ \param val4 = fill value 5
+ \param val5 = fill value 6
+ \param val6 = fill value 7
+ \param val7 = fill value 8
+ \param val8 = fill value 9
+ \param val9 = fill value 10
+ \param val10 = fill value 11
+ \param val11 = fill value 12
+ **/
+ CImg& fill(const T& val0,const T& val1,const T& val2,const T& val3,
+ const T& val4,const T& val5,const T& val6,const T& val7,
+ const T& val8,const T& val9,const T& val10,const T& val11) {
+ if (!is_empty()) {
+ T *ptr, *ptr_end = end()-11;
+ for (ptr=data; ptr<ptr_end; ) {
+ *(ptr++)=val0; *(ptr++)=val1; *(ptr++)=val2; *(ptr++)=val3; *(ptr++)=val4; *(ptr++)=val5;
+ *(ptr++)=val6; *(ptr++)=val7; *(ptr++)=val8; *(ptr++)=val9; *(ptr++)=val10; *(ptr++)=val11;
+ }
+ ptr_end+=11;
+ switch (ptr_end-ptr) {
+ case 11: *(--ptr_end)=val10;
+ case 10: *(--ptr_end)=val9;
+ case 9: *(--ptr_end)=val8;
+ case 8: *(--ptr_end)=val7;
+ case 7: *(--ptr_end)=val6;
+ case 6: *(--ptr_end)=val5;
+ case 5: *(--ptr_end)=val4;
+ case 4: *(--ptr_end)=val3;
+ case 3: *(--ptr_end)=val2;
+ case 2: *(--ptr_end)=val1;
+ case 1: *(--ptr_end)=val0;
+ }
+ }
+ return *this;
+ }
+
+ //! Fill sequentially all pixel values with values \a val0 and \a val1 and \a val2 and \a val3 and \a ... and \a val11.
+ /**
+ \param val0 = fill value 1
+ \param val1 = fill value 2
+ \param val2 = fill value 3
+ \param val3 = fill value 4
+ \param val4 = fill value 5
+ \param val5 = fill value 6
+ \param val6 = fill value 7
+ \param val7 = fill value 8
+ \param val8 = fill value 9
+ \param val9 = fill value 10
+ \param val10 = fill value 11
+ \param val11 = fill value 12
+ \param val12 = fill value 13
+ **/
+ CImg& fill(const T& val0,const T& val1,const T& val2,const T& val3,
+ const T& val4,const T& val5,const T& val6,const T& val7,
+ const T& val8,const T& val9,const T& val10,const T& val11,
+ const T& val12) {
+ if (!is_empty()) {
+ T *ptr, *ptr_end = end()-12;
+ for (ptr=data; ptr<ptr_end; ) {
+ *(ptr++)=val0; *(ptr++)=val1; *(ptr++)=val2; *(ptr++)=val3; *(ptr++)=val4; *(ptr++)=val5;
+ *(ptr++)=val6; *(ptr++)=val7; *(ptr++)=val8; *(ptr++)=val9; *(ptr++)=val10; *(ptr++)=val11;
+ *(ptr++)=val12;
+ }
+ ptr_end+=12;
+ switch (ptr_end-ptr) {
+ case 12: *(--ptr_end)=val11;
+ case 11: *(--ptr_end)=val10;
+ case 10: *(--ptr_end)=val9;
+ case 9: *(--ptr_end)=val8;
+ case 8: *(--ptr_end)=val7;
+ case 7: *(--ptr_end)=val6;
+ case 6: *(--ptr_end)=val5;
+ case 5: *(--ptr_end)=val4;
+ case 4: *(--ptr_end)=val3;
+ case 3: *(--ptr_end)=val2;
+ case 2: *(--ptr_end)=val1;
+ case 1: *(--ptr_end)=val0;
+ }
+ }
+ return *this;
+ }
+
+ //! Fill sequentially all pixel values with values \a val0 and \a val1 and \a val2 and \a val3 and \a ... and \a val15.
+ /**
+ \param val0 = fill value 1
+ \param val1 = fill value 2
+ \param val2 = fill value 3
+ \param val3 = fill value 4
+ \param val4 = fill value 5
+ \param val5 = fill value 6
+ \param val6 = fill value 7
+ \param val7 = fill value 8
+ \param val8 = fill value 9
+ \param val9 = fill value 10
+ \param val10 = fill value 11
+ \param val11 = fill value 12
+ \param val12 = fill value 13
+ \param val13 = fill value 14
+ \param val14 = fill value 15
+ \param val15 = fill value 16
+ **/
+ CImg& fill(const T& val0,const T& val1,const T& val2,const T& val3,
+ const T& val4,const T& val5,const T& val6,const T& val7,
+ const T& val8,const T& val9,const T& val10,const T& val11,
+ const T& val12,const T& val13,const T& val14,const T& val15) {
+ if (!is_empty()) {
+ T *ptr, *ptr_end = end()-15;
+ for (ptr=data; ptr<ptr_end; ) {
+ *(ptr++)=val0; *(ptr++)=val1; *(ptr++)=val2; *(ptr++)=val3; *(ptr++)=val4; *(ptr++)=val5;
+ *(ptr++)=val6; *(ptr++)=val7; *(ptr++)=val8; *(ptr++)=val9; *(ptr++)=val10; *(ptr++)=val11;
+ *(ptr++)=val12; *(ptr++)=val13; *(ptr++)=val14; *(ptr++)=val15;
+ }
+ ptr_end+=15;
+ switch (ptr_end-ptr) {
+ case 15: *(--ptr_end)=val14;
+ case 14: *(--ptr_end)=val13;
+ case 13: *(--ptr_end)=val12;
+ case 12: *(--ptr_end)=val11;
+ case 11: *(--ptr_end)=val10;
+ case 10: *(--ptr_end)=val9;
+ case 9: *(--ptr_end)=val8;
+ case 8: *(--ptr_end)=val7;
+ case 7: *(--ptr_end)=val6;
+ case 6: *(--ptr_end)=val5;
+ case 5: *(--ptr_end)=val4;
+ case 4: *(--ptr_end)=val3;
+ case 3: *(--ptr_end)=val2;
+ case 2: *(--ptr_end)=val1;
+ case 1: *(--ptr_end)=val0;
+ }
+ }
+ return *this;
+ }
+
+ //! Fill sequentially all pixel values with values \a val0 and \a val1 and \a val2 and \a val3 and \a ... and \a val24.
+ /**
+ \param val0 = fill value 1
+ \param val1 = fill value 2
+ \param val2 = fill value 3
+ \param val3 = fill value 4
+ \param val4 = fill value 5
+ \param val5 = fill value 6
+ \param val6 = fill value 7
+ \param val7 = fill value 8
+ \param val8 = fill value 9
+ \param val9 = fill value 10
+ \param val10 = fill value 11
+ \param val11 = fill value 12
+ \param val12 = fill value 13
+ \param val13 = fill value 14
+ \param val14 = fill value 15
+ \param val15 = fill value 16
+ \param val16 = fill value 17
+ \param val17 = fill value 18
+ \param val18 = fill value 19
+ \param val19 = fill value 20
+ \param val20 = fill value 21
+ \param val21 = fill value 22
+ \param val22 = fill value 23
+ \param val23 = fill value 24
+ \param val24 = fill value 25
+ **/
+ CImg& fill(const T& val0,const T& val1,const T& val2,const T& val3,const T& val4,
+ const T& val5,const T& val6,const T& val7,const T& val8,const T& val9,
+ const T& val10,const T& val11,const T& val12,const T& val13,const T& val14,
+ const T& val15,const T& val16,const T& val17,const T& val18,const T& val19,
+ const T& val20,const T& val21,const T& val22,const T& val23,const T& val24) {
+ if (!is_empty()) {
+ T *ptr, *ptr_end = end()-24;
+ for (ptr=data; ptr<ptr_end; ) {
+ *(ptr++)=val0; *(ptr++)=val1; *(ptr++)=val2; *(ptr++)=val3; *(ptr++)=val4;
+ *(ptr++)=val5; *(ptr++)=val6; *(ptr++)=val7; *(ptr++)=val8; *(ptr++)=val9;
+ *(ptr++)=val10; *(ptr++)=val11; *(ptr++)=val12; *(ptr++)=val13; *(ptr++)=val14;
+ *(ptr++)=val15; *(ptr++)=val16; *(ptr++)=val17; *(ptr++)=val18; *(ptr++)=val19;
+ *(ptr++)=val20; *(ptr++)=val21; *(ptr++)=val22; *(ptr++)=val23; *(ptr++)=val24;
+ }
+ ptr_end+=24;
+ switch (ptr_end-ptr) {
+ case 24: *(--ptr_end)=val23;
+ case 23: *(--ptr_end)=val22;
+ case 22: *(--ptr_end)=val21;
+ case 21: *(--ptr_end)=val20;
+ case 20: *(--ptr_end)=val19;
+ case 19: *(--ptr_end)=val18;
+ case 18: *(--ptr_end)=val17;
+ case 17: *(--ptr_end)=val16;
+ case 16: *(--ptr_end)=val15;
+ case 15: *(--ptr_end)=val14;
+ case 14: *(--ptr_end)=val13;
+ case 13: *(--ptr_end)=val12;
+ case 12: *(--ptr_end)=val11;
+ case 11: *(--ptr_end)=val10;
+ case 10: *(--ptr_end)=val9;
+ case 9: *(--ptr_end)=val8;
+ case 8: *(--ptr_end)=val7;
+ case 7: *(--ptr_end)=val6;
+ case 6: *(--ptr_end)=val5;
+ case 5: *(--ptr_end)=val4;
+ case 4: *(--ptr_end)=val3;
+ case 3: *(--ptr_end)=val2;
+ case 2: *(--ptr_end)=val1;
+ case 1: *(--ptr_end)=val0;
+ }
+ }
+ return *this;
+ }
+
+ //! Linear normalization of the pixel values between \a a and \a b.
+ /**
+ \param a = minimum pixel value after normalization.
+ \param b = maximum pixel value after normalization.
+ \see get_normalize(), cut(), get_cut().
+ **/
+ CImg& normalize(const T& a,const T& b) {
+ if (!is_empty()) {
+ const CImgStats st(*this,false);
+ if (st.min==st.max) fill(0);
+ else cimg_map(*this,ptr,T) *ptr=(T)((*ptr-st.min)/(st.max-st.min)*(b-a)+a);
+ }
+ return *this;
+ }
+
+ //! Return the image of normalized values.
+ /**
+ \param a = minimum pixel value after normalization.
+ \param b = maximum pixel value after normalization.
+ \see normalize(), cut(), get_cut().
+ **/
+ CImg get_normalize(const T& a,const T& b) const { return CImg<T>(*this).normalize(a,b); }
+
+ //! Cut pixel values between \a a and \a b.
+ /**
+ \param a = minimum pixel value after cut.
+ \param b = maximum pixel value after cut.
+ \see get_cut(), normalize(), get_normalize().
+ **/
+ CImg& cut(const T& a, const T& b) {
+ if (!is_empty())
+ cimg_map(*this,ptr,T) *ptr = (*ptr<a)?a:((*ptr>b)?b:*ptr);
+ return *this;
+ }
+
+ //! Return the image of cutted values.
+ /**
+ \param a = minimum pixel value after cut.
+ \param b = maximum pixel value after cut.
+ \see cut(), normalize(), get_normalize().
+ **/
+ CImg get_cut(const T& a, const T& b) const { return CImg<T>(*this).cut(a,b); }
+
+ //! Quantize pixel values into \n levels.
+ /**
+ \param n = number of quantification levels
+ \see get_quantize().
+ **/
+ CImg& quantize(const unsigned int n=256) {
+ if (!is_empty()) {
+ if (!n) throw CImgArgumentException("CImg<%s>::quantize() : Cannot quantize image to 0 values.",
+ pixel_type());
+ const CImgStats st(*this,false);
+ const double range = st.max-st.min;
+ if (range>0) cimg_map(*this,ptr,T) {
+ const unsigned int val = (unsigned int)((*ptr-st.min)*n/range);
+ *ptr = (T)(st.min + cimg::min(val,n-1)*range);
+ }
+ }
+ return *this;
+ }
+
+ //! Return a quantified image, with \n levels.
+ /**
+ \param n = number of quantification levels
+ \see quantize().
+ **/
+ CImg get_quantize(const unsigned int n=256) const { return CImg<T>(*this).quantize(n); }
+
+ //! Threshold the image.
+ /**
+ \param thres = threshold
+ \see get_threshold().
+ **/
+ CImg& threshold(const T& thres) {
+ if (!is_empty())
+ cimg_map(*this,ptr,T) *ptr = *ptr<=thres?(T)0:(T)1;
+ return *this;
+ }
+
+ //! Return a thresholded image.
+ /**
+ \param thres = threshold.
+ \see threshold().
+ **/
+ CImg get_threshold(const T& thres) const {
+ return CImg<T>(*this).threshold(thres);
+ }
+
+ //! Return a rotated image.
+ /**
+ \param angle = rotation angle (in degrees).
+ \param cond = rotation type. can be :
+ - 0 = zero-value at borders
+ - 1 = repeat image at borders
+ - 2 = zero-value at borders and linear interpolation
+ \note Returned image will probably have a different size than the instance image *this.
+ \see rotate()
+ **/
+ CImg get_rotate(const float angle, const unsigned int cond=3) const {
+ if (is_empty()) return CImg<T>();
+ CImg dest;
+ const float nangle = cimg::mod(angle,360.0f), rad = (float)((nangle*cimg::PI)/180.0),
+ ca=(float)std::cos(rad), sa=(float)std::sin(rad);
+ if (cond!=1 && cimg::mod(nangle,90.0f)==0) { // optimized version for orthogonal angles
+ const int wm1 = dimx()-1, hm1 = dimy()-1;
+ const int iangle = (int)nangle/90;
+ switch (iangle) {
+ case 1: {
+ dest.assign(height,width,depth,dim);
+ cimg_mapXYZV(dest,x,y,z,v) dest(x,y,z,v) = (*this)(y,hm1-x,z,v);
+ } break;
+ case 2: {
+ dest.assign(*this,false);
+ cimg_mapXYZV(dest,x,y,z,v) dest(x,y,z,v) = (*this)(wm1-x,hm1-y,z,v);
+ } break;
+ case 3: {
+ dest.assign(height,width,depth,dim);
+ cimg_mapXYZV(dest,x,y,z,v) dest(x,y,z,v) = (*this)(wm1-y,x,z,v);
+ } break;
+ default:
+ return *this;
+ }
+ } else { // generic version
+ const float
+ ux = (float)(cimg::abs(width*ca)), uy = (float)(cimg::abs(width*sa)),
+ vx = (float)(cimg::abs(height*sa)), vy = (float)(cimg::abs(height*ca)),
+ w2 = 0.5f*width, h2 = 0.5f*height,
+ dw2 = 0.5f*(ux+vx), dh2 = 0.5f*(uy+vy);
+ dest.assign((int)(ux+vx), (int)(uy+vy),depth,dim);
+ switch (cond) {
+ case 0: {
+ cimg_mapXY(dest,x,y)
+ cimg_mapZV(*this,z,v)
+ dest(x,y,z,v) = pix2d((int)(w2 + (x-dw2)*ca + (y-dh2)*sa),(int)(h2 - (x-dw2)*sa + (y-dh2)*ca),z,v,0);
+ } break;
+ case 1: {
+ cimg_mapXY(dest,x,y)
+ cimg_mapZV(*this,z,v)
+ dest(x,y,z,v) = (*this)(cimg::mod((int)(w2 + (x-dw2)*ca + (y-dh2)*sa),width),
+ cimg::mod((int)(h2 - (x-dw2)*sa + (y-dh2)*ca),height),z,v);
+ } break;
+ case 2: {
+ cimg_mapXY(dest,x,y) {
+ const float X = w2 + (x-dw2)*ca + (y-dh2)*sa, Y = h2 - (x-dw2)*sa + (y-dh2)*ca;
+ cimg_mapZV(*this,z,v) dest(x,y,z,v) = (T)linear_pix2d(X,Y,z,v,0);
+ }
+ } break;
+ default: {
+ cimg_mapXY(dest,x,y) {
+ const float X = w2 + (x-dw2)*ca + (y-dh2)*sa, Y = h2 - (x-dw2)*sa + (y-dh2)*ca;
+ cimg_mapZV(*this,z,v) dest(x,y,z,v) = (T)cubic_pix2d(X,Y,z,v,0);
+ }
+ } break;
+ }
+ }
+ return dest;
+ }
+
+ //! Rotate the image
+ /**
+ \param angle = rotation angle (in degrees).
+ \param cond = rotation type. can be :
+ - 0 = zero-value at borders
+ - 1 = repeat image at borders
+ - 2 = zero-value at borders and linear interpolation
+ \see get_rotate()
+ **/
+ CImg& rotate(const float angle,const unsigned int cond=3) { return get_rotate(angle,cond).swap(*this); }
+
+ //! Return a rotated image around the point (\c cx,\c cy).
+ /**
+ \param angle = rotation angle (in degrees).
+ \param cx = X-coordinate of the rotation center.
+ \param cy = Y-coordinate of the rotation center.
+ \param zoom = zoom.
+ \param cond = rotation type. can be :
+ - 0 = zero-value at borders
+ - 1 = repeat image at borders
+ - 2 = zero-value at borders and linear interpolation
+ \see rotate()
+ **/
+ CImg get_rotate(const float angle,const float cx,const float cy,const float zoom=1,const unsigned int cond=3) const {
+ if (is_empty()) return CImg<T>();
+ CImg dest(*this,false);
+ const float nangle = cimg::mod(angle,360.0f), rad = (float)((nangle*cimg::PI)/180.0),
+ ca=(float)std::cos(rad)/zoom, sa=(float)std::sin(rad)/zoom;
+ if (cond!=1 && zoom==1 && cimg::mod(nangle,90.0f)==0) { // optimized version for orthogonal angles
+ const int iangle = (int)nangle/90;
+ switch (iangle) {
+ case 1: {
+ dest.fill(0);
+ const unsigned int
+ xmin = cimg::max(0,(dimx()-dimy())/2), xmax = cimg::min(width,xmin+height),
+ ymin = cimg::max(0,(dimy()-dimx())/2), ymax = cimg::min(height,ymin+width),
+ xoff = xmin + cimg::min(0,(dimx()-dimy())/2),
+ yoff = ymin + cimg::min(0,(dimy()-dimx())/2);
+ cimg_mapZV(dest,z,v) for (unsigned int y=ymin; y<ymax; y++) for (unsigned int x=xmin; x<xmax; x++)
+ dest(x,y,z,v) = (*this)(y-yoff,height-1-x+xoff,z,v);
+ } break;
+ case 2: {
+ cimg_mapXYZV(dest,x,y,z,v) dest(x,y,z,v) = (*this)(width-1-x,height-1-y,z,v);
+ } break;
+ case 3: {
+ dest.fill(0);
+ const unsigned int
+ xmin = cimg::max(0,(dimx()-dimy())/2), xmax = cimg::min(width,xmin+height),
+ ymin = cimg::max(0,(dimy()-dimx())/2), ymax = cimg::min(height,ymin+width),
+ xoff = xmin + cimg::min(0,(dimx()-dimy())/2),
+ yoff = ymin + cimg::min(0,(dimy()-dimx())/2);
+ cimg_mapZV(dest,z,v) for (unsigned int y=ymin; y<ymax; y++) for (unsigned int x=xmin; x<xmax; x++)
+ dest(x,y,z,v) = (*this)(width-1-y+yoff,x-xoff,z,v);
+ } break;
+ default:
+ return *this;
+ }
+ } else
+ switch (cond) { // generic version
+ case 0: {
+ cimg_mapXY(dest,x,y)
+ cimg_mapZV(*this,z,v)
+ dest(x,y,z,v) = pix2d((int)(cx + (x-cx)*ca + (y-cy)*sa),(int)(cy - (x-cx)*sa + (y-cy)*ca),z,v,0);
+ } break;
+ case 1: {
+ cimg_mapXY(dest,x,y)
+ cimg_mapZV(*this,z,v)
+ dest(x,y,z,v) = (*this)(cimg::mod((int)(cx + (x-cx)*ca + (y-cy)*sa),width),
+ cimg::mod((int)(cy - (x-cx)*sa + (y-cy)*ca),height),z,v);
+ } break;
+ case 2: {
+ cimg_mapXY(dest,x,y) {
+ const float X = cx + (x-cx)*ca + (y-cy)*sa, Y = cy - (x-cx)*sa + (y-cy)*ca;
+ cimg_mapZV(*this,z,v) dest(x,y,z,v) = (T)linear_pix2d(X,Y,z,v,0);
+ }
+ } break;
+ default: {
+ cimg_mapXY(dest,x,y) {
+ const float X = cx + (x-cx)*ca + (y-cy)*sa, Y = cy - (x-cx)*sa + (y-cy)*ca;
+ cimg_mapZV(*this,z,v) dest(x,y,z,v) = (T)cubic_pix2d(X,Y,z,v,0);
+ }
+ } break;
+ }
+ return dest;
+ }
+
+ //! Rotate the image around the point (\c cx,\c cy).
+ /**
+ \param angle = rotation angle (in degrees).
+ \param cx = X-coordinate of the rotation center.
+ \param cy = Y-coordinate of the rotation center.
+ \param zoom = zoom.
+ \param cond = rotation type. can be :
+ - 0 = zero-value at borders
+ - 1 = repeat image at borders
+ - 2 = zero-value at borders and linear interpolation
+ \note Rotation does not change the image size. If you want to get an image with a new size, use get_rotate() instead.
+ \see get_rotate()
+ **/
+ CImg& rotate(const float angle,const float cx,const float cy,const float zoom=1,const unsigned int cond=3) {
+ return get_rotate(angle,cx,cy,zoom,cond).swap(*this);
+ }
+
+ //! Return a resized image.
+ /**
+ \param pdx = Number of columns (new size along the X-axis).
+ \param pdy = Number of rows (new size along the Y-axis).
+ \param pdz = Number of slices (new size along the Z-axis).
+ \param pdv = Number of vector-channels (new size along the V-axis).
+ \param interp = Resizing type :
+ - 0 = no interpolation : additionnal space is filled with 0.
+ - 1 = bloc interpolation (nearest point).
+ - 2 = mosaic : image is repeated if necessary.
+ - 3 = linear interpolation.
+ - 4 = grid interpolation.
+ - 5 = bi-cubic interpolation.
+ \note If pd[x,y,z,v]<0, it corresponds to a percentage of the original size (the default value is -100).
+ **/
+ CImg get_resize(const int pdx=-100,const int pdy=-100,const int pdz=-100,const int pdv=-100,const unsigned int interp=1) const {
+ if (!pdx || !pdy || !pdz || !pdv) return CImg<T>();
+ const unsigned int
+ dx = pdx<0?-pdx*width/100:pdx,
+ dy = pdy<0?-pdy*height/100:pdy,
+ dz = pdz<0?-pdz*depth/100:pdz,
+ dv = pdv<0?-pdv*dim/100:pdv;
+ CImg res(dx?dx:1,dy?dy:1,dz?dz:1,dv?dv:1);
+ if (is_empty()) return res.fill(0);
+ if (width==res.width && height==res.height && depth==res.depth && dim==res.dim) return *this;
+ switch (interp) {
+ case 0: // Zero filling
+ res.fill(0).draw_image(*this,0,0,0,0);
+ break;
+ case 1: { // Nearest-neighbor interpolation
+ unsigned int
+ *const offx = new unsigned int[res.width],
+ *const offy = new unsigned int[res.height+1],
+ *const offz = new unsigned int[res.depth+1],
+ *const offv = new unsigned int[res.dim+1],
+ *poffx, *poffy, *poffz, *poffv;
+ const unsigned int
+ wh = width*height,
+ whd = width*height*depth,
+ rwh = res.width*res.height,
+ rwhd = res.width*res.height*res.depth;
+ float s, curr, old;
+ s = (float)width/res.width;
+ poffx = offx; curr=0; { cimg_mapX(res,x) { old=curr; curr+=s; *(poffx++) = (unsigned int)curr-(unsigned int)old; }}
+ s = (float)height/res.height;
+ poffy = offy; curr=0; { cimg_mapY(res,y) { old=curr; curr+=s; *(poffy++) = width*((unsigned int)curr-(unsigned int)old); }} *poffy=0;
+ s = (float)depth/res.depth;
+ poffz = offz; curr=0; { cimg_mapZ(res,z) { old=curr; curr+=s; *(poffz++) = wh*((unsigned int)curr-(unsigned int)old); }} *poffz=0;
+ s = (float)dim/res.dim;
+ poffv = offv; curr=0; { cimg_mapV(res,v) { old=curr; curr+=s; *(poffv++) = whd*((unsigned int)curr-(unsigned int)old); }} *poffv=0;
+
+ T *ptrd = res.ptr();
+ const T* ptrv = ptr();
+ poffv = offv;
+ for (unsigned int k=0; k<res.dim; ) {
+ const T *ptrz = ptrv;
+ poffz = offz;
+ for (unsigned int z=0; z<res.depth; ) {
+ const T *ptry = ptrz;
+ poffy = offy;
+ for (unsigned int y=0; y<res.height; ) {
+ const T *ptrx = ptry;
+ poffx = offx;
+ cimg_mapX(res,x) { *(ptrd++)=*ptrx; ptrx+=*(poffx++); }
+ y++;
+ unsigned int dy=*(poffy++);
+ for (;!dy && y<res.height; std::memcpy(ptrd, ptrd-res.width, sizeof(T)*res.width), y++, ptrd+=res.width, dy=*(poffy++));
+ ptry+=dy;
+ }
+ z++;
+ unsigned int dz=*(poffz++);
+ for (;!dz && z<res.depth; std::memcpy(ptrd, ptrd-rwh, sizeof(T)*rwh), z++, ptrd+=rwh, dz=*(poffz++));
+ ptrz+=dz;
+ }
+ k++;
+ unsigned int dv=*(poffv++);
+ for (;!dv && k<res.dim; std::memcpy(ptrd, ptrd-rwhd, sizeof(T)*rwhd), k++, ptrd+=rwhd, dv=*(poffv++));
+ ptrv+=dv;
+ }
+ delete[] offx; delete[] offy; delete[] offz;
+ } break;
+ case 2: { // Mosaic filling
+ for (unsigned int k=0; k<res.dim; k+=dim)
+ for (unsigned int z=0; z<res.depth; z+=depth)
+ for (unsigned int y=0; y<res.height; y+=height)
+ for (unsigned int x=0; x<res.width; x+=width) res.draw_image(*this,x,y,z,k);
+ } break;
+ case 3: { // Linear interpolation
+ const bool bx = (res.width<width), by = (res.height<height), bz = (res.depth<depth), bk = (res.dim<dim);
+ const float
+ sx = bx?(width-1.0f)/(res.width+1):(res.width>1?(width-1.0f)/(res.width-1):0),
+ sy = by?(height-1.0f)/(res.height+1):(res.height>1?(height-1.0f)/(res.height-1):0),
+ sz = bz?(depth-1.0f)/(res.depth+1):(res.depth>1?(depth-1.0f)/(res.depth-1):0),
+ sk = bk?(dim-1.0f)/(res.dim+1):(res.dim>1?(dim-1.0f)/(res.dim-1):0),
+ dx = bx?sx:0, dy = by?sy:0, dz = bz?sz:0, dk = bk?sk:0;
+ float cx,cy,cz,ck=dk;
+ cimg_mapV(res,k) { cz = dz;
+ cimg_mapZ(res,z) { cy = dy;
+ cimg_mapY(res,y) { cx = dx;
+ cimg_mapX(res,x) { res(x,y,z,k) = (T)linear_pix4d(cx,cy,cz,ck); cx+=sx;
+ } cy+=sy;
+ } cz+=sz;
+ } ck+=sk;
+ }
+ } break;
+ case 4: { // Grid filling
+ const float sx = (float)width/res.width, sy = (float)height/res.height, sz = (float)depth/res.depth, sk = (float)dim/res.dim;
+ res.fill(0);
+ cimg_mapXYZV(*this,x,y,z,k) res((int)(x/sx),(int)(y/sy),(int)(z/sz),(int)(k/sk)) = (*this)(x,y,z,k);
+ } break;
+ case 5: { // Cubic interpolation
+ const bool bx = (res.width<width), by = (res.height<height), bz = (res.depth<depth), bk = (res.dim<dim);
+ const float
+ sx = bx?(width-1.0f)/(res.width+1):(res.width>1?(width-1.0f)/(res.width-1):0),
+ sy = by?(height-1.0f)/(res.height+1):(res.height>1?(height-1.0f)/(res.height-1):0),
+ sz = bz?(depth-1.0f)/(res.depth+1):(res.depth>1?(depth-1.0f)/(res.depth-1):0),
+ sk = bk?(dim-1.0f)/(res.dim+1):(res.dim>1?(dim-1.0f)/(res.dim-1):0),
+ dx = bx?sx:0, dy = by?sy:0, dz = bz?sz:0, dk = bk?sk:0;
+ float cx,cy,cz,ck=dk;
+ cimg_mapV(res,k) { cz = dz;
+ cimg_mapZ(res,z) { cy = dy;
+ cimg_mapY(res,y) { cx = dx;
+ cimg_mapX(res,x) { res(x,y,z,k) = (T)cubic_pix2d(cx,cy,(int)cz,(int)ck); cx+=sx;
+ } cy+=sy;
+ } cz+=sz;
+ } ck+=sk;
+ }
+ } break;
+ }
+ return res;
+ }
+
+ //! Return a resized image.
+ /**
+ \param src = Image giving the tqgeometry of the resize.
+ \param interp = Resizing type :
+ - 0 = no interpolation : additionnal space is filled with 0.
+ - 1 = bloc interpolation (nearest point).
+ - 2 = mosaic : image is repeated if necessary.
+ - 3 = linear interpolation.
+ - 4 = grid interpolation.
+ - 5 = bi-cubic interpolation.
+ \note If pd[x,y,z,v]<0, it corresponds to a percentage of the original size (the default value is -100).
+ **/
+ template<typename t> CImg get_resize(const CImg<t>& src,const unsigned int interp=1) const {
+ return get_resize(src.width,src.height,src.depth,src.dim,interp);
+ }
+
+ //! Return a resized image.
+ /**
+ \param disp = Display giving the tqgeometry of the resize.
+ \param interp = Resizing type :
+ - 0 = no interpolation : additionnal space is filled with 0.
+ - 1 = bloc interpolation (nearest point).
+ - 2 = mosaic : image is repeated if necessary.
+ - 3 = linear interpolation.
+ - 4 = grid interpolation.
+ - 5 = bi-cubic interpolation.
+ \note If pd[x,y,z,v]<0, it corresponds to a percentage of the original size (the default value is -100).
+ **/
+ CImg get_resize(const CImgDisplay& disp,const unsigned int interp=1) const {
+ return get_resize(disp.width,disp.height,depth,dim,interp);
+ }
+
+ //! Resize the image.
+ /**
+ \param pdx = Number of columns (new size along the X-axis).
+ \param pdy = Number of rows (new size along the Y-axis).
+ \param pdz = Number of slices (new size along the Z-axis).
+ \param pdv = Number of vector-channels (new size along the V-axis).
+ \param interp = Resizing type :
+ - 0 = no interpolation : additionnal space is filled with 0.
+ - 1 = bloc interpolation (nearest point).
+ - 2 = mosaic : image is repeated if necessary.
+ - 3 = linear interpolation.
+ - 4 = grid interpolation.
+ - 5 = bi-cubic interpolation.
+ \note If pd[x,y,z,v]<0, it corresponds to a percentage of the original size (the default value is -100).
+ **/
+ CImg& resize(const int pdx=-100,const int pdy=-100,const int pdz=-100,const int pdv=-100,const unsigned int interp=1) {
+ if (!pdx || !pdy || !pdz || !pdv) return empty();
+ const unsigned int
+ dx = pdx<0?-pdx*width/100:pdx,
+ dy = pdy<0?-pdy*height/100:pdy,
+ dz = pdz<0?-pdz*depth/100:pdz,
+ dv = pdv<0?-pdv*dim/100:pdv;
+ if (width==dx && height==dy && depth==dz && dim==dv) return *this;
+ return get_resize(dx,dy,dz,dv,interp).swap(*this);
+ }
+
+ //! Resize the image.
+ /**
+ \param src = Image giving the tqgeometry of the resize.
+ \param interp = Resizing type :
+ - 0 = no interpolation : additionnal space is filled with 0.
+ - 1 = bloc interpolation (nearest point).
+ - 2 = mosaic : image is repeated if necessary.
+ - 3 = linear interpolation.
+ - 4 = grid interpolation.
+ - 5 = bi-cubic interpolation.
+ \note If pd[x,y,z,v]<0, it corresponds to a percentage of the original size (the default value is -100).
+ **/
+ template<typename t> CImg& resize(const CImg<t>& src,const unsigned int interp=1) {
+ return resize(src.width,src.height,src.depth,src.dim,interp);
+ }
+
+ //! Resize the image
+ /**
+ \param disp = Display giving the tqgeometry of the resize.
+ \param interp = Resizing type :
+ - 0 = no interpolation : additionnal space is filled with 0.
+ - 1 = bloc interpolation (nearest point).
+ - 2 = mosaic : image is repeated if necessary.
+ - 3 = linear interpolation.
+ - 4 = grid interpolation.
+ - 5 = bi-cubic interpolation.
+ \note If pd[x,y,z,v]<0, it corresponds to a percentage of the original size (the default value is -100).
+ **/
+ CImg& resize(const CImgDisplay& disp,const unsigned int interp=1) {
+ return resize(disp.width,disp.height,depth,dim,interp);
+ }
+
+ //! Return an half-resized image, using a special filter.
+ /**
+ \see resize_halfXY(), resize(), get_resize().
+ **/
+ CImg get_resize_halfXY() const {
+ typedef typename cimg::largest<T,float>::type ftype;
+ if (is_empty()) return CImg<T>();
+ CImg<ftype> tqmask = CImg<ftype>::matrix(0.07842776544f, 0.1231940459f, 0.07842776544f,
+ 0.1231940459f, 0.1935127547f, 0.1231940459f,
+ 0.07842776544f, 0.1231940459f, 0.07842776544f);
+ CImg_3x3x1(I,ftype);
+ CImg dest(width/2,height/2,depth,dim);
+ cimg_mapZV(*this,z,k) cimg_map3x3x1(*this,x,y,z,k,I)
+ if (x%2 && y%2) dest(x/2,y/2,z,k) = (T)cimg_conv3x3x1(I,tqmask);
+ return dest;
+ }
+
+ //! Half-resize the image, using a special filter
+ /**
+ \see get_resize_halfXY(), resize(), get_resize().
+ **/
+ CImg& resize_halfXY() {
+ return get_resize_halfXY().swap(*this);
+ }
+
+ //! Return a square region of the image, as a new image
+ /**
+ \param x0 = X-coordinate of the upper-left crop rectangle corner.
+ \param y0 = Y-coordinate of the upper-left crop rectangle corner.
+ \param z0 = Z-coordinate of the upper-left crop rectangle corner.
+ \param v0 = V-coordinate of the upper-left crop rectangle corner.
+ \param x1 = X-coordinate of the lower-right crop rectangle corner.
+ \param y1 = Y-coordinate of the lower-right crop rectangle corner.
+ \param z1 = Z-coordinate of the lower-right crop rectangle corner.
+ \param v1 = V-coordinate of the lower-right crop rectangle corner.
+ \param border_condition = Dirichlet (false) or Neumann border conditions.
+ \see crop()
+ **/
+ CImg get_crop(const unsigned int x0,const unsigned int y0,const unsigned int z0,const unsigned int v0,
+ const unsigned int x1,const unsigned int y1,const unsigned int z1,const unsigned int v1,
+ const bool border_condition = false) const {
+ if (is_empty())
+ throw CImgInstanceException("CImg<%s>::get_crop() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ const unsigned int dx=x1-x0+1, dy=y1-y0+1, dz=z1-z0+1, dv=v1-v0+1;
+ CImg dest(dx,dy,dz,dv);
+ if (x0>=width || x1>=width || y0>=height || y1>=height || z0>=depth || z1>=depth ||
+ v0>=dim || v1>=dim || x1<x0 || y1<y0 || z1<z0 || v1<v0)
+ switch (border_condition) {
+ case false: { cimg_mapXYZV(dest,x,y,z,v) dest(x,y,z,v) = pix4d(x0+x,y0+y,z0+z,v0+v,0); } break;
+ default: { cimg_mapXYZV(dest,x,y,z,v) dest(x,y,z,v) = pix4d(x0+x,y0+y,z0+z,v0+v); } break;
+ } else {
+ const T *psrc = ptr(x0,y0,z0,v0);
+ T *pdest = dest.ptr(0,0,0,0);
+ if (dx!=width)
+ for (unsigned int k=0; k<dv; k++) {
+ for (unsigned int z=0; z<dz; z++) {
+ for (unsigned int y=0; y<dy; y++) {
+ std::memcpy(pdest,psrc,dx*sizeof(T));
+ pdest+=dx;
+ psrc+=width;
+ }
+ psrc+=width*(height-dy);
+ }
+ psrc+=width*height*(depth-dz);
+ }
+ else {
+ if (dy!=height)
+ for (unsigned int k=0; k<dv; k++) {
+ for (unsigned int z=0; z<dz; z++) {
+ std::memcpy(pdest,psrc,dx*dy*sizeof(T));
+ pdest+=dx*dy;
+ psrc+=width*height;
+ }
+ psrc+=width*height*(depth-dz);
+ }
+ else {
+ if (dz!=depth)
+ for (unsigned int k=0; k<dv; k++) {
+ std::memcpy(pdest,psrc,dx*dy*dz*sizeof(T));
+ pdest+=dx*dy*dz;
+ psrc+=width*height*depth;
+ }
+ else std::memcpy(pdest,psrc,dx*dy*dz*dv*sizeof(T));
+ }
+ }
+ }
+ return dest;
+ }
+
+ //! Return a square region of the image, as a new image
+ /**
+ \param x0 = X-coordinate of the upper-left crop rectangle corner.
+ \param y0 = Y-coordinate of the upper-left crop rectangle corner.
+ \param z0 = Z-coordinate of the upper-left crop rectangle corner.
+ \param x1 = X-coordinate of the lower-right crop rectangle corner.
+ \param y1 = Y-coordinate of the lower-right crop rectangle corner.
+ \param z1 = Z-coordinate of the lower-right crop rectangle corner.
+ \param border_condition = determine the type of border condition if
+ some of the desired region is outside the image.
+ \see crop()
+ **/
+ CImg get_crop(const unsigned int x0,const unsigned int y0,const unsigned int z0,
+ const unsigned int x1,const unsigned int y1,const unsigned int z1,
+ const bool border_condition=false) const {
+ return get_crop(x0,y0,z0,0,x1,y1,z1,dim-1,border_condition);
+ }
+
+ //! Return a square region of the image, as a new image
+ /**
+ \param x0 = X-coordinate of the upper-left crop rectangle corner.
+ \param y0 = Y-coordinate of the upper-left crop rectangle corner.
+ \param x1 = X-coordinate of the lower-right crop rectangle corner.
+ \param y1 = Y-coordinate of the lower-right crop rectangle corner.
+ \param border_condition = determine the type of border condition if
+ some of the desired region is outside the image.
+ \see crop()
+ **/
+ CImg get_crop(const unsigned int x0,const unsigned int y0,
+ const unsigned int x1,const unsigned int y1,
+ const bool border_condition=false) const {
+ return get_crop(x0,y0,0,0,x1,y1,depth-1,dim-1,border_condition);
+ }
+
+ //! Return a square region of the image, as a new image
+ /**
+ \param x0 = X-coordinate of the upper-left crop rectangle corner.
+ \param x1 = X-coordinate of the lower-right crop rectangle corner.
+ \param border_condition = determine the type of border condition if
+ some of the desired region is outside the image.
+ \see crop()
+ **/
+ CImg get_crop(const unsigned int x0,const unsigned int x1,const bool border_condition=false) const {
+ return get_crop(x0,0,0,0,x1,height-1,depth-1,dim-1,border_condition);
+ }
+
+ //! Replace the image by a square region of the image
+ /**
+ \param x0 = X-coordinate of the upper-left crop rectangle corner.
+ \param y0 = Y-coordinate of the upper-left crop rectangle corner.
+ \param z0 = Z-coordinate of the upper-left crop rectangle corner.
+ \param v0 = V-coordinate of the upper-left crop rectangle corner.
+ \param x1 = X-coordinate of the lower-right crop rectangle corner.
+ \param y1 = Y-coordinate of the lower-right crop rectangle corner.
+ \param z1 = Z-coordinate of the lower-right crop rectangle corner.
+ \param v1 = V-coordinate of the lower-right crop rectangle corner.
+ \param border_condition = determine the type of border condition if
+ some of the desired region is outside the image.
+ \see get_crop()
+ **/
+ CImg& crop(const unsigned int x0,const unsigned int y0,const unsigned int z0,const unsigned int v0,
+ const unsigned int x1,const unsigned int y1,const unsigned int z1,const unsigned int v1,
+ const bool border_condition=false) {
+ return get_crop(x0,y0,z0,v0,x1,y1,z1,v1,border_condition).swap(*this);
+ }
+
+ //! Replace the image by a square region of the image
+ /**
+ \param x0 = X-coordinate of the upper-left crop rectangle corner.
+ \param y0 = Y-coordinate of the upper-left crop rectangle corner.
+ \param z0 = Z-coordinate of the upper-left crop rectangle corner.
+ \param x1 = X-coordinate of the lower-right crop rectangle corner.
+ \param y1 = Y-coordinate of the lower-right crop rectangle corner.
+ \param z1 = Z-coordinate of the lower-right crop rectangle corner.
+ \param border_condition = determine the type of border condition if
+ some of the desired region is outside the image.
+ \see get_crop()
+ **/
+ CImg& crop(const unsigned int x0,const unsigned int y0,const unsigned int z0,
+ const unsigned int x1,const unsigned int y1,const unsigned int z1,
+ const bool border_condition=false) {
+ return crop(x0,y0,z0,0,x1,y1,z1,dim-1,border_condition);
+ }
+
+ //! Replace the image by a square region of the image
+ /**
+ \param x0 = X-coordinate of the upper-left crop rectangle corner.
+ \param y0 = Y-coordinate of the upper-left crop rectangle corner.
+ \param x1 = X-coordinate of the lower-right crop rectangle corner.
+ \param y1 = Y-coordinate of the lower-right crop rectangle corner.
+ \param border_condition = determine the type of border condition if
+ some of the desired region is outside the image.
+ \see get_crop()
+ **/
+ CImg& crop(const unsigned int x0,const unsigned int y0,
+ const unsigned int x1,const unsigned int y1,
+ const bool border_condition=false) {
+ return crop(x0,y0,0,0,x1,y1,depth-1,dim-1,border_condition);
+ }
+
+ //! Replace the image by a square region of the image
+ /**
+ \param x0 = X-coordinate of the upper-left crop rectangle corner.
+ \param x1 = X-coordinate of the lower-right crop rectangle corner.
+ \param border_condition = determine the type of border condition if
+ some of the desired region is outside the image.
+ \see get_crop()
+ **/
+ CImg& crop(const unsigned int x0,const unsigned int x1,const bool border_condition=false) {
+ return crop(x0,0,0,0,x1,height-1,depth-1,dim-1,border_condition);
+ }
+
+ //! Get a shared-memory image referencing a set of points of the instance image.
+ CImg get_shared_points(const unsigned int x0, const unsigned int x1,
+ const unsigned int y0=0, const unsigned int z0=0, const unsigned int v0=0) {
+ const unsigned long beg = offset(x0,y0,z0,v0), end = offset(x1,y0,z0,v0);
+ if (beg>end || beg>=size() || end>=size())
+ throw CImgArgumentException("CImg<%s>::get_shared_points() : Cannot return a shared-memory subset (%u->%u,%u,%u,%u) from "
+ "a (%u,%u,%u,%u) image.",pixel_type(),x0,x1,y0,z0,v0,width,height,depth,dim);
+ return CImg<T>(data+beg,x1-x0+1,1,1,1,true);
+ }
+
+ //! Get a shared-memory image referencing a set of points of the instance image (const version).
+ const CImg get_shared_points(const unsigned int x0, const unsigned int x1,
+ const unsigned int y0=0, const unsigned int z0=0, const unsigned int v0=0) const {
+ const unsigned long beg = offset(x0,y0,z0,v0), end = offset(x1,y0,z0,v0);
+ if (beg>end || beg>=size() || end>=size())
+ throw CImgArgumentException("CImg<%s>::get_shared_points() : Cannot return a shared-memory subset (%u->%u,%u,%u,%u) from "
+ "a (%u,%u,%u,%u) image.",pixel_type(),x0,x1,y0,z0,v0,width,height,depth,dim);
+ return CImg<T>(data+beg,x1-x0+1,1,1,1,true);
+ }
+
+ //! Get a copy of a set of points of the instance image.
+ CImg get_points(const unsigned int x0, const unsigned int x1,
+ const unsigned int y0=0, const unsigned int z0=0, const unsigned int v0=0) const {
+ const CImg<T> sh = get_shared_points(x0,x1,y0,z0,v0);
+ return CImg<T>(sh.data,sh.width,sh.height,sh.depth,sh.dim);
+ }
+
+ //! Return a shared-memory image referencing a set of lines of the instance image.
+ CImg get_shared_lines(const unsigned int y0, const unsigned int y1,
+ const unsigned int z0=0, const unsigned int v0=0) {
+ const unsigned long beg = offset(0,y0,z0,v0), end = offset(0,y1,z0,v0);
+ if (beg>end || beg>=size() || end>=size())
+ throw CImgArgumentException("CImg<%s>::get_shared_lines() : Cannot return a shared-memory subset (0->%u,%u->%u,%u,%u) from "
+ "a (%u,%u,%u,%u) image.",pixel_type(),width-1,y0,y1,z0,v0,width,height,depth,dim);
+ return CImg<T>(data+beg,width,y1-y0+1,1,1,true);
+ }
+
+ //! Return a shared-memory image referencing a set of lines of the instance image (const version).
+ const CImg get_shared_lines(const unsigned int y0, const unsigned int y1,
+ const unsigned int z0=0, const unsigned int v0=0) const {
+ const unsigned long beg = offset(0,y0,z0,v0), end = offset(0,y1,z0,v0);
+ if (beg>end || beg>=size() || end>=size())
+ throw CImgArgumentException("CImg<%s>::get_shared_lines() : Cannot return a shared-memory subset (0->%u,%u->%u,%u,%u) from "
+ "a (%u,%u,%u,%u) image.",pixel_type(),width-1,y0,y1,z0,v0,width,height,depth,dim);
+ return CImg<T>(data+beg,width,y1-y0+1,1,1,true);
+ }
+
+ //! Get a copy of a set of lines of the instance image.
+ CImg get_lines(const unsigned int y0, const unsigned int y1,
+ const unsigned int z0=0, const unsigned int v0=0) const {
+ const CImg<T> sh = get_shared_lines(y0,y1,z0,v0);
+ return CImg<T>(sh.data,sh.width,sh.height,sh.depth,sh.dim);
+ }
+
+ //! Replace the instance image by a set of lines of the instance image.
+ CImg& lines(const unsigned int y0, const unsigned int y1,
+ const unsigned int z0=0, const unsigned int v0=0) const {
+ return get_lines(y0,y1,z0,v0).swap(*this);
+ }
+
+ //! Return a shared-memory image referencing one particular line (y0,z0,v0) of the instance image.
+ CImg get_shared_line(const unsigned int y0, const unsigned int z0=0, const unsigned int v0=0) {
+ return get_shared_lines(y0,y0,z0,v0);
+ }
+
+ //! Return a shared-memory image referencing one particular line (y0,z0,v0) of the instance image (const version).
+ const CImg get_shared_line(const unsigned int y0,const unsigned int z0=0,const unsigned int v0=0) const {
+ return get_shared_lines(y0,y0,z0,v0);
+ }
+
+ //! Get a copy of a line of the instance image.
+ CImg get_line(const unsigned int y0,
+ const unsigned int z0=0, const unsigned int v0=0) const {
+ return get_lines(y0,y0,z0,v0);
+ }
+
+ //! Replace the instance image by one of its line.
+ CImg& line(const unsigned int y0, const unsigned int z0=0, const unsigned int v0=0) {
+ return get_line(y0,z0,v0).swap(*this);
+ }
+
+ //! Return a shared memory image referencing a set of planes (z0->z1,v0) of the instance image.
+ CImg get_shared_planes(const unsigned int z0, const unsigned int z1, const unsigned int v0=0) {
+ const unsigned long beg = offset(0,0,z0,v0), end = offset(0,0,z1,v0);
+ if (beg>end || beg>=size() || end>=size())
+ throw CImgArgumentException("CImg<%s>::get_shared_planes() : Cannot return a shared-memory subset (0->%u,0->%u,%u->%u,%u) from "
+ "a (%u,%u,%u,%u) image.",pixel_type(),width-1,height-1,z0,z1,v0,width,height,depth,dim);
+ return CImg<T>(data+beg,width,height,z1-z0+1,1,true);
+ }
+
+ //! Return a shared-memory image referencing a set of planes (z0->z1,v0) of the instance image (const version).
+ const CImg get_shared_planes(const unsigned int z0, const unsigned int z1, const unsigned int v0=0) const {
+ const unsigned long beg = offset(0,0,z0,v0), end = offset(0,0,z1,v0);
+ if (beg>end || beg>=size() || end>=size())
+ throw CImgArgumentException("CImg<%s>::get_shared_planes() : Cannot return a shared-memory subset (0->%u,0->%u,%u->%u,%u) from "
+ "a (%u,%u,%u,%u) image.",pixel_type(),width-1,height-1,z0,z1,v0,width,height,depth,dim);
+ return CImg<T>(data+beg,width,height,z1-z0+1,1,true);
+ }
+
+ //! Return a copy of a set of planes of the instance image.
+ CImg get_planes(const unsigned int z0, const unsigned int z1, const unsigned int v0=0) const {
+ CImg<T> sh = get_shared_planes(z0,z1,v0);
+ return CImg<T>(sh.data,sh.width,sh.height,sh.depth,sh.dim);
+ }
+
+ //! Replace the instance image by a set of planes of the instance image.
+ CImg& planes(const unsigned int z0, const unsigned int z1, const unsigned int v0=0) {
+ return get_planes(z0,z1,v0).swap(*this);
+ }
+
+ //! Return a shared-memory image referencing one plane (z0,v0) of the instance image.
+ CImg get_shared_plane(const unsigned int z0, const unsigned int v0=0) {
+ return get_shared_planes(z0,z0,v0);
+ }
+
+ //! Return a shared-memory image referencing one plane (z0,v0) of the instance image (const version).
+ const CImg get_shared_plane(const unsigned int z0, const unsigned int v0=0) const {
+ return get_shared_planes(z0,z0,v0);
+ }
+
+ //! Return a copy of a plane of the instance image.
+ CImg get_plane(const unsigned int z0, const unsigned int v0=0) const {
+ return get_planes(z0,z0,v0);
+ }
+
+ //! Replace the instance image by one plane of the instance image.
+ CImg& plane(const unsigned int z0, const unsigned int v0=0) {
+ return get_plane(z0,v0).swap(*this);
+ }
+
+ //! Return a shared-memory image referencing a set of channels (v0->v1) of the instance image.
+ CImg get_shared_channels(const unsigned int v0, const unsigned int v1) {
+ const unsigned long beg = offset(0,0,0,v0), end = offset(0,0,0,v1);
+ if (beg>end || beg>=size() || end>=size())
+ throw CImgArgumentException("CImg<%s>::get_shared_channels() : Cannot return a shared-memory subset (0->%u,0->%u,0->%u,%u->%u) from "
+ "a (%u,%u,%u,%u) image.",pixel_type(),width-1,height-1,depth-1,v0,v1,width,height,depth,dim);
+ return CImg<T>(data+beg,width,height,depth,v1-v0+1,true);
+ }
+
+ //! Return a shared-memory image referencing a set of channels (v0->v1) of the instance image (const version).
+ const CImg get_shared_channels(const unsigned int v0, const unsigned int v1) const {
+ const unsigned long beg = offset(0,0,0,v0), end = offset(0,0,0,v1);
+ if (beg>end || beg>=size() || end>=size())
+ throw CImgArgumentException("CImg<%s>::get_shared_channels() : Cannot return a shared-memory subset (0->%u,0->%u,0->%u,%u->%u) from "
+ "a (%u,%u,%u,%u) image.",pixel_type(),width-1,height-1,depth-1,v0,v1,width,height,depth,dim);
+ return CImg<T>(data+beg,width,height,depth,v1-v0+1,true);
+ }
+
+ //! Return a copy of a set of channels of the instance image.
+ CImg get_channels(const unsigned int v0, const unsigned int v1) const {
+ CImg<T> sh = get_shared_channels(v0,v1);
+ return CImg<T>(sh.data,sh.width,sh.height,sh.depth,sh.dim);
+ }
+
+ //! Replace the instance image by a set of channels of the instance image.
+ CImg& channels(const unsigned int v0, const unsigned int v1) {
+ return get_channels(v0,v1).swap(*this);
+ }
+
+ //! Return a shared-memory image referencing one channel v0 of the instance image.
+ CImg get_shared_channel(const unsigned int v0) {
+ return get_shared_channels(v0,v0);
+ }
+
+ //! Return a shared-memory image referencing one channel v0 of the instance image (const version).
+ const CImg get_shared_channel(const unsigned int v0) const {
+ return get_shared_channels(v0,v0);
+ }
+
+ //! Return a copy of a channel of the instance image.
+ CImg get_channel(const unsigned int v0) const {
+ return get_channels(v0,v0);
+ }
+
+ //! Replace the instance image by one of its channel.
+ CImg& channel(const unsigned int v0) {
+ return get_channel(v0).swap(*this);
+ }
+
+ //! Return a shared version of the instance image.
+ CImg get_shared() {
+ return CImg<T>(data,width,height,depth,dim,true);
+ }
+
+ //! Return a shared version of the instance image (const version).
+ const CImg get_shared() const {
+ return CImg<T>(data,width,height,depth,dim,true);
+ }
+
+ //! Get the z-slice \a z of *this, as a new image.
+ /**
+ \param z0 = Z-slice to return.
+ \see slice(), get_channel(), channel(), get_plane(), plane().
+ **/
+ CImg get_slice(const unsigned int z0=0) const {
+ return get_crop(0,0,z0,0,width-1,height-1,z0,dim-1);
+ }
+
+ //! Replace the image by one of its slice.
+ CImg& slice(const unsigned int z0) { return get_slice(z0).swap(*this); }
+
+ //! Mirror an image along the specified axis.
+ /**
+ This is the in-place version of get_mirror().
+ \sa get_mirror().
+ **/
+ CImg& mirror(const char axe='x') {
+ if (!is_empty()) {
+ T *pf,*pb,*buf=NULL;
+ switch (cimg::uncase(axe)) {
+ case 'x': {
+ pf = ptr(); pb = ptr(width-1);
+ for (unsigned int yzv=0; yzv<height*depth*dim; yzv++) {
+ for (unsigned int x=0; x<width/2; x++) { const T val = *pf; *(pf++)=*pb; *(pb--)=val; }
+ pf+=width-width/2;
+ pb+=width+width/2;
+ }
+ } break;
+ case 'y': {
+ buf = new T[width];
+ pf = ptr(); pb = ptr(0,height-1);
+ for (unsigned int zv=0; zv<depth*dim; zv++) {
+ for (unsigned int y=0; y<height/2; y++) {
+ std::memcpy(buf,pf,width*sizeof(T));
+ std::memcpy(pf,pb,width*sizeof(T));
+ std::memcpy(pb,buf,width*sizeof(T));
+ pf+=width;
+ pb-=width;
+ }
+ pf+=width*(height-height/2);
+ pb+=width*(height+height/2);
+ }
+ } break;
+ case 'z': {
+ buf = new T[width*height];
+ pf = ptr(); pb = ptr(0,0,depth-1);
+ cimg_mapV(*this,v) {
+ for (unsigned int z=0; z<depth/2; z++) {
+ std::memcpy(buf,pf,width*height*sizeof(T));
+ std::memcpy(pf,pb,width*height*sizeof(T));
+ std::memcpy(pb,buf,width*height*sizeof(T));
+ pf+=width*height;
+ pb-=width*height;
+ }
+ pf+=width*height*(depth-depth/2);
+ pb+=width*height*(depth+depth/2);
+ }
+ } break;
+ case 'v': {
+ buf = new T[width*height*depth];
+ pf = ptr(); pb = ptr(0,0,0,dim-1);
+ for (unsigned int v=0; v<dim/2; v++) {
+ std::memcpy(buf,pf,width*height*depth*sizeof(T));
+ std::memcpy(pf,pb,width*height*depth*sizeof(T));
+ std::memcpy(pb,buf,width*height*depth*sizeof(T));
+ pf+=width*height*depth;
+ pb-=width*height*depth;
+ }
+ } break;
+ default:
+ throw CImgArgumentException("CImg<%s>::mirror() : unknow axe '%c', must be 'x','y','z' or 'v'",pixel_type(),axe);
+ }
+ if (buf) delete[] buf;
+ }
+ return *this;
+ }
+
+ //! Get a mirrored version of the image, along the specified axis.
+ /**
+ \param axe Axe used to mirror the image. Can be \c 'x', \c 'y', \c 'z' or \c 'v'.
+ \sa mirror().
+ **/
+ CImg get_mirror(const char axe='x') {
+ return CImg<T>(*this).mirror(axe);
+ }
+
+ //! Scroll the image
+ /**
+ This is the in-place version of get_scroll().
+ \sa get_scroll().
+ **/
+ CImg& scroll(const int scrollx,const int scrolly=0,const int scrollz=0,const int scrollv=0,const int border_condition=0) {
+ if (!is_empty()) {
+
+ if (scrollx) // Scroll along X-axis
+ switch (border_condition) {
+ case 0:
+ if (cimg::abs(scrollx)>=(int)width) return fill(0);
+ if (scrollx>0) cimg_mapYZV(*this,y,z,k) {
+ std::memmove(ptr(0,y,z,k),ptr(scrollx,y,z,k),(width-scrollx)*sizeof(T));
+ std::memset(ptr(width-scrollx,y,z,k),0,scrollx*sizeof(T));
+ } else cimg_mapYZV(*this,y,z,k) {
+ std::memmove(ptr(-scrollx,y,z,k),ptr(0,y,z,k),(width+scrollx)*sizeof(T));
+ std::memset(ptr(0,y,z,k),0,-scrollx*sizeof(T));
+ }
+ break;
+ case 1:
+ if (scrollx>0) {
+ const int nscrollx = (scrollx>=(int)width)?width-1:scrollx;
+ if (!nscrollx) return *this;
+ cimg_mapYZV(*this,y,z,k) {
+ std::memmove(ptr(0,y,z,k),ptr(nscrollx,y,z,k),(width-nscrollx)*sizeof(T));
+ T *ptrd = ptr(width-1,y,z,k);
+ const T &val = *ptrd;
+ for (int l=0; l<nscrollx-1; l++) *(--ptrd) = val;
+ }
+ } else {
+ const int nscrollx = (-scrollx>=(int)width)?width-1:-scrollx;
+ if (!nscrollx) return *this;
+ cimg_mapYZV(*this,y,z,k) {
+ std::memmove(ptr(nscrollx,y,z,k),ptr(0,y,z,k),(width-nscrollx)*sizeof(T));
+ T *ptrd = ptr(0,y,z,k);
+ const T &val = *ptrd;
+ for (int l=0; l<nscrollx-1; l++) *(++ptrd) = val;
+ }
+ }
+ break;
+ case 2: {
+ const int ml = cimg::mod(scrollx,width), nscrollx = (ml<=(int)width/2)?ml:(ml-(int)width);
+ if (!nscrollx) return *this;
+ T* buf = new T[cimg::abs(nscrollx)];
+ if (nscrollx>0) cimg_mapYZV(*this,y,z,k) {
+ std::memcpy(buf,ptr(0,y,z,k),nscrollx*sizeof(T));
+ std::memmove(ptr(0,y,z,k),ptr(nscrollx,y,z,k),(width-nscrollx)*sizeof(T));
+ std::memcpy(ptr(width-nscrollx,y,z,k),buf,nscrollx*sizeof(T));
+ } else cimg_mapYZV(*this,y,z,k) {
+ std::memcpy(buf,ptr(width+nscrollx,y,z,k),-nscrollx*sizeof(T));
+ std::memmove(ptr(-nscrollx,y,z,k),ptr(0,y,z,k),(width+nscrollx)*sizeof(T));
+ std::memcpy(ptr(0,y,z,k),buf,-nscrollx*sizeof(T));
+ }
+ delete[] buf;
+ } break;
+ }
+
+ if (scrolly) // Scroll along Y-axis
+ switch (border_condition) {
+ case 0:
+ if (cimg::abs(scrolly)>=(int)height) return fill(0);
+ if (scrolly>0) cimg_mapZV(*this,z,k) {
+ std::memmove(ptr(0,0,z,k),ptr(0,scrolly,z,k),width*(height-scrolly)*sizeof(T));
+ std::memset(ptr(0,height-scrolly,z,k),0,width*scrolly*sizeof(T));
+ } else cimg_mapZV(*this,z,k) {
+ std::memmove(ptr(0,-scrolly,z,k),ptr(0,0,z,k),width*(height+scrolly)*sizeof(T));
+ std::memset(ptr(0,0,z,k),0,-scrolly*width*sizeof(T));
+ }
+ break;
+ case 1:
+ if (scrolly>0) {
+ const int nscrolly = (scrolly>=(int)height)?height-1:scrolly;
+ if (!nscrolly) return *this;
+ cimg_mapZV(*this,z,k) {
+ std::memmove(ptr(0,0,z,k),ptr(0,nscrolly,z,k),width*(height-nscrolly)*sizeof(T));
+ T *ptrd = ptr(0,height-nscrolly,z,k), *ptrs = ptr(0,height-1,z,k);
+ for (int l=0; l<nscrolly-1; l++) { std::memcpy(ptrd,ptrs,width*sizeof(T)); ptrd+=width; }
+ }
+ } else {
+ const int nscrolly = (-scrolly>=(int)height)?height-1:-scrolly;
+ if (!nscrolly) return *this;
+ cimg_mapZV(*this,z,k) {
+ std::memmove(ptr(0,nscrolly,z,k),ptr(0,0,z,k),width*(height-nscrolly)*sizeof(T));
+ T *ptrd = ptr(0,1,z,k), *ptrs = ptr(0,0,z,k);
+ for (int l=0; l<nscrolly-1; l++) { std::memcpy(ptrd,ptrs,width*sizeof(T)); ptrd+=width; }
+ }
+ }
+ break;
+ case 2: {
+ const int ml = cimg::mod(scrolly,height), nscrolly = (ml<=(int)height/2)?ml:(ml-(int)height);
+ if (!nscrolly) return *this;
+ T* buf = new T[width*cimg::abs(nscrolly)];
+ if (nscrolly>0) cimg_mapZV(*this,z,k) {
+ std::memcpy(buf,ptr(0,0,z,k),width*nscrolly*sizeof(T));
+ std::memmove(ptr(0,0,z,k),ptr(0,nscrolly,z,k),width*(height-nscrolly)*sizeof(T));
+ std::memcpy(ptr(0,height-nscrolly,z,k),buf,width*nscrolly*sizeof(T));
+ } else cimg_mapZV(*this,z,k) {
+ std::memcpy(buf,ptr(0,height+nscrolly,z,k),-nscrolly*width*sizeof(T));
+ std::memmove(ptr(0,-nscrolly,z,k),ptr(0,0,z,k),width*(height+nscrolly)*sizeof(T));
+ std::memcpy(ptr(0,0,z,k),buf,-nscrolly*width*sizeof(T));
+ }
+ delete[] buf;
+ } break;
+ }
+
+ if (scrollz) // Scroll along Z-axis
+ switch (border_condition) {
+ case 0:
+ if (cimg::abs(scrollz)>=(int)depth) return fill(0);
+ if (scrollz>0) cimg_mapV(*this,k) {
+ std::memmove(ptr(0,0,0,k),ptr(0,0,scrollz,k),width*height*(depth-scrollz)*sizeof(T));
+ std::memset(ptr(0,0,depth-scrollz,k),0,width*height*scrollz*sizeof(T));
+ } else cimg_mapV(*this,k) {
+ std::memmove(ptr(0,0,-scrollz,k),ptr(0,0,0,k),width*height*(depth+scrollz)*sizeof(T));
+ std::memset(ptr(0,0,0,k),0,-scrollz*width*height*sizeof(T));
+ }
+ break;
+ case 1:
+ if (scrollz>0) {
+ const int nscrollz = (scrollz>=(int)depth)?depth-1:scrollz;
+ if (!nscrollz) return *this;
+ cimg_mapV(*this,k) {
+ std::memmove(ptr(0,0,0,k),ptr(0,0,nscrollz,k),width*height*(depth-nscrollz)*sizeof(T));
+ T *ptrd = ptr(0,0,depth-nscrollz,k), *ptrs = ptr(0,0,depth-1,k);
+ for (int l=0; l<nscrollz-1; l++) { std::memcpy(ptrd,ptrs,width*height*sizeof(T)); ptrd+=width*height; }
+ }
+ } else {
+ const int nscrollz = (-scrollz>=(int)depth)?depth-1:-scrollz;
+ if (!nscrollz) return *this;
+ cimg_mapV(*this,k) {
+ std::memmove(ptr(0,0,nscrollz,k),ptr(0,0,0,k),width*height*(depth-nscrollz)*sizeof(T));
+ T *ptrd = ptr(0,0,1,k), *ptrs = ptr(0,0,0,k);
+ for (int l=0; l<nscrollz-1; l++) { std::memcpy(ptrd,ptrs,width*height*sizeof(T)); ptrd+=width*height; }
+ }
+ }
+ break;
+ case 2: {
+ const int ml = cimg::mod(scrollz,depth), nscrollz = (ml<=(int)depth/2)?ml:(ml-(int)depth);
+ if (!nscrollz) return *this;
+ T* buf = new T[width*height*cimg::abs(nscrollz)];
+ if (nscrollz>0) cimg_mapV(*this,k) {
+ std::memcpy(buf,ptr(0,0,0,k),width*height*nscrollz*sizeof(T));
+ std::memmove(ptr(0,0,0,k),ptr(0,0,nscrollz,k),width*height*(depth-nscrollz)*sizeof(T));
+ std::memcpy(ptr(0,0,depth-nscrollz,k),buf,width*height*nscrollz*sizeof(T));
+ } else cimg_mapV(*this,k) {
+ std::memcpy(buf,ptr(0,0,depth+nscrollz,k),-nscrollz*width*height*sizeof(T));
+ std::memmove(ptr(0,0,-nscrollz,k),ptr(0,0,0,k),width*height*(depth+nscrollz)*sizeof(T));
+ std::memcpy(ptr(0,0,0,k),buf,-nscrollz*width*height*sizeof(T));
+ }
+ delete[] buf;
+ } break;
+ }
+
+ if (scrollv) // Scroll along V-axis
+ switch (border_condition) {
+ case 0:
+ if (cimg::abs(scrollv)>=(int)dim) return fill(0);
+ if (scrollv>0) {
+ std::memmove(data,ptr(0,0,0,scrollv),width*height*depth*(dim-scrollv)*sizeof(T));
+ std::memset(ptr(0,0,0,dim-scrollv),0,width*height*depth*scrollv*sizeof(T));
+ } else cimg_mapV(*this,k) {
+ std::memmove(ptr(0,0,0,-scrollv),data,width*height*depth*(dim+scrollv)*sizeof(T));
+ std::memset(data,0,-scrollv*width*height*depth*sizeof(T));
+ }
+ break;
+ case 1:
+ if (scrollv>0) {
+ const int nscrollv = (scrollv>=(int)dim)?dim-1:scrollv;
+ if (!nscrollv) return *this;
+ std::memmove(data,ptr(0,0,0,nscrollv),width*height*depth*(dim-nscrollv)*sizeof(T));
+ T *ptrd = ptr(0,0,0,dim-nscrollv), *ptrs = ptr(0,0,0,dim-1);
+ for (int l=0; l<nscrollv-1; l++) { std::memcpy(ptrd,ptrs,width*height*depth*sizeof(T)); ptrd+=width*height*depth; }
+ } else {
+ const int nscrollv = (-scrollv>=(int)dim)?dim-1:-scrollv;
+ if (!nscrollv) return *this;
+ std::memmove(ptr(0,0,0,nscrollv),data,width*height*depth*(dim-nscrollv)*sizeof(T));
+ T *ptrd = ptr(0,0,0,1);
+ for (int l=0; l<nscrollv-1; l++) { std::memcpy(ptrd,data,width*height*depth*sizeof(T)); ptrd+=width*height*depth; }
+ }
+ break;
+ case 2: {
+ const int ml = cimg::mod(scrollv,dim), nscrollv = (ml<=(int)dim/2)?ml:(ml-(int)dim);
+ if (!nscrollv) return *this;
+ T* buf = new T[width*height*depth*cimg::abs(nscrollv)];
+ if (nscrollv>0) {
+ std::memcpy(buf,data,width*height*depth*nscrollv*sizeof(T));
+ std::memmove(data,ptr(0,0,0,nscrollv),width*height*depth*(dim-nscrollv)*sizeof(T));
+ std::memcpy(ptr(0,0,0,dim-nscrollv),buf,width*height*depth*nscrollv*sizeof(T));
+ } else {
+ std::memcpy(buf,ptr(0,0,0,dim+nscrollv),-nscrollv*width*height*depth*sizeof(T));
+ std::memmove(ptr(0,0,0,-nscrollv),data,width*height*depth*(dim+nscrollv)*sizeof(T));
+ std::memcpy(data,buf,-nscrollv*width*height*depth*sizeof(T));
+ }
+ delete[] buf;
+ } break;
+ }
+ }
+ return *this;
+ }
+
+ //! Return a scrolled image.
+ /**
+ \param scrollx Amount of displacement along the X-axis.
+ \param scrolly Amount of displacement along the Y-axis.
+ \param scrollz Amount of displacement along the Z-axis.
+ \param scrollv Amount of displacement along the V-axis.
+ \param border_condition Border condition.
+
+ - \c border_condition can be :
+ - 0 : Zero border condition (Dirichlet).
+ - 1 : Nearest neighbors (Neumann).
+ - 2 : Repeat Pattern (Fourier style).
+ **/
+ CImg get_scroll(const int scrollx,const int scrolly=0,const int scrollz=0,const int scrollv=0,
+ const int border_condition=0) const {
+ return CImg<T>(*this).scroll(scrollx,scrolly,scrollz,scrollv,border_condition);
+ }
+
+ //! Return a 2D representation of a 3D image, with three slices.
+ CImg get_projections2d(const unsigned int px0,const unsigned int py0,const unsigned int pz0) const {
+ if (is_empty()) return CImg<T>();
+ const unsigned int
+ x0=(px0>=width)?width-1:px0,
+ y0=(py0>=height)?height-1:py0,
+ z0=(pz0>=depth)?depth-1:pz0;
+ CImg res(width+depth,height+depth,1,dim);
+ res.fill((*this)[0]);
+ { cimg_mapXYV(*this,x,y,k) res(x,y,0,k) = (*this)(x,y,z0,k); }
+ { cimg_mapYZV(*this,y,z,k) res(width+z,y,0,k) = (*this)(x0,y,z,k); }
+ { cimg_mapXZV(*this,x,z,k) res(x,height+z,0,k) = (*this)(x,y0,z,k); }
+ return res;
+ }
+
+ //! Return the image histogram.
+ /**
+ The histogram H of an image I is a 1D-function where H(x) is the number of
+ occurences of the value x in I.
+ \param nblevels = Number of different levels of the computed histogram.
+ For classical images, this value is 256 (default value). You should specify more levels
+ if you are working with CImg<float> or images with high range of pixel values.
+ \param val_min = Minimum value considered for the histogram computation. All pixel values lower than val_min
+ won't be counted.
+ \param val_max = Maximum value considered for the histogram computation. All pixel values higher than val_max
+ won't be counted.
+ \note If val_min==val_max==0 (default values), the function first estimates the minimum and maximum
+ pixel values of the current image, then uses these values for the histogram computation.
+ \result The histogram is returned as a 1D CImg<float> image H, having a size of (nblevels,1,1,1) such that
+ H(0) and H(nblevels-1) are respectively equal to the number of occurences of the values val_min and val_max in I.
+ \note Histogram computation always returns a 1D function. Histogram of multi-valued (such as color) images
+ are not multi-dimensional.
+ \see get_equalize_histogram(), equalize_histogram()
+ **/
+ CImg<float> get_histogram(const unsigned int nblevels=256,const T val_min=(T)0,const T val_max=(T)0) const {
+ if (is_empty()) return CImg<float>();
+ if (nblevels<1)
+ throw CImgArgumentException("CImg<%s>::get_histogram() : Can't compute an histogram with %u levels",
+ pixel_type(),nblevels);
+ T vmin=val_min, vmax=val_max;
+ CImg<float> res(nblevels,1,1,1,0);
+ if (vmin==vmax && vmin==0) { CImgStats st(*this,false); vmin = (T)st.min; vmax = (T)st.max; }
+ cimg_map(*this,ptr,T) {
+ const int pos = (int)((*ptr-vmin)*(nblevels-1)/(vmax-vmin));
+ if (pos>=0 && pos<(int)nblevels) res[pos]++;
+ }
+ return res;
+ }
+
+ //! Equalize the image histogram
+ /** This is the in-place version of \ref get_equalize_histogram() **/
+ CImg& equalize_histogram(const unsigned int nblevels=256,const T val_min=(T)0,const T val_max=(T)0) {
+ if (!is_empty()) {
+ T vmin=val_min, vmax=val_max;
+ if (vmin==vmax && vmin==0) { CImgStats st(*this,false); vmin = (T)st.min; vmax = (T)st.max; }
+ CImg<float> hist = get_histogram(nblevels,vmin,vmax);
+ float cumul=0;
+ cimg_mapX(hist,pos) { cumul+=hist[pos]; hist[pos]=cumul; }
+ cimg_map(*this,ptr,T) {
+ const int pos = (unsigned int)((*ptr-vmin)*(nblevels-1)/(vmax-vmin));
+ if (pos>=0 && pos<(int)nblevels) *ptr = (T)(vmin + (vmax-vmin)*hist[pos]/size());
+ }
+ }
+ return *this;
+ }
+
+ //! Return the histogram-equalized version of the current image.
+ /**
+ The histogram equalization is a classical image processing algorithm that enhances the image contrast
+ by expanding its histogram.
+ \param nblevels = Number of different levels of the computed histogram.
+ For classical images, this value is 256 (default value). You should specify more levels
+ if you are working with CImg<float> or images with high range of pixel values.
+ \param val_min = Minimum value considered for the histogram computation. All pixel values lower than val_min
+ won't be changed.
+ \param val_max = Maximum value considered for the histogram computation. All pixel values higher than val_max
+ won't be changed.
+ \note If val_min==val_max==0 (default values), the function acts on all pixel values of the image.
+ \return A new image with same size is returned, where pixels have been equalized.
+ \see get_histogram(), equalize_histogram()
+ **/
+ CImg get_equalize_histogram(const unsigned int nblevels=256,const T val_min=(T)0,const T val_max=(T)0) const {
+ return CImg<T>(*this).equalize_histogram(nblevels,val_min,val_max);
+ }
+
+ //! Return the scalar image of vector norms.
+ /**
+ When dealing with vector-valued images (i.e images with dimv()>1), this function computes the L1,L2 or Linf norm of each
+ vector-valued pixel.
+ \param norm_type = Type of the norm being computed (1 = L1, 2 = L2, -1 = Linf).
+ \return A scalar-valued image CImg<float> with size (dimx(),dimy(),dimz(),1), where each pixel is the norm
+ of the corresponding pixels in the original vector-valued image.
+ \see get_orientation_pointwise, orientation_pointwise, norm_pointwise.
+ **/
+ CImg<typename cimg::largest<T,float>::type> get_norm_pointwise(int norm_type=2) const {
+ typedef typename cimg::largest<T,float>::type restype;
+ if (is_empty()) return CImg<restype>();
+ CImg<restype> res(width,height,depth);
+ switch(norm_type) {
+ case -1: { // Linf norm
+ cimg_mapXYZ(*this,x,y,z) {
+ restype n=0; cimg_mapV(*this,v) {
+ const restype tmp = (restype)cimg::abs((*this)(x,y,z,v));
+ if (tmp>n) n=tmp; res(x,y,z) = n;
+ }
+ }
+ } break;
+ case 1: { // L1 norm
+ cimg_mapXYZ(*this,x,y,z) {
+ restype n=0; cimg_mapV(*this,v) n+=cimg::abs((*this)(x,y,z,v)); res(x,y,z) = n;
+ }
+ } break;
+ default: { // L2 norm
+ cimg_mapXYZ(*this,x,y,z) {
+ restype n=0; cimg_mapV(*this,v) n+=(*this)(x,y,z,v)*(*this)(x,y,z,v); res(x,y,z) = (restype)std::sqrt((double)n);
+ }
+ } break;
+ }
+ return res;
+ }
+
+ //! Replace each pixel value with its vector norm.
+ /**
+ This is the in-place version of \ref get_norm_pointwise().
+ \note Be careful when using this function on CImg<T> with T=char, unsigned char,unsigned int or int. The vector norm
+ is usually a floating point value, and a rough cast will be done here.
+ **/
+ CImg& norm_pointwise() {
+ return CImg<T>(get_norm_pointwise()).swap(*this);
+ }
+
+ //! Return the image of normalized vectors
+ /**
+ When dealing with vector-valued images (i.e images with dimv()>1), this function return the image of normalized vectors
+ (unit vectors). Null vectors are unchanged. The L2-norm is computed for the normalization.
+ \return A new vector-valued image with same size, where each vector-valued pixels have been normalized.
+ \see get_norm_pointwise, norm_pointwise, orientation_pointwise.
+ **/
+ CImg<typename cimg::largest<T,float>::type> get_orientation_pointwise() const {
+ typedef typename cimg::largest<T,float>::type restype;
+ if (is_empty()) return CImg<restype>();
+ return CImg<restype>(*this).orientation_pointwise();
+ }
+
+ //! Replace each pixel value by its normalized vector
+ /** This is the in-place version of \ref get_orientation_pointwise() **/
+ CImg& orientation_pointwise() {
+ cimg_mapXYZ(*this,x,y,z) {
+ float n = 0.0f;
+ cimg_mapV(*this,v) n+=(float)((*this)(x,y,z,v)*(*this)(x,y,z,v));
+ n = (float)std::sqrt(n);
+ if (n>0) cimg_mapV(*this,v) (*this)(x,y,z,v)=(T)((*this)(x,y,z,v)/n);
+ else cimg_mapV(*this,v) (*this)(x,y,z,v)=0;
+ }
+ return *this;
+ }
+
+ //! Split image into a list CImgl<>.
+ CImgl<T> get_split(const char axe,const unsigned int nb=0) const {
+ if (is_empty()) return CImgl<T>();
+ CImgl<T> res;
+ switch (cimg::uncase(axe)) {
+ case 'x': {
+ if (nb>width)
+ throw CImgArgumentException("CImg<%s>::get_split() : Cannot split instance image (%u,%u,%u,%u,%p) along 'x' into %u images.",
+ pixel_type(),width,height,depth,dim,data,nb);
+ res.assign(nb?nb:width);
+ const unsigned int delta = width/res.size + ((width%res.size)?1:0);
+ unsigned int l,x;
+ for (l=0, x=0; l<res.size-1; l++, x+=delta) res[l] = get_crop(x,0,0,0,x+delta-1,height-1,depth-1,dim-1);
+ res[res.size-1] = get_crop(x,0,0,0,width-1,height-1,depth-1,dim-1);
+ } break;
+ case 'y': {
+ if (nb>height)
+ throw CImgArgumentException("CImg<%s>::get_split() : Cannot split instance image (%u,%u,%u,%u,%p) along 'y' into %u images.",
+ pixel_type(),width,height,depth,dim,data,nb);
+ res.assign(nb?nb:height);
+ const unsigned int delta = height/res.size + ((height%res.size)?1:0);
+ unsigned int l,x;
+ for (l=0, x=0; l<res.size-1; l++, x+=delta) res[l] = get_crop(0,x,0,0,width-1,x+delta-1,depth-1,dim-1);
+ res[res.size-1] = get_crop(0,x,0,0,width-1,height-1,depth-1,dim-1);
+ } break;
+ case 'z': {
+ if (nb>depth)
+ throw CImgArgumentException("CImg<%s>::get_split() : Cannot split instance image (%u,%u,%u,%u,%p) along 'z' into %u images.",
+ pixel_type(),width,height,depth,dim,data,nb);
+ res.assign(nb?nb:depth);
+ const unsigned int delta = depth/res.size + ((depth%res.size)?1:0);
+ unsigned int l,x;
+ for (l=0, x=0; l<res.size-1; l++, x+=delta) res[l] = get_crop(0,0,x,0,width-1,height-1,x+delta-1,dim-1);
+ res[res.size-1] = get_crop(0,0,x,0,width-1,height-1,depth-1,dim-1);
+ } break;
+ case 'v': {
+ if (nb>dim)
+ throw CImgArgumentException("CImg<%s>::get_split() : Cannot split instance image (%u,%u,%u,%u,%p) along 'v' into %u images.",
+ pixel_type(),width,height,depth,dim,data,nb);
+ res.assign(nb?nb:dim);
+ const unsigned int delta = dim/res.size + ((dim%res.size)?1:0);
+ unsigned int l,x;
+ for (l=0, x=0; l<res.size-1; l++, x+=delta) res[l] = get_crop(0,0,0,x,width-1,height-1,depth-1,x+delta-1);
+ res[res.size-1] = get_crop(0,0,0,x,width-1,height-1,depth-1,dim-1);
+ } break;
+ default:
+ throw CImgArgumentException("CImg<%s>::get_split() : Unknow axe '%c', must be 'x','y','z' or 'v'",pixel_type(),axe);
+ break;
+ }
+ return res;
+ }
+
+ //! Append an image to another one
+ CImg get_append(const CImg<T>& img,const char axis='x',const char align='c') const {
+ if (img.is_empty()) return *this;
+ if (is_empty()) return img;
+ CImgl<T> temp(2);
+ temp[0].width = width; temp[0].height = height; temp[0].depth = depth;
+ temp[0].dim = dim; temp[0].data = data;
+ temp[1].width = img.width; temp[1].height = img.height; temp[1].depth = img.depth;
+ temp[1].dim = img.dim; temp[1].data = img.data;
+ const CImg<T> res = temp.get_append(axis,align);
+ temp[0].width = temp[0].height = temp[0].depth = temp[0].dim = 0; temp[0].data = NULL;
+ temp[1].width = temp[1].height = temp[1].depth = temp[1].dim = 0; temp[1].data = NULL;
+ return res;
+ }
+
+ //! Append an image to another one (in-place version)
+ CImg& append(const CImg<T>& img,const char axis='x', const char align='c') {
+ if (img.is_empty()) return *this;
+ if (is_empty()) return (*this=img);
+ return get_append(img,axis,align).swap(*this);
+ }
+
+ //! Append an image to another one (in-place operator<< version)
+ CImg& operator<<(const CImg<T>& img) {
+ return append(img);
+ }
+
+ //! Return a list of images, corresponding to the XY-gradients of an image.
+ /**
+ \param scheme = Numerical scheme used for the gradient computation :
+ - -1 = Backward finite differences
+ - 0 = Centered finite differences
+ - 1 = Forward finite differences
+ - 2 = Using Sobel tqmasks
+ - 3 = Using rotation invariant tqmasks
+ - 4 = Using Deriche recusrsive filter.
+ **/
+ CImgl<typename cimg::largest<T,float>::type> get_gradientXY(const int scheme=0) const {
+ typedef typename cimg::largest<T,float>::type restype;
+ if (is_empty()) return CImgl<restype>(2);
+ CImgl<restype> res(2,width,height,depth,dim);
+ switch(scheme) {
+ case -1: { // backward finite differences
+ CImg_3x3x1(I,restype);
+ cimg_mapZV(*this,z,k) cimg_map3x3x1(*this,x,y,z,k,I) { res[0](x,y,z,k) = Icc-Ipc; res[1](x,y,z,k) = Icc-Icp; }
+ } break;
+ case 1: { // forward finite differences
+ CImg_2x2x1(I,restype);
+ cimg_mapZV(*this,z,k) cimg_map2x2x1(*this,x,y,z,k,I) { res[0](x,y,0,k) = Inc-Icc; res[1](x,y,z,k) = Icn-Icc; }
+ } break;
+ case 2: { // using Sobel tqmask
+ CImg_3x3x1(I,restype);
+ const float a = 1, b = 2;
+ cimg_mapZV(*this,z,k) cimg_map3x3x1(*this,x,y,z,k,I) {
+ res[0](x,y,z,k) = -a*Ipp-b*Ipc-a*Ipn+a*Inp+b*Inc+a*Inn;
+ res[1](x,y,z,k) = -a*Ipp-b*Icp-a*Inp+a*Ipn+b*Icn+a*Inn;
+ }
+ } break;
+ case 3: { // using rotation invariant tqmask
+ CImg_3x3x1(I,restype);
+ const float a = (float)(0.25*(2-std::sqrt(2.0))), b = (float)(0.5f*(std::sqrt(2.0)-1));
+ cimg_mapZV(*this,z,k) cimg_map3x3x1(*this,x,y,z,k,I) {
+ res[0](x,y,z,k) = -a*Ipp-b*Ipc-a*Ipn+a*Inp+b*Inc+a*Inn;
+ res[1](x,y,z,k) = -a*Ipp-b*Icp-a*Inp+a*Ipn+b*Icn+a*Inn;
+ }
+ } break;
+ case 4: { // using Deriche filter with low standard variation
+ res[0] = get_deriche(0,1,'x');
+ res[1] = get_deriche(0,1,'y');
+ } break;
+ default: { // central finite differences
+ CImg_3x3x1(I,restype);
+ cimg_mapZV(*this,z,k) cimg_map3x3x1(*this,x,y,z,k,I) {
+ res[0](x,y,z,k) = 0.5f*(Inc-Ipc);
+ res[1](x,y,z,k) = 0.5f*(Icn-Icp);
+ }
+ } break;
+ }
+ return res;
+ }
+
+ //! Return a list of images, corresponding to the XYZ-gradients of an image.
+ /**
+ \see get_gradientXY().
+ **/
+ CImgl<typename cimg::largest<T,float>::type> get_gradientXYZ(const int scheme=0) const {
+ typedef typename cimg::largest<T,float>::type restype;
+ if (is_empty()) return CImgl<restype>(3);
+ CImgl<restype> res(3,width,height,depth,dim);
+ CImg_3x3x3(I,restype);
+ switch(scheme) {
+ case -1: { // backward finite differences
+ cimg_mapV(*this,k) cimg_map3x3x3(*this,x,y,z,k,I) {
+ res[0](x,y,z,k) = Iccc-Ipcc;
+ res[1](x,y,z,k) = Iccc-Icpc;
+ res[2](x,y,z,k) = Iccc-Iccp;
+ }
+ } break;
+ case 1: { // forward finite differences
+ cimg_mapV(*this,k) cimg_map3x3x3(*this,x,y,z,k,I) {
+ res[0](x,y,z,k) = Incc-Iccc;
+ res[1](x,y,z,k) = Icnc-Iccc;
+ res[2](x,y,z,k) = Iccn-Iccc;
+ }
+ } break;
+ case 4: { // using Deriche filter with low standard variation
+ res[0] = get_deriche(0,1,'x');
+ res[1] = get_deriche(0,1,'y');
+ res[2] = get_deriche(0,1,'z');
+ } break;
+ default: { // central finite differences
+ cimg_mapV(*this,k) cimg_map3x3x3(*this,x,y,z,k,I) {
+ res[0](x,y,z,k) = 0.5f*(Incc-Ipcc);
+ res[1](x,y,z,k) = 0.5f*(Icnc-Icpc);
+ res[2](x,y,z,k) = 0.5f*(Iccn-Iccp);
+ }
+ } break;
+ }
+ return res;
+ }
+
+ struct _marching_cubes_func {
+ const CImg<T>& ref;
+ _marching_cubes_func(const CImg<T>& pref):ref(pref) {}
+ float operator()(const float x, const float y, const float z) const {
+ return (float)ref((int)x,(int)y,(int)z);
+ }
+ };
+
+ //! Get a triangularization of an implicit function defined by the instance image
+ template<typename tp, typename tf>
+ const CImg& marching_cubes(const float isovalue,CImgl<tp>& points, CImgl<tf>& primitives,
+ const bool invert_faces = false) const {
+ if (depth<=1 || dim>1)
+ throw CImgInstanceException("CImg<%s>::marching_cubes() : Instance image (%u,%u,%u,%u,%p) is not a 3D scalar image.",
+ pixel_type(),width,height,depth,dim,data);
+ const _marching_cubes_func func(*this);
+ cimg::marching_cubes(func,isovalue,0.0f,0.0f,0.0f,dimx()-1.0f,dimy()-1.0f,dimz()-1.0f,
+ 1.0f,1.0f,1.0f,points,primitives,invert_faces);
+ return *this;
+ }
+
+ struct _marching_cubes_func_float {
+ const CImg<T>& ref;
+ _marching_cubes_func_float(const CImg<T>& pref):ref(pref) {}
+ float operator()(const float x, const float y, const float z) const {
+ return (float)ref.linear_pix3d(x,y,z);
+ }
+ };
+
+ //! Get a triangularization of an implicit function defined by the instance image
+ /**
+ This version allows to specify the marching cube resolution along x,y and z.
+ **/
+ template<typename tp, typename tf>
+ const CImg& marching_cubes(const float isovalue,
+ const float resx, const float resy, const float resz,
+ CImgl<tp>& points, CImgl<tf>& primitives,
+ const bool invert_faces = false) const {
+ if (depth<=1 || dim>1)
+ throw CImgInstanceException("CImg<%s>::marching_cubes() : Instance image (%u,%u,%u,%u,%p) is not a 3D scalar image.",
+ pixel_type(),width,height,depth,dim,data);
+ const _marching_cubes_func_float func(*this);
+ cimg::marching_cubes(func,isovalue,0.0f,0.0f,0.0f,dimx()-1.0f,dimy()-1.0f,dimz()-1.0f,
+ resx,resy,resz,points,primitives,invert_faces);
+ return *this;
+ }
+
+ struct _marching_squares_func {
+ const CImg<T>& ref;
+ _marching_squares_func(const CImg<T>& pref):ref(pref) {}
+ float operator()(const float x, const float y) const {
+ return (float)ref((int)x,(int)y);
+ }
+ };
+
+ //! Get a vectorization of an implicit function defined by the instance image.
+ template<typename tp, typename tf>
+ const CImg& marching_squares(const float isovalue,CImgl<tp>& points, CImgl<tf>& primitives) const {
+ if (height<=1 || depth>1 || dim>1)
+ throw CImgInstanceException("CImg<%s>::marching_squares() : Instance image (%u,%u,%u,%u,%p) is not a 2D scalar image.",
+ pixel_type(),width,height,depth,dim,data);
+ const _marching_squares_func func(*this);
+ cimg::marching_squares(func,isovalue,0.0f,0.0f,dimx()-1.0f,dimy()-1.0f,1.0f,1.0f,points,primitives);
+ return *this;
+ }
+
+ struct _marching_squares_func_float {
+ const CImg<T>& ref;
+ _marching_squares_func_float(const CImg<T>& pref):ref(pref) {}
+ float operator()(const float x, const float y) const {
+ return (float)ref.linear_pix2d(x,y);
+ }
+ };
+
+ //! Get a vectorization of an implicit function defined by the instance image.
+ /**
+ This version allows to specify the marching squares resolution along x,y, and z.
+ **/
+ template<typename tp, typename tf>
+ const CImg& marching_squares(const float isovalue,
+ const float resx, const float resy,
+ CImgl<tp>& points, CImgl<tf>& primitives) const {
+ if (height<=1 || depth>1 || dim>1)
+ throw CImgInstanceException("CImg<%s>::marching_squares() : Instance image (%u,%u,%u,%u,%p) is not a 2D scalar image.",
+ pixel_type(),width,height,depth,dim,data);
+ const _marching_squares_func_float func(*this);
+ cimg::marching_squares(func,isovalue,0.0f,0.0f,dimx()-1.0f,dimy()-1.0f,resx,resy,points,primitives);
+ return *this;
+ }
+
+ //@}
+ //
+ //
+ //
+ //! \name Color conversion functions
+ //@{
+ //
+ //
+
+ //! Return the default 256 colors palette.
+ /**
+ The default color palette is used by %CImg when displaying images on 256 colors displays.
+ It consists in the quantification of the (R,G,B) color space using 3:3:2 bits for color coding
+ (i.e 8 levels for the Red and Green and 4 levels for the Blue).
+ \return A 256x1x1x3 color image defining the palette entries.
+ **/
+ static CImg<T> get_default_LUT8() {
+ static CImg<T> palette;
+ if (!palette.data) {
+ palette.assign(256,1,1,3);
+ for (unsigned int index=0, r=16; r<256; r+=32)
+ for (unsigned int g=16; g<256; g+=32)
+ for (unsigned int b=32; b<256; b+=64) {
+ palette(index,0) = r;
+ palette(index,1) = g;
+ palette(index++,2) = b;
+ }
+ }
+ return palette;
+ }
+
+ //! Convert color pixels from (R,G,B) to match a specified palette.
+ /**
+ This function return a (R,G,B) image where colored pixels are constrained to match entries
+ of the specified color \c palette.
+ \param palette User-defined palette that will constraint the color conversion.
+ \param dithering Enable/Disable Floyd-Steinberg dithering.
+ \param indexing If \c true, each resulting image pixel is an index to the given color palette.
+ Otherwise, (R,G,B) values of the palette are copied instead.
+ **/
+ template<typename t> CImg<t> get_RGBtoLUT(const CImg<t>& palette, const bool dithering=true,const bool indexing=false) const {
+ if (is_empty()) return CImg<t>();
+ if (dim!=3) throw CImgInstanceException("CImg<%s>::RGBtoLUT() : Input image dimension is dim=%u, "
+ "should be a (R,G,B) image.",pixel_type(),dim);
+ if (palette.data && palette.dim!=3)
+ throw CImgArgumentException("CImg<%s>::RGBtoLUT() : Given palette dimension is dim=%u, "
+ "should be a (R,G,B) palette",pixel_type(),palette.dim);
+ CImg<t> res(width,height,depth,indexing?1:3), pal = palette.data?palette:CImg<t>::get_default_LUT8();
+ float *line1 = new float[3*width], *line2 = new float[3*width], *pline1 = line1, *pline2 = line2;
+ cimg_mapZ(*this,z) {
+ float *ptr=pline2; cimg_mapX(*this,x) { *(ptr++)=(*this)(x,0,z,0); *(ptr++)=(*this)(x,0,z,1); *(ptr++)=(*this)(x,0,z,2); }
+ cimg_mapY(*this,y) {
+ cimg::swap(pline1,pline2);
+ if (y<dimy()-1) {
+ const int ny = y+1;
+ float *ptr=pline2; cimg_mapX(*this,x) { *(ptr++)=(*this)(x,ny,z,0); *(ptr++)=(*this)(x,ny,z,1); *(ptr++)=(*this)(x,ny,z,2); }
+ }
+ float *ptr1=pline1, *ptr2=pline2;
+ cimg_mapX(*this,x) {
+ float R = *(ptr1++), G = *(ptr1++), B = *(ptr1++);
+ R = R<0?0:(R>255?255:R); G = G<0?0:(G>255?255:G); B = B<0?0:(B>255?255:B);
+ int best_index = 0;
+ t Rbest=0,Gbest=0,Bbest=0;
+ if (palette.data) { // find best match in given color palette
+ float min = (float)cimg::infinity;
+ cimg_mapX(palette,off) {
+ const t Rp = palette(off,0), Gp = palette(off,1), Bp = palette(off,2);
+ const float error = (float)((Rp-R)*(Rp-R) + (Gp-G)*(Gp-G) + (Bp-B)*(Bp-B));
+ if (error<min) { min=error; best_index=off; Rbest=Rp; Gbest=Gp; Bbest=Bp; }
+ }
+ } else {
+ Rbest = (t)((unsigned char)R&0xe0); Gbest = (t)((unsigned char)G&0xe0); Bbest = (t)((unsigned char)B&0xc0);
+ best_index = (unsigned char)Rbest | ((unsigned char)Gbest>>3) | ((unsigned char)Bbest>>6);
+ }
+ if (indexing) res(x,y,z) = best_index;
+ else { res(x,y,z,0) = Rbest; res(x,y,z,1) = Gbest; res(x,y,z,2) = Bbest; }
+ if (dithering) { // apply dithering to neighborhood pixels if needed
+ const float dR = (float)(R-Rbest), dG = (float)(G-Gbest), dB = (float)(B-Bbest);
+ if (x<dimx()-1) { *(ptr1++)+= dR*7/16; *(ptr1++)+= dG*7/16; *(ptr1++)+= dB*7/16; ptr1-=3; }
+ if (y<dimy()-1) {
+ *(ptr2++)+= dR*5/16; *(ptr2++)+= dG*5/16; *ptr2+= dB*5/16; ptr2-=2;
+ if (x>0) { *(--ptr2)+= dB*3/16; *(--ptr2)+= dG*3/16; *(--ptr2)+= dR*3/16; ptr2+=3; }
+ if (x<dimx()-1) { ptr2+=3; *(ptr2++)+= dR/16; *(ptr2++)+= dG/16; *ptr2+= dB/16; ptr2-=5; }
+ }
+ }
+ ptr2+=3;
+ }
+ }
+ }
+ delete[] line1; delete[] line2;
+ return res;
+ }
+
+ //! Convert color pixels from (R,G,B) to match the default 256 colors palette.
+ /**
+ Same as get_RGBtoLUT() with the default color palette given by get_default_LUT8().
+ **/
+ CImg<T> get_RGBtoLUT(const bool dithering=true, const bool indexing=false) const {
+ CImg<T> foo;
+ return get_RGBtoLUT(foo,dithering,indexing);
+ }
+
+ //! Convert color pixels from (R,G,B) to match the specified color palette.
+ /** This is the in-place version of get_RGBtoLUT(). **/
+ CImg& RGBtoLUT(const CImg<T>& palette,const bool dithering=true,const bool indexing=false) {
+ return get_RGBtoLUT(palette,dithering,indexing).swap(*this);
+ }
+
+ //! Convert color pixels from (R,G,B) to match the specified color palette.
+ /** This is the in-place version of get_RGBtoLUT(). **/
+ CImg& RGBtoLUT(const bool dithering=true,const bool indexing=false) {
+ CImg<T> foo;
+ return get_RGBtoLUT(foo,dithering,indexing).swap(*this);
+ }
+
+ //! Convert an indexed image to a (R,G,B) image using the specified color palette.
+ template<typename t> CImg<t> get_LUTtoRGB(const CImg<t>& palette) const {
+ if (is_empty()) return CImg<t>();
+ if (dim!=1) throw CImgInstanceException("CImg<%s>::LUTtoRGB() : Input image dimension is dim=%u, "
+ "should be a LUT image",pixel_type(),dim);
+ if (palette.data && palette.dim!=3)
+ throw CImgArgumentException("CImg<%s>::LUTtoRGB() : Given palette dimension is dim=%u, "
+ "should be a (R,G,B) palette",pixel_type(),palette.dim);
+ CImg<t> res(width,height,depth,3);
+ CImg<t> pal = palette.data?palette:get_default_LUT8();
+ cimg_mapXYZ(*this,x,y,z) {
+ const unsigned int index = (unsigned int)(*this)(x,y,z);
+ res(x,y,z,0) = pal(index,0);
+ res(x,y,z,1) = pal(index,1);
+ res(x,y,z,2) = pal(index,2);
+ }
+ return res;
+ }
+
+ //! Convert an indexed image (with the default palette) to a (R,G,B) image.
+ CImg<T> get_LUTtoRGB() const {
+ CImg<T> foo;
+ return get_LUTtoRGB(foo);
+ }
+
+ //! In-place version of get_LUTtoRGB().
+ CImg& LUTtoRGB(const CImg<T>& palette) {
+ return get_LUTtoRGB(palette).swap(*this);
+ }
+
+ //! In-place version of get_LUTroRGB().
+ CImg& LUTtoRGB() {
+ CImg<T> foo;
+ return get_LUTtoRGB(foo).swap(*this);
+ }
+
+ //! Convert color pixels from (R,G,B) to (H,S,V).
+ CImg& RGBtoHSV() {
+ if (!is_empty()) {
+ if (dim!=3) throw CImgInstanceException("CImg<%s>::RGBtoHSV() : Input image dimension is dim=%u, "
+ "should be a (R,G,B) image.",pixel_type(),dim);
+ cimg_mapXYZ(*this,x,y,z) {
+ const float
+ R = (float)((*this)(x,y,z,0)/255.0f),
+ G = (float)((*this)(x,y,z,1)/255.0f),
+ B = (float)((*this)(x,y,z,2)/255.0f);
+ const float m = cimg::min(R,G,B), v = cimg::max(R,G,B);
+ float h,s;
+ if (v==m) { h=-1; s=0; } else {
+ const float
+ f = (R==m)?(G-B):((G==m)?(B-R):(R-G)),
+ i = (R==m)?3.0f:((G==m)?5.0f:1.0f);
+ h = (i-f/(v-m));
+ s = (v-m)/v;
+ if (h>=6.0f) h-=6.0f;
+ h*=(float)cimg::PI/3.0f;
+ }
+ (*this)(x,y,z,0) = (T)h;
+ (*this)(x,y,z,1) = (T)s;
+ (*this)(x,y,z,2) = (T)v;
+ }
+ }
+ return *this;
+ }
+
+ //! Convert color pixels from (H,S,V) to (R,G,B).
+ CImg& HSVtoRGB() {
+ if (!is_empty()) {
+ if (dim!=3) throw CImgInstanceException("CImg<%s>::HSVtoRGB() : Input image dimension is dim=%u, "
+ "should be a (H,S,V) image",pixel_type(),dim);
+ cimg_mapXYZ(*this,x,y,z) {
+ float
+ H = (float)((*this)(x,y,z,0)),
+ S = (float)((*this)(x,y,z,1)),
+ V = (float)((*this)(x,y,z,2));
+ float R=0,G=0,B=0;
+ if (H<0) R=G=B=V;
+ else {
+ H/=(float)cimg::PI/3.0f;
+ const int i = (int)std::floor(H);
+ const float
+ f = (i&1)?(H-i):(1.0f-H+i),
+ m = V*(1.0f-S),
+ n = V*(1.0f-S*f);
+ switch(i) {
+ case 6:
+ case 0: R=V; G=n; B=m; break;
+ case 1: R=n; G=V; B=m; break;
+ case 2: R=m; G=V; B=n; break;
+ case 3: R=m; G=n; B=V; break;
+ case 4: R=n; G=m; B=V; break;
+ case 5: R=V; G=m; B=n; break;
+ }
+ }
+ (*this)(x,y,z,0) = (T)(R*255.0f);
+ (*this)(x,y,z,1) = (T)(G*255.0f);
+ (*this)(x,y,z,2) = (T)(B*255.0f);
+ }
+ }
+ return *this;
+ }
+
+ //! Convert color pixels from (R,G,B) to (Y,Cb,Cr)_8 (Thanks to Chen Wang).
+ CImg& RGBtoYCbCr() {
+ if (!is_empty()) {
+ if (dim!=3) throw CImgInstanceException("CImg<%s>::RGBtoYCbCr() : Input image dimension is dim=%u, "
+ "should be a (R,G,B) image (dim=3)",pixel_type(),dim);
+ cimg_mapXYZ(*this,x,y,z) {
+ const int
+ R = (int)((*this)(x,y,z,0)),
+ G = (int)((*this)(x,y,z,1)),
+ B = (int)((*this)(x,y,z,2));
+ const int
+ Y = ((66*R+129*G+25*B+128)>>8) + 16,
+ Cb = ((-38*R-74*G+112*B+128)>>8) + 128,
+ Cr = ((112*R-94*G-18*B+128)>>8) + 128;
+ (*this)(x,y,z,0) = (T)(Y<0?0:(Y>255?255:Y));
+ (*this)(x,y,z,1) = (T)(Cb<0?0:(Cb>255?255:Cb));
+ (*this)(x,y,z,2) = (T)(Cr<0?0:(Cr>255?255:Cr));
+ }
+ }
+ return *this;
+ }
+
+ //! Convert color pixels from (Y,Cb,Cr)_8 to (R,G,B).
+ CImg& YCbCrtoRGB() {
+ if (!is_empty()) {
+ if (dim!=3) throw CImgInstanceException("CImg<%s>::YCbCrtoRGB() : Input image dimension is dim=%u, "
+ "should be a (Y,Cb,Cr)_8 image (dim=3)",pixel_type(),dim);
+ cimg_mapXYZ(*this,x,y,z) {
+ const int
+ Y = (int)((*this)(x, y, z, 0)-16),
+ Cb = (int)((*this)(x, y, z, 1)-128),
+ Cr = (int)((*this)(x, y, z, 2)-128);
+ const int
+ R = ((298*Y + 409*Cr + 128) >> 8 ),
+ G = ((298*Y - 100*Cb - 208*Cr + 128) >> 8 ),
+ B = ((298*Y + 516*Cb + 128) >> 8 );
+ (*this)(x,y,z,0) = (T)(R<0?0:(R>255?255:R));
+ (*this)(x,y,z,1) = (T)(G<0?0:(G>255?255:G));
+ (*this)(x,y,z,2) = (T)(B<0?0:(B>255?255:B));
+ }
+ }
+ return *this;
+ }
+
+ //! Convert color pixels from (R,G,B) to (Y,U,V).
+ CImg& RGBtoYUV() {
+ if (!is_empty()) {
+ if (dim!=3) throw CImgInstanceException("CImg<%s>::RGBtoYUV() : Input image dimension is dim=%u, "
+ "should be a (R,G,B) image (dim=3)",pixel_type(),dim);
+ cimg_mapXYZ(*this,x,y,z) {
+ const float
+ R = (*this)(x,y,z,0)/255.0f,
+ G = (*this)(x,y,z,1)/255.0f,
+ B = (*this)(x,y,z,2)/255.0f,
+ Y = (T)(0.299*R + 0.587*G + 0.114*B);
+ (*this)(x,y,z,0) = Y;
+ (*this)(x,y,z,1) = (T)(0.492*(B-Y));
+ (*this)(x,y,z,2) = (T)(0.877*(R-Y));
+ }
+ }
+ return *this;
+ }
+
+ //! Convert color pixels from (Y,U,V) to (R,G,B).
+ CImg& YUVtoRGB() {
+ if (!is_empty()) {
+ if (dim!=3) throw CImgInstanceException("CImg<%s>::YUVtoRGB() : Input image dimension is dim=%u, "
+ "should be a (Y,U,V) image (dim=3)",pixel_type(),dim);
+ cimg_mapXYZ(*this,x,y,z) {
+ const T Y = (*this)(x,y,z,0), U = (*this)(x,y,z,1), V = (*this)(x,y,z,2);
+ (*this)(x,y,z,0) = (T)((Y + 1.140*V)*255.0f);
+ (*this)(x,y,z,1) = (T)((Y - 0.395*U - 0.581*V)*255.0f);
+ (*this)(x,y,z,2) = (T)((Y + 2.032*U)*255.0f);
+ }
+ }
+ return *this;
+ }
+
+ //! Convert color pixels from (R,G,B) to (X,Y,Z)_709.
+ CImg& RGBtoXYZ() {
+ if (!is_empty()) {
+ if (dim!=3) throw CImgInstanceException("CImg<%s>::RGBtoXYZ() : Input image dimension is dim=%u, "
+ "should be a (R,G,B) image (dim=3)",pixel_type(),dim);
+ cimg_mapXYZ(*this,x,y,z) {
+ const float
+ R = (float)((*this)(x,y,z,0)/255.0f),
+ G = (float)((*this)(x,y,z,1)/255.0f),
+ B = (float)((*this)(x,y,z,2)/255.0f);
+ (*this)(x,y,z,0) = (T)(0.412453*R + 0.357580*G + 0.180423*B);
+ (*this)(x,y,z,1) = (T)(0.212671*R + 0.715160*G + 0.072169*B);
+ (*this)(x,y,z,2) = (T)(0.019334*R + 0.119193*G + 0.950227*B);
+ }
+ }
+ return *this;
+ }
+
+ //! Convert (X,Y,Z)_709 pixels of a color image into the (R,G,B) color space.
+ CImg& XYZtoRGB() {
+ if (!is_empty()) {
+ if (dim!=3) throw CImgInstanceException("CImg<%s>::XYZtoRGB() : Input image dimension is dim=%u, "
+ "should be a (X,Y,Z) image (dim=3)",pixel_type(),dim);
+ cimg_mapXYZ(*this,x,y,z) {
+ const float
+ X = (float)(255.0f*(*this)(x,y,z,0)),
+ Y = (float)(255.0f*(*this)(x,y,z,1)),
+ Z = (float)(255.0f*(*this)(x,y,z,2));
+ (*this)(x,y,z,0) = (T)(3.240479*X - 1.537150*Y - 0.498535*Z);
+ (*this)(x,y,z,1) = (T)(-0.969256*X + 1.875992*Y + 0.041556*Z);
+ (*this)(x,y,z,2) = (T)(0.055648*X - 0.204043*Y + 1.057311*Z);
+ }
+ }
+ return *this;
+ }
+
+ //! Convert (X,Y,Z)_709 pixels of a color image into the (L*,a*,b*) color space.
+#define cimg_Labf(x) ((x)>=0.008856?(std::pow(x,1/3.0)):(7.787*(x)+16.0/116.0))
+#define cimg_Labfi(x) ((x)>=0.206893?((x)*(x)*(x)):(((x)-16.0/116.0)/7.787))
+
+ CImg& XYZtoLab() {
+ if (!is_empty()) {
+ if (dim!=3) throw CImgInstanceException("CImg<%s>::XYZtoLab() : Input image dimension is dim=%u, "
+ "should be a (X,Y,Z) image (dim=3)",pixel_type(),dim);
+ const double
+ Xn = 0.412453 + 0.357580 + 0.180423,
+ Yn = 0.212671 + 0.715160 + 0.072169,
+ Zn = 0.019334 + 0.119193 + 0.950227;
+ cimg_mapXYZ(*this,x,y,z) {
+ const T X = (*this)(x,y,z,0), Y = (*this)(x,y,z,1), Z = (*this)(x,y,z,2);
+ const double
+ XXn = X/Xn, YYn = Y/Yn, ZZn = Z/Zn,
+ fX = cimg_Labf(XXn), fY = cimg_Labf(YYn), fZ = cimg_Labf(ZZn);
+ (*this)(x,y,z,0) = (T)(116*fY-16);
+ (*this)(x,y,z,1) = (T)(500*(fX-fY));
+ (*this)(x,y,z,2) = (T)(200*(fY-fZ));
+ }
+ }
+ return *this;
+ }
+
+ //! Convert (L,a,b) pixels of a color image into the (X,Y,Z) color space.
+ CImg& LabtoXYZ() {
+ if (!is_empty()) {
+ if (dim!=3) throw CImgInstanceException("CImg<%s>::LabtoXYZ() : Input image dimension is dim=%u, "
+ "should be a (X,Y,Z) image (dim=3)",pixel_type(),dim);
+ const double
+ Xn = 0.412453 + 0.357580 + 0.180423,
+ Yn = 0.212671 + 0.715160 + 0.072169,
+ Zn = 0.019334 + 0.119193 + 0.950227;
+ cimg_mapXYZ(*this,x,y,z) {
+ const T L = (*this)(x,y,z,0), a = (*this)(x,y,z,1), b = (*this)(x,y,z,2);
+ const double
+ cY = (L+16)/116.0,
+ Y = Yn*cimg_Labfi(cY),
+ pY = std::pow(Y/Yn,1.0/3),
+ cX = a/500+pY,
+ X = Xn*cX*cX*cX,
+ cZ = pY-b/200,
+ Z = Zn*cZ*cZ*cZ;
+ (*this)(x,y,z,0) = (T)(X);
+ (*this)(x,y,z,1) = (T)(Y);
+ (*this)(x,y,z,2) = (T)(Z);
+ }
+ }
+ return *this;
+ }
+
+ //! Convert (X,Y,Z)_709 pixels of a color image into the (x,y,Y) color space.
+ CImg& XYZtoxyY() {
+ if (!is_empty()) {
+ if (dim!=3) throw CImgInstanceException("CImg<%s>::XYZtoxyY() : Input image dimension is dim=%u, "
+ "should be a (X,Y,Z) image (dim=3)",pixel_type(),dim);
+ cimg_mapXYZ(*this,x,y,z) {
+ const T X = (*this)(x,y,z,0), Y = (*this)(x,y,z,1), Z = (*this)(x,y,z,2), sum = (X+Y+Z), nsum = sum>0?sum:1;
+ (*this)(x,y,z,0) = X/nsum;
+ (*this)(x,y,z,1) = Y/nsum;
+ (*this)(x,y,z,2) = Y;
+ }
+ }
+ return *this;
+ }
+
+ //! Convert (x,y,Y) pixels of a color image into the (X,Y,Z)_709 color space.
+ CImg& xyYtoXYZ() {
+ if (!is_empty()) {
+ if (dim!=3) throw CImgInstanceException("CImg<%s>::xyYtoXYZ() : Input image dimension is dim=%u, "
+ "should be a (x,y,Y) image (dim=3)",pixel_type(),dim);
+ cimg_mapXYZ(*this,x,y,z) {
+ const T px = (*this)(x,y,z,0), py = (*this)(x,y,z,1), Y = (*this)(x,y,z,2), ny = py>0?py:1;
+ (*this)(x,y,z,0) = (T)(px*Y/ny);
+ (*this)(x,y,z,1) = Y;
+ (*this)(x,y,z,2) = (T)((1-px-py)*Y/ny);
+ }
+ }
+ return *this;
+ }
+
+ //! In-place version of get_RGBtoLab().
+ CImg& RGBtoLab() { return RGBtoXYZ().XYZtoLab(); }
+
+ //! In-place version of get_LabtoRGb().
+ CImg& LabtoRGB() { return LabtoXYZ().XYZtoRGB(); }
+
+ //! In-place version of get_RGBtoxyY().
+ CImg& RGBtoxyY() { return RGBtoXYZ().XYZtoxyY(); }
+
+ //! In-place version of get_xyYtoRGB().
+ CImg& xyYtoRGB() { return xyYtoXYZ().XYZtoRGB(); }
+
+ //! Convert a (R,G,B) image to a (H,S,V) one.
+ CImg get_RGBtoHSV() const { return CImg<T>(*this).RGBtoHSV(); }
+
+ //! Convert a (H,S,V) image to a (R,G,B) one.
+ CImg get_HSVtoRGB() const { return CImg<T>(*this).HSVtoRGB(); }
+
+ //! Convert a (R,G,B) image to a (Y,Cb,Cr) one.
+ CImg get_RGBtoYCbCr() const { return CImg<T>(*this).RGBtoYCbCr(); }
+
+ //! Convert a (Y,Cb,Cr) image to a (R,G,B) one.
+ CImg get_YCbCrtoRGB() const { return CImg<T>(*this).YCbCrtoRGB(); }
+
+ //! Convert a (R,G,B) image into a (Y,U,V) one.
+ CImg<typename cimg::largest<T,float>::type> get_RGBtoYUV() const {
+ typedef typename cimg::largest<T,float>::type restype;
+ return CImg<restype>(*this).RGBtoYUV();
+ }
+
+ //! Convert a (Y,U,V) image into a (R,G,B) one.
+ CImg get_YUVtoRGB() const { return CImg<T>(*this).YUVtoRGB(); }
+
+ //! Convert a (R,G,B) image to a (X,Y,Z) one.
+ CImg<typename cimg::largest<T,float>::type> get_RGBtoXYZ() const {
+ typedef typename cimg::largest<T,float>::type restype;
+ return CImg<restype>(*this).RGBtoXYZ();
+ }
+
+ //! Convert a (X,Y,Z) image to a (R,G,B) one.
+ CImg get_XYZtoRGB() const { return CImg<T>(*this).XYZtoRGB(); }
+
+ //! Convert a (X,Y,Z) image to a (L,a,b) one.
+ CImg get_XYZtoLab() const { return CImg<T>(*this).XYZtoLab(); }
+
+ //! Convert a (L,a,b) image to a (X,Y,Z) one.
+ CImg get_LabtoXYZ() const { return CImg<T>(*this).LabtoXYZ(); }
+
+ //! Convert a (X,Y,Z) image to a (x,y,Y) one.
+ CImg get_XYZtoxyY() const { return CImg<T>(*this).XYZtoxyY(); }
+
+ //! Convert a (x,y,Y) image to a (X,Y,Z) one.
+ CImg get_xyYtoXYZ() const { return CImg<T>(*this).xyYtoXYZ(); }
+
+ //! Convert a (R,G,B) image to a (L,a,b) one.
+ CImg get_RGBtoLab() const { return CImg<T>(*this).RGBtoLab(); }
+
+ //! Convert a (L,a,b) image to a (R,G,B) one.
+ CImg get_LabtoRGB() const { return CImg<T>(*this).LabtoRGB(); }
+
+ //! Convert a (R,G,B) image to a (x,y,Y) one.
+ CImg get_RGBtoxyY() const { return CImg<T>(*this).RGBtoxyY(); }
+
+ //! Convert a (x,y,Y) image to a (R,G,B) one.
+ CImg get_xyYtoRGB() const { return CImg<T>(*this).xyYtoRGB(); }
+
+ //@}
+ //
+ //
+ //
+ //! \name Drawing functions
+ //@{
+ //
+ //
+
+ // Should be used only by member functions. Not an user-friendly function.
+ // Pre-requisites : x0<x1, y-coordinate is valid, col is valid.
+ CImg& draw_scanline(const int x0,const int x1,const int y,const T *const color,
+ const float opacity=1, const float brightness=1, const bool init=false) {
+ static float nopacity=0, copacity=0;
+ static unsigned int whz=0;
+ static const T* col = NULL;
+ if (init) {
+ nopacity = cimg::abs(opacity);
+ copacity = 1-cimg::max(opacity,0.0f);
+ whz = width*height*depth;
+ col = color;
+ } else {
+ const int nx0 = cimg::max(x0,0), nx1 = cimg::min(x1,(int)width-1), dx = nx1-nx0;
+ T *ptrd = ptr(0,y) + nx0; // avoid problems when cimg_debug=2
+ if (dx>=0) {
+ if (opacity>=1) {
+ int off = whz-dx-1;
+ if (sizeof(T)!=1) cimg_mapV(*this,k) {
+ const T val = (T)(*(col++)*brightness);
+ for (int x=dx; x>=0; x--) *(ptrd++)=val;
+ ptrd+=off;
+ } else cimg_mapV(*this,k) { std::memset(ptrd,(int)(*(col++)*brightness),dx+1); ptrd+=whz; }
+ col-=dim;
+ } else {
+ int off = whz-dx-1;
+ cimg_mapV(*this,k) {
+ const T val = (T)(*(col++)*brightness);
+ for (int x=dx; x>=0; x--) { *ptrd = (T)(val*nopacity + *ptrd*copacity); ptrd++; }
+ ptrd+=off;
+ }
+ col-=dim;
+ }
+ }
+ }
+ return *this;
+ }
+
+ CImg& draw_scanline(const T *const color,const float opacity=1) { return draw_scanline(0,0,0,color,opacity,1.0f,true); }
+
+ //! Draw a colored point in the instance image, at coordinates (\c x0,\c y0,\c z0).
+ /**
+ \param x0 = X-coordinate of the vector-valued pixel to plot.
+ \param y0 = Y-coordinate of the vector-valued pixel to plot.
+ \param z0 = Z-coordinate of the vector-valued pixel to plot.
+ \param color = array of dimv() values of type \c T, defining the drawing color.
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported.
+ **/
+ CImg& draw_point(const int x0,const int y0,const int z0,
+ const T *const color,const float opacity=1) {
+ if (!is_empty()) {
+ if (!color) throw CImgArgumentException("CImg<%s>::draw_point() : Specified color is (null)",pixel_type());
+ if (x0>=0 && y0>=0 && z0>=0 && x0<dimx() && y0<dimy() && z0<dimz()) {
+ const T *col=color;
+ const unsigned int whz = width*height*depth;
+ const float nopacity = cimg::abs(opacity), copacity = 1-cimg::max(opacity,0.0f);
+ T *ptrd = ptr(x0,y0,z0,0);
+ if (opacity>=1) cimg_mapV(*this,k) { *ptrd = *(col++); ptrd+=whz; }
+ else cimg_mapV(*this,k) { *ptrd=(T)(*(col++)*nopacity + *ptrd*copacity); ptrd+=whz; }
+ }
+ }
+ return *this;
+ }
+
+ //! Draw a colored point in the instance image, at coordinates (\c x0,\c y0).
+ /**
+ \param x0 = X-coordinate of the vector-valued pixel to plot.
+ \param y0 = Y-coordinate of the vector-valued pixel to plot.
+ \param color = array of dimv() values of type \c T, defining the drawing color.
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported.
+ **/
+ CImg& draw_point(const int x0,const int y0,const T *const color,const float opacity=1) {
+ return draw_point(x0,y0,0,color,opacity);
+ }
+
+ //! Draw a 2D colored line in the instance image, at coordinates (\c x0,\c y0)-(\c x1,\c y1).
+ /**
+ \param x0 = X-coordinate of the starting point of the line.
+ \param y0 = Y-coordinate of the starting point of the line.
+ \param x1 = X-coordinate of the ending point of the line.
+ \param y1 = Y-coordinate of the ending point of the line.
+ \param color = array of dimv() values of type \c T, defining the drawing color.
+ \param pattern = An integer whose bits describes the line pattern.
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported.
+ **/
+ CImg& draw_line(const int x0,const int y0,const int x1,const int y1,
+ const T *const color,const unsigned int pattern=~0L,const float opacity=1) {
+ if (!is_empty()) {
+ if (!color) throw CImgArgumentException("CImg<%s>::draw_line() : Specified color is (null)",pixel_type());
+ const T* col=color;
+ unsigned int hatch=1;
+ int nx0=x0, nx1=x1, ny0=y0, ny1=y1;
+ if (nx0>nx1) cimg::swap(nx0,nx1,ny0,ny1);
+ if (nx1<0 || nx0>=dimx()) return *this;
+ if (nx0<0) { ny0-=nx0*(ny1-ny0)/(nx1-nx0); nx0=0; }
+ if (nx1>=dimx()) { ny1+=(nx1-dimx())*(ny0-ny1)/(nx1-nx0); nx1=dimx()-1;}
+ if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1);
+ if (ny1<0 || ny0>=dimy()) return *this;
+ if (ny0<0) { nx0-=ny0*(nx1-nx0)/(ny1-ny0); ny0=0; }
+ if (ny1>=dimy()) { nx1+=(ny1-dimy())*(nx0-nx1)/(ny1-ny0); ny1=dimy()-1;}
+ const unsigned int dmax = (unsigned int)cimg::max(cimg::abs(nx1-nx0),ny1-ny0), whz = width*height*depth;
+ const float px = dmax?(nx1-nx0)/(float)dmax:0, py = dmax?(ny1-ny0)/(float)dmax:0;
+ float x = (float)nx0, y = (float)ny0;
+ if (opacity>=1) for (unsigned int t=0; t<=dmax; t++) {
+ if (!(~pattern) || (~pattern && pattern&hatch)) {
+ T* ptrd = ptr((unsigned int)x,(unsigned int)y,0,0);
+ cimg_mapV(*this,k) { *ptrd=*(col++); ptrd+=whz; }
+ col-=dim;
+ }
+ x+=px; y+=py; if (pattern) hatch=(hatch<<1)+(hatch>>(sizeof(unsigned int)*8-1));
+ } else {
+ const float nopacity = cimg::abs(opacity), copacity=1-cimg::max(opacity,0.0f);
+ for (unsigned int t=0; t<=dmax; t++) {
+ if (!(~pattern) || (~pattern && pattern&hatch)) {
+ T* ptrd = ptr((unsigned int)x,(unsigned int)y,0,0);
+ cimg_mapV(*this,k) { *ptrd = (T)(*(col++)*nopacity + copacity*(*ptrd)); ptrd+=whz; }
+ col-=dim;
+ }
+ x+=px; y+=py; if (pattern) hatch=(hatch<<1)+(hatch>>(sizeof(unsigned int)*8-1));
+ }
+ }
+ }
+ return *this;
+ }
+
+ //! Draw a 3D colored line in the instance image, at coordinates (\c x0,\c y0,\c z0)-(\c x1,\c y1,\c z1).
+ /**
+ \param x0 = X-coordinate of the starting point of the line.
+ \param y0 = Y-coordinate of the starting point of the line.
+ \param z0 = Z-coordinate of the starting point of the line.
+ \param x1 = X-coordinate of the ending point of the line.
+ \param y1 = Y-coordinate of the ending point of the line.
+ \param z1 = Z-coordinate of the ending point of the line.
+ \param color = array of dimv() values of type \c T, defining the drawing color.
+ \param pattern = An integer whose bits describes the line pattern.
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported.
+ **/
+ CImg& draw_line(const int x0,const int y0,const int z0,const int x1,const int y1,const int z1,
+ const T *const color,const unsigned int pattern=~0L,const float opacity=1) {
+ if (!is_empty()) {
+ if (!color) throw CImgArgumentException("CImg<%s>::draw_line() : Specified color is (null)",pixel_type());
+ const T* col=color;
+ unsigned int hatch=1;
+ int nx0=x0, ny0=y0, nz0=z0, nx1=x1, ny1=y1, nz1=z1;
+ if (nx0>nx1) cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1);
+ if (nx1<0 || nx0>=dimx()) return *this;
+ if (nx0<0) { const int D=nx1-nx0; ny0-=nx0*(ny1-ny0)/D; nz0-=nx0*(nz1-nz0)/D; nx0=0; }
+ if (nx1>=dimx()) { const int d=nx1-dimx(), D=nx1-nx0; ny1+=d*(ny0-ny1)/D; nz1+=d*(nz0-nz1)/D; nx1=dimx()-1;}
+ if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1);
+ if (ny1<0 || ny0>=dimy()) return *this;
+ if (ny0<0) { const int D=ny1-ny0; nx0-=ny0*(nx1-nx0)/D; nz0-=ny0*(nz1-nz0)/D; ny0=0; }
+ if (ny1>=dimy()) { const int d=ny1-dimy(), D=ny1-ny0; nx1+=d*(nx0-nx1)/D; nz1+=d*(nz0-nz1)/D; ny1=dimy()-1;}
+ if (nz0>nz1) cimg::swap(nx0,nx1,ny0,ny1,nz0,nz1);
+ if (nz1<0 || nz0>=dimz()) return *this;
+ if (nz0<0) { const int D=nz1-nz0; nx0-=nz0*(nx1-nx0)/D; ny0-=nz0*(ny1-ny0)/D; nz0=0; }
+ if (nz1>=dimz()) { const int d=nz1-dimz(), D=nz1-nz0; nx1+=d*(nx0-nx1)/D; ny1+=d*(ny0-ny1)/D; nz1=dimz()-1;}
+ const unsigned int dmax = (unsigned int)cimg::max(cimg::abs(nx1-nx0),cimg::abs(ny1-ny0),nz1-nz0), whz = width*height*depth;
+ const float px = dmax?(nx1-nx0)/(float)dmax:0, py = dmax?(ny1-ny0)/(float)dmax:0, pz = dmax?(nz1-nz0)/(float)dmax:0;
+ float x = (float)nx0, y = (float)ny0, z = (float)nz0;
+ if (opacity>=1) for (unsigned int t=0; t<=dmax; t++) {
+ if (!(~pattern) || (~pattern && pattern&hatch)) {
+ T* ptrd = ptr((unsigned int)x,(unsigned int)y,(unsigned int)z,0);
+ cimg_mapV(*this,k) { *ptrd=*(col++); ptrd+=whz; }
+ col-=dim;
+ }
+ x+=px; y+=py; z+=pz; if (pattern) hatch=(hatch<<1)+(hatch>>(sizeof(unsigned int)*8-1));
+ } else {
+ const float nopacity = cimg::abs(opacity), copacity = 1-cimg::max(opacity,0.0f);
+ for (unsigned int t=0; t<=dmax; t++) {
+ if (!(~pattern) || (~pattern && pattern&hatch)) {
+ T* ptrd = ptr((unsigned int)x,(unsigned int)y,(unsigned int)z,0);
+ cimg_mapV(*this,k) { *ptrd = (T)(*(col++)*nopacity + copacity*(*ptrd)); ptrd+=whz; }
+ col-=dim;
+ }
+ x+=px; y+=py; z+=pz; if (pattern) hatch=(hatch<<1)+(hatch>>(sizeof(unsigned int)*8-1));
+ }
+ }
+ }
+ return *this;
+ }
+
+ //! Draw a 2D textured line in the instance image, at coordinates (\c x0,\c y0)-(\c x1,\c y1).
+ /**
+ \param x0 = X-coordinate of the starting point of the line.
+ \param y0 = Y-coordinate of the starting point of the line.
+ \param x1 = X-coordinate of the ending point of the line.
+ \param y1 = Y-coordinate of the ending point of the line.
+ \param texture = a colored texture image used to draw the line color.
+ \param tx0 = X-coordinate of the starting point of the texture.
+ \param ty0 = Y-coordinate of the starting point of the texture.
+ \param tx1 = X-coordinate of the ending point of the texture.
+ \param ty1 = Y-coordinate of the ending point of the texture.
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported, but texture coordinates do not support clipping.
+ **/
+ template<typename t> CImg& draw_line(const int x0,const int y0,const int x1,const int y1,
+ const CImg<t>& texture,
+ const int tx0,const int ty0,const int tx1,const int ty1,
+ const float opacity=1) {
+ if (!is_empty()) {
+ if (texture.is_empty() || texture.dim<dim)
+ throw CImgArgumentException("CImg<%s>::draw_line() : specified texture (%u,%u,%u,%u,%p) has wrong dimensions.",
+ pixel_type(),texture.width,texture.height,texture.depth,texture.dim,texture.data);
+ int nx0=x0, ny0=y0, nx1=x1, ny1=y1, ntx0=tx0, nty0=ty0, ntx1=tx1, nty1=ty1;
+ if (nx0>nx1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1);
+ if (nx1<0 || nx0>=dimx()) return *this;
+ if (nx0<0) { const int D=nx1-nx0; ny0-=nx0*(ny1-ny0)/D; ntx0-=nx0*(ntx1-ntx0)/D; nty0-=nx0*(nty1-nty0)/D; nx0=0; }
+ if (nx1>=dimx()) { const int d=nx1-dimx(),D=nx1-nx0; ny1+=d*(ny0-ny1)/D; ntx1+=d*(ntx0-ntx1)/D; nty1+=d*(nty0-nty1)/D; nx1=dimx()-1; }
+ if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1);
+ if (ny1<0 || ny0>=dimy()) return *this;
+ if (ny0<0) { const int D=ny1-ny0; nx0-=ny0*(nx1-nx0)/D; ntx0-=ny0*(ntx1-ntx0)/D; nty0-=ny0*(nty1-nty0)/D; ny0=0; }
+ if (ny1>=dimy()) { const int d=ny1-dimy(),D=ny1-ny0; nx1+=d*(nx0-nx1)/D; ntx1+=d*(ntx0-ntx1)/D; nty1+=d*(nty0-nty1)/D; ny1=dimy()-1; }
+ const unsigned int dmax = (unsigned int)cimg::max(cimg::abs(nx1-nx0),ny1-ny0),
+ whz = width*height*depth, twhz = texture.width*texture.height*texture.depth;
+ const float px = dmax?(nx1-nx0)/(float)dmax:0, py = dmax?(ny1-ny0)/(float)dmax:0,
+ tpx = dmax?(ntx1-ntx0)/(float)dmax:0, tpy = dmax?(nty1-nty0)/(float)dmax:0;
+ float x = (float)nx0, y = (float)ny0, tx = (float)ntx0, ty = (float)nty0;
+ if (opacity>=1) for (unsigned int tt=0; tt<=dmax; tt++) {
+ T *ptrd = ptr((unsigned int)x,(unsigned int)y,0,0);
+ const t *ptrs = texture.ptr((unsigned int)tx,(unsigned int)ty,0,0);
+ cimg_mapV(*this,k) { *ptrd = (T)(*ptrs); ptrd+=whz; ptrs+=twhz; }
+ x+=px; y+=py; tx+=tpx; ty+=tpy;
+ } else {
+ const float nopacity = cimg::abs(opacity), copacity = 1-cimg::max(opacity,0.0f);
+ for (unsigned int tt=0; tt<=dmax; tt++) {
+ T *ptrd = ptr((unsigned int)x,(unsigned int)y,0,0);
+ const t *ptrs = texture.ptr((unsigned int)tx,(unsigned int)ty,0,0);
+ cimg_mapV(*this,k) { *ptrd = (T)(nopacity*(*ptrs) + copacity*(*ptrd)); ptrd+=whz; ptrs+=twhz; }
+ x+=px; y+=py; tx+=tpx; ty+=tpy;
+ }
+ }
+ }
+ return *this;
+ }
+
+ //! Draw a 2D colored arrow in the instance image, at coordinates (\c x0,\c y0)->(\c x1,\c y1).
+ /**
+ \param x0 = X-coordinate of the starting point of the arrow (tail).
+ \param y0 = Y-coordinate of the starting point of the arrow (tail).
+ \param x1 = X-coordinate of the ending point of the arrow (head).
+ \param y1 = Y-coordinate of the ending point of the arrow (head).
+ \param color = array of dimv() values of type \c T, defining the drawing color.
+ \param angle = aperture angle of the arrow head
+ \param length = length of the arrow head. If <0, described as a percentage of the arrow length.
+ \param pattern = An integer whose bits describes the line pattern.
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported.
+ **/
+ CImg& draw_arrow(const int x0,const int y0,const int x1,const int y1,
+ const T *const color,
+ const float angle=30,const float length=-10,const unsigned int pattern=~0L,const float opacity=1) {
+ if (!is_empty()) {
+ const float u = (float)(x0-x1), v = (float)(y0-y1), sq = u*u+v*v,
+ deg = (float)(angle*cimg::PI/180), ang = (sq>0)?(float)std::atan2(v,u):0.0f,
+ l = (length>=0)?length:-length*(float)std::sqrt(sq)/100;
+ if (sq>0) {
+ const double cl = std::cos(ang-deg), sl = std::sin(ang-deg), cr = std::cos(ang+deg), sr = std::sin(ang+deg);
+ const int
+ xl = x1+(int)(l*cl), yl = y1+(int)(l*sl),
+ xr = x1+(int)(l*cr), yr = y1+(int)(l*sr),
+ xc = x1+(int)((l+1)*(cl+cr))/2, yc = y1+(int)((l+1)*(sl+sr))/2;
+ draw_line(x0,y0,xc,yc,color,pattern,opacity).draw_triangle(x1,y1,xl,yl,xr,yr,color,opacity);
+ } else draw_point(x0,y0,color,opacity);
+ }
+ return *this;
+ }
+
+ //! Draw a sprite image in the instance image, at coordinates (\c x0,\c y0,\c z0,\c v0).
+ /**
+ \param sprite = sprite image.
+ \param x0 = X-coordinate of the sprite position in the instance image.
+ \param y0 = Y-coordinate of the sprite position in the instance image.
+ \param z0 = Z-coordinate of the sprite position in the instance image.
+ \param v0 = V-coordinate of the sprite position in the instance image.
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported.
+ **/
+ template<typename t> CImg& draw_image(const CImg<t>& sprite,
+ const int x0=0,const int y0=0,const int z0=0,const int v0=0,const float opacity=1) {
+ if (!is_empty()) {
+ if (sprite.is_empty())
+ throw CImgArgumentException("CImg<%s>::draw_image() : Specified sprite image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),sprite.width,sprite.height,sprite.depth,sprite.dim,sprite.data);
+ const bool bx=(x0<0), by=(y0<0), bz=(z0<0), bv=(v0<0);
+ const int
+ lX = sprite.dimx() - (x0+sprite.dimx()>dimx()?x0+sprite.dimx()-dimx():0) + (bx?x0:0),
+ lY = sprite.dimy() - (y0+sprite.dimy()>dimy()?y0+sprite.dimy()-dimy():0) + (by?y0:0),
+ lZ = sprite.dimz() - (z0+sprite.dimz()>dimz()?z0+sprite.dimz()-dimz():0) + (bz?z0:0),
+ lV = sprite.dimv() - (v0+sprite.dimv()>dimv()?v0+sprite.dimv()-dimv():0) + (bv?v0:0);
+ const t *ptrs = sprite.ptr()-(bx?x0:0)-(by?y0*sprite.dimx():0)+(bz?z0*sprite.dimx()*sprite.dimy():0)+
+ (bv?v0*sprite.dimx()*sprite.dimy()*sprite.dimz():0);
+ const unsigned int
+ offX = width-lX, soffX = sprite.width-lX,
+ offY = width*(height-lY), soffY = sprite.width*(sprite.height-lY),
+ offZ = width*height*(depth-lZ), soffZ = sprite.width*sprite.height*(sprite.depth-lZ);
+ const float nopacity = cimg::abs(opacity), copacity = 1-cimg::max(opacity,0.0f);
+ T *ptrd = ptr(x0<0?0:x0,y0<0?0:y0,z0<0?0:z0,v0<0?0:v0);
+ if (lX>0 && lY>0 && lZ>0 && lV>0)
+ for (int v=0; v<lV; v++) {
+ for (int z=0; z<lZ; z++) {
+ for (int y=0; y<lY; y++) {
+ if (opacity>=1) for (int x=0; x<lX; x++) *(ptrd++) = (T)(*(ptrs++));
+ else for (int x=0; x<lX; x++) { *ptrd = (T)(nopacity*(*(ptrs++)) + copacity*(*ptrd)); ptrd++; }
+ ptrd+=offX; ptrs+=soffX;
+ }
+ ptrd+=offY; ptrs+=soffY;
+ }
+ ptrd+=offZ; ptrs+=soffZ;
+ }
+ }
+ return *this;
+ }
+
+ // Add template overloading for VC++>=7.1
+#if ( !defined(_MSC_VER) || _MSC_VER>1300 )
+ CImg& draw_image(const CImg<T>& sprite,const int x0=0,const int y0=0,const int z0=0,const int v0=0,const float opacity=1) {
+ if (!is_empty()) {
+ if (sprite.is_empty())
+ throw CImgArgumentException("CImg<%s>::draw_image() : Specified sprite image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),sprite.width,sprite.height,sprite.depth,sprite.dim,sprite.data);
+ if (this==&sprite) return draw_image(CImg<T>(sprite),x0,y0,z0,v0,opacity);
+ const bool bx=(x0<0), by=(y0<0), bz=(z0<0), bv=(v0<0);
+ const int
+ lX = sprite.dimx() - (x0+sprite.dimx()>dimx()?x0+sprite.dimx()-dimx():0) + (bx?x0:0),
+ lY = sprite.dimy() - (y0+sprite.dimy()>dimy()?y0+sprite.dimy()-dimy():0) + (by?y0:0),
+ lZ = sprite.dimz() - (z0+sprite.dimz()>dimz()?z0+sprite.dimz()-dimz():0) + (bz?z0:0),
+ lV = sprite.dimv() - (v0+sprite.dimv()>dimv()?v0+sprite.dimv()-dimv():0) + (bv?v0:0);
+ const T *ptrs = sprite.ptr()-(bx?x0:0)-(by?y0*sprite.dimx():0)+(bz?z0*sprite.dimx()*sprite.dimy():0)+
+ (bv?v0*sprite.dimx()*sprite.dimy()*sprite.dimz():0);
+ const unsigned int
+ offX = width-lX, soffX = sprite.width-lX,
+ offY = width*(height-lY), soffY = sprite.width*(sprite.height-lY),
+ offZ = width*height*(depth-lZ), soffZ = sprite.width*sprite.height*(sprite.depth-lZ),
+ slX = lX*sizeof(T);
+ const float nopacity = cimg::abs(opacity), copacity = 1-cimg::max(opacity,0.0f);
+ T *ptrd = ptr(x0<0?0:x0,y0<0?0:y0,z0<0?0:z0,v0<0?0:v0);
+ if (lX>0 && lY>0 && lZ>0 && lV>0)
+ for (int v=0; v<lV; v++) {
+ for (int z=0; z<lZ; z++) {
+ if (opacity>=1) for (int y=0; y<lY; y++) { std::memcpy(ptrd,ptrs,slX); ptrd+=width; ptrs+=sprite.width; }
+ else for (int y=0; y<lY; y++) {
+ for (int x=0; x<lX; x++) { *ptrd = (T)(nopacity*(*(ptrs++)) + copacity*(*ptrd)); ptrd++; }
+ ptrd+=offX; ptrs+=soffX;
+ }
+ ptrd+=offY; ptrs+=soffY;
+ }
+ ptrd+=offZ; ptrs+=soffZ;
+ }
+ }
+ return *this;
+ }
+#endif
+
+ //! Draw a tqmasked sprite image in the instance image, at coordinates (\c x0,\c y0,\c z0,\c v0).
+ /**
+ \param sprite = sprite image.
+ \param tqmask = tqmask image.
+ \param x0 = X-coordinate of the sprite position in the instance image.
+ \param y0 = Y-coordinate of the sprite position in the instance image.
+ \param z0 = Z-coordinate of the sprite position in the instance image.
+ \param v0 = V-coordinate of the sprite position in the instance image.
+ \param tqmask_valmax = Maximum pixel value of the tqmask image \c tqmask.
+ \param opacity = opacity of the drawing.
+ \note Pixel values of \c tqmask set the opacity of the corresponding pixels in \c sprite.
+ \note Clipping is supported.
+ \note Dimensions along x,y and z of \c sprite and \c tqmask must be the same.
+ **/
+ template<typename ti,typename tm> CImg& draw_image(const CImg<ti>& sprite,const CImg<tm>& tqmask,
+ const int x0=0,const int y0=0,const int z0=0,const int v0=0,
+ const tm tqmask_valmax=1,const float opacity=1) {
+ if (!is_empty()) {
+ if (sprite.is_empty())
+ throw CImgArgumentException("CImg<%s>::draw_image() : Specified sprite image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),sprite.width,sprite.height,sprite.depth,sprite.dim,sprite.data);
+ if (tqmask.is_empty())
+ throw CImgArgumentException("CImg<%s>::draw_image() : Specified tqmask image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),tqmask.width,tqmask.height,tqmask.depth,tqmask.dim,tqmask.data);
+ if ((void*)this==(void*)&sprite) return draw_image(CImg<T>(sprite),tqmask,x0,y0,z0,v0);
+ if(tqmask.width!=sprite.width || tqmask.height!=sprite.height || tqmask.depth!=sprite.depth)
+ throw CImgArgumentException("CImg<%s>::draw_image() : Mask dimension is (%u,%u,%u,%u), while sprite is (%u,%u,%u,%u)",
+ pixel_type(),tqmask.width,tqmask.height,tqmask.depth,tqmask.dim,sprite.width,sprite.height,sprite.depth,sprite.dim);
+ const bool bx=(x0<0), by=(y0<0), bz=(z0<0), bv=(v0<0);
+ const int
+ lX = sprite.dimx() - (x0+sprite.dimx()>dimx()?x0+sprite.dimx()-dimx():0) + (bx?x0:0),
+ lY = sprite.dimy() - (y0+sprite.dimy()>dimy()?y0+sprite.dimy()-dimy():0) + (by?y0:0),
+ lZ = sprite.dimz() - (z0+sprite.dimz()>dimz()?z0+sprite.dimz()-dimz():0) + (bz?z0:0),
+ lV = sprite.dimv() - (v0+sprite.dimv()>dimv()?v0+sprite.dimv()-dimv():0) + (bv?v0:0);
+ const int coff = -(bx?x0:0)-(by?y0*tqmask.dimx():0)-(bz?z0*tqmask.dimx()*tqmask.dimy():0)-
+ (bv?v0*tqmask.dimx()*tqmask.dimy()*tqmask.dimz():0),
+ ssize = tqmask.dimx()*tqmask.dimy()*tqmask.dimz();
+ const ti *ptrs = sprite.ptr() + coff;
+ const tm *ptrm = tqmask.ptr() + coff;
+ const unsigned int
+ offX = width-lX, soffX = sprite.width-lX,
+ offY = width*(height-lY), soffY = sprite.width*(sprite.height-lY),
+ offZ = width*height*(depth-lZ), soffZ = sprite.width*sprite.height*(sprite.depth-lZ);
+ T *ptrd = ptr(x0<0?0:x0,y0<0?0:y0,z0<0?0:z0,v0<0?0:v0);
+ if (lX>0 && lY>0 && lZ>0 && lV>0)
+ for (int v=0; v<lV; v++) {
+ ptrm = tqmask.data + (ptrm - tqmask.data)%ssize;
+ for (int z=0; z<lZ; z++) {
+ for (int y=0; y<lY; y++) {
+ for (int x=0; x<lX; x++) {
+ const float mopacity = *(ptrm++)*opacity,
+ nopacity = cimg::abs(mopacity), copacity = tqmask_valmax-cimg::max(mopacity,0.0f);
+ *ptrd = (T)((nopacity*(*(ptrs++))+copacity*(*ptrd))/tqmask_valmax);
+ ptrd++;
+ }
+ ptrd+=offX; ptrs+=soffX; ptrm+=soffX;
+ }
+ ptrd+=offY; ptrs+=soffY; ptrm+=soffY;
+ }
+ ptrd+=offZ; ptrs+=soffZ; ptrm+=soffZ;
+ }
+ }
+ return *this;
+ }
+
+ //! Draw a 4D filled rectangle in the instance image, at coordinates (\c x0,\c y0,\c z0,\c v0)-(\c x1,\c y1,\c z1,\c v1).
+ /**
+ \param x0 = X-coordinate of the upper-left rectangle corner in the instance image.
+ \param y0 = Y-coordinate of the upper-left rectangle corner in the instance image.
+ \param z0 = Z-coordinate of the upper-left rectangle corner in the instance image.
+ \param v0 = V-coordinate of the upper-left rectangle corner in the instance image.
+ \param x1 = X-coordinate of the lower-right rectangle corner in the instance image.
+ \param y1 = Y-coordinate of the lower-right rectangle corner in the instance image.
+ \param z1 = Z-coordinate of the lower-right rectangle corner in the instance image.
+ \param v1 = V-coordinate of the lower-right rectangle corner in the instance image.
+ \param val = scalar value used to fill the rectangle area.
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported.
+ **/
+ CImg& draw_rectangle(const int x0,const int y0,const int z0,const int v0,
+ const int x1,const int y1,const int z1,const int v1,
+ const T& val,const float opacity=1.0f) {
+ if (!is_empty()) {
+ const bool bx=(x0<x1), by=(y0<y1), bz=(z0<z1), bv=(v0<v1);
+ const int nx0=bx?x0:x1, nx1=bx?x1:x0, ny0=by?y0:y1, ny1=by?y1:y0, nz0=bz?z0:z1, nz1=bz?z1:z0, nv0=bv?v0:v1, nv1=bv?v1:v0;
+ const int
+ lX = (1+nx1-nx0) + (nx1>=dimx()?dimx()-1-nx1:0) + (nx0<0?nx0:0),
+ lY = (1+ny1-ny0) + (ny1>=dimy()?dimy()-1-ny1:0) + (ny0<0?ny0:0),
+ lZ = (1+nz1-nz0) + (nz1>=dimz()?dimz()-1-nz1:0) + (nz0<0?nz0:0),
+ lV = (1+nv1-nv0) + (nv1>=dimv()?dimv()-1-nv1:0) + (nv0<0?nv0:0);
+ const unsigned int offX = width-lX, offY = width*(height-lY), offZ = width*height*(depth-lZ);
+ const float nopacity = cimg::abs(opacity), copacity = 1-cimg::max(opacity,0.0f);
+ T *ptrd = ptr(nx0<0?0:nx0,ny0<0?0:ny0,nz0<0?0:nz0,nv0<0?0:nv0);
+ if (lX>0 && lY>0 && lZ>0 && lV>0)
+ for (int v=0; v<lV; v++) {
+ for (int z=0; z<lZ; z++) {
+ for (int y=0; y<lY; y++) {
+ if (opacity>=1) {
+ if (sizeof(T)!=1) { for (int x=0; x<lX; x++) *(ptrd++) = val; ptrd+=offX; }
+ else { std::memset(ptrd,(int)val,lX); ptrd+=width; }
+ } else { for (int x=0; x<lX; x++) { *ptrd = (T)(nopacity*val+copacity*(*ptrd)); ptrd++; } ptrd+=offX; }
+ }
+ ptrd+=offY;
+ }
+ ptrd+=offZ;
+ }
+ }
+ return *this;
+ }
+
+ //! Draw a 3D filled colored rectangle in the instance image, at coordinates (\c x0,\c y0,\c z0)-(\c x1,\c y1,\c z1).
+ /**
+ \param x0 = X-coordinate of the upper-left rectangle corner in the instance image.
+ \param y0 = Y-coordinate of the upper-left rectangle corner in the instance image.
+ \param z0 = Z-coordinate of the upper-left rectangle corner in the instance image.
+ \param x1 = X-coordinate of the lower-right rectangle corner in the instance image.
+ \param y1 = Y-coordinate of the lower-right rectangle corner in the instance image.
+ \param z1 = Z-coordinate of the lower-right rectangle corner in the instance image.
+ \param color = array of dimv() values of type \c T, defining the drawing color.
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported.
+ **/
+ CImg& draw_rectangle(const int x0,const int y0,const int z0,
+ const int x1,const int y1,const int z1,
+ const T *const color,const float opacity=1) {
+ if (!color) throw CImgArgumentException("CImg<%s>::draw_rectangle : specified color is (null)",pixel_type());
+ cimg_mapV(*this,k) draw_rectangle(x0,y0,z0,k,x1,y1,z1,k,color[k],opacity);
+ return *this;
+ }
+
+ //! Draw a 2D filled colored rectangle in the instance image, at coordinates (\c x0,\c y0)-(\c x1,\c y1).
+ /**
+ \param x0 = X-coordinate of the upper-left rectangle corner in the instance image.
+ \param y0 = Y-coordinate of the upper-left rectangle corner in the instance image.
+ \param x1 = X-coordinate of the lower-right rectangle corner in the instance image.
+ \param y1 = Y-coordinate of the lower-right rectangle corner in the instance image.
+ \param color = array of dimv() values of type \c T, defining the drawing color.
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported.
+ **/
+ CImg& draw_rectangle(const int x0,const int y0,const int x1,const int y1,
+ const T *const color,const float opacity=1) {
+ draw_rectangle(x0,y0,0,x1,y1,depth-1,color,opacity);
+ return *this;
+ }
+
+ //! Draw a 2D filled colored triangle in the instance image, at coordinates (\c x0,\c y0)-(\c x1,\c y1)-(\c x2,\c y2).
+ /**
+ \param x0 = X-coordinate of the first corner in the instance image.
+ \param y0 = Y-coordinate of the first corner in the instance image.
+ \param x1 = X-coordinate of the second corner in the instance image.
+ \param y1 = Y-coordinate of the second corner in the instance image.
+ \param x2 = X-coordinate of the third corner in the instance image.
+ \param y2 = Y-coordinate of the third corner in the instance image.
+ \param color = array of dimv() values of type \c T, defining the drawing color.
+ \param opacity = opacity of the drawing (<1)
+ \param brightness = brightness of the drawing (in [0,1])
+ \note Clipping is supported.
+ **/
+ CImg& draw_triangle(const int x0,const int y0,
+ const int x1,const int y1,
+ const int x2,const int y2,
+ const T *const color,
+ const float opacity=1,
+ const float brightness=1) {
+ draw_scanline(color,opacity);
+ int nx0=x0,ny0=y0,nx1=x1,ny1=y1,nx2=x2,ny2=y2;
+ if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1);
+ if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2);
+ if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2);
+ if (ny0>=dimy() || ny2<0) return *this;
+ const float
+ p1 = (ny1-ny0)?(nx1-nx0)/(float)(ny1-ny0):(nx1-nx0),
+ p2 = (ny2-ny0)?(nx2-nx0)/(float)(ny2-ny0):(nx2-nx0),
+ p3 = (ny2-ny1)?(nx2-nx1)/(float)(ny2-ny1):(nx2-nx1);
+ float xleft = (float)nx0, xright = xleft, pleft = (p1<p2)?p1:p2, pright = (p1<p2)?p2:p1;
+ if (ny0<0) { xleft-=ny0*pleft; xright-=ny0*pright; }
+ const int ya = ny1>dimy()?height:ny1;
+ for (int y=ny0<0?0:ny0; y<ya; y++) {
+ draw_scanline((int)xleft,(int)xright,y,color,opacity,brightness);
+ xleft+=pleft; xright+=pright;
+ }
+ if (p1<p2) { xleft=(float)nx1; pleft=p3; if (ny1<0) xleft-=ny1*pleft; }
+ else { xright=(float)nx1; pright=p3; if (ny1<0) xright-=ny1*pright; }
+ const int yb = ny2>=dimy()?height-1:ny2;
+ for (int yy=ny1<0?0:ny1; yy<=yb; yy++) {
+ draw_scanline((int)xleft,(int)xright,yy,color,opacity,brightness);
+ xleft+=pleft; xright+=pright;
+ }
+ return *this;
+ }
+
+ //! Draw a 2D Gouraud-filled triangle in the instance image, at coordinates (\c x0,\c y0)-(\c x1,\c y1)-(\c x2,\c y2).
+ /**
+ \param x0 = X-coordinate of the first corner in the instance image.
+ \param y0 = Y-coordinate of the first corner in the instance image.
+ \param x1 = X-coordinate of the second corner in the instance image.
+ \param y1 = Y-coordinate of the second corner in the instance image.
+ \param x2 = X-coordinate of the third corner in the instance image.
+ \param y2 = Y-coordinate of the third corner in the instance image.
+ \param color = array of dimv() values of type \c T, defining the global drawing color.
+ \param c0 = brightness of the first corner.
+ \param c1 = brightness of the second corner.
+ \param c2 = brightness of the third corner.
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported.
+ **/
+ CImg& draw_triangle(const int x0,const int y0,
+ const int x1,const int y1,
+ const int x2,const int y2,
+ const T *const color,
+ const float c0,const float c1,const float c2,
+ const float opacity=1) {
+ if (!is_empty()) {
+ int nx0=x0,ny0=y0,nx1=x1,ny1=y1,nx2=x2,ny2=y2,whz=width*height*depth;
+ float nc0=c0,nc1=c1,nc2=c2;
+ if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nc0,nc1);
+ if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,nc0,nc2);
+ if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,nc1,nc2);
+ if (ny0>=dimy() || ny2<0) return *this;
+ const float
+ p1 = (ny1-ny0)?(nx1-nx0)/(float)(ny1-ny0):(nx1-nx0),
+ p2 = (ny2-ny0)?(nx2-nx0)/(float)(ny2-ny0):(nx2-nx0),
+ p3 = (ny2-ny1)?(nx2-nx1)/(float)(ny2-ny1):(nx2-nx1),
+ cp1 = (ny1-ny0)?(nc1-nc0)/(float)(ny1-ny0):0,
+ cp2 = (ny2-ny0)?(nc2-nc0)/(float)(ny2-ny0):0,
+ cp3 = (ny2-ny1)?(nc2-nc1)/(float)(ny2-ny1):0;
+ const float nopacity = cimg::abs(opacity), copacity = 1-cimg::max(opacity,0.0f);
+ float pleft,pright,cpleft,cpright,xleft=(float)nx0,xright=xleft,cleft=nc0,cright=cleft;
+ if (p1<p2) { pleft=p1; pright=p2; cpleft=cp1; cpright=cp2; }
+ else { pleft=p2; pright=p1; cpleft=cp2; cpright=cp1; }
+ if (ny0<0) { xleft-=ny0*pleft; xright-=ny0*pright; cleft-=ny0*cpleft; cright-=ny0*cpright; }
+ const int ya = ny1<dimy()?ny1:height;
+ for (int y=(ny0<0?0:ny0); y<ya; y++) {
+ const int dx = (int)xright-(int)xleft;
+ const float
+ cp = dx?(cright-cleft)/dx:0,
+ ci = (xleft>=0)?cleft:(cleft-xleft*cp);
+ const int xmin=(xleft>=0)?(int)xleft:0, xmax=(xright<dimx())?(int)xright:(width-1);
+ if (xmin<=xmax) {
+ const int offx=whz-xmax+xmin-1;
+ T* ptrd = ptr(xmin,y,0,0);
+ if (opacity>=1) cimg_mapV(*this,k) {
+ const T col = color[k];
+ float c=ci;
+ for (int x=xmin; x<=xmax; x++) { *(ptrd++)=(T)(c*col); c+=cp; }
+ ptrd+=offx;
+ } else cimg_mapV(*this,k) {
+ const T col = color[k];
+ float c=ci;
+ for (int x=xmin; x<=xmax; x++) { *ptrd=(T)(nopacity*c*col+copacity*(*ptrd)); ptrd++; c+=cp; }
+ ptrd+=offx;
+ }
+ }
+ xleft+=pleft; xright+=pright; cleft+=cpleft; cright+=cpright;
+ }
+
+ if (p1<p2) {
+ xleft=(float)nx1; pleft=p3; cleft=nc1; cpleft=cp3;
+ if (ny1<0) { xleft-=ny1*pleft; cleft-=ny1*cpleft; }
+ } else {
+ xright=(float)nx1; pright=p3; cright=nc1; cpright=cp3;
+ if (ny1<0) { xright-=ny1*pright; cright-=ny1*cpright; }
+ }
+ const int yb = ny2>=dimy()?(height-1):ny2;
+ for (int yy=(ny1<0?0:ny1); yy<=yb; yy++) {
+ const int dx = (int)xright-(int)xleft;
+ const float
+ cp = dx?(cright-cleft)/dx:0,
+ ci = (xleft>=0)?cleft:(cleft-xleft*cp);
+ const int xmin=(xleft>=0)?(int)xleft:0, xmax=(xright<dimx())?(int)xright:(width-1);
+ if (xmin<=xmax) {
+ const int offx=whz-xmax+xmin-1;
+ T* ptrd = ptr(xmin,yy,0,0);
+ if (opacity>=1) cimg_mapV(*this,k) {
+ const T col = color[k];
+ float c=ci;
+ for (int x=xmin; x<=xmax; x++) { *(ptrd++)=(T)(c*col); c+=cp; }
+ ptrd+=offx;
+ } else cimg_mapV(*this,k) {
+ const T col = color[k];
+ float c=ci;
+ for (int x=xmin; x<=xmax; x++) { *ptrd=(T)(nopacity*c*col+copacity*(*ptrd)); ptrd++; c+=cp; }
+ ptrd+=offx;
+ }
+ }
+ xleft+=pleft; xright+=pright; cleft+=cpleft; cright+=cpright;
+ }
+ }
+ return *this;
+ }
+
+ //! Draw a 2D phong-shaded triangle in the instance image, at coordinates (\c x0,\c y0)-(\c x1,\c y1)-(\c x2,\c y2).
+ /**
+ \param x0 = X-coordinate of the first corner in the instance image.
+ \param y0 = Y-coordinate of the first corner in the instance image.
+ \param x1 = X-coordinate of the second corner in the instance image.
+ \param y1 = Y-coordinate of the second corner in the instance image.
+ \param x2 = X-coordinate of the third corner in the instance image.
+ \param y2 = Y-coordinate of the third corner in the instance image.
+ \param color = array of dimv() values of type \c T, defining the global drawing color.
+ \param light = light image.
+ \param lx0 = X-coordinate of the first corner in the light image.
+ \param ly0 = Y-coordinate of the first corner in the light image.
+ \param lx1 = X-coordinate of the second corner in the light image.
+ \param ly1 = Y-coordinate of the second corner in the light image.
+ \param lx2 = X-coordinate of the third corner in the light image.
+ \param ly2 = Y-coordinate of the third corner in the light image.
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported, but texture coordinates do not support clipping.
+ **/
+ template<typename t> CImg& draw_triangle(const int x0,const int y0,
+ const int x1,const int y1,
+ const int x2,const int y2,
+ const T *const color,
+ const CImg<t>& light,
+ const int lx0,const int ly0,
+ const int lx1,const int ly1,
+ const int lx2,const int ly2,
+ const float opacity=1.0f) {
+ if (!is_empty()) {
+ if (light.is_empty())
+ throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified light texture (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),light.width,light.height,light.depth,light.dim,light.data);
+ int nx0=x0,ny0=y0,nx1=x1,ny1=y1,nx2=x2,ny2=y2,nlx0=lx0,nly0=ly0,nlx1=lx1,nly1=ly1,nlx2=lx2,nly2=ly2,whz=width*height*depth;
+ if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,nlx0,nlx1,nly0,nly1);
+ if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,nlx0,nlx2,nly0,nly2);
+ if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,nlx1,nlx2,nly1,nly2);
+ if (ny0>=dimy() || ny2<0) return *this;
+ const float
+ p1 = (ny1-ny0)?(nx1-nx0)/(float)(ny1-ny0):(nx1-nx0),
+ p2 = (ny2-ny0)?(nx2-nx0)/(float)(ny2-ny0):(nx2-nx0),
+ p3 = (ny2-ny1)?(nx2-nx1)/(float)(ny2-ny1):(nx2-nx1),
+ lpx1 = (ny1-ny0)?(nlx1-nlx0)/(float)(ny1-ny0):0,
+ lpy1 = (ny1-ny0)?(nly1-nly0)/(float)(ny1-ny0):0,
+ lpx2 = (ny2-ny0)?(nlx2-nlx0)/(float)(ny2-ny0):0,
+ lpy2 = (ny2-ny0)?(nly2-nly0)/(float)(ny2-ny0):0,
+ lpx3 = (ny2-ny1)?(nlx2-nlx1)/(float)(ny2-ny1):0,
+ lpy3 = (ny2-ny1)?(nly2-nly1)/(float)(ny2-ny1):0;
+ const float nopacity = cimg::abs(opacity), copacity = 1-cimg::max(opacity,0.0f);
+ float pleft,pright,lpxleft,lpyleft,lpxright,lpyright,
+ xleft=(float)nx0,xright=xleft,lxleft=(float)nlx0,lyleft=(float)nly0,lxright=lxleft,lyright=lyleft;
+ if (p1<p2) { pleft=p1; pright=p2; lpxleft=lpx1; lpyleft=lpy1; lpxright=lpx2; lpyright=lpy2; }
+ else { pleft=p2; pright=p1; lpxleft=lpx2; lpyleft=lpy2; lpxright=lpx1; lpyright=lpy1; }
+ if (ny0<0) { xleft-=ny0*pleft; xright-=ny0*pright; lxleft-=ny0*lpxleft; lyleft-=ny0*lpyleft;
+ lxright-=ny0*lpxright; lyright-=ny0*lpyright; }
+ const int ya = ny1<dimy()?ny1:height;
+ for (int y=(ny0<0?0:ny0); y<ya; y++) {
+ const int dx = (int)xright-(int)xleft;
+ const float
+ lpx = dx?((int)lxright-(int)lxleft)/(float)dx:0,
+ lpy = dx?((int)lyright-(int)lyleft)/(float)dx:0,
+ lxi = (float)((xleft>=0)?(int)lxleft:(int)(lxleft-(int)xleft*lpx)),
+ lyi = (float)((xleft>=0)?(int)lyleft:(int)(lyleft-(int)xleft*lpy));
+ const int xmin=(xleft>=0)?(int)xleft:0, xmax=(xright<dimx())?(int)xright:(width-1);
+ if (xmin<=xmax) {
+ const int offx=whz-xmax+xmin-1;
+ T* ptrd = ptr(xmin,y,0,0);
+ if (opacity>=1) cimg_mapV(*this,k) {
+ float lx=lxi, ly=lyi;
+ for (int x=xmin; x<=xmax; x++) { *(ptrd++)=(T)(light((unsigned int)lx,(unsigned int)ly)*color[k]); lx+=lpx; ly+=lpy; }
+ ptrd+=offx;
+ } else cimg_mapV(*this,k) {
+ float lx=lxi, ly=lyi;
+ for (int x=xmin; x<=xmax; x++) { *ptrd=(T)(nopacity*light((unsigned int)lx,(unsigned int)ly)*color[k]+copacity*(*ptrd)); ptrd++; lx+=lpx; ly+=lpy; }
+ ptrd+=offx;
+ }
+ }
+ xleft+=pleft; xright+=pright; lxleft+=lpxleft; lyleft+=lpyleft; lxright+=lpxright; lyright+=lpyright;
+ }
+
+ if (p1<p2) {
+ xleft=(float)nx1; pleft=p3; lxleft=(float)nlx1; lyleft=(float)nly1; lpxleft=lpx3; lpyleft=lpy3;
+ if (ny1<0) { xleft-=ny1*pleft; lxleft-=ny1*lpxleft; lyleft-=ny1*lpyleft; }
+ } else {
+ xright=(float)nx1; pright=p3; lxright=(float)nlx1; lyright=(float)nly1; lpxright=lpx3; lpyright=lpy3;
+ if (ny1<0) { xright-=ny1*pright; lxright-=ny1*lpxright; lyright-=ny1*lpyright; }
+ }
+ const int yb = ny2>=dimy()?(height-1):ny2;
+ for (int yy=(ny1<0?0:ny1); yy<=yb; yy++) {
+ const int dx = (int)xright-(int)xleft;
+ const float
+ lpx = dx?((int)lxright-(int)lxleft)/(float)dx:0,
+ lpy = dx?((int)lyright-(int)lyleft)/(float)dx:0,
+ lxi = (float)((xleft>=0)?(int)lxleft:(int)(lxleft-(int)xleft*lpx)),
+ lyi = (float)((xleft>=0)?(int)lyleft:(int)(lyleft-(int)xleft*lpy));
+ const int xmin=(xleft>=0)?(int)xleft:0, xmax=(xright<dimx())?(int)xright:(width-1);
+ if (xmin<=xmax) {
+ const int offx=whz-xmax+xmin-1;
+ T* ptrd = ptr(xmin,yy,0,0);
+ if (opacity>=1) cimg_mapV(*this,k) {
+ float lx=lxi, ly=lyi;
+ for (int x=xmin; x<=xmax; x++) { *(ptrd++)=(T)(light((unsigned int)lx,(unsigned int)ly)*color[k]); lx+=lpx; ly+=lpy; }
+ ptrd+=offx;
+ } else cimg_mapV(*this,k) {
+ float lx=lxi, ly=lyi;
+ for (int x=xmin; x<=xmax; x++) { *ptrd=(T)(nopacity*light((unsigned int)lx,(unsigned int)ly)*color[k]+copacity*(*ptrd)); ptrd++; lx+=lpx; ly+=lpy; }
+ ptrd+=offx;
+ }
+ }
+ xleft+=pleft; xright+=pright; lxleft+=lpxleft; lyleft+=lpyleft; lxright+=lpxright; lyright+=lpyright;
+ }
+ }
+ return *this;
+ }
+
+ //! Draw a 2D textured triangle in the instance image, at coordinates (\c x0,\c y0)-(\c x1,\c y1)-(\c x2,\c y2).
+ /**
+ \param x0 = X-coordinate of the first corner in the instance image.
+ \param y0 = Y-coordinate of the first corner in the instance image.
+ \param x1 = X-coordinate of the second corner in the instance image.
+ \param y1 = Y-coordinate of the second corner in the instance image.
+ \param x2 = X-coordinate of the third corner in the instance image.
+ \param y2 = Y-coordinate of the third corner in the instance image.
+ \param texture = texture image used to fill the triangle.
+ \param tx0 = X-coordinate of the first corner in the texture image.
+ \param ty0 = Y-coordinate of the first corner in the texture image.
+ \param tx1 = X-coordinate of the second corner in the texture image.
+ \param ty1 = Y-coordinate of the second corner in the texture image.
+ \param tx2 = X-coordinate of the third corner in the texture image.
+ \param ty2 = Y-coordinate of the third corner in the texture image.
+ \param opacity = opacity of the drawing.
+ \param brightness = brightness of the drawing.
+ \note Clipping is supported, but texture coordinates do not support clipping.
+ **/
+ template<typename t> CImg& draw_triangle(const int x0,const int y0,
+ const int x1,const int y1,
+ const int x2,const int y2,
+ const CImg<t>& texture,
+ const int tx0,const int ty0,
+ const int tx1,const int ty1,
+ const int tx2,const int ty2,
+ const float opacity=1.0f, const float brightness=1.0f) {
+ if (!is_empty()) {
+ if (texture.is_empty())
+ throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified texture (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),texture.width,texture.height,texture.depth,texture.dim,texture.data);
+ int nx0=x0,ny0=y0,nx1=x1,ny1=y1,nx2=x2,ny2=y2,ntx0=tx0,nty0=ty0,ntx1=tx1,nty1=ty1,ntx2=tx2,nty2=ty2,whz=width*height*depth;
+ if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1);
+ if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2);
+ if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2);
+ if (ny0>=dimy() || ny2<0) return *this;
+ const float
+ p1 = (ny1-ny0)?(nx1-nx0)/(float)(ny1-ny0):(nx1-nx0),
+ p2 = (ny2-ny0)?(nx2-nx0)/(float)(ny2-ny0):(nx2-nx0),
+ p3 = (ny2-ny1)?(nx2-nx1)/(float)(ny2-ny1):(nx2-nx1),
+ tpx1 = (ny1-ny0)?(ntx1-ntx0)/(float)(ny1-ny0):0,
+ tpy1 = (ny1-ny0)?(nty1-nty0)/(float)(ny1-ny0):0,
+ tpx2 = (ny2-ny0)?(ntx2-ntx0)/(float)(ny2-ny0):0,
+ tpy2 = (ny2-ny0)?(nty2-nty0)/(float)(ny2-ny0):0,
+ tpx3 = (ny2-ny1)?(ntx2-ntx1)/(float)(ny2-ny1):0,
+ tpy3 = (ny2-ny1)?(nty2-nty1)/(float)(ny2-ny1):0;
+ const float nopacity = cimg::abs(opacity), copacity = 1-cimg::max(opacity,0.0f);
+ float pleft,pright,tpxleft,tpyleft,tpxright,tpyright,
+ xleft=(float)nx0,xright=xleft,txleft=(float)ntx0,tyleft=(float)nty0,txright=txleft,tyright=tyleft;
+ if (p1<p2) { pleft=p1; pright=p2; tpxleft=tpx1; tpyleft=tpy1; tpxright=tpx2; tpyright=tpy2; }
+ else { pleft=p2; pright=p1; tpxleft=tpx2; tpyleft=tpy2; tpxright=tpx1; tpyright=tpy1; }
+ if (ny0<0) { xleft-=ny0*pleft; xright-=ny0*pright; txleft-=ny0*tpxleft; tyleft-=ny0*tpyleft;
+ txright-=ny0*tpxright; tyright-=ny0*tpyright; }
+ const int ya = ny1<dimy()?ny1:height;
+ for (int y=(ny0<0?0:ny0); y<ya; y++) {
+ const int dx = (int)xright-(int)xleft;
+ const float
+ tpx = dx?((int)txright-(int)txleft)/(float)dx:0,
+ tpy = dx?((int)tyright-(int)tyleft)/(float)dx:0,
+ txi = (float)((xleft>=0)?(int)txleft:(int)(txleft-(int)xleft*tpx)),
+ tyi = (float)((xleft>=0)?(int)tyleft:(int)(tyleft-(int)xleft*tpy));
+ const int xmin=(xleft>=0)?(int)xleft:0, xmax=(xright<dimx())?(int)xright:(width-1);
+ if (xmin<=xmax) {
+ const int offx=whz-xmax+xmin-1;
+ T* ptrd = ptr(xmin,y,0,0);
+ if (opacity>=1) cimg_mapV(*this,k) {
+ float tx=txi, ty=tyi;
+ for (int x=xmin; x<=xmax; x++) { *(ptrd++)=(T)(brightness*texture((unsigned int)tx,(unsigned int)ty,0,k)); tx+=tpx; ty+=tpy; }
+ ptrd+=offx;
+ } else cimg_mapV(*this,k) {
+ float tx=txi, ty=tyi;
+ for (int x=xmin; x<=xmax; x++) { *ptrd=(T)(nopacity*brightness*texture((unsigned int)tx,(unsigned int)ty,0,k)+copacity*(*ptrd)); ptrd++; tx+=tpx; ty+=tpy; }
+ ptrd+=offx;
+ }
+ }
+ xleft+=pleft; xright+=pright; txleft+=tpxleft; tyleft+=tpyleft; txright+=tpxright; tyright+=tpyright;
+ }
+
+ if (p1<p2) {
+ xleft=(float)nx1; pleft=p3; txleft=(float)ntx1; tyleft=(float)nty1; tpxleft=tpx3; tpyleft=tpy3;
+ if (ny1<0) { xleft-=ny1*pleft; txleft-=ny1*tpxleft; tyleft-=ny1*tpyleft; }
+ } else {
+ xright=(float)nx1; pright=p3; txright=(float)ntx1; tyright=(float)nty1; tpxright=tpx3; tpyright=tpy3;
+ if (ny1<0) { xright-=ny1*pright; txright-=ny1*tpxright; tyright-=ny1*tpyright; }
+ }
+ const int yb = ny2>=dimy()?(height-1):ny2;
+ for (int yy=(ny1<0?0:ny1); yy<=yb; yy++) {
+ const int dx = (int)xright-(int)xleft;
+ const float
+ tpx = dx?((int)txright-(int)txleft)/(float)dx:0,
+ tpy = dx?((int)tyright-(int)tyleft)/(float)dx:0,
+ txi = (float)((xleft>=0)?(int)txleft:(int)(txleft-(int)xleft*tpx)),
+ tyi = (float)((xleft>=0)?(int)tyleft:(int)(tyleft-(int)xleft*tpy));
+ const int xmin=(xleft>=0)?(int)xleft:0, xmax=(xright<dimx())?(int)xright:(width-1);
+ if (xmin<=xmax) {
+ const int offx=whz-xmax+xmin-1;
+ T* ptrd = ptr(xmin,yy,0,0);
+ if (opacity>=1) cimg_mapV(*this,k) {
+ float tx=txi, ty=tyi;
+ for (int x=xmin; x<=xmax; x++) { *(ptrd++)=(T)(brightness*texture((unsigned int)tx,(unsigned int)ty,0,k)); tx+=tpx; ty+=tpy; }
+ ptrd+=offx;
+ } else cimg_mapV(*this,k) {
+ float tx=txi, ty=tyi;
+ for (int x=xmin; x<=xmax; x++) { *ptrd=(T)(nopacity*brightness*texture((unsigned int)tx,(unsigned int)ty,0,k)+copacity*(*ptrd)); ptrd++; tx+=tpx; ty+=tpy; }
+ ptrd+=offx;
+ }
+ }
+ xleft+=pleft; xright+=pright; txleft+=tpxleft; tyleft+=tpyleft; txright+=tpxright; tyright+=tpyright;
+ }
+ }
+ return *this;
+ }
+
+ //! Draw a 2D textured triangle with Gouraud-Shading in the instance image, at coordinates (\c x0,\c y0)-(\c x1,\c y1)-(\c x2,\c y2).
+ /**
+ \param x0 = X-coordinate of the first corner in the instance image.
+ \param y0 = Y-coordinate of the first corner in the instance image.
+ \param x1 = X-coordinate of the second corner in the instance image.
+ \param y1 = Y-coordinate of the second corner in the instance image.
+ \param x2 = X-coordinate of the third corner in the instance image.
+ \param y2 = Y-coordinate of the third corner in the instance image.
+ \param texture = texture image used to fill the triangle.
+ \param tx0 = X-coordinate of the first corner in the texture image.
+ \param ty0 = Y-coordinate of the first corner in the texture image.
+ \param tx1 = X-coordinate of the second corner in the texture image.
+ \param ty1 = Y-coordinate of the second corner in the texture image.
+ \param tx2 = X-coordinate of the third corner in the texture image.
+ \param ty2 = Y-coordinate of the third corner in the texture image.
+ \param c0 = brightness value of the first corner.
+ \param c1 = brightness value of the second corner.
+ \param c2 = brightness value of the third corner.
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported, but texture coordinates do not support clipping.
+ **/
+ template<typename t> CImg& draw_triangle(const int x0,const int y0,
+ const int x1,const int y1,
+ const int x2,const int y2,
+ const CImg<t>& texture,
+ const int tx0,const int ty0,
+ const int tx1,const int ty1,
+ const int tx2,const int ty2,
+ const float c0,const float c1,const float c2,
+ const float opacity=1) {
+ if (!is_empty()) {
+ if (texture.is_empty())
+ throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified texture (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),texture.width,texture.height,texture.depth,texture.dim,texture.data);
+ int nx0=x0,ny0=y0,nx1=x1,ny1=y1,nx2=x2,ny2=y2,ntx0=tx0,nty0=ty0,ntx1=tx1,nty1=ty1,ntx2=tx2,nty2=ty2,whz=width*height*depth;
+ float nc0=c0,nc1=c1,nc2=c2;
+ if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nc0,nc1);
+ if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nc0,nc2);
+ if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nc1,nc2);
+ if (ny0>=dimy() || ny2<0) return *this;
+ const float
+ p1 = (ny1-ny0)?(nx1-nx0)/(float)(ny1-ny0):(nx1-nx0),
+ p2 = (ny2-ny0)?(nx2-nx0)/(float)(ny2-ny0):(nx2-nx0),
+ p3 = (ny2-ny1)?(nx2-nx1)/(float)(ny2-ny1):(nx2-nx1),
+ tpx1 = (ny1-ny0)?(ntx1-ntx0)/(float)(ny1-ny0):0,
+ tpy1 = (ny1-ny0)?(nty1-nty0)/(float)(ny1-ny0):0,
+ tpx2 = (ny2-ny0)?(ntx2-ntx0)/(float)(ny2-ny0):0,
+ tpy2 = (ny2-ny0)?(nty2-nty0)/(float)(ny2-ny0):0,
+ tpx3 = (ny2-ny1)?(ntx2-ntx1)/(float)(ny2-ny1):0,
+ tpy3 = (ny2-ny1)?(nty2-nty1)/(float)(ny2-ny1):0,
+ cp1 = (ny1-ny0)?(nc1-nc0)/(float)(ny1-ny0):0,
+ cp2 = (ny2-ny0)?(nc2-nc0)/(float)(ny2-ny0):0,
+ cp3 = (ny2-ny1)?(nc2-nc1)/(float)(ny2-ny1):0;
+ const float nopacity = cimg::abs(opacity), copacity = 1-cimg::max(opacity,0.0f);
+ float pleft,pright,tpxleft,tpyleft,tpxright,tpyright,cpleft,cpright,
+ xleft=(float)nx0,xright=xleft,txleft=(float)ntx0,tyleft=(float)nty0,txright=txleft,tyright=tyleft,cleft=nc0,cright=cleft;
+ if (p1<p2) { pleft=p1; pright=p2; tpxleft=tpx1; tpyleft=tpy1; tpxright=tpx2; tpyright=tpy2; cpleft=cp1; cpright=cp2; }
+ else { pleft=p2; pright=p1; tpxleft=tpx2; tpyleft=tpy2; tpxright=tpx1; tpyright=tpy1; cpleft=cp2, cpright=cp1; }
+ if (ny0<0) {
+ xleft-=ny0*pleft; xright-=ny0*pright; txleft-=ny0*tpxleft; tyleft-=ny0*tpyleft; cleft-=ny0*cpleft;
+ txright-=ny0*tpxright; tyright-=ny0*tpyright; cright-=ny0*cpright;
+ }
+ const int ya = ny1<dimy()?ny1:height;
+ for (int y=(ny0<0?0:ny0); y<ya; y++) {
+ const int dx = (int)xright-(int)xleft;
+ const float
+ tpx = dx?((int)txright-(int)txleft)/(float)dx:0,
+ tpy = dx?((int)tyright-(int)tyleft)/(float)dx:0,
+ cp = dx?(cright-cleft)/dx:0,
+ txi = (float)((xleft>=0)?(int)txleft:(int)(txleft-(int)xleft*tpx)),
+ tyi = (float)((xleft>=0)?(int)tyleft:(int)(tyleft-(int)xleft*tpy)),
+ ci = (xleft>=0)?cleft:(cleft-xleft*cp);
+ const int xmin=(xleft>=0)?(int)xleft:0, xmax=(xright<dimx())?(int)xright:(width-1);
+ if (xmin<=xmax) {
+ const int offx=whz-xmax+xmin-1;
+ T* ptrd = ptr(xmin,y,0,0);
+ if (opacity>=1) cimg_mapV(*this,k) {
+ float tx=txi, ty=tyi, c=ci;
+ for (int x=xmin; x<=xmax; x++) { *(ptrd++)=(T)(c*texture((unsigned int)tx,(unsigned int)ty,0,k)); tx+=tpx; ty+=tpy; c+=cp; }
+ ptrd+=offx;
+ } else cimg_mapV(*this,k) {
+ float tx=txi, ty=tyi, c=ci;
+ for (int x=xmin; x<=xmax; x++) { *ptrd=(T)(nopacity*c*texture((unsigned int)tx,(unsigned int)ty,0,k)+copacity*(*ptrd)); ptrd++; tx+=tpx; ty+=tpy; c+=cp; }
+ ptrd+=offx;
+ }
+ }
+ xleft+=pleft; xright+=pright; txleft+=tpxleft; tyleft+=tpyleft; txright+=tpxright; tyright+=tpyright; cleft+=cpleft; cright+=cpright;
+ }
+
+ if (p1<p2) {
+ xleft=(float)nx1; pleft=p3; txleft=(float)ntx1; tyleft=(float)nty1; tpxleft=tpx3; tpyleft=tpy3; cleft=nc1; cpleft=cp3;
+ if (ny1<0) { xleft-=ny1*pleft; txleft-=ny1*tpxleft; tyleft-=ny1*tpyleft; cleft-=ny1*cpleft; }
+ } else {
+ xright=(float)nx1; pright=p3; txright=(float)ntx1; tyright=(float)nty1; tpxright=tpx3; tpyright=tpy3; cright=nc1; cpright=cp3;
+ if (ny1<0) { xright-=ny1*pright; txright-=ny1*tpxright; tyright-=ny1*tpyright; cright-=ny1*cpright; }
+ }
+ const int yb = ny2>=dimy()?(height-1):ny2;
+ for (int yy=(ny1<0?0:ny1); yy<=yb; yy++) {
+ const int dx = (int)xright-(int)xleft;
+ const float
+ tpx = dx?((int)txright-(int)txleft)/(float)dx:0,
+ tpy = dx?((int)tyright-(int)tyleft)/(float)dx:0,
+ cp = dx?(cright-cleft)/dx:0,
+ txi = (float)((xleft>=0)?(int)txleft:(int)(txleft-(int)xleft*tpx)),
+ tyi = (float)((xleft>=0)?(int)tyleft:(int)(tyleft-(int)xleft*tpy)),
+ ci = (xleft>=0)?cleft:(cleft-xleft*cp);
+ const int xmin=(xleft>=0)?(int)xleft:0, xmax=(xright<dimx())?(int)xright:(width-1);
+ if (xmin<=xmax) {
+ const int offx=whz-xmax+xmin-1;
+ T* ptrd = ptr(xmin,yy,0,0);
+ if (opacity>=1) cimg_mapV(*this,k) {
+ float tx=txi, ty=tyi, c=ci;
+ for (int x=xmin; x<=xmax; x++) { *(ptrd++)=(T)(c*texture((unsigned int)tx,(unsigned int)ty,0,k)); tx+=tpx; ty+=tpy; c+=cp; }
+ ptrd+=offx;
+ } else cimg_mapV(*this,k) {
+ float tx=txi, ty=tyi, c=ci;
+ for (int x=xmin; x<=xmax; x++) { *ptrd=(T)(nopacity*c*texture((unsigned int)tx,(unsigned int)ty,0,k)+copacity*(*ptrd)); ptrd++; tx+=tpx; ty+=tpy; c+=ci; }
+ ptrd+=offx;
+ }
+ }
+ xleft+=pleft; xright+=pright; txleft+=tpxleft; tyleft+=tpyleft; txright+=tpxright; tyright+=tpyright; cleft+=cpleft; cright+=cpright;
+ }
+ }
+ return *this;
+ }
+
+ //! Draw a phong-shaded 2D textured triangle in the instance image, at coordinates (\c x0,\c y0)-(\c x1,\c y1)-(\c x2,\c y2).
+ /**
+ \param x0 = X-coordinate of the first corner in the instance image.
+ \param y0 = Y-coordinate of the first corner in the instance image.
+ \param x1 = X-coordinate of the second corner in the instance image.
+ \param y1 = Y-coordinate of the second corner in the instance image.
+ \param x2 = X-coordinate of the third corner in the instance image.
+ \param y2 = Y-coordinate of the third corner in the instance image.
+ \param texture = texture image used to fill the triangle.
+ \param tx0 = X-coordinate of the first corner in the texture image.
+ \param ty0 = Y-coordinate of the first corner in the texture image.
+ \param tx1 = X-coordinate of the second corner in the texture image.
+ \param ty1 = Y-coordinate of the second corner in the texture image.
+ \param tx2 = X-coordinate of the third corner in the texture image.
+ \param ty2 = Y-coordinate of the third corner in the texture image.
+ \param light = light image.
+ \param lx0 = X-coordinate of the first corner in the light image.
+ \param ly0 = Y-coordinate of the first corner in the light image.
+ \param lx1 = X-coordinate of the second corner in the light image.
+ \param ly1 = Y-coordinate of the second corner in the light image.
+ \param lx2 = X-coordinate of the third corner in the light image.
+ \param ly2 = Y-coordinate of the third corner in the light image.
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported, but texture coordinates do not support clipping.
+ **/
+ template<typename t, typename tl> CImg& draw_triangle(const int x0,const int y0,
+ const int x1,const int y1,
+ const int x2,const int y2,
+ const CImg<t>& texture,
+ const int tx0,const int ty0,
+ const int tx1,const int ty1,
+ const int tx2,const int ty2,
+ const CImg<tl>& light,
+ const int lx0,const int ly0,
+ const int lx1,const int ly1,
+ const int lx2,const int ly2,
+ const float opacity=1.0f) {
+ if (!is_empty()) {
+ if (texture.is_empty())
+ throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified texture (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),texture.width,texture.height,texture.depth,texture.dim,texture.data);
+ if (light.is_empty())
+ throw CImgArgumentException("CImg<%s>::draw_triangle() : Specified light (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),light.width,light.height,light.depth,light.dim,light.data);
+ int
+ nx0=x0,ny0=y0,nx1=x1,ny1=y1,nx2=x2,ny2=y2,
+ ntx0=tx0,nty0=ty0,ntx1=tx1,nty1=ty1,ntx2=tx2,nty2=ty2,
+ nlx0=lx0,nly0=ly0,nlx1=lx1,nly1=ly1,nlx2=lx2,nly2=ly2,
+ whz=width*height*depth;
+ if (ny0>ny1) cimg::swap(nx0,nx1,ny0,ny1,ntx0,ntx1,nty0,nty1,nlx0,nlx1,nly0,nly1);
+ if (ny0>ny2) cimg::swap(nx0,nx2,ny0,ny2,ntx0,ntx2,nty0,nty2,nlx0,nlx2,nly0,nly2);
+ if (ny1>ny2) cimg::swap(nx1,nx2,ny1,ny2,ntx1,ntx2,nty1,nty2,nlx1,nlx2,nly1,nly2);
+ if (ny0>=dimy() || ny2<0) return *this;
+ const float
+ p1 = (ny1-ny0)?(nx1-nx0)/(float)(ny1-ny0):(nx1-nx0),
+ p2 = (ny2-ny0)?(nx2-nx0)/(float)(ny2-ny0):(nx2-nx0),
+ p3 = (ny2-ny1)?(nx2-nx1)/(float)(ny2-ny1):(nx2-nx1),
+ tpx1 = (ny1-ny0)?(ntx1-ntx0)/(float)(ny1-ny0):0,
+ tpy1 = (ny1-ny0)?(nty1-nty0)/(float)(ny1-ny0):0,
+ tpx2 = (ny2-ny0)?(ntx2-ntx0)/(float)(ny2-ny0):0,
+ tpy2 = (ny2-ny0)?(nty2-nty0)/(float)(ny2-ny0):0,
+ tpx3 = (ny2-ny1)?(ntx2-ntx1)/(float)(ny2-ny1):0,
+ tpy3 = (ny2-ny1)?(nty2-nty1)/(float)(ny2-ny1):0,
+ lpx1 = (ny1-ny0)?(nlx1-nlx0)/(float)(ny1-ny0):0,
+ lpy1 = (ny1-ny0)?(nly1-nly0)/(float)(ny1-ny0):0,
+ lpx2 = (ny2-ny0)?(nlx2-nlx0)/(float)(ny2-ny0):0,
+ lpy2 = (ny2-ny0)?(nly2-nly0)/(float)(ny2-ny0):0,
+ lpx3 = (ny2-ny1)?(nlx2-nlx1)/(float)(ny2-ny1):0,
+ lpy3 = (ny2-ny1)?(nly2-nly1)/(float)(ny2-ny1):0;
+ const float nopacity = cimg::abs(opacity), copacity = 1-cimg::max(opacity,0.0f);
+ float pleft,pright,tpxleft,tpyleft,tpxright,tpyright,lpxleft,lpyleft,lpxright,lpyright,
+ xleft=(float)nx0,xright=xleft,
+ txleft=(float)ntx0,tyleft=(float)nty0,txright=txleft,tyright=tyleft,
+ lxleft=(float)nlx0,lyleft=(float)nly0,lxright=lxleft,lyright=lyleft;
+ if (p1<p2) {
+ pleft=p1; pright=p2;
+ tpxleft=tpx1; tpyleft=tpy1; tpxright=tpx2; tpyright=tpy2;
+ lpxleft=lpx1; lpyleft=lpy1; lpxright=lpx2; lpyright=lpy2;
+ } else {
+ pleft=p2; pright=p1;
+ tpxleft=tpx2; tpyleft=tpy2; tpxright=tpx1; tpyright=tpy1;
+ lpxleft=tpx2; lpyleft=tpy2; lpxright=tpx1; lpyright=tpy1;
+ }
+ if (ny0<0) {
+ xleft-=ny0*pleft; xright-=ny0*pright;
+ txleft-=ny0*tpxleft; tyleft-=ny0*tpyleft; txright-=ny0*tpxright; tyright-=ny0*tpyright;
+ lxleft-=ny0*lpxleft; lyleft-=ny0*lpyleft; lxright-=ny0*lpxright; lyright-=ny0*lpyright;
+ }
+ const int ya = ny1<dimy()?ny1:height;
+ for (int y=(ny0<0?0:ny0); y<ya; y++) {
+ const int dx = (int)xright-(int)xleft;
+ const float
+ tpx = dx?((int)txright-(int)txleft)/(float)dx:0,
+ tpy = dx?((int)tyright-(int)tyleft)/(float)dx:0,
+ txi = (float)((xleft>=0)?(int)txleft:(int)(txleft-(int)xleft*tpx)),
+ tyi = (float)((xleft>=0)?(int)tyleft:(int)(tyleft-(int)xleft*tpy)),
+ lpx = dx?((int)lxright-(int)lxleft)/(float)dx:0,
+ lpy = dx?((int)lyright-(int)lyleft)/(float)dx:0,
+ lxi = (float)((xleft>=0)?(int)lxleft:(int)(lxleft-(int)xleft*lpx)),
+ lyi = (float)((xleft>=0)?(int)lyleft:(int)(lyleft-(int)xleft*lpy));
+ const int xmin=(xleft>=0)?(int)xleft:0, xmax=(xright<dimx())?(int)xright:(width-1);
+ if (xmin<=xmax) {
+ const int offx=whz-xmax+xmin-1;
+ T* ptrd = ptr(xmin,y,0,0);
+ if (opacity>=1) cimg_mapV(*this,k) {
+ float tx=txi, ty=tyi, lx=lxi, ly=lyi;
+ for (int x=xmin; x<=xmax; x++) {
+ *(ptrd++)=(T)(light((unsigned int)lx,(unsigned int)ly)*texture((unsigned int)tx,(unsigned int)ty,0,k));
+ tx+=tpx; ty+=tpy; lx+=lpx; ly+=lpy;
+ }
+ ptrd+=offx;
+ } else cimg_mapV(*this,k) {
+ float tx=txi, ty=tyi, lx=lxi, ly=lyi;
+ for (int x=xmin; x<=xmax; x++) {
+ *ptrd=(T)(nopacity*light((unsigned int)lx,(unsigned int)ly)*texture((unsigned int)tx,(unsigned int)ty,0,k)+copacity*(*ptrd)); ptrd++;
+ tx+=tpx; ty+=tpy; lx+=lpx; ly+=lpy;
+ }
+ ptrd+=offx;
+ }
+ }
+ xleft+=pleft; xright+=pright;
+ txleft+=tpxleft; tyleft+=tpyleft; txright+=tpxright; tyright+=tpyright;
+ lxleft+=lpxleft; lyleft+=lpyleft; lxright+=lpxright; lyright+=lpyright;
+ }
+
+ if (p1<p2) {
+ xleft=(float)nx1; pleft=p3;
+ txleft=(float)ntx1; tyleft=(float)nty1; tpxleft=tpx3; tpyleft=tpy3;
+ lxleft=(float)nlx1; lyleft=(float)nly1; lpxleft=lpx3; lpyleft=lpy3;
+ if (ny1<0) { xleft-=ny1*pleft; txleft-=ny1*tpxleft; tyleft-=ny1*tpyleft; lxleft-=ny1*lpxleft; lyleft-=ny1*lpyleft; }
+ } else {
+ xright=(float)nx1; pright=p3;
+ txright=(float)ntx1; tyright=(float)nty1; tpxright=tpx3; tpyright=tpy3;
+ lxright=(float)nlx1; lyright=(float)nly1; lpxright=lpx3; lpyright=lpy3;
+ if (ny1<0) { xright-=ny1*pright; txright-=ny1*tpxright; tyright-=ny1*tpyright; lxright-=ny1*lpxright; lyright-=ny1*lpyright; }
+ }
+ const int yb = ny2>=dimy()?(height-1):ny2;
+ for (int yy=(ny1<0?0:ny1); yy<=yb; yy++) {
+ const int dx = (int)xright-(int)xleft;
+ const float
+ tpx = dx?((int)txright-(int)txleft)/(float)dx:0,
+ tpy = dx?((int)tyright-(int)tyleft)/(float)dx:0,
+ txi = (float)((xleft>=0)?(int)txleft:(int)(txleft-(int)xleft*tpx)),
+ tyi = (float)((xleft>=0)?(int)tyleft:(int)(tyleft-(int)xleft*tpy)),
+ lpx = dx?((int)lxright-(int)lxleft)/(float)dx:0,
+ lpy = dx?((int)lyright-(int)lyleft)/(float)dx:0,
+ lxi = (float)((xleft>=0)?(int)lxleft:(int)(lxleft-(int)xleft*lpx)),
+ lyi = (float)((xleft>=0)?(int)lyleft:(int)(lyleft-(int)xleft*lpy));
+ const int xmin=(xleft>=0)?(int)xleft:0, xmax=(xright<dimx())?(int)xright:(width-1);
+ if (xmin<=xmax) {
+ const int offx=whz-xmax+xmin-1;
+ T* ptrd = ptr(xmin,yy,0,0);
+ if (opacity>=1) cimg_mapV(*this,k) {
+ float tx=txi, ty=tyi, lx=lxi, ly=lyi;
+ for (int x=xmin; x<=xmax; x++) {
+ *(ptrd++)=(T)(light((unsigned int)lx,(unsigned int)ly)*texture((unsigned int)tx,(unsigned int)ty,0,k));
+ tx+=tpx; ty+=tpy; lx+=lpx; ly+=lpy;
+ }
+ ptrd+=offx;
+ } else cimg_mapV(*this,k) {
+ float tx=txi, ty=tyi, lx=lxi, ly=lyi;
+ for (int x=xmin; x<=xmax; x++) {
+ *ptrd=(T)(nopacity*light((unsigned int)lx,(unsigned int)ly)*texture((unsigned int)tx,(unsigned int)ty,0,k)+copacity*(*ptrd)); ptrd++;
+ tx+=tpx; ty+=tpy; lx+=lpx; ly+=lpy;
+ }
+ ptrd+=offx;
+ }
+ }
+ xleft+=pleft; xright+=pright;
+ txleft+=tpxleft; tyleft+=tpyleft; txright+=tpxright; tyright+=tpyright;
+ lxleft+=lpxleft; lyleft+=lpyleft; lxright+=lpxright; lyright+=lpyright;
+ }
+ }
+ return *this;
+ }
+
+
+ //! Draw an ellipse on the instance image
+ /**
+ \param x0 = X-coordinate of the ellipse center.
+ \param y0 = Y-coordinate of the ellipse center.
+ \param r1 = First radius of the ellipse.
+ \param r2 = Second radius of the ellipse.
+ \param ru = X-coordinate of the orientation vector related to the first radius.
+ \param rv = Y-coordinate of the orientation vector related to the first radius.
+ \param color = array of dimv() values of type \c T, defining the drawing color.
+ \param pattern = If zero, the ellipse is filled, else pattern is an integer whose bits describe the outline pattern.
+ \param opacity = opacity of the drawing.
+ **/
+ CImg& draw_ellipse(const int x0,const int y0,const float r1,const float r2,const float ru,const float rv,
+ const T *const color,const unsigned int pattern=0L, const float opacity=1) {
+ if (!is_empty()) {
+ draw_scanline(color,opacity);
+ if (!color) throw CImgArgumentException("CImg<%s>::draw_ellipse : Specified color is (null).",pixel_type());
+ unsigned int hatch=1;
+ const float
+ nr1 = cimg::abs(r1), nr2 = cimg::abs(r2),
+ norm = (float)std::sqrt(ru*ru+rv*rv),
+ u = norm>0?ru/norm:1,
+ v = norm>0?rv/norm:0,
+ rmax = cimg::max(nr1,nr2),
+ l1 = (float)std::pow(rmax/(nr1>0?nr1:1e-6),2),
+ l2 = (float)std::pow(rmax/(nr2>0?nr2:1e-6),2),
+ a = l1*u*u + l2*v*v,
+ b = u*v*(l1-l2),
+ c = l1*v*v + l2*u*u;
+ const int
+ yb = (int)std::sqrt(a*rmax*rmax/(a*c-b*b)),
+ ymin = (y0-yb<0)?0:(y0-yb),
+ ymax = (1+y0+yb>=dimy())?height-1:(1+y0+yb);
+ int oxmin=0, oxmax=0;
+ bool first_line = true;
+ for (int y=ymin; y<=ymax; y++) {
+ const float
+ Y = (float)(y-y0),
+ delta = b*b*Y*Y-a*(c*Y*Y-rmax*rmax),
+ sdelta = (float)((delta>0?std::sqrt(delta):0)),
+ fxmin = x0-(b*Y+sdelta)/a,
+ fxmax = x0-(b*Y-sdelta)/a;
+ const int xmin = (int)fxmin, xmax = (int)fxmax;
+ if (!pattern) draw_scanline(xmin,xmax,y,color,opacity);
+ else {
+ if (!(~pattern) || (~pattern && pattern&hatch)) {
+ if (first_line) { draw_scanline(xmin,xmax,y,color,opacity); first_line = false; }
+ else {
+ if (xmin<oxmin) draw_scanline(xmin,oxmin-1,y,color,opacity);
+ else draw_scanline(oxmin+(oxmin==xmin?0:1),xmin,y,color,opacity);
+ if (xmax<oxmax) draw_scanline(xmax,oxmax-1,y,color,opacity);
+ else draw_scanline(oxmax+(oxmax==xmax?0:1),xmax,y,color,opacity);
+ }
+ }
+ }
+ oxmin = xmin; oxmax = xmax;
+ if (pattern) hatch=(hatch<<1)+(hatch>>(sizeof(unsigned int)*8-1));
+ }
+ }
+ return *this;
+ }
+
+ //! Draw an ellipse on the instance image
+ /**
+ \param x0 = X-coordinate of the ellipse center.
+ \param y0 = Y-coordinate of the ellipse center.
+ \param tensor = Diffusion tensor describing the ellipse.
+ \param color = array of dimv() values of type \c T, defining the drawing color.
+ \param pattern = If zero, the ellipse is filled, else pattern is an integer whose bits describe the outline pattern.
+ \param opacity = opacity of the drawing.
+ **/
+ template<typename t> CImg& draw_ellipse(const int x0,const int y0,const CImg<t> &tensor,
+ const T *color,const unsigned int pattern=0L,const float opacity=1) {
+ CImgl<t> eig = tensor.get_symeigen();
+ const CImg<t> &val = eig[0], &vec = eig[1];
+ return draw_ellipse(x0,y0,val(0),val(1),vec(0,0),vec(0,1),color,pattern,opacity);
+ }
+
+ //! Draw a circle on the instance image
+ /**
+ \param x0 = X-coordinate of the circle center.
+ \param y0 = Y-coordinate of the circle center.
+ \param r = radius of the circle.
+ \param color = an array of dimv() values of type \c T, defining the drawing color.
+ \param pattern = If zero, the circle is filled, else pattern is an integer whose bits describe the outline pattern.
+ \param opacity = opacity of the drawing.
+ **/
+ CImg& draw_circle(const int x0,const int y0,float r,const T *const color,const unsigned int pattern=0L,const float opacity=1) {
+ return draw_ellipse(x0,y0,r,r,1,0,color,pattern,opacity);
+ }
+
+ //! Draw a text into the instance image.
+ /**
+ \param text = a C-string containing the text to display.
+ \param x0 = X-coordinate of the text in the instance image.
+ \param y0 = Y-coordinate of the text in the instance image.
+ \param fgcolor = an array of dimv() values of type \c T, defining the foreground color (NULL means 'transparent').
+ \param bgcolor = an array of dimv() values of type \c T, defining the background color (NULL means 'transparent').
+ \param font = List of font characters used for the drawing.
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported.
+ \see get_font().
+ **/
+ template<typename t> CImg& draw_text(const char *const text,
+ const int x0,const int y0,
+ const T *const fgcolor,const T *const bgcolor,
+ const CImgl<t>& font,const float opacity=1) {
+ if (!text)
+ throw CImgArgumentException("CImg<%s>::draw_text() : Specified input string is (null).",pixel_type());
+ if (font.is_empty())
+ throw CImgArgumentException("CImg<%s>::draw_text() : Specified font (%u,%p) is empty.",
+ pixel_type(),font.size,font.data);
+
+ if (is_empty()) {
+ // If needed, pre-compute needed size of the image
+ int x=0, y=0, w=0;
+ for (int i=0; i<cimg::strlen(text); i++) {
+ const unsigned char c = text[i];
+ switch (c) {
+ case '\n': y+=font[' '].height; if (x>w) w=x; x=0; break;
+ case '\t': x+=4*font[' '].width; break;
+ default: if (c<font.size) x+=font[c].width;
+ }
+ }
+ if (x!=0) {
+ if (x>w) w=x;
+ y+=font[' '].height;
+ }
+ assign(x0+w,y0+y,1,font[' '].dim,0);
+ if (bgcolor) cimg_mapV(*this,k) get_shared_channel(k).fill(bgcolor[k]);
+ }
+
+ int x=x0, y=y0;
+ CImg letter;
+ for (int i=0; i<cimg::strlen(text); i++) {
+ const unsigned char c = text[i];
+ switch (c) {
+ case '\n': y+=font[' '].height; x=x0; break;
+ case '\t': x+=4*font[' '].width; break;
+ default: if (c<font.size) {
+ letter = font[c];
+ const CImg& tqmask = (c+256)<(int)font.size?font[c+256]:font[c];
+ if (fgcolor) for (unsigned int p=0; p<letter.width*letter.height; p++)
+ if (tqmask(p)) cimg_mapV(*this,k) letter(p,0,0,k)=(T)(letter(p,0,0,k)*fgcolor[k]);
+ if (bgcolor) for (unsigned int p=0; p<letter.width*letter.height; p++)
+ if (!tqmask(p)) cimg_mapV(*this,k) letter(p,0,0,k)=bgcolor[k];
+ if (!bgcolor && font.size>=512) draw_image(letter,tqmask,x,y,0,0,(T)1,opacity); else draw_image(letter,x,y,0,0,opacity);
+ x+=letter.width;
+ }
+ break;
+ }
+ }
+ return *this;
+ }
+
+ //! Draw a text into the instance image.
+ /**
+ \param text = a C-string containing the text to display.
+ \param x0 = X-coordinate of the text in the instance image.
+ \param y0 = Y-coordinate of the text in the instance image.
+ \param fgcolor = an array of dimv() values of type \c T, defining the foreground color (NULL means 'transparent').
+ \param bgcolor = an array of dimv() values of type \c T, defining the background color (NULL means 'transparent').
+ \param font_size = Height of the desired font (11,13,24,38 or 57)
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported.
+ \see get_font().
+ **/
+ CImg& draw_text(const char *const text,
+ const int x0,const int y0,
+ const T *const fgcolor,const T *const bgcolor=0,
+ const unsigned int font_size=11,const float opacity=1.0f) {
+ return draw_text(text,x0,y0,fgcolor,bgcolor,CImgl<T>::get_font(font_size),opacity);
+ }
+
+
+ //! Draw a text into the instance image.
+ /**
+ \param x0 = X-coordinate of the text in the instance image.
+ \param y0 = Y-coordinate of the text in the instance image.
+ \param fgcolor = an array of dimv() values of type \c T, defining the foreground color (NULL means 'transparent').
+ \param bgcolor = an array of dimv() values of type \c T, defining the background color (NULL means 'transparent').
+ \param opacity = opacity of the drawing.
+ \param format = a 'printf'-style format, followed by arguments.
+ \note Clipping is supported.
+ **/
+ CImg& draw_text(const int x0,const int y0,
+ const T *const fgcolor,const T *const bgcolor, const unsigned int font_size,
+ const float opacity,const char *format,...) {
+ char tmp[2048];
+ std::va_list ap;
+ va_start(ap,format);
+ std::vsprintf(tmp,format,ap);
+ va_end(ap);
+ return draw_text(tmp,x0,y0,fgcolor,bgcolor,font_size,opacity);
+ }
+
+ template<typename t> CImg& draw_text(const int x0,const int y0,
+ const T *const fgcolor,const T *const bgcolor,
+ const CImgl<t>& font, const float opacity, const char *format,...) {
+ char tmp[2048];
+ std::va_list ap;
+ va_start(ap,format);
+ std::vsprintf(tmp,format,ap);
+ va_end(ap);
+ return draw_text(tmp,x0,y0,fgcolor,bgcolor,font,opacity);
+ }
+
+
+ //! Draw a vector field in the instance image.
+ /**
+ \param flow = a 2d image of 2d vectors used as input data.
+ \param color = an array of dimv() values of type \c T, defining the drawing color.
+ \param sampling = length (in pixels) between each arrow.
+ \param factor = length factor of each arrow (if <0, computed as a percentage of the maximum length).
+ \param quiver_type = type of plot. Can be 0 (arrows) or 1 (segments).
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported.
+ **/
+ template<typename t>
+ CImg& draw_quiver(const CImg<t>& flow,const T *const color,const unsigned int sampling=25,const float factor=-20,
+ const int quiver_type=0,const float opacity=1) {
+ if (!is_empty()) {
+ if (flow.is_empty() || flow.dim!=2)
+ throw CImgArgumentException("CImg<%s>::draw_quiver() : Specified flow (%u,%u,%u,%u,%p) has wrong dimensions.",
+ pixel_type(),flow.width,flow.height,flow.depth,flow.dim,flow.data);
+ if (!color)
+ throw CImgArgumentException("CImg<%s>::draw_quiver() : Specified color is (null)",
+ pixel_type());
+ if (sampling<=0)
+ throw CImgArgumentException("CImg<%s>::draw_quiver() : Incorrect sampling value = %g",
+ pixel_type(),sampling);
+
+ float vmax,fact;
+ if (factor<=0) {
+ CImgStats st(flow.get_norm_pointwise(2),false);
+ vmax = (float)cimg::max(cimg::abs(st.min),cimg::abs(st.max));
+ fact = -factor;
+ } else { fact = factor; vmax = 1; }
+
+ for (unsigned int y=sampling/2; y<height; y+=sampling)
+ for (unsigned int x=sampling/2; x<width; x+=sampling) {
+ const unsigned int X = x*flow.width/width, Y = y*flow.height/height;
+ float u = (float)flow(X,Y,0,0)*fact/vmax, v = (float)flow(X,Y,0,1)*fact/vmax;
+ if (!quiver_type) {
+ const int xx = x+(int)u, yy = y+(int)v;
+ draw_arrow(x,y,xx,yy,color,45.0f,sampling/5.0f,~0L,opacity);
+ } else draw_line((int)(x-0.5*u),(int)(y-0.5*v),(int)(x+0.5*u),(int)(y+0.5*v),color,~0L,opacity);
+ }
+ }
+ return *this;
+ }
+
+ //! Draw a vector field in the instance image, using a colormap.
+ /**
+ \param flow = a 2d image of 2d vectors used as input data.
+ \param color = a 2d image of dimv()-D vectors corresponding to the color of each arrow.
+ \param sampling = length (in pixels) between each arrow.
+ \param factor = length factor of each arrow (if <0, computed as a percentage of the maximum length).
+ \param quiver_type = type of plot. Can be 0 (arrows) or 1 (segments).
+ \param opacity = opacity of the drawing.
+ \note Clipping is supported.
+ **/
+ template<typename t1,typename t2>
+ CImg& draw_quiver(const CImg<t1>& flow,const CImg<t2>& color,const unsigned int sampling=25,const float factor=-20,
+ const int quiver_type=0,const float opacity=1) {
+ if (!is_empty()) {
+ if (flow.is_empty() || flow.dim!=2)
+ throw CImgArgumentException("CImg<%s>::draw_quiver() : Specified flow (%u,%u,%u,%u,%p) has wrong dimensions.",
+ pixel_type(),flow.width,flow.height,flow.depth,flow.dim,flow.data);
+ if (color.is_empty() || color.width!=flow.width || color.height!=flow.height)
+ throw CImgArgumentException("CImg<%s>::draw_quiver() : Specified color (%u,%u,%u,%u,%p) has wrong dimensions.",
+ pixel_type(),color.width,color.height,color.depth,color.dim,color.data);
+ if (sampling<=0)
+ throw CImgArgumentException("CImg<%s>::draw_quiver() : Incorrect sampling value = %g",pixel_type(),sampling);
+
+ float vmax,fact;
+ if (factor<=0) {
+ CImgStats st(flow.get_norm_pointwise(2),false);
+ vmax = (float)cimg::max(cimg::abs(st.min),cimg::abs(st.max));
+ fact = -factor;
+ } else { fact = factor; vmax = 1; }
+
+ for (unsigned int y=sampling/2; y<height; y+=sampling)
+ for (unsigned int x=sampling/2; x<width; x+=sampling) {
+ const unsigned int X = x*flow.width/width, Y = y*flow.height/height;
+ float u = (float)flow(X,Y,0,0)*fact/vmax, v = (float)flow(X,Y,0,1)*fact/vmax;
+ if (!quiver_type) {
+ const int xx = x+(int)u, yy = y+(int)v;
+ draw_arrow(x,y,xx,yy,color.get_vector(X,Y).data,45,sampling/5,~0L,opacity);
+ } else draw_line((int)(x-0.5*u),(int)(y-0.5*v),(int)(x+0.5*u),(int)(y+0.5*v),color(X,Y),~0L,opacity);
+ }
+ }
+ return *this;
+ }
+
+ //! Draw a 1D graph on the instance image.
+ /**
+ \param data = an image containing the graph values I = f(x).
+ \param color = an array of dimv() values of type \c T, defining the drawing color.
+ \param gtype = define the type of the plot :
+ - 0 = Plot using linear interpolation (segments).
+ - 1 = Plot with bars.
+ - 2 = Plot using cubic interpolation (3-polynomials).
+ \param ymin = lower bound of the y-range.
+ \param ymax = upper bound of the y-range.
+ \param opacity = opacity of the drawing.
+ \note
+ - if \c ymin==ymax==0, the y-range is computed automatically from the input sample.
+ \see draw_axeX(), draw_axeY(), draw_axeXY().
+ **/
+ template<typename t>
+ CImg& draw_graph(const CImg<t>& data,const T *const color,const unsigned int gtype=0,
+ const double ymin=0,const double ymax=0,const float opacity=1) {
+ if (!is_empty()) {
+ if (!color) throw CImgArgumentException("CImg<%s>::draw_graph() : Specified color is (null)",pixel_type());
+ T *color1 = new T[dim], *color2 = new T[dim];
+ cimg_mapV(*this,k) { color1[k]=(T)(color[k]*0.6f); color2[k]=(T)(color[k]*0.3f); }
+ CImgStats st;
+ if (ymin==ymax) { st = CImgStats(data,false); cimg::swap(st.min,st.max); } else { st.min = ymin; st.max = ymax; }
+ if (st.min==st.max) { st.min--; st.max++; }
+ const float ca = height>1?(float)(st.max-st.min)/(height-1):0, cb = (float)st.min;
+ const int Y0 = (int)(-cb/ca);
+ int pY=0;
+ cimg_mapoff(data,off) {
+ const int Y = (int)((data[off]-cb)/ca);
+ switch (gtype) {
+ case 0: // plot with segments
+ if (off>0) draw_line((int)((off-1)*width/data.size()),pY,(int)(off*width/data.size()),Y,color,~0L,opacity);
+ break;
+ case 1: { // plot with bars
+ const unsigned int X = off*width/data.size(), nX = (off+1)*width/data.size()-1;
+ draw_rectangle(X,(int)Y0,nX,Y,color1,opacity);
+ draw_line(X,Y,X,(int)Y0,color2,~0L,opacity);
+ draw_line(X,(int)Y0,nX,(int)Y0,Y<=Y0?color2:color,~0L,opacity);
+ draw_line(nX,Y,nX,(int)Y0,color,~0L,opacity);
+ draw_line(X,Y,nX,Y,Y<=Y0?color:color2,~0L,opacity);
+ } break;
+ }
+ pY=Y;
+ }
+ if (gtype==2) { // plot with cubic interpolation
+ const CImg<t> ndata = data.get_shared_points(0,data.size()-1);
+ cimg_mapX(*this,x) {
+ const int Y = (int)((ndata.cubic_pix1d((float)x*ndata.width/width)-cb)/ca);
+ if (x>0) draw_line(x,pY,x+1,Y,color,~0L,opacity);
+ pY=Y;
+ }
+ }
+ delete[] color1; delete[] color2;
+ }
+ return *this;
+ }
+
+ //! Draw a labelled horizontal axis on the instance image.
+ /**
+ \param x0 = lower bound of the x-range.
+ \param x1 = upper bound of the x-range.
+ \param y = Y-coordinate of the horizontal axis in the instance image.
+ \param color = an array of dimv() values of type \c T, defining the drawing color.
+ \param precision = precision of the labels.
+ \param opacity = opacity of the drawing.
+ \note if \c precision==0, precision of the labels is automatically computed.
+ \see draw_graph(), draw_axeY(), draw_axeXY().
+ **/
+ CImg& draw_axeX(const double x0,const double x1,const int y,const T *const color,
+ const double precision=0,const float opacity=1) {
+ if (x0==x1) return *this;
+ if (x0<x1) draw_arrow(0,y,width-1,y,color,30,5,~0L,opacity);
+ else draw_arrow(width-1,y,0,y,color,30,5,~0L,opacity);
+ const int yt = (y+14)<dimy()?(y+3):(y-14);
+ double nprecision=precision;
+ if (precision<=0) {
+ const double nb_pow = std::floor(std::log10(cimg::abs(x1-x0)))-1;
+ nprecision = std::pow(10.0,nb_pow);
+ while ((cimg::abs(x1-x0)/nprecision)>(dimx()/40)) nprecision*=2;
+ }
+ const double xmin=x0<x1?x0:x1, xmax=x0<x1?x1:x0,
+ tx0 = cimg::mod(xmin,nprecision)==0?xmin:((xmin+nprecision)-cimg::mod(xmin+nprecision,nprecision)),
+ tx1 = cimg::mod(xmax,nprecision)==0?xmax:((xmax+nprecision)-cimg::mod(xmax+nprecision,nprecision));
+ char txt[32];
+ for (double x=tx0; x<=tx1; x+=nprecision) {
+ std::sprintf(txt,"%g",x);
+ const int xi=(int)((x-x0)*(width-1)/(x1-x0)), xt = xi-(int)std::strlen(txt)*3;
+ draw_point(xi,y-1,color,opacity).draw_point(xi,y+1,color,opacity).
+ draw_text(txt,xt<0?0:xt,yt,color,0,11,opacity);
+ }
+ return *this;
+ }
+
+ //! Draw a labelled vertical axis on the instance image.
+ /**
+ \param x = X-coordinate of the vertical axis in the instance image.
+ \param y0 = lower bound of the y-range.
+ \param y1 = upper bound of the y-range.
+ \param color = an array of dimv() values of type \c T, defining the drawing color.
+ \param precision = precision of the labels.
+ \param opacity = opacity of the drawing.
+ \note if \c precision==0, precision of the labels is automatically computed.
+ \see draw_graph(), draw_axeX(), draw_axeXY().
+ **/
+ CImg& draw_axeY(const int x,const double y0,const double y1,const T *const color,
+ const double precision=0,const float opacity=1) {
+ if (y0==y1) return *this;
+ if (y0<y1) draw_arrow(x,0,x,height-1,color,30,5,~0L,opacity);
+ else draw_arrow(x,height-1,x,0,color,30,5,~0L,opacity);
+ double nprecision=precision;
+ if (precision<=0) {
+ const double nb_pow = std::floor(std::log10(cimg::abs(y1-y0)))-1;
+ nprecision = std::pow(10.0,nb_pow);
+ while ((cimg::abs(y1-y0)/nprecision)>(dimy()/40)) nprecision*=2;
+ }
+ const double ymin=y0<y1?y0:y1, ymax=y0<y1?y1:y0,
+ ty0 = cimg::mod(ymin,nprecision)==0?ymin:((ymin+nprecision)-cimg::mod(ymin+nprecision,nprecision)),
+ ty1 = cimg::mod(ymax,nprecision)==0?ymax:((ymax+nprecision)-cimg::mod(ymax+nprecision,nprecision));
+ char txt[32];
+ for (double y=ty0; y<=ty1; y+=nprecision) {
+ std::sprintf(txt,"%g",y);
+ const int yi = (int)((y-y0)*(height-1)/(y1-y0)), xt = x-(int)std::strlen(txt)*7;
+ draw_point(x-1,yi,color,opacity).draw_point(x+1,yi,color,opacity);
+ if (xt>0) draw_text(txt,xt,yi-5,color,0,11,opacity);
+ else draw_text(txt,x+3,yi-5,color,0,11,opacity);
+ }
+ return *this;
+ }
+
+ //! Draw a labelled coordinate system (X,Y) on the instance image.
+ /**
+ \param x0 = lower bound of the x-range.
+ \param x1 = upper bound of the x-range.
+ \param y0 = lower bound of the y-range.
+ \param y1 = upper bound of the y-range.
+ \param color = an array of dimv() values of type \c T, defining the drawing color.
+ \param precisionx = precision of the labels along the X-axis.
+ \param precisiony = precision of the labels along the Y-axis.
+ \param opacity = opacity of the drawing.
+ \note if precision==0, precision of the labels along the specified axix is automatically computed.
+ \see draw_graph(), draw_axeX(), draw_axeY().
+ **/
+ CImg& draw_axeXY(const double x0,const double x1,const double y0,const double y1,const T *const color,
+ const double precisionx=0,const double precisiony=0,const float opacity=1) {
+ if (x0*x1<=0) {
+ const int xz = (int)(-x0*(width-1)/(x1-x0));
+ if (xz>=0 && xz<dimx()) draw_axeY(xz,y0,y1,color,precisiony,opacity);
+ }
+ if (y0*y1<=0) {
+ const int yz = (int)(-y0*(height-1)/(y1-y0));
+ if (yz>=0 && yz<dimy()) draw_axeX(x0,x1,yz,color,precisionx,opacity);
+ }
+ return *this;
+ }
+
+ // INNER CLASS used by function CImg<>::draw_fill()
+ template<typename T1,typename T2> struct _draw_fill {
+ const T1 *const color;
+ const float sigma,opacity;
+ const CImg<T1> value;
+ CImg<T2> region;
+
+ _draw_fill(const CImg<T1>& img,const int x,const int y,const int z,
+ const T *const pcolor,const float psigma,const float popacity):
+ color(pcolor),sigma(psigma),opacity(popacity),
+ value(img.get_vector(x,y,z)), region(CImg<T2>(img.width,img.height,img.depth,1,(T2)false)) {
+ }
+
+ _draw_fill& operator=(const _draw_fill& d) {
+ color = d.color;
+ sigma = d.sigma;
+ opacity = d.opacity;
+ value = d.value;
+ region = d.region;
+ return *this;
+ }
+
+ bool comp(const CImg<T1>& A,const CImg<T1>& B) const {
+ bool res=true;
+ const T *pA=A.data+A.size();
+ for (const T *pB=B.data+B.size(); res && pA>A.data; res=(cimg::abs(*(--pA)-(*(--pB)))<=sigma) );
+ return res;
+ }
+
+ void fill(CImg<T1>& img,const int x,const int y,const int z) {
+ if (x<0 || x>=img.dimx() || y<0 || y>=img.dimy() || z<0 || z>=img.dimz()) return;
+ if (!region(x,y,z) && comp(value,img.get_vector(x,y,z))) {
+ const T *col=color;
+ const float nopacity = cimg::abs(opacity), copacity = 1-cimg::max(opacity,0.0f);
+ int xmin,xmax;
+ if (opacity>=1) cimg_mapV(img,k) img(x,y,z,k)=*(col++);
+ else cimg_mapV(img,k) img(x,y,z,k)=(T1)(*(col++)*opacity+copacity*img(x,y,z,k));
+ col-=img.dim;
+ region(x,y,z) = (T2)true;
+ for (xmin=x-1; xmin>=0 && comp(value,img.get_vector(xmin,y,z)); xmin--) {
+ if (opacity>=1) cimg_mapV(img,k) img(xmin,y,z,k) = *(col++);
+ else cimg_mapV(img,k) img(xmin,y,z,k)=(T1)(*(col++)*nopacity+copacity*img(xmin,y,z,k));
+ col-=img.dim;
+ region(xmin,y,z)=(T2)true;
+ }
+ for (xmax=x+1; xmax<img.dimx() && comp(value,img.get_vector(xmax,y,z)); xmax++) {
+ if (opacity>=1) cimg_mapV(img,k) img(xmax,y,z,k) = *(col++);
+ else cimg_mapV(img,k) img(xmax,y,z,k)=(T1)(*(col++)*nopacity+copacity*img(xmax,y,z,k));
+ col-=img.dim;
+ region(xmax,y,z)=(T2)true;
+ }
+ xmin++; xmax--;
+ for (; xmin<=xmax; xmin++) {
+ fill(img,xmin,y-1,z);
+ fill(img,xmin,y+1,z);
+ fill(img,xmin,y,z-1);
+ fill(img,xmin,y,z+1);
+ }
+ }
+ }
+ };
+
+ //! Draw a 3D filled region starting from a point (\c x,\c y,\ z) in the instance image.
+ /**
+ \param x = X-coordinate of the starting point of the region to fill.
+ \param y = Y-coordinate of the starting point of the region to fill.
+ \param z = Z-coordinate of the starting point of the region to fill.
+ \param color = an array of dimv() values of type \c T, defining the drawing color.
+ \param region = image that will contain the tqmask of the filled region tqmask, as an output.
+ \param sigma = tolerance concerning neighborhood values.
+ \param opacity = opacity of the drawing.
+
+ \return \p region is initialized with the binary tqmask of the filled region.
+ **/
+ template<typename t> CImg& draw_fill(const int x,const int y,const int z,
+ const T *const color, CImg<t>& region,const float sigma=0,
+ const float opacity=1) {
+ _draw_fill<T,t> F(*this,x,y,z,color,sigma,opacity);
+ F.fill(*this,x,y,z);
+ region = F.region;
+ return *this;
+ }
+
+ //! Draw a 3D filled region starting from a point (\c x,\c y,\ z) in the instance image.
+ /**
+ \param x = X-coordinate of the starting point of the region to fill.
+ \param y = Y-coordinate of the starting point of the region to fill.
+ \param z = Z-coordinate of the starting point of the region to fill.
+ \param color = an array of dimv() values of type \c T, defining the drawing color.
+ \param sigma = tolerance concerning neighborhood values.
+ \param opacity = opacity of the drawing.
+ **/
+ CImg& draw_fill(const int x,const int y,const int z,const T *const color,const float sigma=0,const float opacity=1) {
+ CImg<bool> tmp;
+ return draw_fill(x,y,z,color,tmp,sigma,opacity);
+ }
+
+ //! Draw a 2D filled region starting from a point (\c x,\c y) in the instance image.
+ /**
+ \param x = X-coordinate of the starting point of the region to fill.
+ \param y = Y-coordinate of the starting point of the region to fill.
+ \param color = an array of dimv() values of type \c T, defining the drawing color.
+ \param sigma = tolerance concerning neighborhood values.
+ \param opacity = opacity of the drawing.
+ **/
+ CImg& draw_fill(const int x,const int y,const T *const color,const float sigma=0,const float opacity=1) {
+ CImg<bool> tmp;
+ return draw_fill(x,y,0,color,tmp,sigma,opacity);
+ }
+
+ //! Draw a plasma square in the instance image.
+ /**
+ \param x0 = X-coordinate of the upper-left corner of the plasma.
+ \param y0 = Y-coordinate of the upper-left corner of the plasma.
+ \param x1 = X-coordinate of the lower-right corner of the plasma.
+ \param y1 = Y-coordinate of the lower-right corner of the plasma.
+ \param alpha = Alpha-parameter of the plasma.
+ \param beta = Beta-parameter of the plasma.
+ \param opacity = opacity of the drawing.
+ **/
+ CImg& draw_plasma(const int x0, const int y0, const int x1, const int y1,
+ const double alpha=1.0, const double beta=1.0, const float opacity=1) {
+ if (!is_empty()) {
+ int nx0=x0,nx1=x1,ny0=y0,ny1=y1;
+ if (nx1<nx0) cimg::swap(nx0,nx1);
+ if (ny1<ny0) cimg::swap(ny0,ny1);
+ if (nx0<0) nx0=0;
+ if (nx1>=dimx()) nx1=width-1;
+ if (ny0<0) ny0=0;
+ if (ny1>=dimy()) ny1=height-1;
+ const int xc = (nx0+nx1)/2, yc = (ny0+ny1)/2, dx=(xc-nx0), dy=(yc-ny0);
+ const double dc = std::sqrt((double)(dx*dx+dy*dy))*alpha + beta;
+ cimg_mapV(*this,k) {
+ if (opacity>=1) {
+ (*this)(xc,ny0,0,k) = (T)(0.5*((*this)(nx0,ny0,0,k)+(*this)(nx1,ny0,0,k)));
+ (*this)(xc,ny1,0,k) = (T)(0.5*((*this)(nx0,ny1,0,k)+(*this)(nx1,ny1,0,k)));
+ (*this)(nx0,yc,0,k) = (T)(0.5*((*this)(nx0,ny0,0,k)+(*this)(nx0,ny1,0,k)));
+ (*this)(nx1,yc,0,k) = (T)(0.5*((*this)(nx1,ny0,0,k)+(*this)(nx1,ny1,0,k)));
+ (*this)(xc,yc,0,k) = (T)(0.25*((*this)(nx0,ny0,0,k)+(*this)(nx1,ny0,0,k) +
+ (*this)(nx1,ny1,0,k)+(*this)(nx0,ny1,0,k)) + dc*cimg::grand());
+ } else {
+ const float nopacity = cimg::abs(opacity), copacity = 1-cimg::max(opacity,0.0f);
+ (*this)(xc,ny0,0,k) = (T)(0.5*((*this)(nx0,ny0,0,k)+(*this)(nx1,ny0,0,k))*nopacity + copacity*(*this)(xc,ny0,0,k));
+ (*this)(xc,ny1,0,k) = (T)(0.5*((*this)(nx0,ny1,0,k)+(*this)(nx1,ny1,0,k))*nopacity + copacity*(*this)(xc,ny1,0,k));
+ (*this)(nx0,yc,0,k) = (T)(0.5*((*this)(nx0,ny0,0,k)+(*this)(nx0,ny1,0,k))*nopacity + copacity*(*this)(nx0,yc,0,k));
+ (*this)(nx1,yc,0,k) = (T)(0.5*((*this)(nx1,ny0,0,k)+(*this)(nx1,ny1,0,k))*nopacity + copacity*(*this)(nx1,yc,0,k));
+ (*this)(xc,yc,0,k) = (T)(0.25*(((*this)(nx0,ny0,0,k)+(*this)(nx1,ny0,0,k) +
+ (*this)(nx1,ny1,0,k)+(*this)(nx0,ny1,0,k)) + dc*cimg::grand())*nopacity
+ + copacity*(*this)(xc,yc,0,k));
+ }
+ }
+ if (xc!=nx0 || yc!=ny0) {
+ draw_plasma(nx0,ny0,xc,yc,alpha,beta,opacity);
+ draw_plasma(xc,ny0,nx1,yc,alpha,beta,opacity);
+ draw_plasma(nx0,yc,xc,ny1,alpha,beta,opacity);
+ draw_plasma(xc,yc,nx1,ny1,alpha,beta,opacity);
+ }
+ }
+ return *this;
+ }
+
+ //! Draw a plasma in the instance image.
+ /**
+ \param alpha = Alpha-parameter of the plasma.
+ \param beta = Beta-parameter of the plasma.
+ \param opacity = opacity of the drawing.
+ **/
+ CImg& draw_plasma(const double alpha=1.0,const double beta=1.0,const float opacity=1) {
+ return draw_plasma(0,0,width-1,height-1,alpha,beta,opacity);
+ }
+
+ //! Draw a 1D gaussian function in the instance image.
+ /**
+ \param xc = X-coordinate of the gaussian center.
+ \param sigma = Standard variation of the gaussian distribution.
+ \param color = array of dimv() values of type \c T, defining the drawing color.
+ \param opacity = opacity of the drawing.
+ **/
+ CImg& draw_gaussian(const float xc,const double sigma,const T *const color,const float opacity=1) {
+ if (!is_empty()) {
+ if (!color) throw CImgArgumentException("CImg<%s>::draw_gaussian() : Specified color is (null)",pixel_type());
+ const double sigma2 = 2*sigma*sigma;
+ const float nopacity = cimg::abs(opacity), copacity = 1-cimg::max(opacity,0.0f);
+ const unsigned int whz = width*height*depth;
+ const T *col = color;
+ cimg_mapX(*this,x) {
+ const float dx = (x-xc);
+ const double val = std::exp( -dx*dx/sigma2 );
+ T *ptrd = ptr(x,0,0,0);
+ if (opacity>=1) cimg_mapV(*this,k) { *ptrd = (T)(val*(*col++)); ptrd+=whz; }
+ else cimg_mapV(*this,k) { *ptrd = (T)(nopacity*val*(*col++) + copacity*(*ptrd)); ptrd+=whz; }
+ col-=dim;
+ }
+ }
+ return *this;
+ }
+
+ //! Draw an anisotropic 2D gaussian function in the instance image.
+ /**
+ \param xc = X-coordinate of the gaussian center.
+ \param yc = Y-coordinate of the gaussian center.
+ \param tensor = 2x2 covariance matrix.
+ \param color = array of dimv() values of type \c T, defining the drawing color.
+ \param opacity = opacity of the drawing.
+ **/
+ template<typename t> CImg& draw_gaussian(const float xc,const float yc,const CImg<t>& tensor,
+ const T *const color,const float opacity=1) {
+ if (!is_empty()) {
+ if (tensor.width!=2 || tensor.height!=2 || tensor.depth!=1 || tensor.dim!=1)
+ throw CImgArgumentException("CImg<%s>::draw_gaussian() : Tensor parameter (%u,%u,%u,%u,%p) is not a 2x2 matrix.",
+ pixel_type(),tensor.width,tensor.height,tensor.depth,tensor.dim,tensor.data);
+ if (!color) throw CImgArgumentException("CImg<%s>::draw_gaussian() : Specified color is (null)",pixel_type());
+ const CImg<t> invT = tensor.get_inverse(), invT2 = (invT*invT)/(-2.0);
+ const t &a=invT2(0,0), &b=2*invT2(1,0), &c=invT2(1,1);
+ const float nopacity = cimg::abs(opacity), copacity = 1-cimg::max(opacity,0.0f);
+ const unsigned int whz = width*height*depth;
+ const T *col = color;
+ float dy = -yc;
+ cimg_mapY(*this,y) {
+ float dx = -xc;
+ cimg_mapX(*this,x) {
+ const float val = (float)std::exp(a*dx*dx + b*dx*dy + c*dy*dy);
+ T *ptrd = ptr(x,y,0,0);
+ if (opacity>=1) cimg_mapV(*this,k) { *ptrd = (T)(val*(*col++)); ptrd+=whz; }
+ else cimg_mapV(*this,k) { *ptrd = (T)(nopacity*val*(*col++) + copacity*(*ptrd)); ptrd+=whz; }
+ col-=dim;
+ dx++;
+ }
+ dy++;
+ }
+ }
+ return *this;
+ }
+
+ //! Draw an isotropic 2D gaussian function in the instance image
+ /**
+ \param xc = X-coordinate of the gaussian center.
+ \param yc = Y-coordinate of the gaussian center.
+ \param sigma = standard variation of the gaussian distribution.
+ \param color = array of dimv() values of type \c T, defining the drawing color.
+ \param opacity = opacity of the drawing.
+ **/
+ CImg& draw_gaussian(const float xc,const float yc,const float sigma,const T *const color,const float opacity=1) {
+ return draw_gaussian(xc,yc,CImg<float>::diagonal(sigma,sigma),color,opacity);
+ }
+
+ //! Draw an anisotropic 3D gaussian function in the instance image.
+ /**
+ \param xc = X-coordinate of the gaussian center.
+ \param yc = Y-coordinate of the gaussian center.
+ \param zc = Z-coordinate of the gaussian center.
+ \param tensor = 3x3 covariance matrix.
+ \param color = array of dimv() values of type \c T, defining the drawing color.
+ \param opacity = opacity of the drawing.
+ **/
+ template<typename t> CImg& draw_gaussian(const float xc,const float yc,const float zc,const CImg<t>& tensor,
+ const T *const color,const float opacity=1) {
+ if (!is_empty()) {
+ if (tensor.width!=3 || tensor.height!=3 || tensor.depth!=1 || tensor.dim!=1)
+ throw CImgArgumentException("CImg<%s>::draw_gaussian() : Tensor parameter (%u,%u,%u,%u,%p) is not a 3x3 matrix.",
+ pixel_type(),tensor.width,tensor.height,tensor.depth,tensor.dim,tensor.data);
+ const CImg<t> invT = tensor.get_inverse(), invT2 = (invT*invT)/(-2.0);
+ const t a=invT(0,0), b=2*invT(1,0), c=2*invT(2,0), d=invT(1,1), e=2*invT(2,1), f=invT(2,2);
+ const float nopacity = cimg::abs(opacity), copacity = 1-cimg::max(opacity,0.0f);
+ const unsigned int whz = width*height*depth;
+ const T *col = color;
+ cimg_mapXYZ(*this,x,y,z) {
+ const float dx = (x-xc), dy = (y-yc), dz = (z-zc);
+ const double val = std::exp(a*dx*dx + b*dx*dy + c*dx*dz + d*dy*dy + e*dy*dz + f*dz*dz);
+ T *ptrd = ptr(x,y,z,0);
+ if (opacity>=1) cimg_mapV(*this,k) { *ptrd = (T)(val*(*col++)); ptrd+=whz; }
+ else cimg_mapV(*this,k) { *ptrd = (T)(nopacity*val*(*col++) + copacity*(*ptrd)); ptrd+=whz; }
+ col-=dim;
+ }
+ }
+ return *this;
+ }
+
+ //! Draw an isotropic 3D gaussian function in the instance image
+ /**
+ \param xc = X-coordinate of the gaussian center.
+ \param yc = Y-coordinate of the gaussian center.
+ \param zc = Z-coordinate of the gaussian center.
+ \param sigma = standard variation of the gaussian distribution.
+ \param color = array of dimv() values of type \c T, defining the drawing color.
+ \param opacity = opacity of the drawing.
+ **/
+ CImg& draw_gaussian(const float xc,const float yc,const float zc,
+ const double sigma,const T *const color,const float opacity=1) {
+ return draw_gaussian(xc,yc,zc,CImg<float>::diagonal(sigma,sigma,sigma),color,opacity);
+ }
+
+ //! Draw a 3D object in the instance image
+ /**
+ \param X = X-coordinate of the 3d object position
+ \param Y = Y-coordinate of the 3d object position
+ \param Z = Z-coordinate of the 3d object position
+ \param points = Image N*3 describing 3D point coordinates
+ \param primitives = List of P primitives
+ \param colors = List of P color (or textures)
+ \param opacities = Image of P opacities
+ \param render_type = Render type (0=Points, 1=Lines, 2=Faces (no light), 3=Faces (flat), 4=Faces(Gouraud)
+ \param double_sided = Tell if object faces have two sides or are oriented.
+ \param focale = length of the focale
+ \param lightx = X-coordinate of the light
+ \param lighty = Y-coordinate of the light
+ \param lightz = Z-coordinate of the light
+ \param ambiant_light = Brightness (between 0..1) of the ambiant light
+ **/
+ template<typename tp, typename tf, typename to>
+ CImg& draw_object3d(const float X, const float Y, const float Z,
+ const CImg<tp>& points, const CImgl<tf>& primitives,
+ const CImgl<T>& colors, const CImg<to>& opacities,
+ const unsigned int render_type=4,
+ const bool double_sided=false, const float focale=500,
+ const float lightx=0, const float lighty=0, const float lightz=-5000,
+ const float ambiant_light = 0.05f) {
+
+ static CImg<float> light_texture;
+ if (is_empty() || points.is_empty() || primitives.is_empty() || colors.is_empty()) return *this;
+ if (opacities.is_empty())
+ return draw_object3d(X,Y,Z,points,primitives,colors,CImg<to>(primitives.size,1,1,1,(to)1),
+ render_type,double_sided,focale,lightx,lighty,lightz,ambiant_light);
+ if (points.height<3)
+ return draw_object3d(X,Y,Z,points.get_resize(-100,3,1,1,0),primitives,colors,opacities,
+ render_type,double_sided,focale,lightx,lighty,lightz,ambiant_light);
+ if (colors.size<primitives.size)
+ throw CImgArgumentException("CImg<%s>::draw_object3d() : Not enough defined colors (size=%u) regarding primitives (size=%u).",
+ pixel_type(),colors.size,primitives.size);
+ if (opacities.width<primitives.size)
+ throw CImgArgumentException("CImg<%s>::draw_object3d() : Not enough defined opacities (size=%u) regarding primitives (size=%u).",
+ pixel_type(),opacities.width,primitives.size);
+
+ // Create light texture
+ if (render_type==5) {
+ if (colors.size>primitives.size) light_texture = colors[primitives.size];
+ else {
+ static float olightx=0, olighty=0, olightz=0, oambiant_light=0;
+ if (light_texture.is_empty() || lightx!=olightx || lighty!=olighty || lightz!=olightz || ambiant_light!=oambiant_light) {
+ light_texture.assign(512,512);
+ const float white[1]={ 1.0f },
+ dlx = lightx-X, dly = lighty-Y, dlz = lightz-Z,
+ nl = (float)std::sqrt(dlx*dlx+dly*dly+dlz*dlz),
+ nlx = light_texture.width/2*(1+dlx/nl),
+ nly = light_texture.height/2*(1+dly/nl);
+ (light_texture.draw_gaussian(nlx,nly,light_texture.width/3.0f,white)+=ambiant_light).cut(0.0f,1.0f);
+ olightx = lightx; olighty = lighty; olightz = lightz; oambiant_light = ambiant_light;
+ }
+ }
+ }
+
+ // Compute 3D to 2D projection
+ CImg<float> projected(points.width,2);
+ cimg_mapX(points,l) {
+ const float
+ x = (float)points(l,0),
+ y = (float)points(l,1),
+ z = (float)points(l,2);
+ const float projectedz = z + Z + focale;
+ projected(l,1) = Y + focale*y/projectedz;
+ projected(l,0) = X + focale*x/projectedz;
+ }
+
+ // Compute and sort visible primitives
+ CImg<unsigned int> visibles(primitives.size);
+ CImg<float> zrange(primitives.size);
+ unsigned int nb_visibles = 0;
+ const float zmin = -focale;
+ { cimgl_map(primitives,l) {
+ const CImg<tf>& primitive = primitives[l];
+ switch (primitive.size()) {
+ case 1: { // Point
+ const unsigned int i0 = (unsigned int)primitive(0);
+ const float z0 = (float)(Z+points(i0,2));
+ if (z0>zmin) {
+ visibles(nb_visibles) = (unsigned int)l;
+ zrange(nb_visibles++) = z0;
+ }
+ } break;
+ case 2: // Line or textured line
+ case 6: {
+ const unsigned int
+ i0 = (unsigned int)primitive(0),
+ i1 = (unsigned int)primitive(1);
+ const float
+ z0 = (float)(Z+points(i0,2)),
+ z1 = (float)(Z+points(i1,2));
+ if (z0>zmin && z1>zmin) {
+ visibles(nb_visibles) = (unsigned int)l;
+ zrange(nb_visibles++) = 0.5f*(z0+z1);
+ }
+ } break;
+ case 3: // Triangle or textured triangle
+ case 9: {
+ const unsigned int
+ i0 = (unsigned int)primitive(0),
+ i1 = (unsigned int)primitive(1),
+ i2 = (unsigned int)primitive(2);
+ const float
+ z0 = (float)(Z+points(i0,2)),
+ z1 = (float)(Z+points(i1,2)),
+ z2 = (float)(Z+points(i2,2));
+ if (z0>zmin && z1>zmin && z2>zmin) {
+ const float
+ x0 = projected(i0,0), y0 = projected(i0,1),
+ x1 = projected(i1,0), y1 = projected(i1,1),
+ x2 = projected(i2,0), y2 = projected(i2,1),
+ dx1 = x1-x0, dy1 = y1-y0, dx2 = x2-x0, dy2 = y2-y0;
+ if (double_sided || dx1*dy2-dx2*dy1<0) {
+ visibles(nb_visibles) = (unsigned int)l;
+ zrange(nb_visibles++) = (z0+z1+z2)/3;
+ }
+ }
+ } break;
+ case 4: // Rectangle or textured rectangle
+ case 12: {
+ const unsigned int
+ i0 = (unsigned int)primitive(0),
+ i1 = (unsigned int)primitive(1),
+ i2 = (unsigned int)primitive(2),
+ i3 = (unsigned int)primitive(3);
+ const float
+ z0 = (float)(Z+points(i0,2)),
+ z1 = (float)(Z+points(i1,2)),
+ z2 = (float)(Z+points(i2,2)),
+ z3 = (float)(Z+points(i3,2));
+ if (z0>zmin && z1>zmin && z2>zmin && z3>zmin) {
+ const float
+ x0 = projected(i0,0), y0 = projected(i0,1),
+ x1 = projected(i1,0), y1 = projected(i1,1),
+ x2 = projected(i2,0), y2 = projected(i2,1),
+ dx1 = x1-x0, dy1 = y1-y0, dx2 = x2-x0, dy2 = y2-y0;
+ if (double_sided || dx1*dy2-dx2*dy1<0) {
+ visibles(nb_visibles) = (unsigned int)l;
+ zrange(nb_visibles++) = (z0+z1+z2+z3)/4;
+ }
+ }
+ } break;
+ default:
+ throw CImgArgumentException("CImg<%s>::draw_object3d() : Primitive %u is invalid (size = %u, can be 1,2,3,4,6,9 or 12)",
+ pixel_type(),l,primitive.size());
+ }}
+ }
+ if (nb_visibles<=0) return *this;
+ CImg<unsigned int> permutations;
+ CImg<float>(zrange.data,nb_visibles,1,1,1,true).sort(permutations,false);
+
+ // Compute light properties
+ CImg<float> lightprops;
+ switch (render_type) {
+ case 3: { // Flat Shading
+ lightprops.assign(nb_visibles);
+ cimg_mapX(lightprops,l) {
+ const CImg<tf>& primitive = primitives(visibles(permutations(l)));
+ const unsigned int psize = primitive.size();
+ if (psize==3 || psize==4 || psize==9 || psize==12) {
+ const unsigned int
+ i0 = (unsigned int)primitive(0),
+ i1 = (unsigned int)primitive(1),
+ i2 = (unsigned int)primitive(2);
+ const float
+ x0 = (float)points(i0,0), y0 = (float)points(i0,1), z0 = (float)points(i0,2),
+ x1 = (float)points(i1,0), y1 = (float)points(i1,1), z1 = (float)points(i1,2),
+ x2 = (float)points(i2,0), y2 = (float)points(i2,1), z2 = (float)points(i2,2),
+ dx1 = x1-x0, dy1 = y1-y0, dz1 = z1-z0,
+ dx2 = x2-x0, dy2 = y2-y0, dz2 = z2-z0,
+ nx = dy1*dz2-dz1*dy2,
+ ny = dz1*dx2-dx1*dz2,
+ nz = dx1*dy2-dy1*dx2,
+ norm = (float)std::sqrt(1e-5f+nx*nx+ny*ny+nz*nz),
+ lx = X+(x0+x1+x2)/3-lightx,
+ ly = Y+(y0+y1+y2)/3-lighty,
+ lz = Z+(z0+z1+z2)/3-lightz,
+ nl = (float)std::sqrt(1e-5f+lx*lx+ly*ly+lz*lz),
+ factor = (-lx*nx-ly*ny-lz*nz)/(norm*nl),
+ nfactor = double_sided?cimg::abs(factor):cimg::max(factor,0.0f);
+ lightprops[l] = cimg::min(nfactor+ambiant_light,1.0f);
+ } else lightprops[l] = 1.0f;
+ }
+ } break;
+
+ case 4: // Gouraud Shading
+ case 5: { // Phong-Shading
+ CImg<float> points_normals(points.width,3,1,1,0);
+ cimgl_map(primitives,l) {
+ const CImg<tf>& primitive = primitives[l];
+ const unsigned int psize = primitive.size();
+ const bool
+ triangle_flag = (psize==3) || (psize==9),
+ rectangle_flag = (psize==4) || (psize==12);
+ if (triangle_flag || rectangle_flag) {
+ const unsigned int
+ i0 = (unsigned int)primitive(0),
+ i1 = (unsigned int)primitive(1),
+ i2 = (unsigned int)primitive(2),
+ i3 = rectangle_flag?(unsigned int)primitive(3):0;
+ const float
+ x0 = (float)points(i0,0), y0 = (float)points(i0,1), z0 = (float)points(i0,2)+Z,
+ x1 = (float)points(i1,0), y1 = (float)points(i1,1), z1 = (float)points(i1,2)+Z,
+ x2 = (float)points(i2,0), y2 = (float)points(i2,1), z2 = (float)points(i2,2)+Z,
+ dx1 = x1-x0, dy1 = y1-y0, dz1 = z1-z0,
+ dx2 = x2-x0, dy2 = y2-y0, dz2 = z2-z0,
+ nx = dy1*dz2-dz1*dy2,
+ ny = dz1*dx2-dx1*dz2,
+ nz = dx1*dy2-dy1*dx2,
+ norm = (float)std::sqrt(1e-5f+nx*nx+ny*ny+nz*nz),
+ nnx = nx/norm,
+ nny = ny/norm,
+ nnz = nz/norm;
+ points_normals(i0,0)+=nnx; points_normals(i0,1)+=nny; points_normals(i0,2)+=nnz;
+ points_normals(i1,0)+=nnx; points_normals(i1,1)+=nny; points_normals(i1,2)+=nnz;
+ points_normals(i2,0)+=nnx; points_normals(i2,1)+=nny; points_normals(i2,2)+=nnz;
+ if (rectangle_flag) {
+ points_normals(i3,0)+=nnx; points_normals(i3,1)+=nny; points_normals(i3,2)+=nnz;
+ }
+ }
+ }
+
+ if (render_type==4) {
+ lightprops.assign(points.width);
+ cimg_mapX(points,ll) {
+ const float
+ nx = points_normals(ll,0),
+ ny = points_normals(ll,1),
+ nz = points_normals(ll,2),
+ norm = (float)std::sqrt(1e-5f+nx*nx+ny*ny+nz*nz),
+ lx = (float)(X+points(ll,0)-lightx),
+ ly = (float)(Y+points(ll,1)-lighty),
+ lz = (float)(Z+points(ll,2)-lightz),
+ nl = (float)std::sqrt(1e-5f+lx*lx+ly*ly+lz*lz),
+ factor = (-lx*nx-ly*ny-lz*nz)/(norm*nl),
+ nfactor = double_sided?cimg::abs(factor):cimg::max(factor,0.0f);
+ lightprops[ll] = cimg::min(nfactor+ambiant_light,1.0f);
+ }
+ } else {
+ lightprops.assign(points.width,2);
+ cimg_mapX(points,ll) {
+ const float
+ nx = points_normals(ll,0),
+ ny = points_normals(ll,1),
+ nz = points_normals(ll,2),
+ norm = (float)std::sqrt(1e-5f+nx*nx+ny*ny+nz*nz),
+ nnx = nx/norm, nny = ny/norm;
+ lightprops(ll,0) = (light_texture.width/2-1)*(1+nnx);
+ lightprops(ll,1) = (light_texture.height/2-1)*(1+nny);
+ }
+ }
+ } break;
+ }
+
+ // Draw visible primitives
+ { for (unsigned int l=0; l<nb_visibles; l++) {
+ const unsigned int n_primitive = visibles(permutations(l));
+ const CImg<tf>& primitive = primitives[n_primitive];
+ const CImg<T>& color = colors[n_primitive];
+ const float opacity = (float)opacities(n_primitive,0);
+
+ switch (primitive.size()) {
+ case 1: { // colored point
+ const unsigned int n0 = (unsigned int)primitive[0];
+ const int x0 = (int)projected(n0,0), y0 = (int)projected(n0,1);
+ draw_point(x0,y0,color.ptr(),opacity);
+ } break;
+ case 2: { // colored line
+ const unsigned int
+ n0 = (unsigned int)primitive[0],
+ n1 = (unsigned int)primitive[1];
+ const int
+ x0 = (int)projected(n0,0), y0 = (int)projected(n0,1),
+ x1 = (int)projected(n1,0), y1 = (int)projected(n1,1);
+ if (render_type) draw_line(x0,y0,x1,y1,color.ptr(),~0L,opacity);
+ else draw_point(x0,y0,color.ptr(),opacity).draw_point(x1,y1,color.ptr(),opacity);
+ } break;
+ case 6: { // textured line
+ const unsigned int
+ n0 = (unsigned int)primitive[0],
+ n1 = (unsigned int)primitive[1],
+ tx0 = (unsigned int)primitive[2],
+ ty0 = (unsigned int)primitive[3],
+ tx1 = (unsigned int)primitive[4],
+ ty1 = (unsigned int)primitive[5];
+ const int
+ x0 = (int)projected(n0,0), y0 = (int)projected(n0,1),
+ x1 = (int)projected(n1,0), y1 = (int)projected(n1,1);
+ if (render_type) draw_line(x0,y0,x1,y1,color,tx0,ty0,tx1,ty1,opacity);
+ else draw_point(x0,y0,color.get_vector(tx0,ty0).ptr(),opacity).
+ draw_point(x1,y1,color.get_vector(tx1,ty1).ptr(),opacity);
+ } break;
+ case 3: { // colored triangle
+ const unsigned int
+ n0 = (unsigned int)primitive[0],
+ n1 = (unsigned int)primitive[1],
+ n2 = (unsigned int)primitive[2];
+ const int
+ x0 = (int)projected(n0,0), y0 = (int)projected(n0,1),
+ x1 = (int)projected(n1,0), y1 = (int)projected(n1,1),
+ x2 = (int)projected(n2,0), y2 = (int)projected(n2,1);
+ switch(render_type) {
+ case 0:
+ draw_point(x0,y0,color.ptr(),opacity).draw_point(x1,y1,color.ptr(),opacity).draw_point(x2,y2,color.ptr(),opacity);
+ break;
+ case 1:
+ draw_line(x0,y0,x1,y1,color.ptr(),~0L,opacity).draw_line(x0,y0,x2,y2,color.ptr(),~0L,opacity).
+ draw_line(x1,y1,x2,y2,color.ptr(),~0L,opacity);
+ break;
+ case 2:
+ draw_triangle(x0,y0,x1,y1,x2,y2,color.ptr(),opacity);
+ break;
+ case 3:
+ draw_triangle(x0,y0,x1,y1,x2,y2,color.ptr(),opacity,lightprops(l));
+ break;
+ case 4:
+ draw_triangle(x0,y0,x1,y1,x2,y2,color.ptr(),lightprops(n0),lightprops(n1),lightprops(n2),opacity);
+ break;
+ case 5:
+ draw_triangle(x0,y0,x1,y1,x2,y2,color.ptr(),light_texture,
+ (unsigned int)lightprops(n0,0), (unsigned int)lightprops(n0,1),
+ (unsigned int)lightprops(n1,0), (unsigned int)lightprops(n1,1),
+ (unsigned int)lightprops(n2,0), (unsigned int)lightprops(n2,1),
+ opacity);
+ break;
+ }
+ } break;
+ case 4: { // colored rectangle
+ const unsigned int
+ n0 = (unsigned int)primitive[0],
+ n1 = (unsigned int)primitive[1],
+ n2 = (unsigned int)primitive[2],
+ n3 = (unsigned int)primitive[3];
+ const int
+ x0 = (int)projected(n0,0), y0 = (int)projected(n0,1),
+ x1 = (int)projected(n1,0), y1 = (int)projected(n1,1),
+ x2 = (int)projected(n2,0), y2 = (int)projected(n2,1),
+ x3 = (int)projected(n3,0), y3 = (int)projected(n3,1);
+ switch(render_type) {
+ case 0:
+ draw_point(x0,y0,color.ptr(),opacity).draw_point(x1,y1,color.ptr(),opacity).
+ draw_point(x2,y2,color.ptr(),opacity).draw_point(x3,y3,color.ptr(),opacity);
+ break;
+ case 1:
+ draw_line(x0,y0,x1,y1,color.ptr(),~0L,opacity).draw_line(x1,y1,x2,y2,color.ptr(),~0L,opacity).
+ draw_line(x2,y2,x3,y3,color.ptr(),~0L,opacity).draw_line(x3,y3,x0,y0,color.ptr(),~0L,opacity);
+ break;
+ case 2:
+ draw_triangle(x0,y0,x1,y1,x2,y2,color.ptr(),opacity).draw_triangle(x0,y0,x2,y2,x3,y3,color.ptr(),opacity);
+ break;
+ case 3:
+ draw_triangle(x0,y0,x1,y1,x2,y2,color.ptr(),opacity,lightprops(l)).
+ draw_triangle(x0,y0,x2,y2,x3,y3,color.ptr(),opacity,lightprops(l));
+ break;
+ case 4: {
+ const float
+ lightprop0 = lightprops(n0), lightprop1 = lightprops(n1),
+ lightprop2 = lightprops(n2), lightprop3 = lightprops(n3);
+ draw_triangle(x0,y0,x1,y1,x2,y2,color.ptr(),lightprop0,lightprop1,lightprop2,opacity).
+ draw_triangle(x0,y0,x2,y2,x3,y3,color.ptr(),lightprop0,lightprop2,lightprop3,opacity);
+ } break;
+ case 5: {
+ const unsigned int
+ lx0 = (unsigned int)lightprops(n0,0), ly0 = (unsigned int)lightprops(n0,1),
+ lx1 = (unsigned int)lightprops(n1,0), ly1 = (unsigned int)lightprops(n1,1),
+ lx2 = (unsigned int)lightprops(n2,0), ly2 = (unsigned int)lightprops(n2,1),
+ lx3 = (unsigned int)lightprops(n3,0), ly3 = (unsigned int)lightprops(n3,1);
+ draw_triangle(x0,y0,x1,y1,x2,y2,color.ptr(),light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity).
+ draw_triangle(x0,y0,x2,y2,x3,y3,color.ptr(),light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opacity);
+ } break;
+ }
+ } break;
+ case 9: { // Textured triangle
+ const unsigned int
+ n0 = (unsigned int)primitive[0],
+ n1 = (unsigned int)primitive[1],
+ n2 = (unsigned int)primitive[2],
+ tx0 = (unsigned int)primitive[3],
+ ty0 = (unsigned int)primitive[4],
+ tx1 = (unsigned int)primitive[5],
+ ty1 = (unsigned int)primitive[6],
+ tx2 = (unsigned int)primitive[7],
+ ty2 = (unsigned int)primitive[8];
+ const int
+ x0 = (int)projected(n0,0), y0 = (int)projected(n0,1),
+ x1 = (int)projected(n1,0), y1 = (int)projected(n1,1),
+ x2 = (int)projected(n2,0), y2 = (int)projected(n2,1);
+ switch(render_type) {
+ case 0:
+ draw_point(x0,y0,color.get_vector(tx0,ty0).ptr(),opacity).
+ draw_point(x1,y1,color.get_vector(tx1,ty1).ptr(),opacity).
+ draw_point(x2,y2,color.get_vector(tx2,ty2).ptr(),opacity);
+ break;
+ case 1:
+ draw_line(x0,y0,x1,y1,color,tx0,ty0,tx1,ty1,opacity).
+ draw_line(x0,y0,x2,y2,color,tx0,ty0,tx2,ty2,opacity).
+ draw_line(x1,y1,x2,y2,color,tx1,ty1,tx2,ty2,opacity);
+ break;
+ case 2:
+ draw_triangle(x0,y0,x1,y1,x2,y2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity);
+ break;
+ case 3:
+ draw_triangle(x0,y0,x1,y1,x2,y2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l));
+ break;
+ case 4:
+ draw_triangle(x0,y0,x1,y1,x2,y2,color,tx0,ty0,tx1,ty1,tx2,ty2,lightprops(n0),lightprops(n1),lightprops(n2),opacity);
+ break;
+ case 5:
+ draw_triangle(x0,y0,x1,y1,x2,y2,color,tx0,ty0,tx1,ty1,tx2,ty2,light_texture,
+ (unsigned int)lightprops(n0,0), (unsigned int)lightprops(n0,1),
+ (unsigned int)lightprops(n1,0), (unsigned int)lightprops(n1,1),
+ (unsigned int)lightprops(n2,0), (unsigned int)lightprops(n2,1),
+ opacity);
+ break;
+ }
+ } break;
+ case 12: { // Textured rectangle
+ const unsigned int
+ n0 = (unsigned int)primitive[0],
+ n1 = (unsigned int)primitive[1],
+ n2 = (unsigned int)primitive[2],
+ n3 = (unsigned int)primitive[3],
+ tx0 = (unsigned int)primitive[4],
+ ty0 = (unsigned int)primitive[5],
+ tx1 = (unsigned int)primitive[6],
+ ty1 = (unsigned int)primitive[7],
+ tx2 = (unsigned int)primitive[8],
+ ty2 = (unsigned int)primitive[9],
+ tx3 = (unsigned int)primitive[10],
+ ty3 = (unsigned int)primitive[11];
+ const int
+ x0 = (int)projected(n0,0), y0 = (int)projected(n0,1),
+ x1 = (int)projected(n1,0), y1 = (int)projected(n1,1),
+ x2 = (int)projected(n2,0), y2 = (int)projected(n2,1),
+ x3 = (int)projected(n3,0), y3 = (int)projected(n3,1);
+ switch(render_type) {
+ case 0:
+ draw_point(x0,y0,color.get_vector(tx0,ty0).ptr(),opacity).
+ draw_point(x1,y1,color.get_vector(tx1,ty1).ptr(),opacity).
+ draw_point(x2,y2,color.get_vector(tx2,ty2).ptr(),opacity).
+ draw_point(x3,y3,color.get_vector(tx3,ty3).ptr(),opacity);
+ break;
+ case 1:
+ draw_line(x0,y0,x1,y1,color,tx0,ty0,tx1,ty1,opacity).
+ draw_line(x1,y1,x2,y2,color,tx1,ty1,tx2,ty2,opacity).
+ draw_line(x2,y2,x3,y3,color,tx2,ty2,tx3,ty3,opacity).
+ draw_line(x3,y3,x0,y0,color,tx3,ty3,tx0,ty0,opacity);
+ break;
+ case 2:
+ draw_triangle(x0,y0,x1,y1,x2,y2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity).
+ draw_triangle(x0,y0,x2,y2,x3,y3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity);
+ break;
+ case 3:
+ draw_triangle(x0,y0,x1,y1,x2,y2,color,tx0,ty0,tx1,ty1,tx2,ty2,opacity,lightprops(l)).
+ draw_triangle(x0,y0,x2,y2,x3,y3,color,tx0,ty0,tx2,ty2,tx3,ty3,opacity,lightprops(l));
+ break;
+ case 4: {
+ const float
+ lightprop0 = lightprops(n0), lightprop1 = lightprops(n1),
+ lightprop2 = lightprops(n2), lightprop3 = lightprops(n3);
+ draw_triangle(x0,y0,x1,y1,x2,y2,color,tx0,ty0,tx1,ty1,tx2,ty2,lightprop0,lightprop1,lightprop2,opacity).
+ draw_triangle(x0,y0,x2,y2,x3,y3,color,tx0,ty0,tx2,ty2,tx3,ty3,lightprop0,lightprop2,lightprop3,opacity);
+ } break;
+ case 5: {
+ const unsigned int
+ lx0 = (unsigned int)lightprops(n0,0), ly0 = (unsigned int)lightprops(n0,1),
+ lx1 = (unsigned int)lightprops(n1,0), ly1 = (unsigned int)lightprops(n1,1),
+ lx2 = (unsigned int)lightprops(n2,0), ly2 = (unsigned int)lightprops(n2,1),
+ lx3 = (unsigned int)lightprops(n3,0), ly3 = (unsigned int)lightprops(n3,1);
+ draw_triangle(x0,y0,x1,y1,x2,y2,color,tx0,ty0,tx1,ty1,tx2,ty2,light_texture,lx0,ly0,lx1,ly1,lx2,ly2,opacity).
+ draw_triangle(x0,y0,x2,y2,x3,y3,color,tx0,ty0,tx1,ty1,tx2,ty2,light_texture,lx0,ly0,lx2,ly2,lx3,ly3,opacity);
+ } break;
+ }
+ } break;
+ }
+ }
+ }
+ return *this;
+ }
+
+ //! Draw a 3D object in the instance image
+ template<typename tp, typename tf, typename to>
+ CImg& draw_object3d(const float X, const float Y, const float Z,
+ const CImg<tp>& points, const CImgl<tf>& primitives,
+ const CImgl<T>& colors, const CImgl<to>& opacities,
+ const unsigned int render_type=4,
+ const bool double_sided=false, const float focale=500,
+ const float lightx=0, const float lighty=0, const float lightz=-5000,
+ const float ambiant_light = 0.05f) {
+ if (opacities.is_empty())
+ return draw_object3d(X,Y,Z,points,primitives,colors,CImg<to>(),
+ render_type,double_sided,focale,lightx,lighty,lightz,ambiant_light);
+ CImg<to> nopacities(opacities.size);
+ to *ptrd = nopacities.ptr();
+ cimg_mapoff(nopacities,l) if (opacities(l).size()) *(ptrd++) = opacities(l,0);
+ else
+ throw CImgArgumentException("CImg<%s>::draw_object3d() : Given opacities (size=%u) contains a null element at "
+ "position %u.",pixel_type(),opacities.size,l);
+ return draw_object3d(X,Y,Z,points,primitives,colors,nopacities,
+ render_type,double_sided,focale,lightx,lighty,lightz,ambiant_light);
+ }
+
+ //! Draw a 3D object in the instance image
+ template<typename tp, typename tf, typename to>
+ CImg& draw_object3d(const float X, const float Y, const float Z,
+ const CImgl<tp>& points, const CImgl<tf>& primitives,
+ const CImgl<T>& colors, const CImg<to>& opacities,
+ const unsigned int render_type=4,
+ const bool double_sided=false, const float focale=500,
+ const float lightx=0, const float lighty=0, const float lightz=-5000,
+ const float ambiant_light = 0.05f) {
+ if (points.is_empty()) return *this;
+ CImg<tp> npoints(points.size,3,1,1,0);
+ tp *ptrX = npoints.ptr(), *ptrY = npoints.ptr(0,1), *ptrZ = npoints.ptr(0,2);
+ cimg_mapX(npoints,l) {
+ const CImg<tp>& point = points[l];
+ const unsigned int siz = point.size();
+ if (!siz)
+ throw CImgArgumentException("CImg<%s>::draw_object3d() : Given points (size=%u) contains a null element at "
+ "position %u.",pixel_type(),points.size,l);
+ *(ptrZ++) = (siz>2)?point(2):0;
+ *(ptrY++) = (siz>1)?point(1):0;
+ *(ptrX++) = point(0);
+ }
+ return draw_object3d(X,Y,Z,npoints,primitives,colors,opacities,
+ render_type,double_sided,focale,lightx,lighty,lightz,ambiant_light);
+ }
+
+ //! Draw a 3D object in the instance image
+ template<typename tp, typename tf, typename to>
+ CImg& draw_object3d(const float X, const float Y, const float Z,
+ const CImgl<tp>& points, const CImgl<tf>& primitives,
+ const CImgl<T>& colors, const CImgl<to>& opacities,
+ const unsigned int render_type=4,
+ const bool double_sided=false, const float focale=500,
+ const float lightx=0, const float lighty=0, const float lightz=-5000,
+ const float ambiant_light = 0.05f) {
+ if (opacities.is_empty())
+ return draw_object3d(X,Y,Z,points,primitives,colors,CImg<to>(),
+ render_type,double_sided,focale,lightx,lighty,lightz,ambiant_light);
+ CImg<to> nopacities(opacities.size);
+ to *ptrd = nopacities.ptr();
+ cimg_mapoff(nopacities,l) if (opacities(l).size()) *(ptrd++) = opacities(l,0);
+ else
+ throw CImgArgumentException("CImg<%s>::draw_object3d() : Given opacities (size=%u) contains a null element at "
+ "position %u.",pixel_type(),opacities.size,l);
+ return draw_object3d(X,Y,Z,points,primitives,colors,nopacities,
+ render_type,double_sided,focale,lightx,lighty,lightz,ambiant_light);
+ }
+
+ //! Draw a 3D object in the instance image
+ template<typename tp, typename tf>
+ CImg& draw_object3d(const float X, const float Y, const float Z,
+ const tp& points, const CImgl<tf>& primitives,
+ const CImgl<T>& colors,
+ const unsigned int render_type=4,
+ const bool double_sided=false, const float focale=500,
+ const float lightx=0, const float lighty=0, const float lightz=-5000,
+ const float ambiant_light = 0.05f, const float opacity=1.0f) {
+ return draw_object3d(X,Y,Z,points,primitives,colors,
+ CImg<float>(primitives.size,1,1,1,opacity),
+ render_type,double_sided,focale,lightx,lighty,lightz,
+ ambiant_light);
+ }
+
+ //@}
+ //----------------------------
+ //
+ //! \name Filtering functions
+ //@{
+ //----------------------------
+
+ //! Return the correlation of the image by a tqmask.
+ /**
+ The result \p res of the correlation of an image \p img by a tqmask \p tqmask is defined to be :
+
+ res(x,y,z) = sum_{i,j,k} img(x+i,y+j,z+k)*tqmask(i,j,k)
+
+ \param tqmask = the correlation kernel.
+ \param cond = the border condition type (0=zero, 1=dirichlet)
+ \param weighted_correl = enable local normalization.
+ **/
+ template<typename t> CImg<typename cimg::largest<T,t>::type>
+ get_correlate(const CImg<t>& tqmask,const unsigned int cond=1,const bool weighted_correl=false) const {
+ typedef typename cimg::largest<T,t>::type restype;
+ typedef typename cimg::largest<t,float>::type fftype;
+ typedef typename cimg::largest<T,fftype>::type ftype;
+
+ if (is_empty()) return CImg<restype>();
+ if (tqmask.is_empty() || tqmask.dim!=1)
+ throw CImgArgumentException("CImg<%s>::get_correlate() : Specified tqmask (%u,%u,%u,%u,%p) is not scalar.",
+ pixel_type(),tqmask.width,tqmask.height,tqmask.depth,tqmask.dim,tqmask.data);
+ CImg<restype> dest(*this,false);
+ if (cond && tqmask.width==tqmask.height && ((tqmask.depth==1 && tqmask.width<=5) || (tqmask.depth==tqmask.width && tqmask.width<=3))) {
+ // A special optimization is done for 2x2,3x3,4x4,5x5,2x2x2 and 3x3x3 tqmask (with cond=1)
+ switch (tqmask.depth) {
+ case 3: {
+ CImg_3x3x3(I,T);
+ if (!weighted_correl) cimg_mapZV(*this,z,v) cimg_map3x3x3(*this,x,y,z,v,I) dest(x,y,z,v) = cimg_corr3x3x3(I,tqmask);
+ else cimg_mapZV(*this,z,v) cimg_map3x3x3(*this,x,y,z,v,I) {
+ const double norm = (double)cimg_squaresum3x3x3(I);
+ dest(x,y,z,v) = (norm!=0)?(restype)(cimg_corr3x3x3(I,tqmask)/std::sqrt(norm)):0;
+ }
+ } break;
+ case 2: {
+ CImg_2x2x2(I,T);
+ if (!weighted_correl) cimg_mapZV(*this,z,v) cimg_map2x2x2(*this,x,y,z,v,I) dest(x,y,z,v) = cimg_corr2x2x2(I,tqmask);
+ else cimg_mapZV(*this,z,v) cimg_map2x2x2(*this,x,y,z,v,I) {
+ const double norm = (double)cimg_squaresum2x2x2(I);
+ dest(x,y,z,v) = (norm!=0)?(restype)(cimg_corr2x2x2(I,tqmask)/std::sqrt(norm)):0;
+ }
+ } break;
+ default:
+ case 1:
+ switch (tqmask.width) {
+ case 5: {
+ CImg_5x5x1(I,T);
+ if (!weighted_correl) cimg_mapZV(*this,z,v) cimg_map5x5x1(*this,x,y,z,v,I) dest(x,y,z,v) = cimg_corr5x5x1(I,tqmask);
+ else cimg_mapZV(*this,z,v) cimg_map5x5x1(*this,x,y,z,v,I) {
+ const double norm = (double)cimg_squaresum5x5x1(I);
+ dest(x,y,z,v) = (norm!=0)?(restype)(cimg_corr5x5x1(I,tqmask)/std::sqrt(norm)):0;
+ }
+ } break;
+ case 4: {
+ CImg_4x4x1(I,T);
+ if (!weighted_correl) cimg_mapZV(*this,z,v) cimg_map4x4x1(*this,x,y,z,v,I) dest(x,y,z,v) = cimg_corr4x4x1(I,tqmask);
+ else cimg_mapZV(*this,z,v) cimg_map4x4x1(*this,x,y,z,v,I) {
+ const double norm = (double)cimg_squaresum4x4x1(I);
+ dest(x,y,z,v) = (norm!=0)?(restype)(cimg_corr4x4x1(I,tqmask)/std::sqrt(norm)):0;
+ }
+ } break;
+ case 3: {
+ CImg_3x3x1(I,T);
+ if (!weighted_correl) cimg_mapZV(*this,z,v) cimg_map3x3x1(*this,x,y,z,v,I) dest(x,y,z,v) = cimg_corr3x3x1(I,tqmask);
+ else cimg_mapZV(*this,z,v) cimg_map3x3x1(*this,x,y,z,v,I) {
+ const double norm = (double)cimg_squaresum3x3x1(I);
+ dest(x,y,z,v) = (norm!=0)?(restype)(cimg_corr3x3x1(I,tqmask)/std::sqrt(norm)):0;
+ }
+ } break;
+ case 2: {
+ CImg_2x2x1(I,T);
+ if (!weighted_correl) cimg_mapZV(*this,z,v) cimg_map2x2x1(*this,x,y,z,v,I) dest(x,y,z,v) = cimg_corr2x2x1(I,tqmask);
+ else cimg_mapZV(*this,z,v) cimg_map2x2x1(*this,x,y,z,v,I) {
+ const double norm = (double)cimg_squaresum2x2x1(I);
+ dest(x,y,z,v) = (norm!=0)?(restype)(cimg_corr2x2x1(I,tqmask)/std::sqrt(norm)):0;
+ }
+ } break;
+ case 1: dest = tqmask(0)*(*this); break;
+ }
+ }
+ } else {
+ // Generic version for other tqmasks
+ const int cxm=tqmask.width/2, cym=tqmask.height/2, czm=tqmask.depth/2, fxm=cxm-1+(tqmask.width%2), fym=cym-1+(tqmask.height%2), fzm=czm-1+(tqmask.depth%2);
+ cimg_mapV(*this,v)
+ if (!weighted_correl) { // Classical correlation
+ for (int z=czm; z<dimz()-czm; z++) for (int y=cym; y<dimy()-cym; y++) for (int x=cxm; x<dimx()-cxm; x++) {
+ ftype val = 0;
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ val+= (*this)(x+xm,y+ym,z+zm,v)*tqmask(cxm+xm,cym+ym,czm+zm,0);
+ dest(x,y,z,v)=(restype)val;
+ }
+ if (cond) cimg_mapYZV(*this,y,z,v)
+ for (int x=0; x<dimx(); (y<cym || y>=dimy()-cym || z<czm || z>=dimz()-czm)?x++:((x<cxm-1 || x>=dimx()-cxm)?x++:(x=dimx()-cxm))) {
+ ftype val = 0;
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ val+= pix3d(x+xm,y+ym,z+zm,v)*tqmask(cxm+xm,cym+ym,czm+zm,0);
+ dest(x,y,z,v)=(restype)val;
+ }
+ else cimg_mapYZV(*this,y,z,v)
+ for (int x=0; x<dimx(); (y<cym || y>=dimy()-cym || z<czm || z>=dimz()-czm)?x++:((x<cxm-1 || x>=dimx()-cxm)?x++:(x=dimx()-cxm))) {
+ ftype val = 0;
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ val+= pix3d(x+xm,y+ym,z+zm,v,0)*tqmask(cxm+xm,cym+ym,czm+zm,0);
+ dest(x,y,z,v)=(restype)val;
+ }
+ } else { // Weighted correlation
+ for (int z=czm; z<dimz()-czm; z++) for (int y=cym; y<dimy()-cym; y++) for (int x=cxm; x<dimx()-cxm; x++) {
+ ftype val = 0, norm = 0;
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++) {
+ const T cval = (*this)(x+xm,y+ym,z+zm,v);
+ val+= cval*tqmask(cxm+xm,cym+ym,czm+zm,0);
+ norm+= cval*cval;
+ }
+ dest(x,y,z,v)=(norm!=0)?(restype)(val/std::sqrt((double)norm)):0;
+ }
+ if (cond) cimg_mapYZV(*this,y,z,v)
+ for (int x=0; x<dimx(); (y<cym || y>=dimy()-cym || z<czm || z>=dimz()-czm)?x++:((x<cxm-1 || x>=dimx()-cxm)?x++:(x=dimx()-cxm))) {
+ ftype val = 0, norm = 0;
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++) {
+ const T cval = pix3d(x+xm,y+ym,z+zm,v);
+ val+= cval*tqmask(cxm+xm,cym+ym,czm+zm,0);
+ norm+=cval*cval;
+ }
+ dest(x,y,z,v)=(norm!=0)?(restype)(val/std::sqrt((double)norm)):0;
+ }
+ else cimg_mapYZV(*this,y,z,v)
+ for (int x=0; x<dimx(); (y<cym || y>=dimy()-cym || z<czm || z>=dimz()-czm)?x++:((x<cxm-1 || x>=dimx()-cxm)?x++:(x=dimx()-cxm))) {
+ ftype val = 0, norm = 0;
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++) {
+ const T cval = pix3d(x+xm,y+ym,z+zm,v,0);
+ val+= cval*tqmask(cxm+xm,cym+ym,czm+zm,0);
+ norm+= cval*cval;
+ }
+ dest(x,y,z,v)=(norm!=0)?(restype)(val/std::sqrt((double)norm)):0;
+ }
+ }
+ }
+ return dest;
+ }
+
+
+ //! Correlate the image by a tqmask
+ /**
+ This is the in-place version of get_correlate.
+ \see get_correlate
+ **/
+ template<typename t> CImg& correlate(const CImg<t>& tqmask,const unsigned int cond=1,const bool weighted_correl=false) {
+ return get_correlate(tqmask,cond,weighted_correl).swap(*this);
+ }
+
+ //! Return the convolution of the image by a tqmask
+ /**
+ The result \p res of the convolution of an image \p img by a tqmask \p tqmask is defined to be :
+
+ res(x,y,z) = sum_{i,j,k} img(x-i,y-j,z-k)*tqmask(i,j,k)
+
+ \param tqmask = the correlation kernel.
+ \param cond = the border condition type (0=zero, 1=dirichlet)
+ \param weighted_convol = enable local normalization.
+ **/
+ template<typename t> CImg<typename cimg::largest<T,t>::type>
+ get_convolve(const CImg<t>& tqmask,const unsigned int cond=1,const bool weighted_convol=false) const {
+ typedef typename cimg::largest<T,t>::type restype;
+ typedef typename cimg::largest<t,float>::type fftype;
+ typedef typename cimg::largest<T,fftype>::type ftype;
+
+ if (is_empty()) return CImg<restype>();
+ if (tqmask.is_empty() || tqmask.dim!=1)
+ throw CImgArgumentException("CImg<%s>::get_convolve() : Specified tqmask (%u,%u,%u,%u,%p) is not scalar.",
+ pixel_type(),tqmask.width,tqmask.height,tqmask.depth,tqmask.dim,tqmask.data);
+ CImg<restype> dest(*this,false);
+ if (cond && tqmask.width==tqmask.height && ((tqmask.depth==1 && tqmask.width<=5) || (tqmask.depth==tqmask.width && tqmask.width<=3))) { // optimized version
+ switch (tqmask.depth) {
+ case 3: {
+ CImg_3x3x3(I,T);
+ if (!weighted_convol) cimg_mapZV(*this,z,v) cimg_map3x3x3(*this,x,y,z,v,I) dest(x,y,z,v) = cimg_conv3x3x3(I,tqmask);
+ else cimg_mapZV(*this,z,v) cimg_map3x3x3(*this,x,y,z,v,I) {
+ const double norm = (double)cimg_squaresum3x3x3(I);
+ dest(x,y,z,v) = (norm!=0)?(restype)(cimg_conv3x3x3(I,tqmask)/std::sqrt(norm)):0;
+ }
+ } break;
+ case 2: {
+ CImg_2x2x2(I,T);
+ if (!weighted_convol) cimg_mapZV(*this,z,v) cimg_map2x2x2(*this,x,y,z,v,I) dest(x,y,z,v) = cimg_conv2x2x2(I,tqmask);
+ else cimg_mapZV(*this,z,v) cimg_map2x2x2(*this,x,y,z,v,I) {
+ const double norm = (double)cimg_squaresum2x2x2(I);
+ dest(x,y,z,v) = (norm!=0)?(restype)(cimg_conv2x2x2(I,tqmask)/std::sqrt(norm)):0;
+ }
+ } break;
+ default:
+ case 1:
+ switch (tqmask.width) {
+ case 5: {
+ CImg_5x5x1(I,T);
+ if (!weighted_convol) cimg_mapZV(*this,z,v) cimg_map5x5x1(*this,x,y,z,v,I) dest(x,y,z,v) = cimg_conv5x5x1(I,tqmask);
+ else cimg_mapZV(*this,z,v) cimg_map5x5x1(*this,x,y,z,v,I) {
+ const double norm = (double)cimg_squaresum5x5x1(I);
+ dest(x,y,z,v) = (norm!=0)?(restype)(cimg_conv5x5x1(I,tqmask)/std::sqrt(norm)):0;
+ }
+ } break;
+ case 4: {
+ CImg_4x4x1(I,T);
+ if (!weighted_convol) cimg_mapZV(*this,z,v) cimg_map4x4x1(*this,x,y,z,v,I) dest(x,y,z,v) = (T)cimg_conv4x4x1(I,tqmask);
+ else cimg_mapZV(*this,z,v) cimg_map4x4x1(*this,x,y,z,v,I) {
+ const double norm = (double)cimg_squaresum4x4x1(I);
+ dest(x,y,z,v) = (norm!=0)?(restype)(cimg_conv4x4x1(I,tqmask)/std::sqrt(norm)):0;
+ }
+ } break;
+ case 3: {
+ CImg_3x3x1(I,T);
+ if (!weighted_convol) cimg_mapZV(*this,z,v) cimg_map3x3x1(*this,x,y,z,v,I) dest(x,y,z,v) = (T)cimg_conv3x3x1(I,tqmask);
+ else cimg_mapZV(*this,z,v) cimg_map3x3x1(*this,x,y,z,v,I) {
+ const double norm = (double)cimg_squaresum3x3x1(I);
+ dest(x,y,z,v) = (norm!=0)?(restype)(cimg_conv3x3x1(I,tqmask)/std::sqrt(norm)):0;
+ }
+ } break;
+ case 2: {
+ CImg_2x2x1(I,T);
+ if (!weighted_convol) cimg_mapZV(*this,z,v) cimg_map2x2x1(*this,x,y,z,v,I) dest(x,y,z,v) = (T)cimg_conv2x2x1(I,tqmask);
+ else cimg_mapZV(*this,z,v) cimg_map2x2x1(*this,x,y,z,v,I) {
+ const double norm = (double)cimg_squaresum2x2x1(I);
+ dest(x,y,z,v) = (norm!=0)?(restype)(cimg_conv2x2x1(I,tqmask)/std::sqrt(norm)):0;
+ }
+ } break;
+ case 1: dest = tqmask(0)*(*this); break;
+ }
+ }
+ } else { // generic version
+
+ const int cxm=tqmask.width/2, cym=tqmask.height/2, czm=tqmask.depth/2, fxm=cxm-1+(tqmask.width%2), fym=cym-1+(tqmask.height%2), fzm=czm-1+(tqmask.depth%2);
+ cimg_mapV(*this,v)
+ if (!weighted_convol) { // Classical convolution
+ for (int z=czm; z<dimz()-czm; z++) for (int y=cym; y<dimy()-cym; y++) for (int x=cxm; x<dimx()-cxm; x++) {
+ ftype val = 0;
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ val+= (*this)(x-xm,y-ym,z-zm,v)*tqmask(cxm+xm,cym+ym,czm+zm,0);
+ dest(x,y,z,v)=(restype)val;
+ }
+ if (cond) cimg_mapYZV(*this,y,z,v)
+ for (int x=0; x<dimx(); (y<cym || y>=dimy()-cym || z<czm || z>=dimz()-czm)?x++:((x<cxm-1 || x>=dimx()-cxm)?x++:(x=dimx()-cxm))) {
+ ftype val = 0;
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ val+= pix3d(x-xm,y-ym,z-zm,v)*tqmask(cxm+xm,cym+ym,czm+zm,0);
+ dest(x,y,z,v)=(restype)val;
+ }
+ else cimg_mapYZV(*this,y,z,v)
+ for (int x=0; x<dimx(); (y<cym || y>=dimy()-cym || z<czm || z>=dimz()-czm)?x++:((x<cxm-1 || x>=dimx()-cxm)?x++:(x=dimx()-cxm))) {
+ ftype val = 0;
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ val+= pix3d(x-xm,y-ym,z-zm,v,0)*tqmask(cxm+xm,cym+ym,czm+zm,0);
+ dest(x,y,z,v)=(restype)val;
+ }
+ } else { // Weighted convolution
+ for (int z=czm; z<dimz()-czm; z++) for (int y=cym; y<dimy()-cym; y++) for (int x=cxm; x<dimx()-cxm; x++) {
+ ftype val = 0, norm = 0;
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++) {
+ const T cval = (*this)(x-xm,y-ym,z-zm,v);
+ val+= cval*tqmask(cxm+xm,cym+ym,czm+zm,0);
+ norm+= cval*cval;
+ }
+ dest(x,y,z,v)=(norm!=0)?(restype)(val/std::sqrt(norm)):0;
+ }
+ if (cond) cimg_mapYZV(*this,y,z,v)
+ for (int x=0; x<dimx(); (y<cym || y>=dimy()-cym || z<czm || z>=dimz()-czm)?x++:((x<cxm-1 || x>=dimx()-cxm)?x++:(x=dimx()-cxm))) {
+ ftype val = 0, norm = 0;
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++) {
+ const T cval = pix3d(x-xm,y-ym,z-zm,v);
+ val+= cval*tqmask(cxm+xm,cym+ym,czm+zm,0);
+ norm+=cval*cval;
+ }
+ dest(x,y,z,v)=(norm!=0)?(restype)(val/std::sqrt(norm)):0;
+ }
+ else cimg_mapYZV(*this,y,z,v)
+ for (int x=0; x<dimx(); (y<cym || y>=dimy()-cym || z<czm || z>=dimz()-czm)?x++:((x<cxm-1 || x>=dimx()-cxm)?x++:(x=dimx()-cxm))) {
+ double val = 0, norm = 0;
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++) {
+ const T cval = pix3d(x-xm,y-ym,z-zm,v,0);
+ val+= cval*tqmask(cxm+xm,cym+ym,czm+zm,0);
+ norm+= cval*cval;
+ }
+ dest(x,y,z,v)=(norm!=0)?(restype)(val/std::sqrt(norm)):0;
+ }
+ }
+ }
+ return dest;
+ }
+
+ //! Convolve the image by a tqmask
+ /**
+ This is the in-place version of get_convolve().
+ \see get_convolve()
+ **/
+ template<typename t> CImg& convolve(const CImg<t>& tqmask,const unsigned int cond=1,const bool weighted_convol=false) {
+ return get_convolve(tqmask,cond,weighted_convol).swap(*this);
+ }
+
+ //! Return the erosion of the image by a structuring element.
+ template<typename t> CImg<typename cimg::largest<T,t>::type>
+ get_erode(const CImg<t>& tqmask, const unsigned int cond=1, const bool weighted_erosion=false) const {
+ typedef typename cimg::largest<T,t>::type restype;
+ if (is_empty()) return CImg<restype>();
+ if (tqmask.is_empty() || tqmask.dim!=1)
+ throw CImgArgumentException("CImg<%s>::get_erosion() : Specified tqmask (%u,%u,%u,%u,%p) is not a scalar image.",
+ pixel_type(),tqmask.width,tqmask.height,tqmask.depth,tqmask.dim,tqmask.data);
+ CImg<restype> dest(*this,false);
+ const int cxm=tqmask.width/2, cym=tqmask.height/2, czm=tqmask.depth/2,
+ fxm=cxm-1+(tqmask.width%2), fym=cym-1+(tqmask.height%2), fzm=czm-1+(tqmask.depth%2);
+ cimg_mapV(*this,v)
+ if (!weighted_erosion) { // Classical erosion
+ for (int z=czm; z<dimz()-czm; z++) for (int y=cym; y<dimy()-cym; y++) for (int x=cxm; x<dimx()-cxm; x++) {
+ restype foo, min_val = cimg::get_type_max(foo);
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ if (tqmask(cxm+xm,cym+ym,czm+zm,0)) min_val = cimg::min((restype)(*this)(x+xm,y+ym,z+zm,v),min_val);
+ dest(x,y,z,v)=min_val;
+ }
+ if (cond) cimg_mapYZV(*this,y,z,v)
+ for (int x=0; x<dimx(); (y<cym || y>=dimy()-cym || z<czm || z>=dimz()-czm)?x++:((x<cxm-1 || x>=dimx()-cxm)?x++:(x=dimx()-cxm))) {
+ restype foo, min_val = cimg::get_type_max(foo);
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ if (tqmask(cxm+xm,cym+ym,czm+zm,0)) min_val = cimg::min((restype)pix3d(x+xm,y+ym,z+zm,v),min_val);
+ dest(x,y,z,v)=min_val;
+ }
+ else cimg_mapYZV(*this,y,z,v)
+ for (int x=0; x<dimx(); (y<cym || y>=dimy()-cym || z<czm || z>=dimz()-czm)?x++:((x<cxm-1 || x>=dimx()-cxm)?x++:(x=dimx()-cxm))) {
+ restype foo, min_val = cimg::get_type_max(foo);
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ if (tqmask(cxm+xm,cym+ym,czm+zm,0)) min_val = cimg::min((restype)pix3d(x+xm,y+ym,z+zm,v,0),min_val);
+ dest(x,y,z,v)=min_val;
+ }
+ } else { // Weighted erosion
+ t mval=0;
+ for (int z=czm; z<dimz()-czm; z++) for (int y=cym; y<dimy()-cym; y++) for (int x=cxm; x<dimx()-cxm; x++) {
+ restype foo, min_val = cimg::get_type_max(foo);
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ if ((mval=tqmask(cxm+xm,cym+ym,czm+zm,0))!=0) min_val = cimg::min((restype)((*this)(x+xm,y+ym,z+zm,v)+mval),min_val);
+ dest(x,y,z,v)=min_val;
+ }
+ if (cond) cimg_mapYZV(*this,y,z,v)
+ for (int x=0; x<dimx(); (y<cym || y>=dimy()-cym || z<czm || z>=dimz()-czm)?x++:((x<cxm-1 || x>=dimx()-cxm)?x++:(x=dimx()-cxm))) {
+ restype foo, min_val = cimg::get_type_max(foo);
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ if ((mval=tqmask(cxm+xm,cym+ym,czm+zm,0))!=0) min_val = cimg::min((restype)(pix3d(x+xm,y+ym,z+zm,v)+mval),min_val);
+ dest(x,y,z,v)=min_val;
+ }
+ else cimg_mapYZV(*this,y,z,v)
+ for (int x=0; x<dimx(); (y<cym || y>=dimy()-cym || z<czm || z>=dimz()-czm)?x++:((x<cxm-1 || x>=dimx()-cxm)?x++:(x=dimx()-cxm))) {
+ restype foo, min_val = cimg::get_type_max(foo);
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ if ((mval=tqmask(cxm+xm,cym+ym,czm+zm,0))!=0) min_val = cimg::min((restype)(pix3d(x+xm,y+ym,z+zm,v,0)+mval),min_val);
+ dest(x,y,z,v)=min_val;
+ }
+ }
+ return dest;
+ }
+
+ //! Erode the image by a structuring element
+ /**
+ This is the in-place version of get_erode().
+ \see get_erode()
+ **/
+ template<typename t> CImg& erode(const CImg<t>& tqmask,const unsigned int cond=1,const bool weighted_erosion=false) {
+ return get_erode(tqmask,cond,weighted_erosion).swap(*this);
+ }
+
+ //! Erode the image by a square structuring element of size n
+ CImg get_erode(const unsigned int n=1, const unsigned int cond=1) const {
+ static const CImg<T> tqmask(3,3,1,1,1);
+ return get_erode(tqmask,cond,false);
+ }
+
+ //! Erode the image by a square structuring element of size n
+ CImg& erode(const unsigned int n=1, const unsigned int cond=1) {
+ return get_erode(n,cond).swap(*this);
+ }
+
+ //! Return the dilatation of the image by a structuring element.
+ template<typename t> CImg<typename cimg::largest<T,t>::type>
+ get_dilate(const CImg<t>& tqmask, const unsigned int cond=1, const bool weighted_dilatation=false) const {
+ typedef typename cimg::largest<T,t>::type restype;
+ if (is_empty()) return CImg<restype>();
+ if (tqmask.is_empty() || tqmask.dim!=1)
+ throw CImgArgumentException("CImg<%s>::get_dilate() : Specified tqmask (%u,%u,%u,%u,%p) is not a scalar image.",
+ pixel_type(),tqmask.width,tqmask.height,tqmask.depth,tqmask.dim,tqmask.data);
+ CImg<restype> dest(*this,false);
+ const int cxm=tqmask.width/2, cym=tqmask.height/2, czm=tqmask.depth/2,
+ fxm=cxm-1+(tqmask.width%2), fym=cym-1+(tqmask.height%2), fzm=czm-1+(tqmask.depth%2);
+ cimg_mapV(*this,v)
+ if (!weighted_dilatation) { // Classical dilatation
+ for (int z=czm; z<dimz()-czm; z++) for (int y=cym; y<dimy()-cym; y++) for (int x=cxm; x<dimx()-cxm; x++) {
+ restype foo, max_val = cimg::get_type_min(foo);
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ if (tqmask(cxm+xm,cym+ym,czm+zm,0)) max_val = cimg::max((restype)(*this)(x+xm,y+ym,z+zm,v),max_val);
+ dest(x,y,z,v)=max_val;
+ }
+ if (cond) cimg_mapYZV(*this,y,z,v)
+ for (int x=0; x<dimx(); (y<cym || y>=dimy()-cym || z<czm || z>=dimz()-czm)?x++:((x<cxm-1 || x>=dimx()-cxm)?x++:(x=dimx()-cxm))) {
+ restype foo, max_val = cimg::get_type_min(foo);
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ if (tqmask(cxm+xm,cym+ym,czm+zm,0)) max_val = cimg::max((restype)pix3d(x+xm,y+ym,z+zm,v),max_val);
+ dest(x,y,z,v)=max_val;
+ }
+ else cimg_mapYZV(*this,y,z,v)
+ for (int x=0; x<dimx(); (y<cym || y>=dimy()-cym || z<czm || z>=dimz()-czm)?x++:((x<cxm-1 || x>=dimx()-cxm)?x++:(x=dimx()-cxm))) {
+ restype foo, max_val = cimg::get_type_min(foo);
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ if (tqmask(cxm+xm,cym+ym,czm+zm,0)) max_val = cimg::max((restype)pix3d(x+xm,y+ym,z+zm,v,0),max_val);
+ dest(x,y,z,v)=max_val;
+ }
+ } else { // Weighted dilatation
+ t mval=0;
+ for (int z=czm; z<dimz()-czm; z++) for (int y=cym; y<dimy()-cym; y++) for (int x=cxm; x<dimx()-cxm; x++) {
+ restype foo, max_val = cimg::get_type_min(foo);
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ if ((mval=tqmask(cxm+xm,cym+ym,czm+zm,0))!=0) max_val = cimg::max((restype)((*this)(x+xm,y+ym,z+zm,v)-mval),max_val);
+ dest(x,y,z,v)=max_val;
+ }
+ if (cond) cimg_mapYZV(*this,y,z,v)
+ for (int x=0; x<dimx(); (y<cym || y>=dimy()-cym || z<czm || z>=dimz()-czm)?x++:((x<cxm-1 || x>=dimx()-cxm)?x++:(x=dimx()-cxm))) {
+ restype foo, max_val = cimg::get_type_min(foo);
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ if ((mval=tqmask(cxm+xm,cym+ym,czm+zm,0))!=0) max_val = cimg::max((restype)(pix3d(x+xm,y+ym,z+zm,v)-mval),max_val);
+ dest(x,y,z,v)=max_val;
+ }
+ else cimg_mapYZV(*this,y,z,v)
+ for (int x=0; x<dimx(); (y<cym || y>=dimy()-cym || z<czm || z>=dimz()-czm)?x++:((x<cxm-1 || x>=dimx()-cxm)?x++:(x=dimx()-cxm))) {
+ restype foo, max_val = cimg::get_type_min(foo);
+ for (int zm=-czm; zm<=fzm; zm++) for (int ym=-cym; ym<=fym; ym++) for (int xm=-cxm; xm<=fxm; xm++)
+ if ((mval=tqmask(cxm+xm,cym+ym,czm+zm,0))!=0) max_val = cimg::max((restype)(pix3d(x+xm,y+ym,z+zm,v,0)-mval),max_val);
+ dest(x,y,z,v)=max_val;
+ }
+ }
+ return dest;
+ }
+
+ //! Dilate the image by a structuring element
+ /**
+ This is the in-place version of get_dilate().
+ \see get_dilate()
+ **/
+ template<typename t> CImg& dilate(const CImg<t>& tqmask,const unsigned int cond=1,const bool weighted_dilatation=false) {
+ return get_dilate(tqmask,cond,weighted_dilatation).swap(*this);
+ }
+
+ //! Dilate the image by a square structuring element of size n
+ CImg get_dilate(const unsigned int n=1, const unsigned int cond=1) const {
+ static const CImg<T> tqmask(3,3,1,1,1);
+ return get_dilate(tqmask,cond,false);
+ }
+
+ //! Dilate the image by a square structuring element of size n
+ CImg& dilate(const unsigned int n=1, const unsigned int cond=1) {
+ return get_dilate(n,cond).swap(*this);
+ }
+
+ //! Add noise to the image
+ /**
+ This is the in-place version of get_noise.
+ \see get_noise.
+ **/
+ CImg& noise(const double sigma=-20,const unsigned int ntype=0) {
+ if (!is_empty()) {
+ T tmp;
+ double nsigma = sigma, max = (double)cimg::get_type_max(tmp), min = (double)cimg::get_type_min(tmp);
+ static bool first_time = true;
+ if (first_time) { std::srand((unsigned int)::time(NULL)); first_time = false; }
+ CImgStats st;
+ if (nsigma==0) return *this;
+ if (nsigma<0 || ntype==2) st = CImgStats(*this,false);
+ if (nsigma<0) nsigma = -nsigma*(st.max-st.min)/100.0;
+ switch (ntype) {
+ case 0: { // Gaussian noise
+ cimg_map(*this,ptr,T) {
+ double val = *ptr+nsigma*cimg::grand();
+ if (val>max) val = max;
+ if (val<min) val = min;
+ *ptr = (T)val;
+ }
+ } break;
+ case 1: { // Uniform noise
+ cimg_map(*this,ptr,T) {
+ double val = *ptr+nsigma*cimg::crand();
+ if (val>max) val = max;
+ if (val<min) val = min;
+ *ptr = (T)val;
+ }
+ } break;
+ case 2: { // Salt & Pepper noise
+ if (st.max==st.min) { st.min=0; st.max=255; }
+ cimg_map(*this,ptr,T) if (cimg::rand()*100<nsigma) *ptr=(T)(cimg::rand()<0.5?st.max:st.min);
+ } break;
+ }
+ }
+ return *this;
+ }
+
+ //! Return a noisy image
+ /**
+ \param sigma = power of the noise. if sigma<0, it corresponds to the percentage of the maximum image value.
+ \param ntype = noise type. can be 0=gaussian, 1=uniform or 2=Salt and Pepper.
+ \return A noisy version of the instance image.
+ **/
+ CImg get_noise(const double sigma=-20,const unsigned int ntype=0) const { return CImg<T>(*this).noise(sigma,ntype); }
+
+#define cimg_deriche_map(x0,y0,z0,k0,nb,offset,T) { \
+ ima = ptr(x0,y0,z0,k0); \
+ I2 = *ima; ima+=offset; I1 = *ima; ima+=offset; \
+ Y2 = *(Y++) = sumg0*I2; Y1 = *(Y++) = g0*I1 + sumg1*I2; \
+ for (i=2; i<(nb); i++) { I1 = *ima; ima+=offset; \
+ Y0 = *(Y++) = a1*I1 + a2*I2 + b1*Y1 + b2*Y2; \
+ I2=I1; Y2=Y1; Y1=Y0; } \
+ ima-=offset; I2 = *ima; Y2 = Y1 = parity*sumg1*I2; *ima = (T)(*(--Y)+Y2); \
+ ima-=offset; I1 = *ima; *ima = (T)(*(--Y)+Y1); \
+ for (i=(nb)-3; i>=0; i--) { Y0=a3*I1+a4*I2+b1*Y1+b2*Y2; ima-=offset; \
+ I2=I1; I1=*ima; *ima=(T)(*(--Y)+Y0); Y2=Y1; Y1=Y0; } \
+ }
+
+ //! Apply a deriche filter on the image
+ /**
+ This is the in-place version of get_deriche
+ \see get_deriche.
+ **/
+ CImg& deriche(const float sigma=1,const int order=0,const char axe='x',const unsigned int cond=1) {
+ if (!is_empty()) {
+ if (sigma<0 || order<0 || order>2)
+ throw CImgArgumentException("CImg<%s>::deriche() : Bad arguments (sigma=%g, order=%d)",pixel_type(),sigma,order);
+ const float alpha=sigma>0?(1.695f/sigma):20,ea=(float)std::exp(alpha),ema=(float)std::exp(-alpha),em2a=ema*ema,b1=2*ema,b2=-em2a;
+ float ek,ekn,parity,a1,a2,a3,a4,g0,sumg1,sumg0;
+ double *Y,Y0,Y1,Y2;
+ int i,offset,nb;
+ T *ima,I1,I2;
+ switch(order) {
+ case 1: // first derivative
+ ek = -(1-ema)*(1-ema)*(1-ema)/(2*(ema+1)*ema); a1 = a4 = 0; a2 = ek*ema; a3 = -ek*ema; parity =-1;
+ if (cond) { sumg1 = (ek*ea) / ((ea-1)*(ea-1)); g0 = 0; sumg0 = g0+sumg1; }
+ else g0 = sumg0 = sumg1 = 0;
+ break;
+ case 2: // second derivative
+ ekn = ( -2*(-1+3*ea-3*ea*ea+ea*ea*ea)/(3*ea+1+3*ea*ea+ea*ea*ea) );
+ ek = -(em2a-1)/(2*alpha*ema); a1 = ekn; a2 = -ekn*(1+ek*alpha)*ema; a3 = ekn*(1-ek*alpha)*ema; a4 = -ekn*em2a; parity =1;
+ if (cond) { sumg1 = ekn/2; g0 = ekn; sumg0 = g0+sumg1; }
+ else g0=sumg0=sumg1=0;
+ break;
+ default: // smoothing
+ ek = (1-ema)*(1-ema) / (1+2*alpha*ema - em2a); a1 = ek; a2 = ek*ema*(alpha-1); a3 = ek*ema*(alpha+1); a4 = -ek*em2a; parity = 1;
+ if (cond) { sumg1 = ek*(alpha*ea+ea-1) / ((ea-1)*(ea-1)); g0 = ek; sumg0 = g0+sumg1; }
+ else g0=sumg0=sumg1=0;
+ break;
+ }
+ // filter init
+ Y = new double[cimg::max(width,height,depth)];
+ switch(cimg::uncase(axe)) {
+ case 'x': if (width>1) { offset = 1; nb = width; cimg_mapYZV(*this,y,z,k) cimg_deriche_map(0,y,z,k,nb,offset,T); } break;
+ case 'y': if (height>1) { offset = width; nb = height; cimg_mapXZV(*this,x,z,k) cimg_deriche_map(x,0,z,k,nb,offset,T); } break;
+ case 'z': if (depth>1) { offset = width*height; nb = depth; cimg_mapXYV(*this,x,y,k) cimg_deriche_map(x,y,0,k,nb,offset,T); } break;
+ default: throw CImgArgumentException("CImg<%s>::deriche() : unknow axe '%c', must be 'x','y' or 'z'",pixel_type(),axe);
+ }
+ delete[] Y;
+ }
+ return *this;
+ }
+
+ //! Return the result of the Deriche filter
+ /**
+ The Canny-Deriche filter is a recursive algorithm allowing to compute blurred derivatives of
+ order 0,1 or 2 of an image.
+ \see blur
+ **/
+ CImg get_deriche(const float sigma=1,const int order=0,const char axe='x',const unsigned int cond=1) const {
+ return CImg<T>(*this).deriche(sigma,order,axe,cond);
+ }
+
+ //! Blur the image with a Deriche filter (anisotropically)
+ /**
+ This is the in-place version of get_blur().
+ \see get_blur().
+ **/
+ CImg& blur(const float sigmax,const float sigmay,const float sigmaz,const unsigned int cond=1) {
+ if (!is_empty()) {
+ if (width>1 && sigmax>0) deriche(sigmax,0,'x',cond);
+ if (height>1 && sigmay>0) deriche(sigmay,0,'y',cond);
+ if (depth>1 && sigmaz>0) deriche(sigmaz,0,'z',cond);
+ }
+ return *this;
+ }
+
+ //! Blur the image with a Canny-Deriche filter.
+ /** This is the in-place version of get_blur(). **/
+ CImg& blur(const float sigma,const unsigned int cond=1) { return blur(sigma,sigma,sigma,cond); }
+
+ //! Return a blurred version of the image, using a Canny-Deriche filter.
+ /**
+ Blur the image with an anisotropic exponential filter (Deriche filter of order 0).
+ **/
+ CImg get_blur(const float sigmax,const float sigmay,const float sigmaz,const unsigned int cond=1) const {
+ return CImg<T>(*this).blur(sigmax,sigmay,sigmaz,cond);
+ }
+
+ //! Return a blurred version of the image, using a Canny-Deriche filter.
+ CImg get_blur(const float sigma,const unsigned int cond=1) const { return CImg<T>(*this).blur(sigma,cond); }
+
+ //! Blur an image following a field of diffusion tensors.
+ /** This is the in-place version of get_blur_anisotropic(). **/
+ template<typename t>
+ CImg& blur_anisotropic(const CImg<t>& G, const float amplitude=30.0f, const float dl=0.8f,const float da=30.0f,
+ const float gauss_prec=2.0f, const unsigned int interpolation=0, const bool fast_approx=true) {
+
+ // Check arguments and init variables
+ if (!is_empty() && amplitude>0) {
+ if (G.is_empty() || (G.dim!=3 && G.dim!=6) || G.width!=width || G.height!=height || G.depth!=depth)
+ throw CImgArgumentException("CImg<%s>::blur_anisotropic() : Specified tensor field (%u,%u,%u,%u) is not valid.",
+ pixel_type(),G.width,G.height,G.depth,G.dim);
+
+ const int dx1 = dimx()-1, dy1 = dimy()-1, dz1 = dimz()-1;
+ const bool threed = (G.dim>=6);
+ CImg<t> dest(width,height,depth,dim,0), tmp(dim), W(width,height,depth,threed?4:3);
+ int N = 0;
+ const float sqrt2amplitude = (float)std::sqrt(2*amplitude);
+
+ if (threed)
+ // 3D version of the algorithm
+ for (float phi=(180%(int)da)/2.0f; phi<=180; phi+=da) {
+ const float phir = (float)(phi*cimg::PI/180), datmp = (float)(da/std::cos(phir)), da2 = datmp<1?360.0f:datmp;
+ for (float theta=0; theta<360; (theta+=da2),N++) {
+ const float thetar = (float)(theta*cimg::PI/180),
+ vx = (float)(std::cos(thetar)*std::cos(phir)),
+ vy = (float)(std::sin(thetar)*std::cos(phir)),
+ vz = (float)std::sin(phir);
+ const t
+ *pa = G.ptr(0,0,0,0), *pb = G.ptr(0,0,0,1), *pc = G.ptr(0,0,0,2),
+ *pd = G.ptr(0,0,0,3), *pe = G.ptr(0,0,0,4), *pf = G.ptr(0,0,0,5);
+ t *pd0 = W.ptr(0,0,0,0), *pd1 = W.ptr(0,0,0,1), *pd2 = W.ptr(0,0,0,2), *pd3 = W.ptr(0,0,0,3);
+ cimg_mapXYZ(G,xg,yg,zg) {
+ const t
+ a = *(pa++), b = *(pb++), c = *(pc++),
+ d = *(pd++), e = *(pe++), f = *(pf++),
+ u = a*vx + b*vy + c*vz,
+ v = b*vx + d*vy + e*vz,
+ w = c*vx + e*vy + f*vz,
+ n = (t)std::sqrt(1e-5+u*u+v*v+w*w),
+ dln = dl/n;
+ *(pd0++) = u*dln;
+ *(pd1++) = v*dln;
+ *(pd2++) = w*dln;
+ *(pd3++) = n;
+ }
+
+ cimg_mapXYZ(*this,x,y,z) {
+ tmp.fill(0);
+ const t cu = W(x,y,z,0), cv = W(x,y,z,1), cw = W(x,y,z,2), n = W(x,y,z,3);
+ const float
+ fsigma = (float)(n*sqrt2amplitude),
+ length = gauss_prec*fsigma,
+ fsigma2 = 2*fsigma*fsigma;
+ float l, S=0, pu=cu, pv=cv, pw=cw, X=(float)x, Y=(float)y, Z=(float)z;
+ if (fast_approx) switch (interpolation) {
+ case 0: // Nearest neighbor interpolation
+ for (l=0; l<length; l+=dl) {
+ const float
+ Xn = X<0?0:(X>=dx1?dx1:X),
+ Yn = Y<0?0:(Y>=dy1?dy1:Y),
+ Zn = Z<0?0:(Z>=dz1?dz1:Z);
+ const int xi = (int)(Xn+0.5f), yi = (int)(Yn+0.5f), zi = (int)(Zn+0.5f);
+ t u = W(xi,yi,zi,0), v = W(xi,yi,zi,1), w = W(xi,yi,zi,2);
+ if ((pu*u+pv*v+pw*w)<0) { u=-u; v=-v; w=-w; }
+ cimg_mapV(*this,k) tmp[k]+=(t)(*this)(xi,yi,zi,k);
+ X+=(pu=u); Y+=(pv=v); Z+=(pw=w); S++;
+ } break;
+ case 1: // Linear interpolation
+ for (l=0; l<length; l+=dl) {
+ t u = (t)(W.linear_pix3d(X,Y,Z,0)), v = (t)(W.linear_pix3d(X,Y,Z,1)), w = (t)(W.linear_pix3d(X,Y,Z,2));
+ if ((pu*u+pv*v+pw*w)<0) { u=-u; v=-v; w=-w; }
+ cimg_mapV(*this,k) tmp[k]+=(t)linear_pix3d(X,Y,Z,k);
+ X+=(pu=u); Y+=(pv=v); Z+=(pw=w); S++;
+ } break;
+ default: // 2nd order Runge Kutta interpolation
+ for (l=0; l<length; l+=dl) {
+ t u0 = (t)(0.5f*dl*W.linear_pix3d(X,Y,Z,0)), v0 = (t)(0.5f*dl*W.linear_pix3d(X,Y,Z,1)), w0 = (t)(0.5f*dl*W.linear_pix3d(X,Y,Z,2));
+ if ((pu*u0+pv*v0+pw*w0)<0) { u0=-u0; v0=-v0; w0=-w0; }
+ t u = (t)(W.linear_pix3d(X+u0,Y+v0,Z+w0,0)), v = (t)(W.linear_pix3d(X+u0,Y+v0,Z+w0,1)), w = (t)(W.linear_pix3d(X+u0,Y+v0,Z+w0,2));
+ if ((pu*u+pv*v+pw*w)<0) { u=-u; v=-v; w=-w; }
+ cimg_mapV(*this,k) tmp[k]+=(t)linear_pix3d(X,Y,Z,k);
+ X+=(pu=u); Y+=(pv=v); Z+=(pw=w); S++;
+ } break;
+ }
+ else switch (interpolation) {
+ case 0: // Nearest neighbor interpolation
+ for (l=0; l<length; l+=dl) {
+ const float
+ coef = (float)std::exp(-l*l/fsigma2),
+ Xn = X<0?0:(X>=dx1?dx1:X),
+ Yn = Y<0?0:(Y>=dy1?dy1:Y),
+ Zn = Z<0?0:(Z>=dz1?dz1:Z);
+ const int xi = (int)(Xn+0.5f), yi = (int)(Yn+0.5f), zi = (int)(Zn+0.5f);
+ t u = W(xi,yi,zi,0), v = W(xi,yi,zi,1), w = W(xi,yi,zi,2);
+ if ((pu*u+pv*v+pw*w)<0) { u=-u; v=-v; w=-w; }
+ cimg_mapV(*this,k) tmp[k]+=(t)(coef*(*this)(xi,yi,zi,k));
+ X+=(pu=u); Y+=(pv=v); Z+=(pw=w); S+=coef;
+ } break;
+ case 1: // Linear interpolation
+ for (l=0; l<length; l+=dl) {
+ const float coef = (float)std::exp(-l*l/fsigma2);
+ t u = (t)(W.linear_pix3d(X,Y,Z,0)), v = (t)(W.linear_pix3d(X,Y,Z,1)), w = (t)(W.linear_pix3d(X,Y,Z,2));
+ if ((pu*u+pv*v+pw*w)<0) { u=-u; v=-v; w=-w; }
+ cimg_mapV(*this,k) tmp[k]+=(t)(coef*linear_pix3d(X,Y,Z,k));
+ X+=(pu=u); Y+=(pv=v); Z+=(pw=w); S+=coef;
+ } break;
+ default: // 2nd order Runge Kutta interpolation
+ for (l=0; l<length; l+=dl) {
+ const float coef = (float)std::exp(-l*l/fsigma2);
+ t u0 = (t)(0.5f*dl*W.linear_pix3d(X,Y,Z,0)), v0 = (t)(0.5f*dl*W.linear_pix3d(X,Y,Z,1)), w0 = (t)(0.5f*dl*W.linear_pix3d(X,Y,Z,2));
+ if ((pu*u0+pv*v0+pw*w0)<0) { u0=-u0; v0=-v0; w0=-w0; }
+ t u = (t)(W.linear_pix3d(X+u0,Y+v0,Z+w0,0)), v = (t)(W.linear_pix3d(X+u0,Y+v0,Z+w0,1)), w = (t)(W.linear_pix3d(X+u0,Y+v0,Z+w0,2));
+ if ((pu*u+pv*v+pw*w)<0) { u=-u; v=-v; w=-w; }
+ cimg_mapV(*this,k) tmp[k]+=(t)(coef*linear_pix3d(X,Y,Z,k));
+ X+=(pu=u); Y+=(pv=v); Z+=(pw=w); S+=coef;
+ } break;
+ }
+ if (S>0) cimg_mapV(dest,k) dest(x,y,z,k)+=tmp[k]/S;
+ else cimg_mapV(dest,k) dest(x,y,z,k)+=(t)((*this)(x,y,z,k));
+ }
+ }
+ } else
+ // 2D version of the algorithm
+ for (float theta=(360%(int)da)/2.0f; theta<360; (theta+=da),N++) {
+ const float thetar = (float)(theta*cimg::PI/180), vx = (float)(std::cos(thetar)), vy = (float)(std::sin(thetar));
+
+ const t *pa = G.ptr(0,0,0,0), *pb = G.ptr(0,0,0,1), *pc = G.ptr(0,0,0,2);
+ t *pd0 = W.ptr(0,0,0,0), *pd1 = W.ptr(0,0,0,1), *pd2 = W.ptr(0,0,0,2);
+ cimg_mapXY(G,xg,yg) {
+ const t
+ a = *(pa++), b = *(pb++), c = *(pc++),
+ u = a*vx + b*vy, v = b*vx + c*vy,
+ n = (t)std::sqrt(1e-5+u*u+v*v),
+ dln = dl/n;
+ *(pd0++) = u*dln;
+ *(pd1++) = v*dln;
+ *(pd2++) = n;
+ }
+
+ cimg_mapXY(*this,x,y) {
+ tmp.fill(0);
+ const t cu = W(x,y,0,0), cv = W(x,y,0,1), n = W(x,y,0,2);
+ const float
+ fsigma = (float)(n*sqrt2amplitude),
+ length = gauss_prec*fsigma,
+ fsigma2 = 2*fsigma*fsigma;
+ float l, S=0, pu=cu, pv=cv, X=(float)x, Y=(float)y;
+ if (fast_approx) switch (interpolation) {
+ case 0: // Nearest-neighbor interpolation
+ for (l=0; l<length; l+=dl) {
+ const float
+ Xn = X<0?0:(X>=dx1?dx1:X),
+ Yn = Y<0?0:(Y>=dy1?dy1:Y);
+ const int xi = (int)(Xn+0.5f), yi = (int)(Yn+0.5f);
+ t u = W(xi,yi,0,0), v = W(xi,yi,0,1);
+ if ((pu*u+pv*v)<0) { u=-u; v=-v; }
+ cimg_mapV(*this,k) tmp[k]+=(t)(*this)(xi,yi,0,k);
+ X+=(pu=u); Y+=(pv=v); S++;
+ } break;
+ case 1: // Linear interpolation
+ for (l=0; l<length; l+=dl) {
+ t u = (t)(W.linear_pix2d(X,Y,0,0)), v = (t)(W.linear_pix2d(X,Y,0,1));
+ if ((pu*u+pv*v)<0) { u=-u; v=-v; }
+ cimg_mapV(*this,k) tmp[k]+=(t)linear_pix2d(X,Y,0,k);
+ X+=(pu=u); Y+=(pv=v); S++;
+ } break;
+ default: // 2nd-order Runge-kutta interpolation
+ for (l=0; l<length; l+=dl) {
+ t u0 = (t)(0.5f*dl*W.linear_pix2d(X,Y,0,0)), v0 = (t)(0.5f*dl*W.linear_pix2d(X,Y,0,1));
+ if ((pu*u0+pv*v0)<0) { u0=-u0; v0=-v0; }
+ t u = (t)(W.linear_pix2d(X+u0,Y+v0,0,0)), v = (t)(W.linear_pix2d(X+u0,Y+v0,0,1));
+ if ((pu*u+pv*v)<0) { u=-u; v=-v; }
+ cimg_mapV(*this,k) tmp[k]+=(t)linear_pix2d(X,Y,0,k);
+ X+=(pu=u); Y+=(pv=v); S++;
+ } break;
+ }
+ else switch (interpolation) {
+ case 0: // Nearest-neighbor interpolation
+ for (l=0; l<length; l+=dl) {
+ const float
+ coef = (float)std::exp(-l*l/fsigma2),
+ Xn = X<0?0:(X>=dx1?dx1:X),
+ Yn = Y<0?0:(Y>=dy1?dy1:Y);
+ const int xi = (int)(Xn+0.5f), yi = (int)(Yn+0.5f);
+ t u = W(xi,yi,0,0), v = W(xi,yi,0,1);
+ if ((pu*u+pv*v)<0) { u=-u; v=-v; }
+ cimg_mapV(*this,k) tmp[k]+=(t)(coef*(*this)(xi,yi,0,k));
+ X+=(pu=u); Y+=(pv=v); S+=coef;
+ } break;
+ case 1: // Linear interpolation
+ for (l=0; l<length; l+=dl) {
+ const float coef = (float)std::exp(-l*l/fsigma2);
+ t u = (t)(W.linear_pix2d(X,Y,0,0)), v = (t)(W.linear_pix2d(X,Y,0,1));
+ if ((pu*u+pv*v)<0) { u=-u; v=-v; }
+ cimg_mapV(*this,k) tmp[k]+=(t)(coef*linear_pix2d(X,Y,0,k));
+ X+=(pu=u); Y+=(pv=v); S+=coef;
+ } break;
+ default: // 2nd-order Runge-kutta interpolation
+ for (l=0; l<length; l+=dl) {
+ const float coef = (float)std::exp(-l*l/fsigma2);
+ t u0 = (t)(0.5f*dl*W.linear_pix2d(X,Y,0,0)), v0 = (t)(0.5f*dl*W.linear_pix2d(X,Y,0,1));
+ if ((pu*u0+pv*v0)<0) { u0=-u0; v0=-v0; }
+ t u = (t)(W.linear_pix2d(X+u0,Y+v0,0,0)), v = (t)(W.linear_pix2d(X+u0,Y+v0,0,1));
+ if ((pu*u+pv*v)<0) { u=-u; v=-v; }
+ cimg_mapV(*this,k) tmp[k]+=(t)(coef*linear_pix2d(X,Y,0,k));
+ X+=(pu=u); Y+=(pv=v); S+=coef;
+ } break;
+ }
+ if (S>0) cimg_mapV(dest,k) dest(x,y,0,k)+=tmp[k]/S;
+ else cimg_mapV(dest,k) dest(x,y,0,k)+=(t)((*this)(x,y,0,k));
+ }
+ }
+ const float *ptrs = dest.data+dest.size(); cimg_map(*this,ptrd,T) *ptrd = (T)(*(--ptrs)/N);
+ }
+ return *this;
+ }
+
+ //! Get a blurred version of an image following a field of diffusion tensors.
+ /**
+ \param G = Field of square roots of diffusion tensors used to drive the smoothing.
+ \param amplitude = amplitude of the smoothing.
+ \param dl = spatial discretization.
+ \param da = angular discretization.
+ \param gauss_prec = precision of the gaussian function.
+ \param interpolation Used interpolation scheme (0 = nearest-neighbor, 1 = linear, 2 = Runge-Kutta)
+ \param fast_approx = Tell to use the fast approximation or not.
+ **/
+ template<typename t>
+ CImg get_blur_anisotropic(const CImg<t>& G, const float amplitude=30.0f, const float dl=0.8f,const float da=30.0f,
+ const float gauss_prec=2.0f, const unsigned int interpolation=0, const bool fast_approx=true) const {
+ return CImg<T>(*this).blur_anisotropic(G,amplitude,dl,da,gauss_prec,interpolation,fast_approx);
+ }
+
+ //! Blur an image following a field of diffusion tensors.
+ CImg& blur_anisotropic(const float amplitude, const float sharpness=0.8f, const float anisotropy=0.5f,
+ const float alpha=0.2f,const float sigma=0.8f, const float dl=0.8f,const float da=30.0f,
+ const float gauss_prec=2.0f, const unsigned int interpolation=0, const bool fast_approx=true) {
+ if (!is_empty() && amplitude>0) {
+ if (amplitude==0) return *this;
+ if (amplitude<0 || sharpness<0 || anisotropy<0 || anisotropy>1 || alpha<0 || sigma<0 || dl<0 || da<0 || gauss_prec<0)
+ throw CImgArgumentException("CImg<%s>::blur_anisotropic() : Given parameters are amplitude(%g), sharpness(%g), "
+ "anisotropy(%g), alpha(%g), sigma(%g), dl(%g), da(%g), gauss_prec(%g).\n"
+ "Admissible parameters are in the range : amplitude>0, sharpness>0, anisotropy in [0,1], "
+ "alpha>0, sigma>0, dl>0, da>0, gauss_prec>0.",
+ pixel_type(),amplitude,sharpness,anisotropy,alpha,sigma,dl,da,gauss_prec);
+ const bool threed = (depth>1);
+ CImg<float> G(width,height,depth,(threed?6:3),0);
+ const float power1 = 0.5f*sharpness, power2 = power1/(1e-7f+1.0f-anisotropy);
+ float nmax = 0;
+
+ if (threed) { // Field for 3D volumes
+ CImg<float> val(3),vec(3,3);
+ CImg_3x3x3(I,float);
+ const CImg<float> blurred = get_blur(alpha);
+ cimg_mapV(*this,k) cimg_map3x3x3(blurred,x,y,z,k,I) {
+ const float
+ ixf = Incc-Iccc, iyf = Icnc-Iccc, izf = Iccn-Iccc,
+ ixb = Iccc-Ipcc, iyb = Iccc-Icpc, izb = Iccc-Iccp;
+ G(x,y,z,0) += 0.5f*(ixf*ixf + ixb*ixb);
+ G(x,y,z,1) += 0.25f*(ixf*iyf + ixf*iyb + ixb*iyf + ixb*iyb);
+ G(x,y,z,2) += 0.25f*(ixf*izf + ixf*izb + ixb*izf + ixb*izb);
+ G(x,y,z,3) += 0.5f*(iyf*iyf + iyb*iyb);
+ G(x,y,z,4) += 0.25f*(iyf*izf + iyf*izb + iyb*izf + iyb*izb);
+ G(x,y,z,5) += 0.5f*(izf*izf + izb*izb);
+ }
+ G.blur(sigma);
+ cimg_mapXYZ(*this,x,y,z) {
+ G.get_tensor(x,y,z).symeigen(val,vec);
+ const float l1 = val[2], l2 = val[1], l3 = val[0],
+ ux = vec(0,0), uy = vec(0,1), uz = vec(0,2),
+ vx = vec(1,0), vy = vec(1,1), vz = vec(1,2),
+ wx = vec(2,0), wy = vec(2,1), wz = vec(2,2),
+ n1 = (float)std::pow(1.0f+l1+l2+l3,-power1),
+ n2 = (float)std::pow(1.0f+l1+l2+l3,-power2);
+ G(x,y,z,0) = n1*(ux*ux + vx*vx) + n2*wx*wx;
+ G(x,y,z,1) = n1*(ux*uy + vx*vy) + n2*wx*wy;
+ G(x,y,z,2) = n1*(ux*uz + vx*vz) + n2*wx*wz;
+ G(x,y,z,3) = n1*(uy*uy + vy*vy) + n2*wy*wy;
+ G(x,y,z,4) = n1*(uy*uz + vy*vz) + n2*wy*wz;
+ G(x,y,z,5) = n1*(uz*uz + vz*vz) + n2*wz*wz;
+ if (n1>nmax) nmax=n1;
+ }
+ } else { // Field for 2D images
+ CImg<float> val(2),vec(2,2);
+ CImg_3x3x1(I,float);
+ const CImg<float> blurred = get_blur(alpha);
+ cimg_mapV(*this,k) cimg_map3x3x1(blurred,x,y,0,k,I) {
+ const float
+ ixf = Inc-Icc, iyf = Icn-Icc,
+ ixb = Icc-Ipc, iyb = Icc-Icp;
+ G(x,y,0,0) += 0.5f*(ixf*ixf+ixb*ixb);
+ G(x,y,0,1) += 0.25f*(ixf*iyf+ixf*iyb+ixb*iyf+ixb*iyb);
+ G(x,y,0,2) += 0.5f*(iyf*iyf+iyb*iyb);
+ }
+ G.blur(sigma);
+ cimg_mapXY(*this,x,y) {
+ G.get_tensor(x,y).symeigen(val,vec);
+ const float l1 = val[1], l2 = val[0],
+ ux = vec(1,0), uy = vec(1,1),
+ vx = vec(0,0), vy = vec(0,1),
+ n1 = (float)std::pow(1.0f+l1+l2,-power1),
+ n2 = (float)std::pow(1.0f+l1+l2,-power2);
+ G(x,y,0,0) = n1*ux*ux + n2*vx*vx;
+ G(x,y,0,1) = n1*ux*uy + n2*vx*vy;
+ G(x,y,0,2) = n1*uy*uy + n2*vy*vy;
+ if (n1>nmax) nmax=n1;
+ }
+ }
+ G/=nmax;
+ blur_anisotropic(G,amplitude,dl,da,gauss_prec,interpolation,fast_approx);
+ }
+ return *this;
+ }
+
+ //! Blur an image following a field of diffusion tensors.
+ /**
+ \param amplitude = amplitude of the smoothing.
+ \param sharpness = define the contour preservation.
+ \param anisotropy = define the smoothing anisotropy.
+ \param alpha = image pre-blurring (gaussian).
+ \param sigma = regularity of the tensor-valued tqgeometry.
+ \param dl = spatial discretization.
+ \param da = angular discretization.
+ \param gauss_prec = precision of the gaussian function.
+ \param interpolation Used interpolation scheme (0 = nearest-neighbor, 1 = linear, 2 = Runge-Kutta)
+ \param fast_approx = Tell to use the fast approximation or not
+ **/
+ CImg get_blur_anisotropic(const float amplitude, const float sharpness=0.8f, const float anisotropy=0.5f,
+ const float alpha=0.2f, const float sigma=0.8f, const float dl=0.8f,
+ const float da=30.0f, const float gauss_prec=2.0f, const unsigned int interpolation=0,
+ const bool fast_approx=true) const {
+
+ return CImg<T>(*this).blur_anisotropic(amplitude,sharpness,anisotropy,alpha,sigma,dl,da,gauss_prec,interpolation,fast_approx);
+ }
+
+ //! Return the Fast Fourier Transform of an image (along a specified axis)
+ CImgl<typename cimg::largest<T,float>::type> get_FFT(const char axe,const bool inverse=false) const {
+ typedef typename cimg::largest<T,float>::type restype;
+ return CImgl<restype>(*this,CImg<restype>(width,height,depth,dim,0)).FFT(axe,inverse);
+ }
+
+ //! Return the Fast Fourier Transform on an image
+ CImgl<typename cimg::largest<T,float>::type> get_FFT(const bool inverse=false) const {
+ typedef typename cimg::largest<T,float>::type restype;
+ return CImgl<restype>(*this,CImg<restype>(width,height,depth,dim,0)).FFT(inverse);
+ }
+
+ //! Apply a median filter.
+ CImg get_blur_median(const unsigned int n=3) {
+ CImg<T> res(*this,false);
+ if (!n || n==1) return *this;
+ const int hl=n/2, hr=hl-1+n%2;
+ if (res.depth!=1) { // 3D median filter
+ CImg<T> vois;
+ cimg_mapXYZV(*this,x,y,z,k) {
+ vois = get_crop(x-hl,y-hl,z-hl,k,x+hr,y+hr,z+hr,k);
+ res(x,y,z,k) = vois.median();
+ }
+ } else { // 2D median filter
+#define _median_sort(a,b) if ((a)>(b)) cimg::swap(a,b)
+ switch (n) {
+ case 3: {
+ CImg_3x3(I,T);
+ CImg_3x3(J,T);
+ cimg_mapV(*this,k) cimg_map3x3(*this,x,y,0,k,I) {
+ cimg_copy3x3x1(I,J);
+ _median_sort(Jcp, Jnp); _median_sort(Jcc, Jnc); _median_sort(Jcn, Jnn);
+ _median_sort(Jpp, Jcp); _median_sort(Jpc, Jcc); _median_sort(Jpn, Jcn);
+ _median_sort(Jcp, Jnp); _median_sort(Jcc, Jnc); _median_sort(Jcn, Jnn);
+ _median_sort(Jpp, Jpc); _median_sort(Jnc, Jnn); _median_sort(Jcc, Jcn);
+ _median_sort(Jpc, Jpn); _median_sort(Jcp, Jcc); _median_sort(Jnp, Jnc);
+ _median_sort(Jcc, Jcn); _median_sort(Jcc, Jnp); _median_sort(Jpn, Jcc);
+ _median_sort(Jcc, Jnp);
+ res(x,y,0,k) = Jcc;
+ }
+ } break;
+ case 5: {
+ CImg_5x5(I,T);
+ CImg_5x5(J,T);
+ cimg_mapV(*this,k) cimg_map5x5(*this,x,y,0,k,I) {
+ cimg_copy5x5x1(I,J);
+ _median_sort(Jbb, Jpb); _median_sort(Jnb, Jab); _median_sort(Jcb, Jab); _median_sort(Jcb, Jnb);
+ _median_sort(Jpp, Jcp); _median_sort(Jbp, Jcp); _median_sort(Jbp, Jpp); _median_sort(Jap, Jbc);
+ _median_sort(Jnp, Jbc); _median_sort(Jnp, Jap); _median_sort(Jcc, Jnc); _median_sort(Jpc, Jnc);
+ _median_sort(Jpc, Jcc); _median_sort(Jbn, Jpn); _median_sort(Jac, Jpn); _median_sort(Jac, Jbn);
+ _median_sort(Jnn, Jan); _median_sort(Jcn, Jan); _median_sort(Jcn, Jnn); _median_sort(Jpa, Jca);
+ _median_sort(Jba, Jca); _median_sort(Jba, Jpa); _median_sort(Jna, Jaa); _median_sort(Jcb, Jbp);
+ _median_sort(Jnb, Jpp); _median_sort(Jbb, Jpp); _median_sort(Jbb, Jnb); _median_sort(Jab, Jcp);
+ _median_sort(Jpb, Jcp); _median_sort(Jpb, Jab); _median_sort(Jpc, Jac); _median_sort(Jnp, Jac);
+ _median_sort(Jnp, Jpc); _median_sort(Jcc, Jbn); _median_sort(Jap, Jbn); _median_sort(Jap, Jcc);
+ _median_sort(Jnc, Jpn); _median_sort(Jbc, Jpn); _median_sort(Jbc, Jnc); _median_sort(Jba, Jna);
+ _median_sort(Jcn, Jna); _median_sort(Jcn, Jba); _median_sort(Jpa, Jaa); _median_sort(Jnn, Jaa);
+ _median_sort(Jnn, Jpa); _median_sort(Jan, Jca); _median_sort(Jnp, Jcn); _median_sort(Jap, Jnn);
+ _median_sort(Jbb, Jnn); _median_sort(Jbb, Jap); _median_sort(Jbc, Jan); _median_sort(Jpb, Jan);
+ _median_sort(Jpb, Jbc); _median_sort(Jpc, Jba); _median_sort(Jcb, Jba); _median_sort(Jcb, Jpc);
+ _median_sort(Jcc, Jpa); _median_sort(Jnb, Jpa); _median_sort(Jnb, Jcc); _median_sort(Jnc, Jca);
+ _median_sort(Jab, Jca); _median_sort(Jab, Jnc); _median_sort(Jac, Jna); _median_sort(Jbp, Jna);
+ _median_sort(Jbp, Jac); _median_sort(Jbn, Jaa); _median_sort(Jpp, Jaa); _median_sort(Jpp, Jbn);
+ _median_sort(Jcp, Jpn); _median_sort(Jcp, Jan); _median_sort(Jnc, Jpa); _median_sort(Jbn, Jna);
+ _median_sort(Jcp, Jnc); _median_sort(Jcp, Jbn); _median_sort(Jpb, Jap); _median_sort(Jnb, Jpc);
+ _median_sort(Jbp, Jcn); _median_sort(Jpc, Jcn); _median_sort(Jap, Jcn); _median_sort(Jab, Jbc);
+ _median_sort(Jpp, Jcc); _median_sort(Jcp, Jac); _median_sort(Jab, Jpp); _median_sort(Jab, Jcp);
+ _median_sort(Jcc, Jac); _median_sort(Jbc, Jac); _median_sort(Jpp, Jcp); _median_sort(Jbc, Jcc);
+ _median_sort(Jpp, Jbc); _median_sort(Jpp, Jcn); _median_sort(Jcc, Jcn); _median_sort(Jcp, Jcn);
+ _median_sort(Jcp, Jbc); _median_sort(Jcc, Jnn); _median_sort(Jcp, Jcc); _median_sort(Jbc, Jnn);
+ _median_sort(Jcc, Jba); _median_sort(Jbc, Jba); _median_sort(Jbc, Jcc);
+ res(x,y,0,k) = Jcc;
+ }
+ } break;
+ default: {
+ CImg<T> vois;
+ cimg_mapXYV(*this,x,y,k) {
+ vois = get_crop(x-hl,y-hl,0,k,x+hr,y+hr,0,k);
+ res(x,y,0,k) = vois.median();
+ }
+ } break;
+ }
+ }
+ return res;
+ }
+
+ //! Apply a median filter
+ CImg& blur_median(const unsigned int n=3) { return get_blur_median(n).swap(*this); }
+
+ //@}
+ //
+ //
+ //
+ //! \name Matrix and vector computation
+ //@{
+ //
+ //
+
+ //! Return a vector with specified coefficients
+ static CImg vector(const T& a1) { return CImg<T>(1,1).fill(a1); }
+
+ //! Return a vector with specified coefficients
+ static CImg vector(const T& a1,const T& a2) { return CImg<T>(1,2).fill(a1,a2); }
+
+ //! Return a vector with specified coefficients
+ static CImg vector(const T& a1,const T& a2,const T& a3) { return CImg<T>(1,3).fill(a1,a2,a3); }
+
+ //! Return a vector with specified coefficients
+ static CImg vector(const T& a1,const T& a2,const T& a3,const T& a4) { return CImg<T>(1,4).fill(a1,a2,a3,a4); }
+
+ //! Return a vector with specified coefficients
+ static CImg vector(const T& a1,const T& a2,const T& a3,const T& a4,const T& a5) { return CImg<T>(1,5).fill(a1,a2,a3,a4,a5); }
+
+ //! Return a vector with specified coefficients
+ static CImg vector(const T& a1,const T& a2,const T& a3,const T& a4,const T& a5,const T& a6) { return CImg<T>(1,6).fill(a1,a2,a3,a4,a5,a6); }
+
+ //! Return a vector with specified coefficients
+ static CImg vector(const T& a1,const T& a2,const T& a3,const T& a4,
+ const T& a5,const T& a6,const T& a7) { return CImg<T>(1,7).fill(a1,a2,a3,a4,a5,a6,a7); }
+
+ //! Return a vector with specified coefficients
+ static CImg vector(const T& a1,const T& a2,const T& a3,const T& a4,
+ const T& a5,const T& a6,const T& a7,const T& a8) { return CImg<T>(1,8).fill(a1,a2,a3,a4,a5,a6,a7,a8); }
+
+ //! Return a vector with specified coefficients
+ static CImg vector(const T& a1,const T& a2,const T& a3,const T& a4,
+ const T& a5,const T& a6,const T& a7,const T& a8,const T& a9) { return CImg<T>(1,9).fill(a1,a2,a3,a4,a5,a6,a7,a8,a9); }
+
+ //! Return a vector with specified coefficients
+ static CImg vector(const T& a1,const T& a2,const T& a3,const T& a4,
+ const T& a5,const T& a6,const T& a7,const T& a8,
+ const T& a9,const T& a10) { return CImg<T>(1,10).fill(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10); }
+
+ //! Return a vector with specified coefficients
+ static CImg vector(const T& a1,const T& a2,const T& a3,const T& a4,
+ const T& a5,const T& a6,const T& a7,const T& a8,
+ const T& a9,const T& a10, const T& a11) {
+ return CImg<T>(1,11).fill(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11);
+ }
+
+ //! Return a vector with specified coefficients
+ static CImg vector(const T& a1,const T& a2,const T& a3,const T& a4,
+ const T& a5,const T& a6,const T& a7,const T& a8,
+ const T& a9,const T& a10, const T& a11, const T& a12) {
+ return CImg<T>(1,12).fill(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12);
+ }
+
+ //! Return a vector with specified coefficients
+ static CImg vector(const T& a1,const T& a2,const T& a3,const T& a4,
+ const T& a5,const T& a6,const T& a7,const T& a8,
+ const T& a9,const T& a10, const T& a11, const T& a12,
+ const T& a13) {
+ return CImg<T>(1,13).fill(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13);
+ }
+
+ //! Return a square matrix with specified coefficients
+ static CImg matrix(const T& a1) { return vector(a1); }
+
+ //! Return a square matrix with specified coefficients
+ static CImg matrix(const T& a1,const T& a2,
+ const T& a3,const T& a4) {
+ return CImg<T>(2,2).fill(a1,a2,
+ a3,a4);
+ }
+
+ //! Return a square matrix with specified coefficients
+ static CImg matrix(const T& a1,const T& a2,const T& a3,
+ const T& a4,const T& a5,const T& a6,
+ const T& a7,const T& a8,const T& a9) {
+ return CImg<T>(3,3).fill(a1,a2,a3,
+ a4,a5,a6,
+ a7,a8,a9);
+ }
+
+ //! Return a square matrix with specified coefficients
+ static CImg matrix(const T& a1,const T& a2,const T& a3,const T& a4,
+ const T& a5,const T& a6,const T& a7,const T& a8,
+ const T& a9,const T& a10,const T& a11,const T& a12,
+ const T& a13,const T& a14,const T& a15,const T& a16) {
+ return CImg<T>(4,4).fill(a1,a2,a3,a4,
+ a5,a6,a7,a8,
+ a9,a10,a11,a12,
+ a13,a14,a15,a16);
+ }
+
+ //! Return a square matrix with specified coefficients
+ static CImg matrix(const T& a1,const T& a2,const T& a3,const T& a4,const T& a5,
+ const T& a6,const T& a7,const T& a8,const T& a9,const T& a10,
+ const T& a11,const T& a12,const T& a13,const T& a14,const T& a15,
+ const T& a16,const T& a17,const T& a18,const T& a19,const T& a20,
+ const T& a21,const T& a22,const T& a23,const T& a24,const T& a25) {
+ return CImg<T>(5,5).fill(a1,a2,a3,a4,a5,
+ a6,a7,a8,a9,a10,
+ a11,a12,a13,a14,a15,
+ a16,a17,a18,a19,a20,
+ a21,a22,a23,a24,a25);
+ }
+
+ //! Return a diffusion tensor with specified coefficients
+ static CImg tensor(const T& a1) { return matrix(a1); }
+
+ //! Return a diffusion tensor with specified coefficients
+ static CImg tensor(const T& a1,const T& a2,const T& a3) {
+ return matrix(a1,a2,
+ a2,a3);
+ }
+
+ //! Return a diffusion tensor with specified coefficients
+ static CImg tensor(const T& a1,const T& a2,const T& a3,const T& a4,const T& a5,const T& a6) {
+ return matrix(a1,a2,a3,
+ a2,a4,a5,
+ a3,a5,a6);
+ }
+
+ //! Return a diagonal matrix with specified coefficients
+ static CImg diagonal(const T& a1) { return matrix(a1); }
+
+ //! Return a diagonal matrix with specified coefficients
+ static CImg diagonal(const T& a1,const T& a2) {
+ return matrix(a1,0,
+ 0,a2);
+ }
+
+ //! Return a diagonal matrix with specified coefficients
+ static CImg diagonal(const T& a1,const T& a2,const T& a3) {
+ return matrix(a1,0,0,
+ 0,a2,0,
+ 0,0,a3);
+ }
+
+ //! Return a diagonal matrix with specified coefficients
+ static CImg diagonal(const T& a1,const T& a2,const T& a3,const T& a4) {
+ return matrix(a1,0,0,0,
+ 0,a2,0,0,
+ 0,0,a3,0,
+ 0,0,0,a4);
+ }
+
+ //! Return a diagonal matrix with specified coefficients
+ static CImg diagonal(const T& a1,const T& a2,const T& a3,const T& a4,const T& a5) {
+ return matrix(a1,0,0,0,0,
+ 0,a2,0,0,0,
+ 0,0,a3,0,0,
+ 0,0,0,a4,0,
+ 0,0,0,0,a5);
+ }
+
+
+ //! Return a new image corresponding to the vector located at (\p x,\p y,\p z) of the current vector-valued image.
+ CImg get_vector(const unsigned int x=0,const unsigned int y=0,const unsigned int z=0) const {
+ CImg dest(1,dim);
+ cimg_mapV(*this,k) dest[k]=(*this)(x,y,z,k);
+ return dest;
+ }
+
+ //! Return a new image corresponding to the \a square \a matrix located at (\p x,\p y,\p z) of the current vector-valued image.
+ CImg get_matrix(const unsigned int x=0,const unsigned int y=0,const unsigned int z=0) const {
+ const int n = (int)std::sqrt((double)dim);
+ CImg dest(n,n);
+ cimg_mapV(*this,k) dest[k]=(*this)(x,y,z,k);
+ return dest;
+ }
+
+ //! Return a new image corresponding to the \a diffusion \a tensor located at (\p x,\p y,\p z) of the current vector-valued image.
+ CImg get_tensor(const unsigned int x=0,const unsigned int y=0,const unsigned int z=0) const {
+ if (dim==6) return tensor((*this)(x,y,z,0),(*this)(x,y,z,1),(*this)(x,y,z,2),
+ (*this)(x,y,z,3),(*this)(x,y,z,4),(*this)(x,y,z,5));
+ if (dim==3) return tensor((*this)(x,y,z,0),(*this)(x,y,z,1),(*this)(x,y,z,2));
+ return tensor((*this)(x,y,z,0));
+ }
+
+ //! Set the image \p vec as the \a vector \a valued pixel located at (\p x,\p y,\p z) of the current vector-valued image.
+ CImg& set_vector(const CImg& vec,const unsigned int x=0,const unsigned int y=0,const unsigned int z=0) {
+ return draw_point(x,y,z,vec.data,1);
+ }
+ //! Set the image \p vec as the \a square \a matrix-valued pixel located at (\p x,\p y,\p z) of the current vector-valued image.
+ CImg& set_matrix(const CImg& mat,const unsigned int x=0,const unsigned int y=0,const unsigned int z=0) {
+ return set_vector(mat,x,y,z);
+ }
+ //! Set the image \p vec as the \a tensor \a valued pixel located at (\p x,\p y,\p z) of the current vector-valued image.
+ CImg& set_tensor(const CImg& ten,const unsigned int x=0,const unsigned int y=0,const unsigned int z=0) {
+ if (ten.height==2) {
+ (*this)(x,y,z,0)=ten[0];
+ (*this)(x,y,z,1)=ten[1];
+ (*this)(x,y,z,2)=ten[3];
+ }
+ else {
+ (*this)(x,y,z,0)=ten[0];
+ (*this)(x,y,z,1)=ten[1];
+ (*this)(x,y,z,2)=ten[2];
+ (*this)(x,y,z,3)=ten[4];
+ (*this)(x,y,z,4)=ten[5];
+ (*this)(x,y,z,5)=ten[8];
+ }
+ return *this;
+ }
+ //! Set the current matrix to be the identity matrix.
+ CImg& identity_matrix(const unsigned int N) { return get_identity_matrix(N).swap(*this); }
+
+ //! Return a matrix \p dim * \p dim equal to \p factor * \a Identity.
+ static CImg get_identity_matrix(const unsigned int N) {
+ CImg<T> res(N,N,1,1,0);
+ cimg_mapX(res,x) res(x,x)=1;
+ return res;
+ }
+
+ //! Return a rotation matrix along the (x,y,z)-axis with an angle w.
+ static CImg get_rotation_matrix(const float x,const float y,const float z,const float w, const bool quaternion_data=false) {
+ float X,Y,Z,W;
+ if (!quaternion_data) {
+ const float norm = (float)std::sqrt(x*x + y*y + z*z),
+ nx = norm>0?x/norm:0,
+ ny = norm>0?y/norm:0,
+ nz = norm>0?z/norm:1,
+ nw = norm>0?w:0,
+ sina = (float)std::sin(nw/2),
+ cosa = (float)std::cos(nw/2);
+ X = nx*sina;
+ Y = ny*sina;
+ Z = nz*sina;
+ W = cosa;
+ } else {
+ const float norm = (float)std::sqrt(x*x + y*y + z*z + w*w);
+ if (norm>0) { X=x/norm; Y=y/norm; Z=z/norm; W=w/norm; }
+ else { X=Y=Z=0; W=1; }
+ }
+ const float xx=X*X, xy=X*Y, xz=X*Z, xw=X*W, yy=Y*Y, yz=Y*Z, yw=Y*W, zz=Z*Z, zw=Z*W;
+ return CImg<T>::matrix(1-2*(yy+zz), 2*(xy+zw), 2*(xz-yw),
+ 2*(xy-zw), 1-2*(xx+zz), 2*(yz+xw),
+ 2*(xz+yw), 2*(yz-xw), 1-2*(xx+yy));
+ }
+
+ //! In-place version of get_rotationX_matrix
+ CImg& rotation_matrix(const float x, const float y, const float z, const float w, const bool quaternion_data=false) {
+ return get_rotation_matrix(x,y,z,w,quaternion_data).swap(*this);
+ }
+
+ //! Return the transpose version of the current matrix.
+ CImg get_transpose() const {
+ CImg<T> res(height,width,depth,dim);
+ cimg_mapXYZV(*this,x,y,z,v) res(y,x,z,v) = (*this)(x,y,z,v);
+ return res;
+ }
+
+ //! Replace the current matrix by its transpose.
+ CImg& transpose() {
+ if (width==1) { width=height; height=1; return *this; }
+ if (height==1) { height=width; width=1; return *this; }
+ if (width==height) {
+ cimg_mapYZV(*this,y,z,v) for (int x=y; x<(int)width; x++) cimg::swap((*this)(x,y,z,v),(*this)(y,x,z,v));
+ return *this;
+ }
+ return (*this)=get_transpose();
+ }
+
+ //! Get a diagonal matrix, whose diagonal coefficients are the coefficients of the input image
+ CImg get_diagonal() const {
+ if (is_empty()) return CImg<T>();
+ CImg res(size(),size(),1,1,0);
+ cimg_mapoff(*this,off) res(off,off)=(*this)(off);
+ return res;
+ }
+
+ //! Replace a vector by a diagonal matrix containing the original vector coefficients.
+ CImg& diagonal() {
+ return get_diagonal().swap(*this);
+ }
+
+ //! Inverse the current matrix.
+ CImg& inverse(const bool use_LU=true) {
+ if (!is_empty()) {
+ if (width!=height || depth!=1 || dim!=1)
+ throw CImgInstanceException("CImg<%s>::inverse() : Instance matrix (%u,%u,%u,%u,%p) is not square.",
+ pixel_type(),width,height,depth,dim,data);
+ const double dete = width>3?-1.0:det();
+ if (dete!=0.0 && width==2) {
+ const double
+ a = data[0], c = data[1],
+ b = data[2], d = data[3];
+ data[0] = (T)(d/dete); data[1] = (T)(-c/dete);
+ data[2] = (T)(-b/dete), data[3] = (T)(a/dete);
+ } else if (dete!=0.0 && width==3) {
+ const double
+ a = data[0], d = data[1], g = data[2],
+ b = data[3], e = data[4], h = data[5],
+ c = data[6], f = data[7], i = data[8];
+ data[0] = (T)((i*e-f*h)/dete), data[1] = (T)((g*f-i*d)/dete), data[2] = (T)((d*h-g*e)/dete);
+ data[3] = (T)((h*c-i*b)/dete), data[4] = (T)((i*a-c*g)/dete), data[5] = (T)((g*b-a*h)/dete);
+ data[6] = (T)((b*f-e*c)/dete), data[7] = (T)((d*c-a*f)/dete), data[8] = (T)((a*e-d*b)/dete);
+ } else {
+ if (use_LU) { // LU-based inverse computation
+ CImg<T> A(*this), indx, col(1,width);
+ bool d;
+ A._LU(indx,d);
+ cimg_mapX(*this,j) {
+ col.fill(0); col(j)=1;
+ col._solve(A,indx);
+ cimg_mapX(*this,i) (*this)(j,i) = col(i);
+ }
+ } else { // SVD-based inverse computation
+ CImg<T> U(width,width),S(1,width),V(width,width);
+ SVD(U,S,V,false);
+ U.transpose();
+ cimg_mapY(S,k) if (S[k]!=0) S[k]=1/S[k];
+ S.diagonal();
+ *this = V*S*U;
+ }
+ }
+ }
+ return *this;
+ }
+
+ //! Return the inverse of the current matrix.
+ CImg<typename cimg::largest<T,float>::type> get_inverse(const bool use_LU=true) const {
+ typedef typename cimg::largest<T,float>::type restype;
+ return CImg<restype>(*this).inverse(use_LU);
+ }
+
+ //! Return the pseudo-inverse (Moore-Penrose) of the matrix
+ CImg<typename cimg::largest<T,float>::type> get_pseudoinverse() const {
+ typedef typename cimg::largest<T,float>::type restype;
+ CImg<restype> At = get_transpose(), At2(At);
+ return (((At*=*this).inverse())*=At2);
+ }
+
+ //! Replace the matrix by its pseudo-inverse
+ CImg& pseudoinverse() {
+ typedef typename cimg::largest<T,float>::type restype;
+ CImg<restype> At = get_transpose(), At2(At);
+ ((At*=*this).inverse())*=At2;
+ return ((*this)=At);
+ }
+
+ //! Return the trace of the current matrix.
+ double trace() const {
+ if (is_empty())
+ throw CImgInstanceException("CImg<%s>::trace() : Instance matrix (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ double res=0;
+ cimg_mapX(*this,k) res+=(*this)(k,k);
+ return res;
+ }
+
+ //! Return the kth smallest element of the image
+ // (Adapted from the numerical recipies for CImg)
+ const T kth_smallest(const unsigned int k) const {
+ if (is_empty())
+ throw CImgInstanceException("CImg<%s>::kth_smallest() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ CImg<T> arr(*this);
+ unsigned long l=0,ir=size()-1;
+ for (;;) {
+ if (ir<=l+1) {
+ if (ir==l+1 && arr[ir]<arr[l]) cimg::swap(arr[l],arr[ir]);
+ return arr[k];
+ } else {
+ const unsigned long mid = (l+ir)>>1;
+ cimg::swap(arr[mid],arr[l+1]);
+ if (arr[l]>arr[ir]) cimg::swap(arr[l],arr[ir]);
+ if (arr[l+1]>arr[ir]) cimg::swap(arr[l+1],arr[ir]);
+ if (arr[l]>arr[l+1]) cimg::swap(arr[l],arr[l+1]);
+ unsigned long i = l+1, j = ir;
+ const T pivot = arr[l+1];
+ for (;;) {
+ do i++; while (arr[i]<pivot);
+ do j--; while (arr[j]>pivot);
+ if (j<i) break;
+ cimg::swap(arr[i],arr[j]);
+ }
+ arr[l+1] = arr[j];
+ arr[j] = pivot;
+ if (j>=k) ir=j-1;
+ if (j<=k) l=i;
+ }
+ }
+ return 0;
+ }
+
+ //! Return the median of the image
+ const T median() const {
+ const unsigned int s = size();
+ const T res = kth_smallest(s>>1);
+ return (s%2)?res:((res+kth_smallest((s>>1)-1))/2);
+ }
+
+ //! Return the dot product of the current vector/matrix with the vector/matrix \p img.
+ double dot(const CImg& img) const {
+ if (is_empty())
+ throw CImgInstanceException("CImg<%s>::dot() : Instance object (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (img.is_empty())
+ throw CImgArgumentException("CImg<%s>::trace() : Specified argument (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),img.width,img.height,img.depth,img.dim,img.data);
+ const unsigned long nb = cimg::min(size(),img.size());
+ double res=0;
+ for (unsigned long off=0; off<nb; off++) res+=data[off]*img[off];
+ return res;
+ }
+
+ //! Return the cross product between two 3d vectors
+ CImg& cross(const CImg& img) {
+ if (width!=1 || height<3 || img.width!=1 || img.height<3)
+ throw CImgInstanceException("CImg<%s>::cross() : Arguments (%u,%u,%u,%u,%p) and (%u,%u,%u,%u,%p) must be both 3d vectors.",
+ pixel_type(),width,height,depth,dim,data,img.width,img.height,img.depth,img.dim,img.data);
+ const T x = (*this)[0], y = (*this)[1], z = (*this)[2];
+ (*this)[0] = y*img[2]-z*img[1];
+ (*this)[1] = z*img[0]-x*img[2];
+ (*this)[2] = x*img[1]-y*img[0];
+ return *this;
+ }
+
+ //! Return the cross product between two 3d vectors
+ CImg get_cross(const CImg& img) const {
+ return CImg<T>(*this).cross(img);
+ }
+
+ //! Return the determinant of the current matrix.
+ double det() const {
+ if (is_empty() || width!=height || depth!=1 || dim!=1)
+ throw CImgInstanceException("CImg<%s>::det() : Instance matrix (%u,%u,%u,%u,%p) is not square or is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ switch (width) {
+ case 1: return (*this)(0,0);
+ case 2: return (*this)(0,0)*(*this)(1,1)-(*this)(0,1)*(*this)(1,0);
+ case 3: {
+ const double
+ a = data[0], d = data[1], g = data[2],
+ b = data[3], e = data[4], h = data[5],
+ c = data[6], f = data[7], i = data[8];
+ return i*a*e-a*h*f-i*b*d+b*g*f+c*d*h-c*g*e;
+ }
+ default: {
+ typedef typename cimg::largest<T,float>::type ftype;
+ CImg<ftype> lu(*this);
+ CImg<unsigned int> indx;
+ bool d;
+ lu._LU(indx,d);
+ double res = d?1.0:-1.0;
+ cimg_mapX(lu,i) res*=lu(i,i);
+ return res;
+ }
+ }
+ return 0;
+ }
+
+ //! Return the norm of the current vector/matrix. \p ntype = norm type (0=L2, 1=L1, -1=Linf).
+ double norm(const int ntype=2) const {
+ if (is_empty())
+ throw CImgInstanceException("CImg<%s>::norm() : Instance object (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ double res = 0;
+ switch (ntype) {
+ case -1: {
+ cimg_mapoff(*this,off) {
+ const double tmp = cimg::abs((double)data[off]);
+ if (tmp>res) res = tmp;
+ }
+ return res;
+ } break;
+ case 1 : {
+ cimg_mapoff(*this,off) res+=cimg::abs((double)data[off]);
+ return res;
+ } break;
+ default: { return std::sqrt(dot(*this)); }
+ }
+ return 0;
+ }
+
+ //! Return the sum of all the pixel values in an image.
+ double sum() const {
+ if (is_empty())
+ throw CImgInstanceException("CImg<%s>::sum() : Instance object (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ double res=0;
+ cimg_map(*this,ptr,T) res+=*ptr;
+ return res;
+ }
+
+ //! Compute the SVD of a general matrix.
+ template<typename t> const CImg& SVD(CImg<t>& U, CImg<t>& S, CImg<t>& V,
+ const bool sorting=true, const unsigned int max_iter=40) const {
+ if (is_empty()) { U.empty(); S.empty(); V.empty(); }
+ else {
+ U = *this;
+ if (S.size()<width) S.assign(1,width);
+ if (V.width<width || V.height<height) V.assign(width,width);
+ CImg<t> rv1(width);
+ t anorm=0,c,f,g=0,h,s,scale=0;
+ int l=0,nm=0;
+
+ cimg_mapX(U,i) {
+ l = i+1; rv1[i] = scale*g; g = s = scale = 0;
+ if (i<dimy()) {
+ for (int k=i; k<dimy(); k++) scale+= cimg::abs(U(i,k));
+ if (scale) {
+ for (int k=i; k<dimy(); k++) { U(i,k)/=scale; s+= U(i,k)*U(i,k); }
+ f = U(i,i); g = (t)((f>=0?-1:1)*std::sqrt(s)); h=f*g-s; U(i,i)=f-g;
+ for (int j=l; j<dimx(); j++) {
+ s = 0; for (int k=i; k<dimy(); k++) s+= U(i,k)*U(j,k);
+ f = s/h;
+ { for (int k=i; k<dimy(); k++) U(j,k)+= f*U(i,k); }
+ }
+ { for (int k=i; k<dimy(); k++) U(i,k)*= scale; }
+ }
+ }
+ S[i]=scale*g;
+
+ g = s = scale = 0;
+ if (i<dimy() && i!=dimx()-1) {
+ for (int k=l; k<dimx(); k++) scale += cimg::abs(U(k,i));
+ if (scale) {
+ for (int k=l; k<dimx(); k++) { U(k,i)/= scale; s+= U(k,i)*U(k,i); }
+ f = U(l,i); g = (t)((f>=0?-1:1)*std::sqrt(s)); h = f*g-s; U(l,i) = f-g;
+ { for (int k=l; k<dimx(); k++) rv1[k]=U(k,i)/h; }
+ for (int j=l; j<dimy(); j++) {
+ s=0; for (int k=l; k<dimx(); k++) s+= U(k,j)*U(k,i);
+ { for (int k=l; k<dimx(); k++) U(k,j)+= s*rv1[k]; }
+ }
+ { for (int k=l; k<dimx(); k++) U(k,i)*= scale; }
+ }
+ }
+ anorm=cimg::max((t)anorm,(cimg::abs(S[i])+cimg::abs(rv1[i])));
+ }
+
+ { for (int i=dimx()-1; i>=0; i--) {
+ if (i<dimx()-1) {
+ if (g) {
+ { for (int j=l; j<dimx(); j++) V(i,j) =(U(j,i)/U(l,i))/g; }
+ for (int j=l; j<dimx(); j++) {
+ s=0; for (int k=l; k<dimx(); k++) s+= U(k,i)*V(j,k);
+ { for (int k=l; k<dimx(); k++) V(j,k)+= s*V(i,k); }
+ }
+ }
+ for (int j=l; j<dimx(); j++) V(j,i)=V(i,j)=0.0;
+ }
+ V(i,i) = 1.0; g = rv1[i]; l = i;
+ }
+ }
+
+ { for (int i=cimg::min(dimx(),dimy())-1; i>=0; i--) {
+ l = i+1; g = S[i];
+ for (int j=l; j<dimx(); j++) U(j,i) = 0;
+ if (g) {
+ g = 1/g;
+ for (int j=l; j<dimx(); j++) {
+ s=0; for (int k=l; k<dimy(); k++) s+= U(i,k)*U(j,k);
+ f = (s/U(i,i))*g;
+ { for (int k=i; k<dimy(); k++) U(j,k)+= f*U(i,k); }
+ }
+ { for (int j=i; j<dimy(); j++) U(i,j)*= g; }
+ } else for (int j=i; j<dimy(); j++) U(i,j)=0;
+ U(i,i)++;
+ }
+ }
+
+ for (int k=dimx()-1; k>=0; k--) {
+ for (unsigned int its=0; its<max_iter; its++) {
+ bool flag = true;
+ for (l=k; l>=0; l--) {
+ nm = l-1;
+ if ((cimg::abs(rv1[l])+anorm)==anorm) { flag = false; break; }
+ if ((cimg::abs(S[nm])+anorm)==anorm) break;
+ }
+ if (flag) {
+ c = 0; s = 1;
+ for (int i=l; i<=k; i++) {
+ f = s*rv1[i]; rv1[i] = c*rv1[i];
+ if ((cimg::abs(f)+anorm)==anorm) break;
+ g = S[i]; h = (t)cimg::pythagore(f,g); S[i] = h; h = 1/h; c = g*h; s = -f*h;
+ cimg_mapY(U,j) { const t y = U(nm,j), z = U(i,j); U(nm,j) = y*c+z*s; U(i,j) = z*c-y*s; }
+ }
+ }
+ const t& z = S[k];
+ if (l==k) { if (z<0) { S[k] = -z; cimg_mapX(U,j) V(k,j) = -V(k,j); } break; }
+ nm = k-1;
+ t x = S[l], y = S[nm];
+ g = rv1[nm]; h = rv1[k];
+ f = ((y-z)*(y+z)+(g-h)*(g+h))/(2*h*y);
+ g = (t)cimg::pythagore(f,1.0);
+ f = ((x-z)*(x+z)+h*((y/(f+ (f>=0?g:-g)))-h))/x;
+ c = s = 1;
+ for (int j=l; j<=nm; j++) {
+ const int i = j+1;
+ g = rv1[i]; h = s*g; g = c*g;
+ t y = S[i];
+ t z = (t)cimg::pythagore(f,h);
+ rv1[j] = z; c = f/z; s = h/z;
+ f = x*c+g*s; g = g*c-x*s; h = y*s; y*=c;
+ cimg_mapX(U,jj) { const t x = V(j,jj), z = V(i,jj); V(j,jj) = x*c+z*s; V(i,jj) = z*c-x*s; }
+ z = (t)cimg::pythagore(f,h); S[j] = z;
+ if (z) { z = 1/z; c = f*z; s = h*z; }
+ f = c*g+s*y; x = c*y-s*g;
+ { cimg_mapY(U,jj) { const t y = U(j,jj); z = U(i,jj); U(j,jj) = y*c+z*s; U(i,jj) = z*c-y*s; }}
+ }
+ rv1[l] = 0; rv1[k]=f; S[k]=x;
+ }
+ }
+
+ if (sorting) {
+ CImg<int> permutations(width);
+ S.sort(permutations,false);
+ cimg_mapX(permutations,x) {
+ const int n = permutations(x);
+ if (x<n) {
+ cimg_mapY(U,k) cimg::swap(U(x,k),U(n,k));
+ cimg_mapY(V,l) cimg::swap(V(x,l),V(n,l));
+ }
+ }
+ }
+ }
+ return *this;
+ }
+
+ //! Compute the SVD of a general matrix.
+ template<typename t> const CImg& SVD(CImgl<t>& USV) const {
+ if (USV.size<3) USV.assign(3);
+ return SVD(USV[0],USV[1],USV[2]);
+ }
+
+ //! Compute the SVD of a general matrix.
+ CImgl<typename cimg::largest<T,float>::type> get_SVD(const bool sorting=true) const {
+ typedef typename cimg::largest<T,float>::type restype;
+ CImgl<restype> res(3);
+ SVD(res[0],res[1],res[2],sorting);
+ return res;
+ }
+
+ // INNER ROUTINE : Compute the LU decomposition of a permuted matrix (c.f. numerical recipies)
+ template<typename t> CImg& _LU(CImg<t>& indx, bool& d) {
+ typedef typename cimg::largest<T,float>::type ftype;
+ const int N = dimx();
+ int imax=0;
+ CImg<ftype> vv(N);
+ indx.assign(N);
+ d=true;
+ cimg_mapX(*this,i) {
+ ftype vmax=0.0;
+ cimg_mapX(*this,j) {
+ const ftype tmp = cimg::abs((*this)(j,i));
+ if (tmp>vmax) vmax = tmp;
+ }
+ if (vmax==0) return fill(0);
+ vv[i] = 1/vmax;
+ }
+ cimg_mapX(*this,j) {
+ for (int i=0; i<j; i++) {
+ ftype sum=(*this)(j,i);
+ for (int k=0; k<i; k++) sum-=(*this)(k,i)*(*this)(j,k);
+ (*this)(j,i) = (T)sum;
+ }
+ ftype vmax=0;
+ { for (int i=j; i<dimx(); i++) {
+ ftype sum=(*this)(j,i);
+ for (int k=0; k<j; k++) sum-=(*this)(k,i)*(*this)(j,k);
+ (*this)(j,i) = (T)sum;
+ const ftype tmp = vv[i]*cimg::abs(sum);
+ if (tmp>=vmax) { vmax=tmp; imax=i; }
+ }}
+ if (j!=imax) {
+ cimg_mapX(*this,k) cimg::swap((*this)(k,imax),(*this)(k,j));
+ d =!d;
+ vv[imax] = vv[j];
+ }
+ indx[j] = (t)imax;
+ if ((*this)(j,j)==0) (*this)(j,j)=(T)1e-20;
+ if (j<N) {
+ const ftype tmp = 1/(ftype)(*this)(j,j);
+ for (int i=j+1; i<N; i++) (*this)(j,i)*=tmp;
+ }
+ }
+ return *this;
+ }
+
+ // INNER ROUTINE : Solve a linear system, using the LU decomposition
+ template<typename t> CImg& _solve(const CImg<T>& A, const CImg<t>& indx) {
+ typedef typename cimg::largest<T,float>::type ftype;
+ const int N = size();
+ int ii=-1;
+ ftype sum;
+ for (int i=0; i<N; i++) {
+ const int ip = (int)indx[i];
+ ftype sum = (*this)(ip);
+ (*this)(ip) = (*this)(i);
+ if (ii>=0) for (int j=ii; j<=i-1; j++) sum-=A(j,i)*(*this)(j);
+ else if (sum!=0) ii=i;
+ (*this)(i)=sum;
+ }
+ { for (int i=N-1; i>=0; i--) {
+ sum = (*this)(i);
+ for (int j=i+1; j<N; j++) sum-=A(j,i)*(*this)(j);
+ (*this)(i)=sum/A(i,i);
+ }}
+ return *this;
+ }
+
+ //! Solve a linear system AX=B where B=*this. (in-place version)
+ CImg& solve(const CImg& A) {
+ if (width!=1 || depth!=1 || dim!=1 || height!=A.height || A.depth!=1 || A.dim!=1)
+ throw CImgArgumentException("CImg<%s>::solve() : Instance matrix size is (%u,%u,%u,%u) while "
+ "size of given matrix A is (%u,%u,%u,%u).",
+ pixel_type(),width,height,depth,dim,A.width,A.height,A.depth,A.dim);
+ if (A.width==A.height) {
+ CImg<T> lu(A);
+ CImg<T> indx;
+ bool d;
+ lu._LU(indx,d);
+ _solve(lu,indx);
+ } else assign(A.get_pseudoinverse()*(*this));
+ return *this;
+ }
+
+ //! Solve a linear system AX=B where B=*this.
+ CImg<typename cimg::largest<T,float>::type> get_solve(const CImg& A) const {
+ typedef typename cimg::largest<T,float>::type restype;
+ return CImg<restype>(*this).solve(A);
+ }
+
+ //! Compute the eigenvalues and eigenvectors of a matrix.
+ template<typename t> const CImg<T>& eigen(CImg<t>& val, CImg<t> &vec) const {
+ if (is_empty()) { val.empty(); vec.empty(); }
+ else {
+ if (width!=height || depth>1 || dim>1)
+ throw CImgInstanceException("CImg<%s>::eigen() : Instance object (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (val.size()<width) val.assign(1,width);
+ if (vec.size()<width*width) vec.assign(width,width);
+ switch(width) {
+ case 1: { val[0]=(t)(*this)[0]; vec[0]=(t)1; } break;
+ case 2: {
+ const double a = (*this)[0], b = (*this)[1], c = (*this)[2], d = (*this)[3], e = a+d;
+ double f = e*e-4*(a*d-b*c);
+ cimg::warn(f<0,"CImg<%s>::eigen() : Complex eigenvalues",pixel_type());
+ f = std::sqrt(f);
+ const double l1 = 0.5*(e-f), l2 = 0.5*(e+f);
+ const double theta1 = std::atan2(l2-a,b), theta2 = std::atan2(l1-a,b);
+ val[0]=(t)l2;
+ val[1]=(t)l1;
+ vec(0,0) = (t)std::cos(theta1);
+ vec(0,1) = (t)std::sin(theta1);
+ vec(1,0) = (t)std::cos(theta2);
+ vec(1,1) = (t)std::sin(theta2);
+ } break;
+ default:
+ throw CImgInstanceException("CImg<%s>::eigen() : Eigenvalues computation of general matrices is limited"
+ "to 2x2 matrices (given is %ux%u)", pixel_type(),width,height);
+ }
+ }
+ return *this;
+ }
+
+ //! Return the eigenvalues and eigenvectors of a matrix.
+ CImgl<typename cimg::largest<T,float>::type> get_eigen() const {
+ typedef typename cimg::largest<T,float>::type restype;
+ CImgl<restype> res(2);
+ eigen(res[0],res[1]);
+ return res;
+ }
+
+ //! Compute the eigenvalues and eigenvectors of a matrix.
+ template<typename t> const CImg<T>& eigen(CImgl<t>& eig) const {
+ if (eig.size<2) eig.assign(2);
+ eigen(eig[0],eig[1]);
+ return *this;
+ }
+
+ //! Compute the eigenvalues and eigenvectors of a symmetric matrix.
+ template<typename t> const CImg<T>& symeigen(CImg<t>& val, CImg<t>& vec) const {
+ if (is_empty()) { val.empty(); vec.empty(); }
+ else {
+ if (width!=height || depth>1 || dim>1)
+ throw CImgInstanceException("CImg<%s>::eigen() : Instance object (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+
+ if (val.size()<width) val.assign(1,width);
+ if (vec.data && vec.size()<width*width) vec.assign(width,width);
+ if (width<3) return eigen(val,vec);
+ CImg<t> V(width,width);
+ SVD(vec,val,V,false);
+ cimg_mapX(vec,x) { // check for negative eigenvalues
+ t scal=0;
+ cimg_mapY(vec,y) scal+=vec(x,y)*V(x,y);
+ if (scal<0) val[x]=-val[x];
+ }
+ CImg<int> permutations(width); // sort eigenvalues in decreasing order
+ val.sort(permutations,false);
+ { cimg_mapX(permutations,x) {
+ const int n = permutations(x);
+ if (x<n) cimg_mapY(vec,k) cimg::swap(vec(x,k),vec(n,k));
+ }
+ }
+ }
+ return *this;
+ }
+
+ //! Compute the eigenvalues and eigenvectors of a symmetric matrix.
+ CImgl<typename cimg::largest<T,float>::type> get_symeigen() const {
+ typedef typename cimg::largest<T,float>::type restype;
+ CImgl<restype> res(2);
+ symeigen(res[0],res[1]);
+ return res;
+ }
+
+ //! Compute the eigenvalues and eigenvectors of a symmetric matrix.
+ template<typename t> const CImg<T>& symeigen(CImgl<t>& eig) const {
+ if (eig.size<2) eig.assign(2);
+ symeigen(eig[0],eig[1]);
+ return *this;
+ }
+
+ template<typename t> CImg<T>& _quicksort(const int min,const int max,CImg<t>& permutations,const bool increasing) {
+ if (min<max) {
+ const int mid = (min+max)/2;
+ if (increasing) {
+ if ((*this)[min]>(*this)[mid]) {
+ cimg::swap((*this)[min],(*this)[mid]); cimg::swap(permutations[min],permutations[mid]); }
+ if ((*this)[mid]>(*this)[max]) {
+ cimg::swap((*this)[max],(*this)[mid]); cimg::swap(permutations[max],permutations[mid]); }
+ if ((*this)[min]>(*this)[mid]) {
+ cimg::swap((*this)[min],(*this)[mid]); cimg::swap(permutations[min],permutations[mid]); }
+ } else {
+ if ((*this)[min]<(*this)[mid]) {
+ cimg::swap((*this)[min],(*this)[mid]); cimg::swap(permutations[min],permutations[mid]); }
+ if ((*this)[mid]<(*this)[max]) {
+ cimg::swap((*this)[max],(*this)[mid]); cimg::swap(permutations[max],permutations[mid]); }
+ if ((*this)[min]<(*this)[mid]) {
+ cimg::swap((*this)[min],(*this)[mid]); cimg::swap(permutations[min],permutations[mid]); }
+ }
+ if (max-min>=3) {
+ const T pivot = (*this)[mid];
+ int i = min, j = max;
+ if (increasing) {
+ do {
+ while ((*this)[i]<pivot) i++;
+ while ((*this)[j]>pivot) j--;
+ if (i<=j) {
+ cimg::swap((*this)[i],(*this)[j]);
+ cimg::swap(permutations[i++],permutations[j--]);
+ }
+ } while (i<=j);
+ } else {
+ do {
+ while ((*this)[i]>pivot) i++;
+ while ((*this)[j]<pivot) j--;
+ if (i<=j) {
+ cimg::swap((*this)[i],(*this)[j]);
+ cimg::swap(permutations[i++],permutations[j--]);
+ }
+ } while (i<=j);
+ }
+ if (min<j) _quicksort(min,j,permutations,increasing);
+ if (i<max) _quicksort(i,max,permutations,increasing);
+ }
+ }
+ return *this;
+ }
+
+ //! Sort values of a vector and get permutations.
+ template<typename t>
+ CImg<T>& sort(CImg<t>& permutations,const bool increasing=true) {
+ if (is_empty()) permutations.empty();
+ else {
+ if (permutations.size()!=size()) permutations.assign(size());
+ cimg_mapoff(permutations,off) permutations[off] = off;
+ _quicksort(0,size()-1,permutations,increasing);
+ }
+ return *this;
+ }
+
+ //! Sort values of a vector.
+ CImg<T>& sort(const bool increasing=true) { CImg<T> foo; return sort(foo,increasing); }
+
+ //! Get a sorted version a of vector, with permutations.
+ template<typename t> CImg<T> get_sort(CImg<t>& permutations,const bool increasing=true) {
+ return CImg<T>(*this).sort(permutations,increasing);
+ }
+
+ //! Get a sorted version of a vector.
+ CImg<T> get_sort(const bool increasing=true) {
+ return CImg<T>(*this).sort(increasing);
+ }
+
+ //@}
+ //---------------------------
+ //
+ //! \name Display functions
+ //@{
+ //---------------------------
+
+
+ //! Display an image into a CImgDisplay window.
+ const CImg& display(CImgDisplay& disp) const { disp.display(*this); return *this; }
+
+ //! Same as \ref cimg::wait()
+ const CImg& wait(const unsigned int milliseconds) const { cimg::wait(milliseconds); return *this; }
+
+ //! Display an image in a window with a title \p title, and wait a 'closed' or 'keyboard' event.\n
+ //! Parameters \p min_size and \p max_size set the minimum and maximum dimensions of the display window.
+ //! If negative, they corresponds to a percentage of the original image size.
+ const CImg& display(const char* title,const int min_size=128,const int max_size=1024) const {
+ if (is_empty())
+ throw CImgInstanceException("CImg<%s>::display() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ CImgDisplay *disp;
+ unsigned int w = width+(depth>1?depth:0), h = height+(depth>1?depth:0), XYZ[3];
+ print(title);
+ const unsigned int dmin = cimg::min(w,h), minsiz = min_size>=0?min_size:(-min_size)*dmin/100;
+ if (dmin<minsiz) { w=w*minsiz/dmin; w+=(w==0); h=h*minsiz/dmin; h+=(h==0); }
+ const unsigned int dmax = cimg::max(w,h), maxsiz = max_size>=0?max_size:(-max_size)*dmax/100;
+ if (dmax>maxsiz) { w=w*maxsiz/dmax; w+=(w==0); h=h*maxsiz/dmax; h+=(h==0); }
+ disp = new CImgDisplay(CImg<unsigned char>(w,h,1,1,0),title,1,3);
+ XYZ[0] = width/2; XYZ[1] = height/2; XYZ[2] = depth/2;
+ while (!disp->closed && !disp->key) feature_selection(NULL,1,*disp,XYZ);
+ delete disp;
+ return *this;
+ }
+
+ //! Display an image in a window, with a default title. See also \see display() for details on parameters.
+ const CImg& display(const int min_size=128,const int max_size=1024) const { return display(" ",min_size,max_size); }
+
+ //! High-level interface to select features from images
+ const CImg& feature_selection(int* const selection, const int feature_type,CImgDisplay &disp,
+ unsigned int *const XYZ=NULL,const unsigned char *const color=NULL) const {
+ if (is_empty())
+ throw CImgInstanceException("CImg<%s>::feature_selection() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ const unsigned int oevents = disp.events, onormalization = disp.normalization;
+ disp.events = 3; disp.normalization = 0;
+ unsigned char fgcolor[3]={255,255,105}, bgcolor[3]={0,0,0};
+ if (color) std::memcpy(fgcolor,color,sizeof(unsigned char)*cimg::min(3,dimv()));
+ int carea=0,area=0,phase=0,
+ X0=(int)((XYZ?XYZ[0]:width/2)%width), Y0=(int)((XYZ?XYZ[1]:height/2)%height), Z0=(int)((XYZ?XYZ[2]:depth/2)%depth),
+ X=-1,Y=-1,Z=-1,oX=-1,oY=-1,oZ=-1,X1=-1,Y1=-1,Z1=-1;
+ unsigned int hatch=feature_type?0xF0F0F0F0:~0L;
+ bool feature_selected = false, ytext = false, oresized = disp.resized;
+ CImg<unsigned char> visu, visu0;
+ char text[1024];
+
+ disp.show().key=0;
+ while (!disp.key && !disp.closed && !feature_selected) {
+
+ // Init visu0 if necessary
+ if (disp.resized || !visu0.data) {
+ if (disp.resized) { disp.resize(); oresized = true; }
+ if (depth==1) visu0=get_normalize(0,(T)255); else visu0=get_projections2d(X0,Y0,Z0).get_normalize(0,(T)255);
+ visu0.resize(disp.width,disp.height,1,cimg::min(3,dimv()));
+ }
+ visu = visu0;
+
+ // Handle motion and selection
+ const int mx = disp.mouse_x, my = disp.mouse_y, b = disp.button;
+ if (mx>=0 && my>=0) {
+ const int mX = mx*(width+(depth>1?depth:0))/disp.width, mY = my*(height+(depth>1?depth:0))/disp.height;
+ if (mX<dimx() && mY<dimy()) { area=1; X=mX; Y=mY; Z=phase?Z1:Z0; }
+ if (mX<dimx() && mY>=dimy()) { area=2; X=mX; Y=phase?Y1:Y0; Z=mY-height; }
+ if (mX>=dimx() && mY<dimy()) { area=3; X=phase?X1:X0; Y=mY; Z=mX-width; }
+ if (mX>=dimx() && mY>=dimy()) { X=X0; Y=Y0; Z=Z0; }
+ if ((!(phase%2) && (b&1)) || (phase%2 && !(b&1))) {
+ if (!carea) carea=area;
+ if (!(phase++)) { X0=X; Y0=Y; Z0=Z; }
+ }
+ if (b&2) { if (!phase) { X0=X; Y0=Y; Z0=Z; } else { X1=Y1=Z1=-1; phase=carea=0; }}
+ if ((b&2 || phase) && depth>1)
+ visu0 = get_projections2d(X,Y,Z).normalize(0,(T)255).resize(disp.width,disp.height,1,cimg::min(3,dimv()));
+ if (phase) {
+ if (!feature_type) feature_selected = phase?true:false;
+ else {
+ if (depth>1) feature_selected = (phase==3)?true:false;
+ else feature_selected = (phase==2)?true:false;
+ }
+ if (!feature_selected) {
+ if (phase<2) { X1=X; Y1=Y; Z1=Z; }
+ else switch(carea) {
+ case 1: Z1=Z; break;
+ case 2: Y1=Y; break;
+ case 3: X1=X; break;
+ }
+ }
+ }
+ if (!phase || !feature_type) {
+ if (depth>1) std::sprintf(text,"Coords (%d,%d,%d)={ ",X,Y,Z); else std::sprintf(text,"Coords (%d,%d)={ ",X,Y);
+ cimg_mapV(*this,k) std::sprintf(text+cimg::strlen(text),"%g ",(double)(*this)(X,Y,Z,k));
+ std::sprintf(text+cimg::strlen(text),"}");
+ if (!feature_type) { X1=X0; Y1=Y0; Z1=Z0; }
+ } else
+ switch (feature_type) {
+ case 1: {
+ const double dX=(double)(X0-X1), dY=(double)(Y0-Y1), dZ=(double)(Z0-Z1), norm = std::sqrt(dX*dX+dY*dY+dZ*dZ);
+ if (depth>1) std::sprintf(text,"Vect (%d,%d,%d)-(%d,%d,%d), norm=%g",X0,Y0,Z0,X1,Y1,Z1,norm);
+ else std::sprintf(text,"Vect (%d,%d)-(%d,%d), norm=%g",X0,Y0,X1,Y1,norm);
+ } break;
+ case 2:
+ if (depth>1) std::sprintf(text,"Box (%d,%d,%d)-(%d,%d,%d), Size=(%d,%d,%d)",
+ X0<X1?X0:X1,Y0<Y1?Y0:Y1,Z0<Z1?Z0:Z1,
+ X0<X1?X1:X0,Y0<Y1?Y1:Y0,Z0<Z1?Z1:Z0,
+ 1+cimg::abs(X0-X1),1+cimg::abs(Y0-Y1),1+cimg::abs(Z0-Z1));
+ else std::sprintf(text,"Box (%d,%d)-(%d,%d), Size=(%d,%d)",
+ X0<X1?X0:X1,Y0<Y1?Y0:Y1,X0<X1?X1:X0,Y0<Y1?Y1:Y0,1+cimg::abs(X0-X1),1+cimg::abs(Y0-Y1));
+ break;
+ case 3:
+ if (depth>1) std::sprintf(text,"Ellipse (%d,%d,%d)-(%d,%d,%d), Radii=(%d,%d,%d)",
+ X0,Y0,Z0,X1,Y1,Z1,1+cimg::abs(X0-X1),1+cimg::abs(Y0-Y1),1+cimg::abs(Z0-Z1));
+ else std::sprintf(text,"Ellipse (%d,%d)-(%d,%d), Radii=(%d,%d)",
+ X0,Y0,X1,Y1,1+cimg::abs(X0-X1),1+cimg::abs(Y0-Y1));
+
+ break;
+ }
+ if (my<12) ytext=true;
+ if (my>=visu.dimy()-11) ytext=false;
+ visu.draw_text(text,0,ytext?visu.dimy()-11:0,fgcolor,bgcolor,11,0.7f);
+ } else { X=Y=Z=-1; if (phase) disp.button=phase%2; }
+
+ // Draw image + selection on display window
+ if (X>=0 && Y>=0 && Z>=0) {
+ hatch=cimg::ror(hatch);
+ if (feature_type==1 && phase) {
+ const int d=(depth>1)?depth:0,
+ x0=(int)((X0+0.5f)*disp.width/(width+d)), y0=(int)((Y0+0.5f)*disp.height/(height+d)),
+ x1=(int)((X1+0.5f)*disp.width/(width+d)), y1=(int)((Y1+0.5f)*disp.height/(height+d));
+ visu.draw_arrow(x0,y0,x1,y1,fgcolor,30.0f,5.0f,hatch);
+ if (d) {
+ const int zx0=(int)((width+Z0+0.5f)*disp.width/(width+d)), zx1=(int)((width+Z1+0.5f)*disp.width/(width+d)),
+ zy0=(int)((height+Z0+0.5f)*disp.height/(height+d)), zy1=(int)((height+Z1+0.5f)*disp.height/(height+d));
+ visu.draw_arrow(zx0,y0,zx1,y1,fgcolor,30.0f,5.0f,hatch).draw_arrow(x0,zy0,x1,zy1,fgcolor,30.0f,5.0f,hatch);
+ }
+ } else switch(feature_type) {
+ case 2: {
+ const bool cond=(phase&&feature_type);
+ const int d=(depth>1)?depth:0,
+ nX0=cond?X0:X, nY0=cond?Y0:Y, nZ0=cond?Z0:Z,
+ nX1=cond?X1:X, nY1=cond?Y1:Y, nZ1=cond?Z1:Z,
+ x0=(nX0<nX1?nX0:nX1)*disp.width/(width+d),
+ y0=(nY0<nY1?nY0:nY1)*disp.height/(height+d),
+ x1=((nX0<nX1?nX1:nX0)+1)*disp.width/(width+d)-1,
+ y1=((nY0<nY1?nY1:nY0)+1)*disp.height/(height+d)-1;
+ const unsigned int nhatch=phase?hatch:~0L;
+ visu.draw_rectangle(x0,y0,x1,y1,fgcolor,0.2f).draw_line(x0,y0,x1,y0,fgcolor,nhatch).
+ draw_line(x1,y0,x1,y1,fgcolor,nhatch).draw_line(x1,y1,x0,y1,fgcolor,nhatch).draw_line(x0,y1,x0,y0,fgcolor,nhatch);
+ if (d) {
+ const int
+ zx0=(int)((width+(nZ0<nZ1?nZ0:nZ1))*disp.width/(width+d)),
+ zy0=(int)((height+(nZ0<nZ1?nZ0:nZ1))*disp.height/(height+d)),
+ zx1=(int)((width+(nZ0<nZ1?nZ1:nZ0)+1)*disp.width/(width+d))-1,
+ zy1=(int)((height+(nZ0<nZ1?nZ1:nZ0)+1)*disp.height/(height+d))-1;
+ visu.draw_rectangle(zx0,y0,zx1,y1,fgcolor,0.2f).draw_line(zx0,y0,zx1,y0,fgcolor,nhatch).
+ draw_line(zx1,y0,zx1,y1,fgcolor,nhatch).draw_line(zx1,y1,zx0,y1,fgcolor,nhatch).draw_line(zx0,y1,zx0,y0,fgcolor,nhatch);
+ visu.draw_rectangle(x0,zy0,x1,zy1,fgcolor,0.2f).draw_line(x0,zy0,x1,zy0,fgcolor,nhatch).
+ draw_line(x1,zy0,x1,zy1,fgcolor,nhatch).draw_line(x1,zy1,x0,zy1,fgcolor,nhatch).draw_line(x0,zy1,x0,zy0,fgcolor,nhatch);
+ }
+ } break;
+ case 3: {
+ const bool cond=(phase&&feature_type);
+ const int d=(depth>1)?depth:0,
+ x0=(cond?X0:X)*disp.width/(width+d),
+ y0=(cond?Y0:Y)*disp.height/(height+d),
+ x1=(cond?X1:X)*disp.width/(width+d)-1,
+ y1=(cond?Y1:Y)*disp.height/(height+d)-1;
+ const unsigned int nhatch=phase?hatch:~0L;
+ visu.draw_ellipse(x0,y0,(float)(x1-x0),(float)(y1-y0),1.0f,0.0f,fgcolor,0L,0.2f).
+ draw_ellipse(x0,y0,(float)(x1-x0),(float)(y1-y0),1.0f,0.0f,fgcolor,nhatch);
+ if (d) {
+ const int
+ zx0=(int)((width+(cond?Z0:Z))*disp.width/(width+d)),
+ zy0=(int)((height+(cond?Z0:Z))*disp.height/(height+d)),
+ zx1=(int)((width+(cond?Z1:Z)+1)*disp.width/(width+d))-1,
+ zy1=(int)((height+(cond?Z1:Z)+1)*disp.height/(height+d))-1;
+ visu.draw_ellipse(zx0,y0,(float)(zx1-zx0),(float)(y1-y0),1.0f,0.0f,fgcolor,0L,0.2f).
+ draw_ellipse(zx0,y0,(float)(zx1-zx0),(float)(y1-y0),1.0f,0.0f,fgcolor,nhatch).
+ draw_ellipse(x0,zy0,(float)(x1-x0),(float)(zy1-zy0),1.0f,0.0f,fgcolor,0L,0.2f).
+ draw_ellipse(x0,zy0,(float)(x1-x0),(float)(zy1-zy0),1.0f,0.0f,fgcolor,nhatch);
+ }
+ } break;
+ }
+ }
+ visu.display(disp).wait(32);
+ if ((!feature_selected && !phase && oX==X && oY==Y && oZ==Z) || (X<0 || Y<0 || Z<0)) disp.wait();
+ oX=X; oY=Y; oZ=Z;
+ }
+
+ // Return result
+ if (XYZ) { XYZ[0] = (unsigned int)X; XYZ[1] = (unsigned int)Y; XYZ[2] = (unsigned int)Z; }
+ if (feature_selected) {
+ if (feature_type==2) {
+ if (X0>X1) cimg::swap(X0,X1);
+ if (Y0>Y1) cimg::swap(Y0,Y1);
+ if (Z0>Z1) cimg::swap(Z0,Z1);
+ }
+ if (selection) {
+ if (X1<0 || Y1<0 || Z1<0) X0=Y0=Z0=X1=Y1=Z1=-1;
+ switch(feature_type) {
+ case 1:
+ case 2: selection[3] = X1; selection[4] = Y1; selection[5] = Z1;
+ default: selection[0] = X0; selection[1] = Y0; selection[2] = Z0;
+ }
+ }
+ } else if (selection) selection[0]=selection[1]=selection[2]=selection[3]=selection[4]=selection[5]=-1;
+ disp.button=0;
+ disp.events = oevents;
+ disp.normalization = onormalization;
+ disp.resized = oresized;
+ return *this;
+ }
+
+ //! High-level interface to select features in images
+ const CImg& feature_selection(int *const selection, const int feature_type,
+ unsigned int *const XYZ=NULL,const unsigned char *const color=NULL) const {
+ unsigned int w = width + (depth>1?depth:0), h = height + (depth>1?depth:0);
+ const unsigned int dmin = cimg::min(w,h), minsiz = 256;
+ if (dmin<minsiz) { w=w*minsiz/dmin; h=h*minsiz/dmin; }
+ const unsigned int dmax = cimg::max(w,h), maxsiz = 1024;
+ if (dmax>maxsiz) { w=w*maxsiz/dmax; h=h*maxsiz/dmax; }
+ CImgDisplay disp(w,h," ",0,3);
+ return feature_selection(selection,feature_type,disp,XYZ,color);
+ }
+
+ //! High-level interface for displaying a 3d object
+ template<typename tp, typename tf, typename to>
+ const CImg& display_object3d(const CImg<tp>& points,const CImgl<tf>& primitives,
+ const CImgl<T>& colors, const CImg<to>& opacities, CImgDisplay& disp,
+ const bool centering=true,
+ const int render_static=4, const int render_motion=1,
+ const bool double_sided=false,
+ const float focale=500.0f, const float ambiant_light=0.05f,
+ const bool display_axes=true, const bool keep_pos = false) const {
+
+ if (points.is_empty())
+ throw CImgArgumentException("CImg<%s>::display_object3d() : Given points are empty.",
+ pixel_type());
+ if (primitives.is_empty())
+ throw CImgArgumentException("CImg<%s>::display_object3d() : Given primitives are empty.",
+ pixel_type());
+
+ if (is_empty())
+ return CImg<T>(disp.width,disp.height,1,colors[0].size(),0).
+ display_object3d(points,primitives,colors,opacities,disp,centering,
+ render_static,render_motion,double_sided,focale,ambiant_light);
+ if (opacities.is_empty())
+ return display_object3d(points,primitives,colors,CImg<to>(primitives.size,1,1,1,(to)1),disp,
+ centering,render_static,render_motion,double_sided,focale,ambiant_light);
+ if (points.height<3)
+ return display_object3d(points.get_resize(-100,3,1,1,0),primitives,colors,opacities,disp,
+ centering,render_static,render_motion,double_sided,focale,ambiant_light);
+
+ if (colors.size!=primitives.size)
+ throw CImgArgumentException("CImg<%s>::display_object3d() : Given colors (size=%u) and primitives (size=%u) have "
+ "different sizes.",pixel_type(),colors.size,primitives.size);
+ if (opacities.width!=primitives.size)
+ throw CImgArgumentException("CImg<%s>::display_object3d() : Given opacities (size=%u) and primitives (size=%u) have "
+ "different sizes", pixel_type(),opacities.width,primitives.size);
+
+ static float oX=0,oY=0,oZ=0;
+ static CImg<float> rot;
+
+ bool init = true, clicked = false, redraw = true, stopflag = false;
+ CImg<float> centered_points, rotated_points(points.width,3);
+ CImg<T> visu0(*this), visu;
+ int x0=0,y0=0,x1=0,y1=0;
+
+ const unsigned int oevents = disp.events;
+ disp.show().button=disp.key=0;
+ disp.events=3;
+
+ // Compute object statistics
+ cimg_mapX(rotated_points,xx) {
+ rotated_points(xx,0) = (float)points(xx,0);
+ rotated_points(xx,1) = (float)points(xx,1);
+ rotated_points(xx,2) = (float)points(xx,2);
+ }
+ const CImg<float>
+ x = rotated_points.get_shared_line(0),
+ y = rotated_points.get_shared_line(1),
+ z = rotated_points.get_shared_line(2);
+ const CImgStats sx(x,false), sy(y,false), sz(z,false);
+ const float
+ xm = (float)sx.min, xM = (float)sx.max,
+ ym = (float)sy.min, yM = (float)sy.max,
+ zm = (float)sz.min, zM = (float)sz.max,
+ delta = cimg::max(xM-xm,yM-ym,zM-zm),
+ ratio = delta>0?(2.0f*cimg::min(width,height)/(3.0f*delta)):0,
+ dx = 0.5f*(xM+xm), dy = 0.5f*(yM+ym), dz = 0.5f*(zM+zm);
+ if (centering) {
+ centered_points.assign(points.width,3);
+ cimg_mapX(points,l) {
+ centered_points(l,0) = (float)((points(l,0)-dx)*ratio);
+ centered_points(l,1) = (float)((points(l,1)-dy)*ratio);
+ centered_points(l,2) = (float)((points(l,2)-dz)*ratio);
+ }
+ }
+
+ // Create bounding box if necessary
+ CImgl<T> bbox_colors;
+ CImgl<tf> bbox_primitives;
+ CImg<float> bbox_points, rotated_bbox_points, bbox_opacities;
+ const T foo=0, valmax = cimg::get_type_max(foo);
+
+ if (render_static<0 || render_motion<0) {
+ bbox_colors.assign(12,dim,1,1,1,valmax);
+ bbox_primitives.assign(12,1,2);
+ bbox_points.assign(8,3);
+ rotated_bbox_points.assign(8,3);
+ bbox_points(0,0) = xm; bbox_points(0,1) = ym; bbox_points(0,2) = zm;
+ bbox_points(1,0) = xM; bbox_points(1,1) = ym; bbox_points(1,2) = zm;
+ bbox_points(2,0) = xM; bbox_points(2,1) = yM; bbox_points(2,2) = zm;
+ bbox_points(3,0) = xm; bbox_points(3,1) = yM; bbox_points(3,2) = zm;
+ bbox_points(4,0) = xm; bbox_points(4,1) = ym; bbox_points(4,2) = zM;
+ bbox_points(5,0) = xM; bbox_points(5,1) = ym; bbox_points(5,2) = zM;
+ bbox_points(6,0) = xM; bbox_points(6,1) = yM; bbox_points(6,2) = zM;
+ bbox_points(7,0) = xm; bbox_points(7,1) = yM; bbox_points(7,2) = zM;
+ bbox_primitives[0].fill(0,1); bbox_primitives[1].fill(1,2); bbox_primitives[2].fill(2,3); bbox_primitives[3].fill(3,0);
+ bbox_primitives[4].fill(4,5); bbox_primitives[5].fill(5,6); bbox_primitives[6].fill(6,7); bbox_primitives[7].fill(7,4);
+ bbox_primitives[8].fill(0,4); bbox_primitives[9].fill(1,5); bbox_primitives[10].fill(2,6); bbox_primitives[11].fill(3,7);
+ bbox_opacities.assign(bbox_primitives.size,1,1,1,1.0f);
+ }
+
+ // Create small axes display on the bottom
+ CImgl<tf> axes_primitives;
+ CImgl<T> axes_colors;
+ CImg<float> axes_points, rotated_axes_points, axes_opacities;
+ if (display_axes) {
+ axes_points.assign(7,3);
+ rotated_axes_points.assign(7,3);
+ axes_opacities.assign(3,1,1,1,1.0f);
+ axes_colors.assign(3,dim,1,1,1,valmax);
+ axes_points(0,0) = 0; axes_points(0,1) = 0; axes_points(0,2) = 0;
+ axes_points(1,0) = 20; axes_points(1,1) = 0; axes_points(1,2) = 0;
+ axes_points(2,0) = 0; axes_points(2,1) = 20; axes_points(2,2) = 0;
+ axes_points(3,0) = 0; axes_points(3,1) = 0; axes_points(3,2) = 20;
+ axes_points(4,0) = 22; axes_points(4,1) = -6; axes_points(4,2) = 0;
+ axes_points(5,0) = -6; axes_points(5,1) = 22; axes_points(5,2) = 0;
+ axes_points(6,0) = -6; axes_points(6,1) = -6; axes_points(6,2) = 22;
+ axes_primitives.insert(CImg<tf>::vector(0,1));
+ axes_primitives.insert(CImg<tf>::vector(0,2));
+ axes_primitives.insert(CImg<tf>::vector(0,3));
+ }
+
+ // Begin user interaction
+ while (!disp.closed && !stopflag) {
+
+ // Init object position and scale if necessary
+ if (init) {
+ if (!keep_pos) {
+ oX = oY = oZ = 0;
+ rot = CImg<float>::get_identity_matrix(3);
+ }
+ init = false;
+ redraw = true;
+ }
+
+ // Handle user interaction
+ if (disp.button && disp.mouse_x>=0 && disp.mouse_y>=0) {
+ redraw = true;
+ if (!clicked) { x0 = x1 = disp.mouse_x; y0 = y1 = disp.mouse_y; clicked = true; }
+ else { x1 = disp.mouse_x; y1 = disp.mouse_y; }
+ if (disp.button&1) {
+ const float
+ R = 0.4f*cimg::min(disp.width,disp.height),
+ R2 = R*R,
+ u0 = (float)(x0-disp.dimx()/2),
+ v0 = (float)(y0-disp.dimy()/2),
+ u1 = (float)(x1-disp.dimx()/2),
+ v1 = (float)(y1-disp.dimy()/2),
+ n0 = (float)std::sqrt(u0*u0+v0*v0),
+ n1 = (float)std::sqrt(u1*u1+v1*v1),
+ nu0 = n0>R?(u0*R/n0):u0,
+ nv0 = n0>R?(v0*R/n0):v0,
+ nw0 = (float)std::sqrt(cimg::max(0.0f,R2-nu0*nu0-nv0*nv0)),
+ nu1 = n1>R?(u1*R/n1):u1,
+ nv1 = n1>R?(v1*R/n1):v1,
+ nw1 = (float)std::sqrt(cimg::max(0.0f,R2-nu1*nu1-nv1*nv1)),
+ u = nv0*nw1-nw0*nv1,
+ v = nw0*nu1-nu0*nw1,
+ w = nv0*nu1-nu0*nv1,
+ n = (float)std::sqrt(u*u+v*v+w*w),
+ alpha = (float)std::asin(n/R2);
+ rot = CImg<float>::get_rotation_matrix(u,v,w,alpha)*rot;
+ x0=x1; y0=y1;
+ }
+ if (disp.button&2) { oZ+=(y1-y0); x0=x1; y0=y1; }
+ if (disp.button&4) { oX+=(x1-x0); oY+=(y1-y0); x0=x1; y0=y1; }
+ if ((disp.button&1) && (disp.button&2)) { init = true; disp.button=0; x0=x1; y0=y1; }
+ } else if (clicked) { x0=x1; y0=y1; clicked = false; redraw = true; }
+ if (disp.key) { redraw = false; stopflag = true; }
+ if (disp.resized) { disp.resize(); visu0 = get_resize(disp,1); redraw = true; }
+
+ if (redraw) {
+
+ // Rotate object
+ const float
+ r00 = (float)rot(0,0), r10 = (float)rot(1,0), r20 = (float)rot(2,0),
+ r01 = (float)rot(0,1), r11 = (float)rot(1,1), r21 = (float)rot(2,1),
+ r02 = (float)rot(0,2), r12 = (float)rot(1,2), r22 = (float)rot(2,2);
+
+ if ((clicked && render_motion>=0) || (!clicked && render_static>=0)) {
+ if (centering) cimg_mapX(points,l) {
+ const float
+ x = centered_points(l,0),
+ y = centered_points(l,1),
+ z = centered_points(l,2);
+ rotated_points(l,0) = r00*x + r10*y + r20*z;
+ rotated_points(l,1) = r01*x + r11*y + r21*z;
+ rotated_points(l,2) = r02*x + r12*y + r22*z;
+ } else cimg_mapX(points,l) {
+ const float
+ x = (float)points(l,0)-oX,
+ y = (float)points(l,1)-oY,
+ z = (float)points(l,2);
+ rotated_points(l,0) = r00*x + r10*y + r20*z;
+ rotated_points(l,1) = r01*x + r11*y + r21*z;
+ rotated_points(l,2) = r02*x + r12*y + r22*z;
+ }
+ } else {
+ if (!centering) cimg_mapX(bbox_points,l) {
+ const float
+ x = bbox_points(l,0),
+ y = bbox_points(l,1),
+ z = bbox_points(l,2);
+ rotated_bbox_points(l,0) = r00*x + r10*y + r20*z;
+ rotated_bbox_points(l,1) = r01*x + r11*y + r21*z;
+ rotated_bbox_points(l,2) = r02*x + r12*y + r22*z;
+ } else cimg_mapX(bbox_points,l) {
+ const float
+ x = (bbox_points(l,0)-dx)*ratio,
+ y = (bbox_points(l,1)-dy)*ratio,
+ z = (bbox_points(l,2)-dz)*ratio;
+ rotated_bbox_points(l,0) = r00*x + r10*y + r20*z;
+ rotated_bbox_points(l,1) = r01*x + r11*y + r21*z;
+ rotated_bbox_points(l,2) = r02*x + r12*y + r22*z;
+ }
+ }
+
+ // Draw object
+ visu=visu0;
+ if ((clicked && render_motion<0) || (!clicked && render_static<0))
+ visu.draw_object3d(visu.width/2.0f + oX, visu.height/2.0f + oY,oZ,
+ rotated_bbox_points,bbox_primitives,bbox_colors,bbox_opacities,1,
+ false,focale,visu.dimx()/2.0f,visu.dimy()/2.0f,-5000.0f,0.2f);
+ else visu.draw_object3d(visu.width/2.0f + oX, visu.height/2.0f + oY,oZ,
+ rotated_points,primitives,colors,opacities,clicked?render_motion:render_static,
+ double_sided,focale,visu.dimx()/2.0f,visu.dimy()/2.0f,-5000.0f,ambiant_light);
+
+ // Draw axes
+ if (display_axes) {
+ const float Xaxes = 25.0f, Yaxes = visu.height-35.0f;
+ cimg_mapX(axes_points,l) {
+ const float x = axes_points(l,0), y = axes_points(l,1), z = axes_points(l,2);
+ rotated_axes_points(l,0) = r00*x + r10*y + r20*z;
+ rotated_axes_points(l,1) = r01*x + r11*y + r21*z;
+ rotated_axes_points(l,2) = r02*x + r12*y + r22*z;
+ }
+ axes_colors(0)=(rotated_axes_points(1,2)>0)?valmax/2:valmax;
+ axes_colors(1)=(rotated_axes_points(2,2)>0)?valmax/2:valmax;
+ axes_colors(2)=(rotated_axes_points(3,2)>0)?valmax/2:valmax;
+ visu.draw_object3d(Xaxes, Yaxes, 0, rotated_axes_points,axes_primitives,axes_colors,axes_opacities,1,false,focale,0,0,0,0).
+ draw_text("X",(int)(Xaxes+rotated_axes_points(4,0)), (int)(Yaxes+rotated_axes_points(4,1)), axes_colors[0].ptr()).
+ draw_text("Y",(int)(Xaxes+rotated_axes_points(5,0)), (int)(Yaxes+rotated_axes_points(5,1)), axes_colors[1].ptr()).
+ draw_text("Z",(int)(Xaxes+rotated_axes_points(6,0)), (int)(Yaxes+rotated_axes_points(6,1)), axes_colors[2].ptr());
+ }
+
+ visu.display(disp);
+ if (!clicked || render_motion==render_static) redraw = false;
+ }
+ wait(20);
+ }
+
+ disp.events = oevents;
+ disp.button = 0;
+ return *this;
+ }
+
+ //! High-level interface for displaying a 3d object
+ template<typename tp, typename tf, typename to>
+ const CImg& display_object3d(const CImg<tp>& points, const CImgl<tf>& primitives,
+ const CImgl<T>& colors, const CImgl<to>& opacities, CImgDisplay& disp,
+ const bool centering=true,
+ const int render_static=4, const int render_motion=1,
+ const bool double_sided=false,
+ const float focale=500.0f, const float ambiant_light=0.05f,
+ const bool display_axes=true, const bool keep_pos = false) const {
+ if (opacities.is_empty())
+ return display_object3d(points,primitives,colors,CImg<to>(),disp,centering,
+ render_static,render_motion,double_sided,focale,ambiant_light,display_axes,keep_pos);
+ CImg<to> nopacities(opacities.size);
+ to *ptrd = nopacities.ptr();
+ cimg_mapoff(nopacities,l) if (opacities(l).size()) *(ptrd++) = opacities(l,0);
+ else
+ throw CImgArgumentException("CImg<%s>::display_object3d() : Given opacities (size=%u) contains a null element at "
+ "position %u.",pixel_type(),opacities.size,l);
+ return display_object3d(points,primitives,colors,nopacities,disp,centering,
+ render_static,render_motion,double_sided,focale,ambiant_light,display_axes,keep_pos);
+
+ }
+
+ //! High-level interface for displaying a 3d object
+ template<typename tp, typename tf, typename to>
+ const CImg& display_object3d(const CImgl<tp>& points,const CImgl<tf>& primitives,
+ const CImgl<T>& colors, const CImg<to>& opacities, CImgDisplay& disp,
+ const bool centering=true,
+ const int render_static=4, const int render_motion=1,
+ const bool double_sided=false,
+ const float focale=500.0f, const float ambiant_light=0.05f,
+ const bool display_axes=true, const bool keep_pos = false) const {
+ if (points.is_empty())
+ throw CImgArgumentException("CImg<%s>::display_object3d() : Given points are empty.",
+ pixel_type());
+ CImg<tp> npoints(points.size,3,1,1,0);
+ tp *ptrX = npoints.ptr(), *ptrY = npoints.ptr(0,1), *ptrZ = npoints.ptr(0,2);
+ cimg_mapX(npoints,l) {
+ const CImg<tp>& point = points[l];
+ const unsigned int siz = point.size();
+ if (!siz)
+ throw CImgArgumentException("CImg<%s>::display_object3d() : Given points (size=%u) contains a null element at "
+ "position %u.",pixel_type(),points.size,l);
+ *(ptrZ++) = (siz>2)?point(2):0;
+ *(ptrY++) = (siz>1)?point(1):0;
+ *(ptrX++) = point(0);
+ }
+ return display_object3d(npoints,primitives,colors,opacities,disp,centering,
+ render_static,render_motion,double_sided,focale,ambiant_light,display_axes,keep_pos);
+ }
+
+ //! High-level interface for displaying a 3d object
+ template<typename tp, typename tf, typename to>
+ const CImg& display_object3d(const CImgl<tp>& points,const CImgl<tf>& primitives,
+ const CImgl<T>& colors, const CImgl<to>& opacities, CImgDisplay &disp,
+ const bool centering=true,
+ const int render_static=4, const int render_motion=1,
+ const bool double_sided=false,
+ const float focale=500.0f, const float ambiant_light=0.05f,
+ const bool display_axes=true, const bool keep_pos = false) const {
+ if (opacities.is_empty())
+ return display_object3d(points,primitives,colors,CImg<to>(),disp,centering,
+ render_static,render_motion,double_sided,focale,ambiant_light,display_axes,keep_pos);
+ CImg<to> nopacities(opacities.size);
+ to *ptrd = nopacities.ptr();
+ cimg_mapoff(nopacities,l) if (opacities(l).size()) *(ptrd++) = opacities(l,0);
+ else
+ throw CImgArgumentException("CImg<%s>::display_object3d() : Given opacities (size=%u) contains a null element at "
+ "position %u.",pixel_type(),opacities.size,l);
+ return display_object3d(points,primitives,colors,nopacities,disp,centering,
+ render_static,render_motion,double_sided,focale,ambiant_light,display_axes,keep_pos);
+ }
+
+ //! High-level interface for displaying a 3d object
+ template<typename tp, typename tf, typename to>
+ const CImg& display_object3d(const tp& points, const CImgl<tf>& primitives,
+ const CImgl<T> colors, const to& opacities,
+ const bool centering=true,
+ const int render_static=4, const int render_motion=1,
+ const bool double_sided=false,
+ const float focale=500.0f, const float ambiant_light=0.05f,
+ const bool display_axes=true, const bool keep_pos = false) const {
+ CImgDisplay disp(width,height," ",0);
+ return display_object3d(points,primitives,colors,opacities,disp,centering,
+ render_static,render_motion,double_sided,focale,ambiant_light,display_axes,keep_pos);
+ }
+
+ //! High-level interface for displaying a 3d object
+ template<typename tp, typename tf>
+ const CImg& display_object3d(const tp& points, const CImgl<tf>& primitives,
+ const CImgl<T> colors,
+ const bool centering=true,
+ const int render_static=4, const int render_motion=1,
+ const bool double_sided=false,
+ const float focale=500.0f, const float ambiant_light=0.05f,
+ const float opacity=1.0f, const bool display_axes=true, const bool keep_pos = false) const {
+ CImgDisplay disp(width,height," ",0);
+ return display_object3d(points,primitives,colors,CImg<float>(primitives.size,1,1,1,opacity),
+ disp,centering,render_static,render_motion,double_sided,
+ focale,ambiant_light,display_axes,keep_pos);
+ }
+
+ //! High-level interface for displaying a 3d object
+ template<typename tp, typename tf>
+ const CImg& display_object3d(const tp& points, const CImgl<tf>& primitives,
+ const CImgl<T> colors, CImgDisplay &disp,
+ const bool centering=true,
+ const int render_static=4, const int render_motion=1,
+ const bool double_sided=false,
+ const float focale=500.0f, const float ambiant_light=0.05f,
+ const float opacity=1.0f, const bool display_axes=true, const bool keep_pos = false) const {
+ return display_object3d(points,primitives,colors,CImg<float>(primitives.size,1,1,1,opacity),
+ disp,centering,render_static,render_motion,double_sided,
+ focale,ambiant_light,display_axes,keep_pos);
+ }
+
+ //@}
+ //--------------------------------
+ //
+ //! \name Input-Output functions
+ //@{
+ //--------------------------------
+
+ //! Load an image from a file.
+ /**
+ \param filename = name of the image file to load.
+ \return A CImg<T> instance containing the pixel data defined in the image file.
+ \note The extension of \c filename defines the file format. If no filename
+ extension is provided, CImg<T>::get_load() will try to load a CRAW file (CImg Raw file).
+ **/
+ static CImg get_load(const char *filename) {
+ if (!filename) throw CImgArgumentException("CImg<%s>::get_load() : Can't load (null) filename",pixel_type());
+ const char *ext = cimg::filename_split(filename);
+ if (!cimg::strcasecmp(ext,"asc")) return get_load_ascii(filename);
+ if (!cimg::strcasecmp(ext,"dlm")) return get_load_dlm(filename);
+ if (!cimg::strcasecmp(ext,"inr")) return get_load_inr(filename);
+ if (!cimg::strcasecmp(ext,"hdr")) return get_load_analyze(filename);
+ if (!cimg::strcasecmp(ext,"par") ||
+ !cimg::strcasecmp(ext,"rec")) return get_load_parrec(filename);
+ if (!cimg::strcasecmp(ext,"pan")) return get_load_pandore(filename);
+ if (!cimg::strcasecmp(ext,"bmp")) return get_load_bmp(filename);
+ if (!cimg::strcasecmp(ext,"png")) return get_load_png(filename);
+ if (!cimg::strcasecmp(ext,"jpg") ||
+ !cimg::strcasecmp(ext,"jpeg")) return get_load_jpeg(filename);
+ if (!cimg::strcasecmp(ext,"ppm") ||
+ !cimg::strcasecmp(ext,"pgm") ||
+ !cimg::strcasecmp(ext,"pnm")) return get_load_pnm(filename);
+ if (!cimg::strcasecmp(ext,"cimg") || ext[0]=='\0') return get_load_cimg(filename);
+ if (!cimg::strcasecmp(ext,"dcm") ||
+ !cimg::strcasecmp(ext,"dicom")) return get_load_dicom(filename);
+ return get_load_convert(filename);
+ }
+
+ //! Load an image from a file
+ /** This is the in-place version of get_load(). **/
+ CImg& load(const char *filename) { return get_load(filename).swap(*this); }
+
+ //! Load an image from an ASCII file.
+ static CImg get_load_ascii(const char *filename) {
+ std::FILE *file = cimg::fopen(filename,"rb");
+ char line[256] = {0};
+ std::fscanf(file,"%255[^\n]",line);
+ unsigned int off;
+ int err=1, dx=0, dy=1, dz=1, dv=1;
+ std::sscanf(line,"%d %d %d %d",&dx,&dy,&dz,&dv);
+ if (!dx || !dy || !dz || !dv)
+ throw CImgIOException("CImg<%s>::get_load_ascii() : File '%s' does not appear to be a valid ASC file.\n"
+ "Specified image dimensions are (%d,%d,%d,%d)",pixel_type(),filename,dx,dy,dz,dv);
+ CImg dest(dx,dy,dz,dv);
+ double val;
+ T *ptr = dest.data;
+ for (off=0; off<dest.size() && err==1; off++) {
+ err = std::fscanf(file,"%lf%*[^0-9.eE+-]",&val);
+ *(ptr++)=(T)val;
+ }
+ cimg::warn(off<dest.size(),"CImg<%s>::get_load_ascii() : File '%s', only %u values read, instead of %u",
+ pixel_type(),filename,off,dest.size());
+ cimg::fclose(file);
+ return dest;
+ }
+
+ //! Load an image from an ASCII file (in-place version).
+ /** This is the in-place version of get_load_ascii(). **/
+ CImg& load_ascii(const char *filename) { return get_load_ascii(filename).swap(*this); }
+
+ //! Load an image from a DLM file
+ static CImg get_load_dlm(const char *filename) {
+ std::FILE *file = cimg::fopen(filename,"r");
+ CImg<T> dest(256,256);
+ unsigned int cdx=0,dx=0,dy=0;
+ double val;
+ char c, delimiter[256]={0}, tmp[256];
+ int oerr=0, err;
+ while ((err = std::fscanf(file,"%lf%255[^0-9.eE+-]",&val,delimiter))!=EOF) {
+ oerr = err;
+ if (err>0) dest(cdx++,dy) = (T)val;
+ if (cdx>=dest.width) dest.resize(dest.width+256,1,1,1,0);
+ c=0; if (!std::sscanf(delimiter,"%255[^\n]%c",tmp,&c) || c=='\n') {
+ dx = cimg::max(cdx,dx);
+ dy++;
+ if (dy>=dest.height) dest.resize(dest.width,dest.height+256,1,1,0);
+ cdx=0;
+ }
+ }
+ if (cdx && oerr==1) { dx=cdx; dy++; }
+ if (!dx || !dy) throw CImgIOException("CImg<%s>::get_load_dlm() : File '%s' does not appear to be a "
+ "valid DLM file (width = %d, height = %d)\n",pixel_type(),filename,dx,dy);
+ dest.resize(dx,dy,1,1,0);
+ cimg::fclose(file);
+ return dest;
+ }
+
+ //! Load an image from a DLM file (in-place version).
+ /** This is the in-place version of get_load_dlm(). **/
+ CImg& load_dlm(const char *filename) { return get_load_dlm(filename).swap(*this); }
+
+ //! Load an image from a PNM file
+ static CImg get_load_pnm(const char *filename) {
+ std::FILE *file=cimg::fopen(filename,"rb");
+ char item[1024]={0};
+ unsigned int ppm_type,width,height,colormax=255;
+ int err;
+
+ while ((err=std::fscanf(file,"%1023[^\n]",item))!=EOF && (item[0]=='#' || !err)) std::fgetc(file);
+ if(std::sscanf(item," P%u",&ppm_type)!=1)
+ throw CImgIOException("CImg<%s>::get_load_pnm() : file '%s',PPM header 'P?' not found",pixel_type(),filename);
+ while ((err=std::fscanf(file," %1023[^\n]",item))!=EOF && (item[0]=='#' || !err)) std::fgetc(file);
+ if ((err=std::sscanf(item," %u %u %u",&width,&height,&colormax))<2)
+ throw CImgIOException("CImg<%s>::get_load_pnm() : file '%s',WIDTH and HEIGHT not defined",pixel_type(),filename);
+ if (err==2) {
+ while ((err=std::fscanf(file," %1023[^\n]",item))!=EOF && (item[0]=='#' || !err)) std::fgetc(file);
+ cimg::warn(std::sscanf(item,"%u",&colormax)!=1,
+ "CImg<%s>::get_load_pnm() : file '%s',COLORMAX not defined",pixel_type(),filename);
+ }
+ std::fgetc(file);
+
+ CImg dest;
+ int rval,gval,bval;
+
+ switch (ppm_type) {
+ case 2: { // Grey Ascii
+ dest.assign(width,height,1,1);
+ T* rdata = dest.ptr();
+ cimg_mapoff(dest,off) { std::fscanf(file,"%d",&rval); *(rdata++)=(T)rval; }
+ } break;
+ case 3: { // Color Ascii
+ dest.assign(width,height,1,3);
+ T *rdata = dest.ptr(0,0,0,0), *gdata = dest.ptr(0,0,0,1), *bdata = dest.ptr(0,0,0,2);
+ cimg_mapXY(dest,x,y) {
+ std::fscanf(file,"%d %d %d",&rval,&gval,&bval);
+ *(rdata++)=(T)rval;
+ *(gdata++)=(T)gval;
+ *(bdata++)=(T)bval; }
+ } break;
+ case 5: { // Grey Binary
+ if (colormax<256) { // 8 bits
+ CImg<unsigned char> raw(width,height,1,1);
+ cimg::fread(raw.data,width*height,file);
+ dest=raw;
+ } else { // 16 bits
+ CImg<unsigned short> raw(width,height,1,1);
+ cimg::fread(raw.data,width*height,file);
+ if (!cimg::endian()) cimg::endian_swap(raw.data,width*height);
+ dest=raw;
+ }
+ } break;
+ case 6: { // Color Binary
+ if (colormax<256) { // 8 bits
+ CImg<unsigned char> raw(width,height,1,3);
+ cimg::fread(raw.data,width*height*3,file);
+ dest.assign(width,height,1,3);
+ T *rdata = dest.ptr(0,0,0,0), *gdata = dest.ptr(0,0,0,1), *bdata = dest.ptr(0,0,0,2);
+ const unsigned char *ptrs = raw.ptr();
+ for (unsigned int off = raw.width*raw.height; off; --off) {
+ *(rdata++) = (T)(*(ptrs++));
+ *(gdata++) = (T)(*(ptrs++));
+ *(bdata++) = (T)(*(ptrs++));
+ }
+ } else { // 16 bits
+ CImg<unsigned short> raw(width,height,1,3);
+ cimg::fread(raw.data,width*height*3,file);
+ if (!cimg::endian()) cimg::endian_swap(raw.data,width*height*3);
+ dest.assign(width,height,1,3);
+ T *rdata = dest.ptr(0,0,0,0), *gdata = dest.ptr(0,0,0,1), *bdata = dest.ptr(0,0,0,2);
+ const unsigned short *ptrs = raw.ptr();
+ for (unsigned int off = raw.width*raw.height; off; --off) {
+ *(rdata++) = (T)(*(ptrs++));
+ *(gdata++) = (T)(*(ptrs++));
+ *(bdata++) = (T)(*(ptrs++));
+ }
+ }
+ } break;
+ default:
+ cimg::fclose(file);
+ throw CImgIOException("CImg<%s>::get_load_pnm() : file '%s', PPM type 'P%d' not supported",pixel_type(),filename,ppm_type);
+ }
+ cimg::fclose(file);
+ return dest;
+ }
+
+ //! Load an image from a PNM file (in-place version).
+ CImg& load_pnm(const char *filename) { return get_load_pnm(filename).swap(*this); }
+
+ //! Load a YUV image sequence file.
+ static CImg get_load_yuv(const char *filename,
+ const unsigned int sizex, const unsigned int sizey,
+ const unsigned int first_frame=0, const int last_frame=-1,
+ const bool yuv2rgb = true) {
+ return CImgl<T>::get_load_yuv(filename,sizex,sizey,first_frame,last_frame,yuv2rgb).get_append('z','c');
+ }
+
+ //! Load a YUV image sequence file (in-place).
+ CImg& load_yuv(const char *filename,
+ const unsigned int sizex, const unsigned int sizey,
+ const unsigned int first_frame=0, const int last_frame=-1,
+ const bool yuv2rgb = true) {
+ return get_load_yuv(filename,sizex,sizey,first_frame,last_frame,yuv2rgb).swap(*this);
+ }
+
+ //! Load an image from a BMP file.
+ static CImg get_load_bmp(const char *filename) {
+ unsigned char header[64];
+ std::FILE *file = cimg::fopen(filename,"rb");
+ cimg::fread(header,54,file);
+ if (header[0]!='B' || header[1]!='M')
+ throw CImgIOException("CImg<%s>::get_load_bmp() : filename '%s' does not appear to be a valid BMP file",
+ pixel_type(),filename);
+
+ // Read header and pixel buffer
+ int
+ file_size = header[0x02] + (header[0x03]<<8) + (header[0x04]<<16) + (header[0x05]<<24),
+ offset = header[0x0A] + (header[0x0B]<<8) + (header[0x0C]<<16) + (header[0x0D]<<24),
+ dx = header[0x12] + (header[0x13]<<8) + (header[0x14]<<16) + (header[0x15]<<24),
+ dy = header[0x16] + (header[0x17]<<8) + (header[0x18]<<16) + (header[0x19]<<24),
+ compression = header[0x1E] + (header[0x1F]<<8) + (header[0x20]<<16) + (header[0x21]<<24),
+ nb_colors = header[0x2E] + (header[0x2F]<<8) + (header[0x30]<<16) + (header[0x31]<<24),
+ bpp = header[0x1C] + (header[0x1D]<<8),
+ *palette = NULL;
+ const int
+ dx_bytes = (bpp==1)?(dx/8+(dx%8?1:0)):((bpp==4)?(dx/2+(dx%2?1:0)):(dx*bpp/8)),
+ align = (4-dx_bytes%4)%4,
+ buf_size = cimg::min(cimg::abs(dy)*(dx_bytes+align),file_size-offset);
+
+ if (bpp<16) { if (!nb_colors) nb_colors=1<<bpp; } else nb_colors=0;
+ if (nb_colors) { palette = new int[nb_colors]; cimg::fread(palette,nb_colors,file); }
+ const int xoffset = offset-54-4*nb_colors;
+ if (xoffset>0) std::fseek(file,xoffset,SEEK_CUR);
+ unsigned char *buffer = new unsigned char[buf_size], *ptrs = buffer;
+ cimg::fread(buffer,buf_size,file);
+ cimg::fclose(file);
+
+ // Decompress buffer (if necessary)
+ if (compression) return get_load_convert(filename);
+
+ // Read pixel data
+ CImg res(dx,cimg::abs(dy),1,3);
+ switch (bpp) {
+ case 1: { // Monochrome
+ for (int y=res.height-1; y>=0; y--) {
+ unsigned char tqmask = 0x80, val = 0;
+ cimg_mapX(res,x) {
+ if (tqmask==0x80) val = *(ptrs++);
+ const unsigned char *col = (unsigned char*)(palette+(val&tqmask?1:0));
+ res(x,y,2) = (T)*(col++);
+ res(x,y,1) = (T)*(col++);
+ res(x,y,0) = (T)*(col++);
+ tqmask = cimg::ror(tqmask);
+ } ptrs+=align; }
+ } break;
+ case 4: { // 16 colors
+ for (int y=res.height-1; y>=0; y--) {
+ unsigned char tqmask = 0xF0, val = 0;
+ cimg_mapX(res,x) {
+ if (tqmask==0xF0) val = *(ptrs++);
+ const unsigned char color = (tqmask<16)?(val&tqmask):((val&tqmask)>>4);
+ unsigned char *col = (unsigned char*)(palette+color);
+ res(x,y,2) = (T)*(col++);
+ res(x,y,1) = (T)*(col++);
+ res(x,y,0) = (T)*(col++);
+ tqmask = cimg::ror(tqmask,4);
+ } ptrs+=align; }
+ } break;
+ case 8: { // 256 colors
+ for (int y=res.height-1; y>=0; y--) { cimg_mapX(res,x) {
+ const unsigned char *col = (unsigned char*)(palette+*(ptrs++));
+ res(x,y,2) = (T)*(col++);
+ res(x,y,1) = (T)*(col++);
+ res(x,y,0) = (T)*(col++);
+ } ptrs+=align; }
+ } break;
+ case 16: { // 16 bits colors
+ for (int y=res.height-1; y>=0; y--) { cimg_mapX(res,x) {
+ const unsigned char c1 = *(ptrs++), c2 = *(ptrs++);
+ const unsigned short col = c1+(c2<<8);
+ res(x,y,2) = (T)(col&0x1F);
+ res(x,y,1) = (T)((col>>5)&0x1F);
+ res(x,y,0) = (T)((col>>10)&0x1F);
+ } ptrs+=align; }
+ } break;
+ case 24: { // 24 bits colors
+ for (int y=res.height-1; y>=0; y--) { cimg_mapX(res,x) {
+ res(x,y,2) = (T)*(ptrs++);
+ res(x,y,1) = (T)*(ptrs++);
+ res(x,y,0) = (T)*(ptrs++);
+ } ptrs+=align; }
+ } break;
+ case 32: { // 32 bits colors
+ for (int y=res.height-1; y>=0; y--) { cimg_mapX(res,x) {
+ res(x,y,2) = (T)*(ptrs++);
+ res(x,y,1) = (T)*(ptrs++);
+ res(x,y,0) = (T)*(ptrs++);
+ ptrs++;
+ } ptrs+=align; }
+ } break;
+ }
+
+ if (palette) delete[] palette;
+ delete[] buffer;
+ if (dy<0) res.mirror('y');
+ return res;
+ }
+
+ //! Load an image from a BMP file
+ CImg& load_bmp(const char *filename) { return get_load_bmp(filename).swap(*this); }
+
+ //! Load an image from a PNG file.
+ // Note : Most of this function has been written by Eric Fausett
+ static CImg get_load_png(const char *filename) {
+#ifndef cimg_use_png
+ return get_load_convert(filename);
+#else
+ // Open file and check for PNG validity
+ unsigned char pngCheck[8];
+ std::FILE *file = cimg::fopen(filename,"rb");
+ cimg::fread(pngCheck,8,file);
+ if(png_sig_cmp(pngCheck,0,8)){
+ cimg::fclose(file);
+ throw CImgIOException("CImg<%s>::get_load_png() : filename '%s' does not appear to be a valid PNG file",pixel_type(),filename);
+ }
+
+ // Setup PNG structures for read
+ png_voidp user_error_ptr=0;
+ png_error_ptr user_error_fn=0, user_warning_fn=0;
+ png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, // Verifies libpng version correct
+ user_error_ptr, user_error_fn, user_warning_fn);
+ if(!png_ptr){
+ cimg::fclose(file);
+ throw CImgIOException("CImg<%s>::get_load_png() : trouble initializing 'png_ptr' data structure",pixel_type());
+ }
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if(!info_ptr){
+ cimg::fclose(file);
+ png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+ throw CImgIOException("CImg<%s>::get_load_png() : trouble initializing 'info_ptr' data structure",pixel_type());
+ }
+ png_infop end_info = png_create_info_struct(png_ptr);
+ if(!end_info){
+ cimg::fclose(file);
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+ throw CImgIOException("CImg<%s>::get_load_png() : trouble initializing 'end_info' data structure",pixel_type());
+ }
+
+ // Error handling callback for png file reading
+ if (setjmp(png_jmpbuf(png_ptr))){
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+ cimg::fclose(file);
+ throw CImgIOException("CImg<%s>::get_load_png() : unspecified error reading PNG file '%s'",pixel_type(),filename);
+ }
+ png_init_io(png_ptr, file);
+ png_set_sig_bytes(png_ptr, 8);
+
+ // Get PNG Header Info up to data block
+ png_read_info(png_ptr, info_ptr);
+ png_uint_32 width, height;
+ int bit_depth, color_type, interlace_type;
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type,
+ int_p_NULL, int_p_NULL);
+ int new_bit_depth = bit_depth;
+ int new_color_type = color_type;
+
+ // Transforms to unify image data
+ if (new_color_type == PNG_COLOR_TYPE_PALETTE){
+ png_set_palette_to_rgb(png_ptr);
+ new_color_type -= PNG_COLOR_MASK_PALETTE;
+ new_bit_depth = 8;
+ }
+ if (new_color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8){
+ png_set_gray_1_2_4_to_8(png_ptr);
+ new_bit_depth = 8;
+ }
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha(png_ptr);
+ if (new_color_type == PNG_COLOR_TYPE_GRAY || new_color_type == PNG_COLOR_TYPE_GRAY_ALPHA){
+ png_set_gray_to_rgb(png_ptr);
+ new_color_type |= PNG_COLOR_MASK_COLOR;
+ }
+ if (new_color_type == PNG_COLOR_TYPE_RGB) png_set_filler(png_ptr, 0xffffU, PNG_FILLER_AFTER);
+ png_read_update_info(png_ptr, info_ptr);
+ if (!(new_bit_depth==8 || new_bit_depth==16))
+ throw CImgIOException("CImg<%s>::get_load_png() : Wrong bit coding 'bit_depth=%u'",pixel_type(),new_bit_depth);
+ const int byte_depth = new_bit_depth>>3;
+
+ // Allocate Memory for Image Read
+ png_bytep *imgData = new png_bytep[height];
+ for (unsigned int row=0; row < height; row++) imgData[row] = new png_byte[byte_depth * 4 * width];
+ png_read_image(png_ptr, imgData);
+ png_read_end(png_ptr, end_info);
+
+ // Read pixel data
+ if (!(new_color_type==PNG_COLOR_TYPE_RGB || new_color_type==PNG_COLOR_TYPE_RGB_ALPHA))
+ throw CImgIOException("CImg<%s>::get_load_png() : Wrong color coding new_color_type=%u",pixel_type(),new_color_type);
+ const bool no_alpha_channel = (new_color_type==PNG_COLOR_TYPE_RGB);
+ CImg res(width,height,1,no_alpha_channel?3:4);
+ const unsigned long off = width*height;
+ T *ptr1 = res.data, *ptr2 = ptr1+off, *ptr3 = ptr2+off, *ptr4 = ptr3+off;
+ switch(new_bit_depth){
+ case 8: {
+ cimg_mapY(res,y){
+ const unsigned char *ptrs = (unsigned char*)imgData[y];
+ cimg_mapX(res,x){
+ *(ptr1++) = (T)*(ptrs++);
+ *(ptr2++) = (T)*(ptrs++);
+ *(ptr3++) = (T)*(ptrs++);
+ if (no_alpha_channel) ptrs++; else *(ptr4++) = (T)*(ptrs++);
+ }
+ }
+ } break;
+ case 16: {
+ cimg_mapY(res,y){
+ const unsigned short *ptrs = (unsigned short*)(imgData[y]);
+ cimg_mapX(res,x){
+ *(ptr1++) = (T)*(ptrs++);
+ *(ptr2++) = (T)*(ptrs++);
+ *(ptr3++) = (T)*(ptrs++);
+ if (no_alpha_channel) ptrs++; else *(ptr4++) = (T)*(ptrs++);
+ }
+ }
+ } break;
+ }
+ png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
+
+ // Deallocate Image Read Memory
+ for (unsigned int n=0; n<height; n++) delete[] imgData[n];
+ delete[] imgData;
+ cimg::fclose(file);
+ return res;
+#endif
+ }
+
+ //! Load an image from a PNG file
+ CImg& load_png(const char *filename) { return get_load_png(filename).swap(*this); }
+
+ //! Load a file in JPEG format.
+ static CImg get_load_jpeg(const char *filename) {
+#ifndef cimg_use_jpeg
+ return get_load_convert(filename);
+#else
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ std::FILE *file = cimg::fopen(filename,"rb");
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_decompress(&cinfo);
+ jpeg_stdio_src(&cinfo,file);
+ jpeg_read_header(&cinfo,TRUE);
+ jpeg_start_decompress(&cinfo);
+
+ if (cinfo.output_components!=1 && cinfo.output_components!=3 && cinfo.output_components!=4) {
+ cimg::warn(true,"CImg<%s>::get_load_jpeg() : Don't know how to read image '%s' with libpeg,"
+ "trying ImageMagick's convert",
+ pixel_type(),filename);
+ return get_load_convert(filename);
+ }
+
+ const unsigned int row_stride = cinfo.output_width * cinfo.output_components;
+ unsigned char *buf = new unsigned char[cinfo.output_width*cinfo.output_height*cinfo.output_components], *buf2 = buf;
+ JSAMPROW row_pointer[1];
+ while (cinfo.output_scanline < cinfo.output_height) {
+ row_pointer[0] = &buf[cinfo.output_scanline*row_stride];
+ jpeg_read_scanlines(&cinfo,row_pointer,1);
+ }
+ jpeg_finish_decompress(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+ cimg::fclose(file);
+
+ CImg<T> dest(cinfo.output_width,cinfo.output_height,1,cinfo.output_components);
+ switch (dest.dim) {
+ case 1: {
+ T *ptr_g = dest.ptr();
+ cimg_mapXY(dest,x,y) *(ptr_g++) = (T)*(buf2++);
+ } break;
+ case 3: {
+ T *ptr_r = dest.ptr(0,0,0,0), *ptr_g = dest.ptr(0,0,0,1), *ptr_b = dest.ptr(0,0,0,2);
+ cimg_mapXY(dest,x,y) {
+ *(ptr_r++) = (T)*(buf2++);
+ *(ptr_g++) = (T)*(buf2++);
+ *(ptr_b++) = (T)*(buf2++);
+ }
+ } break;
+ case 4: {
+ T *ptr_r = dest.ptr(0,0,0,0), *ptr_g = dest.ptr(0,0,0,1),
+ *ptr_b = dest.ptr(0,0,0,2), *ptr_a = dest.ptr(0,0,0,3);
+ cimg_mapXY(dest,x,y) {
+ *(ptr_r++) = (T)*(buf2++);
+ *(ptr_g++) = (T)*(buf2++);
+ *(ptr_b++) = (T)*(buf2++);
+ *(ptr_a++) = (T)*(buf2++);
+ }
+ } break;
+ }
+ delete[] buf;
+ return dest;
+#endif
+ }
+
+ //! Load an image from a JPEG file
+ CImg& load_jpeg(const char *filename) { return get_load_jpeg(filename).swap(*this); }
+
+ //! Load an image from a RAW file.
+ static CImg get_load_raw(const char *filename,
+ const unsigned int sizex, const unsigned int sizey=1,
+ const unsigned int sizez=1, const unsigned int sizev=1,
+ const bool multiplexed = false, const bool endian_swap = false) {
+ CImg<T> res(sizex,sizey,sizez,sizev,0);
+ if (res.is_empty()) return res;
+ std::FILE *file = cimg::fopen(filename,"rb");
+ if (!multiplexed) {
+ cimg::fread(res.ptr(),res.size(),file);
+ if (endian_swap) cimg::endian_swap(res.ptr(),res.size());
+ }
+ else {
+ CImg<T> buf(1,1,1,sizev);
+ cimg_mapXYZ(res,x,y,z) {
+ cimg::fread(buf.ptr(),sizev,file);
+ if (endian_swap) cimg::endian_swap(buf.ptr(),sizev);
+ res.set_vector(buf,x,y,z); }
+ }
+ cimg::fclose(file);
+ return res;
+ }
+
+ //! In-place version of get_load_raw()
+ CImg& load_raw(const char *filename,
+ const unsigned int sizex, const unsigned int sizey=1,
+ const unsigned int sizez=1, const unsigned int sizev=1,
+ const bool multiplexed = false, const bool endian_swap = false) {
+ return get_load_raw(filename,sizex,sizey,sizez,sizev,multiplexed,endian_swap).swap(*this);
+ }
+
+ //! Load an image from a RGBA file.
+ static CImg get_load_rgba(const char *filename,const unsigned int dimw,const unsigned int dimh) {
+ std::FILE *file = cimg::fopen(filename,"rb");
+ unsigned char *buffer = new unsigned char[dimw*dimh*4];
+ cimg::fread(buffer,dimw*dimh*4,file);
+ cimg::fclose(file);
+ CImg res(dimw,dimh,1,4);
+ T *pR = res.ptr(0,0,0,0), *pG = res.ptr(0,0,0,1), *pB = res.ptr(0,0,0,2), *pA = res.ptr(0,0,0,3);
+ const unsigned char *ptrs = buffer;
+ for (unsigned int off=res.width*res.height; off>0; --off) {
+ *(pR++) = *(ptrs++);
+ *(pG++) = *(ptrs++);
+ *(pB++) = *(ptrs++);
+ *(pA++) = *(ptrs++);
+ }
+ delete[] buffer;
+ return res;
+ }
+
+ //! In-place version of get_load_rgba()
+ CImg& load_rgba(const char *filename,const unsigned int dimw,const unsigned int dimh) {
+ return get_load_rgba(filename,dimw,dimh).swap(*this);
+ }
+
+ //! Load an image from a RGB file.
+ static CImg get_load_rgb(const char *filename,const unsigned int dimw,const unsigned int dimh) {
+ std::FILE *file = cimg::fopen(filename,"rb");
+ unsigned char *buffer = new unsigned char[dimw*dimh*3];
+ cimg::fread(buffer,dimw*dimh*3,file);
+ cimg::fclose(file);
+ CImg res(dimw,dimh,1,3);
+ T *pR = res.ptr(0,0,0,0), *pG = res.ptr(0,0,0,1), *pB=res.ptr(0,0,0,2);
+ const unsigned char *ptrs = buffer;
+ for (unsigned int off=res.width*res.height; off>0; --off) {
+ *(pR++) = *(ptrs++);
+ *(pG++) = *(ptrs++);
+ *(pB++) = *(ptrs++);
+ }
+ delete[] buffer;
+ return res;
+ }
+
+ //! In-place version of get_load_rgb()
+ CImg& load_rgb(const char *filename,const unsigned int dimw,const unsigned int dimh) {
+ return get_load_rgb(filename,dimw,dimh).swap(*this);
+ }
+
+#define cimg_load_inr_case(Tf,sign,pixsize,Ts) \
+ if (!loaded && fopt[6]==pixsize && fopt[4]==Tf && fopt[5]==sign) { \
+ Ts *xval, *val = new Ts[fopt[0]*fopt[3]]; \
+ cimg_mapYZ(dest,y,z) { \
+ cimg::fread(val,fopt[0]*fopt[3],file); \
+ if (fopt[7]!=endian) cimg::endian_swap(val,fopt[0]*fopt[3]); \
+ xval = val; cimg_mapX(dest,x) cimg_mapV(dest,k) \
+ dest(x,y,z,k) = (T)*(xval++); \
+ } \
+ delete[] val; \
+ loaded = true; \
+ }
+
+ static void _load_inr(std::FILE *file,int out[8],float *voxsize=NULL) {
+ char item[1024],tmp1[64],tmp2[64];
+ out[0]=out[1]=out[2]=out[3]=out[5]=1; out[4]=out[6]=out[7]=-1;
+ std::fscanf(file,"%63s",item);
+ if(cimg::strncasecmp(item,"#INRIMAGE-4#{",13)!=0)
+ throw CImgIOException("CImg<%s>::get_load_inr() : File does not appear to be a valid INR file.\n"
+ "(INRIMAGE-4 identifier not found)",pixel_type());
+ while (std::fscanf(file," %63[^\n]%*c",item)!=EOF && cimg::strncmp(item,"##}",3)) {
+ std::sscanf(item," XDIM%*[^0-9]%d",out);
+ std::sscanf(item," YDIM%*[^0-9]%d",out+1);
+ std::sscanf(item," ZDIM%*[^0-9]%d",out+2);
+ std::sscanf(item," VDIM%*[^0-9]%d",out+3);
+ std::sscanf(item," PIXSIZE%*[^0-9]%d",out+6);
+ if (voxsize) {
+ std::sscanf(item," VX%*[^0-9.eE+-]%f",voxsize);
+ std::sscanf(item," VY%*[^0-9.eE+-]%f",voxsize+1);
+ std::sscanf(item," VZ%*[^0-9.eE+-]%f",voxsize+2);
+ }
+ if (std::sscanf(item," CPU%*[ =]%s",tmp1)) out[7]=cimg::strncasecmp(tmp1,"sun",3)?0:1;
+ switch(std::sscanf(item," TYPE%*[ =]%s %s",tmp1,tmp2)) {
+ case 0: break;
+ case 2: out[5] = cimg::strncasecmp(tmp1,"unsigned",8)?1:0; std::strcpy(tmp1,tmp2);
+ case 1:
+ if (!cimg::strncasecmp(tmp1,"int",3) || !cimg::strncasecmp(tmp1,"fixed",5)) out[4]=0;
+ if (!cimg::strncasecmp(tmp1,"float",5) || !cimg::strncasecmp(tmp1,"double",6)) out[4]=1;
+ if (!cimg::strncasecmp(tmp1,"packed",6)) out[4]=2;
+ if (out[4]>=0) break;
+ default: throw CImgIOException("cimg::inr_header_read() : Invalid TYPE '%s'",tmp2);
+ }
+ }
+ if(out[0]<0 || out[1]<0 || out[2]<0 || out[3]<0)
+ throw CImgIOException("CImg<%s>::get_load_inr() : Bad dimensions in .inr file = ( %d , %d , %d , %d )",
+ pixel_type(),out[0],out[1],out[2],out[3]);
+ if(out[4]<0 || out[5]<0) throw CImgIOException("CImg<%s>::get_load_inr() : TYPE is not fully defined",pixel_type());
+ if(out[6]<0) throw CImgIOException("CImg<%s>::get_load_inr() : PIXSIZE is not fully defined",pixel_type());
+ if(out[7]<0) throw CImgIOException("CImg<%s>::get_load_inr() : Big/Little Endian coding type is not defined",pixel_type());
+ }
+
+ //! Load an image from an INRIMAGE-4 file.
+ static CImg get_load_inr(const char *filename, float *voxsize = NULL) {
+ std::FILE *file = cimg::fopen(filename,"rb");
+ int fopt[8], endian=cimg::endian()?1:0;
+ bool loaded = false;
+ if (voxsize) voxsize[0]=voxsize[1]=voxsize[2]=1;
+ _load_inr(file,fopt,voxsize);
+ CImg<T> dest(fopt[0],fopt[1],fopt[2],fopt[3]);
+ cimg_load_inr_case(0,0,8, unsigned char);
+ cimg_load_inr_case(0,1,8, char);
+ cimg_load_inr_case(0,0,16,unsigned short);
+ cimg_load_inr_case(0,1,16,short);
+ cimg_load_inr_case(0,0,32,unsigned int);
+ cimg_load_inr_case(0,1,32,int);
+ cimg_load_inr_case(1,0,32,float);
+ cimg_load_inr_case(1,1,32,float);
+ cimg_load_inr_case(1,0,64,double);
+ cimg_load_inr_case(1,1,64,double);
+ if (!loaded) throw CImgIOException("CImg<%s>::get_load_inr() : File '%s', can't read images of the type specified in the file",
+ pixel_type(),filename);
+ cimg::fclose(file);
+ return dest;
+ }
+
+ //! In-place version of get_load_inr()
+ CImg& load_inr(const char *filename, float *voxsize = NULL) { return get_load_inr(filename,voxsize).swap(*this); }
+
+#define cimg_load_pandore_case(nid,nbdim,nwidth,nheight,ndepth,ndim,stype) \
+ case nid: { \
+ cimg::fread(dims,nbdim,file); \
+ if (endian) cimg::endian_swap(dims,nbdim); \
+ dest.assign(nwidth,nheight,ndepth,ndim); \
+ stype *buffer = new stype[dest.size()]; \
+ cimg::fread(buffer,dest.size(),file); \
+ if (endian) cimg::endian_swap(buffer,dest.size()); \
+ T *ptrd = dest.ptr(); \
+ cimg_mapoff(dest,off) *(ptrd++) = (T)(*(buffer++)); \
+ buffer-=dest.size(); \
+ delete[] buffer; \
+ } \
+ break;
+
+ //! Load an image from a PANDORE-5 file.
+ static CImg get_load_pandore(const char *filename) {
+ std::FILE *file = cimg::fopen(filename,"rb");
+ typedef unsigned char uchar;
+ typedef unsigned short ushort;
+ typedef unsigned int uint;
+ typedef unsigned long ulong;
+ CImg dest;
+ char tmp[32];
+ cimg::fread(tmp,12,file);
+ if (cimg::strncasecmp("PANDORE",tmp,7))
+ throw CImgIOException("CImg<%s>::get_load_pandore() : File '%s' does not appear to be a valid PANDORE file.\n"
+ "(PANDORE identifier not found)",pixel_type(),filename);
+ unsigned int imageid,dims[8];
+ int ptbuf[4];
+ cimg::fread(&imageid,1,file);
+ const bool endian = (imageid>255);
+ if (endian) cimg::endian_swap(imageid);
+
+ cimg::fread(tmp,20,file);
+ switch (imageid) {
+ cimg_load_pandore_case(2,2,dims[1],1,1,1,uchar);
+ cimg_load_pandore_case(3,2,dims[1],1,1,1,long);
+ cimg_load_pandore_case(4,2,dims[1],1,1,1,float);
+ cimg_load_pandore_case(5,3,dims[2],dims[1],1,1,uchar);
+ cimg_load_pandore_case(6,3,dims[2],dims[1],1,1,long);
+ cimg_load_pandore_case(7,3,dims[2],dims[1],1,1,float);
+ cimg_load_pandore_case(8,4,dims[3],dims[2],dims[1],1,uchar);
+ cimg_load_pandore_case(9,4,dims[3],dims[2],dims[1],1,long);
+ cimg_load_pandore_case(10,4,dims[3],dims[2],dims[1],1,float);
+
+ case 11: { // Region 1D
+ cimg::fread(dims,3,file);
+ if (endian) cimg::endian_swap(dims,3);
+ dest.assign(dims[1],1,1,1);
+ if (dims[2]<256) {
+ unsigned char *buffer = new unsigned char[dest.size()];
+ cimg::fread(buffer,dest.size(),file);
+ T *ptrd = dest.ptr();
+ cimg_mapoff(dest,off) *(ptrd++) = (T)(*(buffer++));
+ buffer-=dest.size();
+ delete[] buffer;
+ } else {
+ if (dims[2]<65536) {
+ unsigned short *buffer = new unsigned short[dest.size()];
+ cimg::fread(buffer,dest.size(),file);
+ if (endian) cimg::endian_swap(buffer,dest.size());
+ T *ptrd = dest.ptr();
+ cimg_mapoff(dest,off) *(ptrd++) = (T)(*(buffer++));
+ buffer-=dest.size();
+ delete[] buffer;
+ } else {
+ unsigned int *buffer = new unsigned int[dest.size()];
+ cimg::fread(buffer,dest.size(),file);
+ if (endian) cimg::endian_swap(buffer,dest.size());
+ T *ptrd = dest.ptr();
+ cimg_mapoff(dest,off) *(ptrd++) = (T)(*(buffer++));
+ buffer-=dest.size();
+ delete[] buffer;
+ }
+ }
+ }
+ break;
+ case 12: { // Region 2D
+ cimg::fread(dims,4,file);
+ if (endian) cimg::endian_swap(dims,4);
+ dest.assign(dims[2],dims[1],1,1);
+ if (dims[3]<256) {
+ unsigned char *buffer = new unsigned char[dest.size()];
+ cimg::fread(buffer,dest.size(),file);
+ T *ptrd = dest.ptr();
+ cimg_mapoff(dest,off) *(ptrd++) = (T)(*(buffer++));
+ buffer-=dest.size();
+ delete[] buffer;
+ } else {
+ if (dims[3]<65536) {
+ unsigned short *buffer = new unsigned short[dest.size()];
+ cimg::fread(buffer,dest.size(),file);
+ if (endian) cimg::endian_swap(buffer,dest.size());
+ T *ptrd = dest.ptr();
+ cimg_mapoff(dest,off) *(ptrd++) = (T)(*(buffer++));
+ buffer-=dest.size();
+ delete[] buffer;
+ } else {
+ unsigned long *buffer = new unsigned long[dest.size()];
+ cimg::fread(buffer,dest.size(),file);
+ if (endian) cimg::endian_swap(buffer,dest.size());
+ T *ptrd = dest.ptr();
+ cimg_mapoff(dest,off) *(ptrd++) = (T)(*(buffer++));
+ buffer-=dest.size();
+ delete[] buffer;
+ }
+ }
+ }
+ break;
+ case 13: { // Region 3D
+ cimg::fread(dims,5,file);
+ if (endian) cimg::endian_swap(dims,5);
+ dest.assign(dims[3],dims[2],dims[1],1);
+ if (dims[4]<256) {
+ unsigned char *buffer = new unsigned char[dest.size()];
+ cimg::fread(buffer,dest.size(),file);
+ T *ptrd = dest.ptr();
+ cimg_mapoff(dest,off) *(ptrd++) = (T)(*(buffer++));
+ buffer-=dest.size();
+ delete[] buffer;
+ } else {
+ if (dims[4]<65536) {
+ unsigned short *buffer = new unsigned short[dest.size()];
+ cimg::fread(buffer,dest.size(),file);
+ if (endian) cimg::endian_swap(buffer,dest.size());
+ T *ptrd = dest.ptr();
+ cimg_mapoff(dest,off) *(ptrd++) = (T)(*(buffer++));
+ buffer-=dest.size();
+ delete[] buffer;
+ } else {
+ unsigned int *buffer = new unsigned int[dest.size()];
+ cimg::fread(buffer,dest.size(),file);
+ if (endian) cimg::endian_swap(buffer,dest.size());
+ T *ptrd = dest.ptr();
+ cimg_mapoff(dest,off) *(ptrd++) = (T)(*(buffer++));
+ buffer-=dest.size();
+ delete[] buffer;
+ }
+ }
+ }
+ break;
+ cimg_load_pandore_case(16,4,dims[2],dims[1],1,3,uchar);
+ cimg_load_pandore_case(17,4,dims[2],dims[1],1,3,long);
+ cimg_load_pandore_case(18,4,dims[2],dims[1],1,3,float);
+ cimg_load_pandore_case(19,5,dims[3],dims[2],dims[1],3,uchar);
+ cimg_load_pandore_case(20,5,dims[3],dims[2],dims[1],3,long);
+ cimg_load_pandore_case(21,5,dims[3],dims[2],dims[1],3,float);
+ cimg_load_pandore_case(22,2,dims[1],1,1,dims[0],uchar);
+ cimg_load_pandore_case(23,2,dims[1],1,1,dims[0],long);
+ cimg_load_pandore_case(24,2,dims[1],1,1,dims[0],ulong);
+ cimg_load_pandore_case(25,2,dims[1],1,1,dims[0],float);
+ cimg_load_pandore_case(26,3,dims[2],dims[1],1,dims[0],uchar);
+ cimg_load_pandore_case(27,3,dims[2],dims[1],1,dims[0],long);
+ cimg_load_pandore_case(28,3,dims[2],dims[1],1,dims[0],ulong);
+ cimg_load_pandore_case(29,3,dims[2],dims[1],1,dims[0],float);
+ cimg_load_pandore_case(30,4,dims[3],dims[2],dims[1],dims[0],uchar);
+ cimg_load_pandore_case(31,4,dims[3],dims[2],dims[1],dims[0],long);
+ cimg_load_pandore_case(32,4,dims[3],dims[2],dims[1],dims[0],ulong);
+ cimg_load_pandore_case(33,4,dims[3],dims[2],dims[1],dims[0],float);
+ case 34: // Points 1D
+ cimg::fread(ptbuf,1,file);
+ if (endian) cimg::endian_swap(ptbuf,1);
+ dest.assign(1); dest[0]=(T)ptbuf[0];
+ break;
+ case 35: // Points 2D
+ cimg::fread(ptbuf,2,file);
+ if (endian) cimg::endian_swap(ptbuf,2);
+ dest.assign(2); dest[0]=(T)ptbuf[1]; dest[1]=(T)ptbuf[0];
+ break;
+ case 36: // Points 3D
+ cimg::fread(ptbuf,3,file);
+ if (endian) cimg::endian_swap(ptbuf,3);
+ dest.assign(3); dest[0]=(T)ptbuf[2]; dest[1]=(T)ptbuf[1]; dest[2]=(T)ptbuf[0];
+ break;
+ default:
+ throw CImgIOException("CImg<%s>::get_load_pandore() : File '%s', can't read images with ID_type=%u",pixel_type(),filename,imageid);
+ }
+ return dest;
+ }
+
+ //! In-place version of get_load_pandore()
+ CImg& load_pandore(const char *filename) { return get_load_pandore(filename).swap(*this); }
+
+ //! Load an image from an ANALYZE7.5 file
+ static CImg get_load_analyze(const char *filename, float *voxsize = NULL) {
+
+ // Open header and data files
+ std::FILE *file_header=NULL, *file=NULL;
+ char body[1024];
+ const char *ext = cimg::filename_split(filename,body);
+ if (!cimg::strcasecmp(ext,"hdr") || !cimg::strcasecmp(ext,"img")) {
+ std::sprintf(body+cimg::strlen(body),".hdr");
+ file_header = cimg::fopen(body,"rb");
+ std::sprintf(body+cimg::strlen(body)-3,"img");
+ file = cimg::fopen(body,"rb");
+ } else throw CImgIOException("CImg<%s>::get_load_analyze() : Cannot load filename '%s' as an analyze format",pixel_type(),filename);
+
+ // Read header
+ bool endian = false;
+ unsigned int header_size;
+ cimg::fread(&header_size,1,file_header);
+ if (header_size>=4096) { endian = true; cimg::endian_swap(header_size); }
+ unsigned char *header = new unsigned char[header_size];
+ cimg::fread(header+4,header_size-4,file_header);
+ cimg::fclose(file_header);
+ if (endian) {
+ cimg::endian_swap((short*)(header+40),5);
+ cimg::endian_swap((short*)(header+70),1);
+ cimg::endian_swap((short*)(header+72),1);
+ cimg::endian_swap((float*)(header+76),4);
+ cimg::endian_swap((float*)(header+112),1);
+ }
+ unsigned short *dim = (unsigned short*)(header+40), dimx=1, dimy=1, dimz=1, dimv=1;
+ cimg::warn(!dim[0],"CImg<%s>::get_load_analyze() : Specified image has zero dimensions.",pixel_type());
+ cimg::warn(dim[0]>4,"CImg<%s>::get_load_analyze() : Number of image dimension is %d, reading only the 4 first dimensions",
+ pixel_type(),dim[0]);
+ if (dim[0]>=1) dimx = dim[1];
+ if (dim[0]>=2) dimy = dim[2];
+ if (dim[0]>=3) dimz = dim[3];
+ if (dim[0]>=4) dimv = dim[4];
+
+ float scalefactor = *(float*)(header+112); if (scalefactor==0) scalefactor=1;
+ const unsigned short datatype = *(short*)(header+70);
+ if (voxsize) { const float *vsize = (float*)(header+76); voxsize[0] = vsize[1]; voxsize[1] = vsize[2]; voxsize[2] = vsize[3]; }
+ delete[] header;
+
+ // Read pixel data
+ CImg dest(dimx,dimy,dimz,dimv);
+ switch (datatype) {
+ case 2: {
+ unsigned char *buffer = new unsigned char[dimx*dimy*dimz*dimv];
+ cimg::fread(buffer,dimx*dimy*dimz*dimv,file);
+ cimg_mapoff(dest,off) dest.data[off] = (T)(buffer[off]*scalefactor);
+ delete[] buffer;
+ } break;
+ case 4: {
+ short *buffer = new short[dimx*dimy*dimz*dimv];
+ cimg::fread(buffer,dimx*dimy*dimz*dimv,file);
+ if (endian) cimg::endian_swap(buffer,dimx*dimy*dimz*dimv);
+ cimg_mapoff(dest,off) dest.data[off] = (T)(buffer[off]*scalefactor);
+ delete[] buffer;
+ } break;
+ case 8: {
+ int *buffer = new int[dimx*dimy*dimz*dimv];
+ cimg::fread(buffer,dimx*dimy*dimz*dimv,file);
+ if (endian) cimg::endian_swap(buffer,dimx*dimy*dimz*dimv);
+ cimg_mapoff(dest,off) dest.data[off] = (T)(buffer[off]*scalefactor);
+ delete[] buffer;
+ } break;
+ case 16: {
+ float *buffer = new float[dimx*dimy*dimz*dimv];
+ cimg::fread(buffer,dimx*dimy*dimz*dimv,file);
+ if (endian) cimg::endian_swap(buffer,dimx*dimy*dimz*dimv);
+ cimg_mapoff(dest,off) dest.data[off] = (T)(buffer[off]*scalefactor);
+ delete[] buffer;
+ } break;
+ case 64: {
+ double *buffer = new double[dimx*dimy*dimz*dimv];
+ cimg::fread(buffer,dimx*dimy*dimz*dimv,file);
+ if (endian) cimg::endian_swap(buffer,dimx*dimy*dimz*dimv);
+ cimg_mapoff(dest,off) dest.data[off] = (T)(buffer[off]*scalefactor);
+ delete[] buffer;
+ } break;
+ default: throw CImgIOException("CImg<%s>::get_load_analyze() : Cannot read images width 'datatype = %d'",pixel_type(),datatype);
+ }
+ cimg::fclose(file);
+ return dest;
+ }
+
+ //! In-place version of get_load_analyze()
+ CImg& load_analyze(const char *filename, float *voxsize = NULL) { return get_load_analyze(filename,voxsize).swap(*this); }
+
+ //! Load PAR-REC (Philips) image file
+ static CImg get_load_parrec(const char *filename,const char axe='v',const char align='p') {
+ return CImgl<T>::get_load_parrec(filename).get_append(axe,align);
+ }
+
+ //! In-place version of get_load_parrec()
+ CImg& load_parrec(const char *filename, const char axis='v', const char align='p') {
+ return get_load_parrec(filename,axis,align).swap(*this);
+ }
+
+ //! Load an image from a CImg RAW file
+ static CImg get_load_cimg(const char *filename, const char axis='v', const char align='p') {
+ return CImgl<T>(filename).get_append(axis,align);
+ }
+
+ //! In-place version of get_load_cimg()
+ CImg& load_cimg(const char* filename, const char axis='v', const char align='p') {
+ return get_load_cimg(filename,axis,align).swap(*this);
+ }
+
+ //! Function that loads the image for other file formats that are not natively handled by CImg, using the tool 'convert' from the ImageMagick package.\n
+ //! This is the case for all compressed image formats (GIF,PNG,JPG,TIF,...). You need to install the ImageMagick package in order to get
+ //! this function working properly (see http://www.imagemagick.org ).
+ static CImg get_load_convert(const char *filename) {
+ static bool first_time = true;
+ char command[1024], filetmp[512];
+ if (first_time) { std::srand((unsigned int)::time(NULL)); first_time = false; }
+ std::FILE *file = NULL;
+ do {
+ if (file) std::fclose(file);
+ std::sprintf(filetmp,"%s/CImg%.4d.ppm",cimg::temporary_path(),std::rand()%10000);
+ file = std::fopen(filetmp,"rb");
+ } while (file);
+ std::sprintf(command,"\"%s\" \"%s\" %s",cimg::convert_path(),filename,filetmp);
+ cimg::system(command);
+ file = std::fopen(filetmp,"rb");
+ if (!file) {
+ std::fclose(cimg::fopen(filename,"r"));
+ throw CImgIOException("CImg<%s>::get_load_convert() : Failed to open image '%s' with 'convert'.\n"
+ "Check that you have installed the ImageMagick package in a standard directory.",
+ pixel_type(),filename);
+ } else cimg::fclose(file);
+ const CImg dest = CImg<T>::get_load_pnm(filetmp);
+ std::remove(filetmp);
+ return dest;
+ }
+
+ //! In-place version of get_load_convert()
+ CImg& load_convert(const char *filename) { return get_load_convert(filename).swap(*this); }
+
+ //! Load an image from a Dicom file (need '(X)Medcon' : http://xmedcon.sourceforge.net )
+ static CImg get_load_dicom(const char *filename) {
+ static bool first_time = true;
+ char command[1024], filetmp[512], body[512];
+ if (first_time) { std::srand((unsigned int)::time(NULL)); first_time = false; }
+ cimg::fclose(cimg::fopen(filename,"r"));
+ std::FILE *file = NULL;
+ do {
+ if (file) std::fclose(file);
+ std::sprintf(filetmp,"CImg%.4d.hdr",std::rand()%10000);
+ file = std::fopen(filetmp,"rb");
+ } while (file);
+ std::sprintf(command,"\"%s\" -w -c anlz -o \"%s\" -f \"%s\"",cimg::medcon_path(),filetmp,filename);
+ cimg::system(command);
+ cimg::filename_split(filetmp,body);
+ std::sprintf(command,"m000-%s.hdr",body);
+ file = std::fopen(command,"rb");
+ if (!file) {
+ std::fclose(cimg::fopen(filename,"r"));
+ throw CImgIOException("CImg<%s>::get_load_dicom() : Failed to open image '%s' with 'medcon'.\n"
+ "Check that you have installed the XMedCon package in a standard directory.",
+ pixel_type(),filename);
+ } else cimg::fclose(file);
+ const CImg dest = CImg<T>::get_load_analyze(command);
+ std::remove(command);
+ std::sprintf(command,"m000-%s.img",body);
+ std::remove(command);
+ return dest;
+ }
+
+ //! In-place version of get_load_dicom()
+ CImg& load_dicom(const char *filename) { return get_load_dicom(filename).swap(*this); }
+
+ //! Load OFF files (GeomView 3D object files)
+ template<typename tf,typename tc>
+ static CImg<T> get_load_off(const char *filename, CImgl<tf>& primitives, CImgl<tc>& colors, const bool invert_faces=false) {
+ std::FILE *file=cimg::fopen(filename,"r");
+ unsigned int nb_points=0, nb_triangles=0;
+ int err;
+ if ((err = std::fscanf(file,"OFF%u%u%*[^\n]",&nb_points,&nb_triangles))!=2)
+ throw CImgIOException("CImg<%s>::get_load_off() : File '%s' does not appear to be a valid OFF file.\n",
+ pixel_type(),filename);
+
+ // Read points data
+ CImg<T> points(nb_points,3);
+ float X=0,Y=0,Z=0;
+ cimg_mapX(points,l) {
+ if ((err = std::fscanf(file,"%f%f%f%*[^\n]",&X,&Y,&Z))!=3)
+ throw CImgIOException("CImg<%s>::get_load_off() : File '%s', cannot read point %u.\n",
+ pixel_type(),filename,l);
+ points(l,0) = (T)X; points(l,1) = (T)Y; points(l,2) = (T)Z;
+ }
+
+ // Read primitive data
+ primitives.empty();
+ colors.empty();
+ bool stopflag = false;
+ while (!stopflag) {
+ unsigned int prim=0;
+ if ((err = std::fscanf(file,"%u",&prim))!=1) stopflag=true;
+ else switch (prim) {
+ case 3: {
+ unsigned int i0=0,i1=0,i2=0;
+ float c0=0.5,c1=0.5,c2=0.5;
+ if ((err = std::fscanf(file,"%u%u%u%f%f%f%*[^\n]",&i0,&i1,&i2,&c0,&c1,&c2))<3) stopflag = true;
+ else {
+ if (invert_faces) primitives.insert(CImg<tf>::vector(i0,i1,i2));
+ else primitives.insert(CImg<tf>::vector(i0,i2,i1));
+ colors.insert(CImg<tc>::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255)));
+ }
+ } break;
+ case 4: {
+ unsigned int i0=0,i1=0,i2=0,i3=0;
+ float c0=0.5,c1=0.5,c2=0.5;
+ if ((err = std::fscanf(file,"%u%u%u%u%f%f%f%*[^\n]",&i0,&i1,&i2,&i3,&c0,&c1,&c2))<4) stopflag = true;
+ else {
+ if (invert_faces) primitives.insert(CImg<tf>::vector(i0,i1,i2,i3));
+ else primitives.insert(CImg<tf>::vector(i0,i3,i2,i1));
+ colors.insert(CImg<tc>::vector((tc)(c0*255),(tc)(c1*255),(tc)(c2*255),(tc)(c2*255)));
+ }
+ } break;
+ default: stopflag = true;
+ }
+ }
+ cimg::fclose(file);
+ cimg::warn(primitives.size!=nb_triangles,
+ "CImg<%s>::get_load_off() : File '%s' contained %u triangles instead of %u as claimed in the header.",
+ pixel_type(),filename,primitives.size,nb_triangles);
+ return points;
+ }
+
+ //! In-place version of get_load_off()
+ template<typename tf,typename tc>
+ CImg& load_off(const char *filename, CImgl<tf>& primitives, CImgl<tc>& colors, const bool invert_faces=false) {
+ return get_load_off(filename,primitives,colors,invert_faces).swap(*this);
+ }
+
+ //! Save the image as a file.
+ /**
+ The used file format is defined by the file extension in the filename \p filename.\n
+ Parameter \p number can be used to add a 6-digit number to the filename before saving.\n
+ If \p normalize is true, a normalized version of the image (between [0,255]) is saved.
+ **/
+ const CImg& save(const char *filename,const int number=-1) const {
+ if (!filename) throw CImgArgumentException("CImg<%s>::save() : Specified filename is (null).",pixel_type());
+ const char *ext = cimg::filename_split(filename);
+ char nfilename[1024];
+ if (number>=0) filename = cimg::filename_number(filename,number,6,nfilename);
+ if (!cimg::strcasecmp(ext,"asc")) return save_ascii(filename);
+ if (!cimg::strcasecmp(ext,"dlm")) return save_dlm(filename);
+ if (!cimg::strcasecmp(ext,"inr")) return save_inr(filename);
+ if (!cimg::strcasecmp(ext,"hdr")) return save_analyze(filename);
+ if (!cimg::strcasecmp(ext,"dcm")) return save_dicom(filename);
+ if (!cimg::strcasecmp(ext,"pan")) return save_pandore(filename);
+ if (!cimg::strcasecmp(ext,"bmp")) return save_bmp(filename);
+ if (!cimg::strcasecmp(ext,"png")) return save_png(filename);
+ if (!cimg::strcasecmp(ext,"jpg") ||
+ !cimg::strcasecmp(ext,"jpeg")) return save_jpeg(filename);
+ if (!cimg::strcasecmp(ext,"rgba")) return save_rgba(filename);
+ if (!cimg::strcasecmp(ext,"rgb")) return save_rgb(filename);
+ if (!cimg::strcasecmp(ext,"raw")) return save_raw(filename);
+ if (!cimg::strcasecmp(ext,"cimg") || ext[0]=='\0') return save_cimg(filename);
+ if (!cimg::strcasecmp(ext,"pgm") ||
+ !cimg::strcasecmp(ext,"ppm") ||
+ !cimg::strcasecmp(ext,"pnm")) return save_pnm(filename);
+ if (!cimg::strcasecmp(ext,"yuv")) return save_yuv(filename,true);
+ return save_convert(filename);
+ }
+
+ //! Save the image as an ASCII file.
+ const CImg& save_ascii(const char *filename) const {
+ if (is_empty()) throw CImgInstanceException("CImg<%s>::save_ascii() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (!filename) throw CImgArgumentException("CImg<%s>::save_ascii() : Specified filename is (null).",pixel_type());
+ std::FILE *file = cimg::fopen(filename,"w");
+ std::fprintf(file,"%u %u %u %u\n",width,height,depth,dim);
+ const T* ptrs = data;
+ cimg_mapYZV(*this,y,z,v) {
+ cimg_mapX(*this,x) std::fprintf(file,"%g ",(double)*(ptrs++));
+ std::fputc('\n',file);
+ }
+ cimg::fclose(file);
+ return *this;
+ }
+
+ //! Save the image as a DLM file.
+ const CImg& save_dlm(const char *filename) const {
+ if (is_empty()) throw CImgInstanceException("CImg<%s>::save_dlm() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (!filename) throw CImgArgumentException("CImg<%s>::save_dlm() : Specified filename is (null).",pixel_type());
+ std::FILE *file = cimg::fopen(filename,"w");
+ const T* ptrs = data;
+ cimg_mapYZV(*this,y,z,v) {
+ cimg_mapX(*this,x) std::fprintf(file,"%g%s",(double)*(ptrs++),(x==(int)width-1)?"":",");
+ std::fputc('\n',file);
+ }
+ cimg::fclose(file);
+ return *this;
+ }
+
+ //! Save the image as a PNM file.
+ const CImg& save_pnm(const char *filename) const {
+ if (is_empty()) throw CImgInstanceException("CImg<%s>::save_pnm() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (!filename) throw CImgArgumentException("CImg<%s>::save_pnm() : Specified filename is (null).",pixel_type());
+ const char *ext = cimg::filename_split(filename);
+ const CImgStats st(*this,false);
+
+ if (dim>1 && !cimg::strcasecmp(ext,"pgm")) {
+ get_norm_pointwise().normalize(0.0f,(float)st.max).save_pnm(filename);
+ return *this;
+ }
+ std::FILE *file = cimg::fopen(filename,"wb");
+ const T
+ *ptrR = ptr(0,0,0,0),
+ *ptrG = (dim>=2)?ptr(0,0,0,1):ptrR,
+ *ptrB = (dim>=3)?ptr(0,0,0,2):ptrR;
+ const unsigned int buf_size = width*height*(dim==1?1:3);
+
+ std::fprintf(file,"P%c\n# CREATOR: CImg : Original size=%ux%ux%ux%u\n%u %u\n%u\n",
+ (dim==1?'5':'6'),width,height,depth,dim,width,height,(st.max)<256?255:65535);
+
+ switch(dim) {
+ case 1: {
+ if ((st.max)<256) { // Binary PGM 8 bits
+ unsigned char *ptrd = new unsigned char[buf_size], *xptrd = ptrd;
+ cimg_mapXY(*this,x,y) *(xptrd++) = (unsigned char)*(ptrR++);
+ cimg::fwrite(ptrd,buf_size,file);
+ delete[] ptrd;
+ } else { // Binary PGM 16 bits
+ unsigned short *ptrd = new unsigned short[buf_size], *xptrd = ptrd;
+ cimg_mapXY(*this,x,y) *(xptrd++) = (unsigned short)*(ptrR++);
+ if (!cimg::endian()) cimg::endian_swap(ptrd,buf_size);
+ cimg::fwrite(ptrd,buf_size,file);
+ delete[] ptrd;
+ }
+ } break;
+ default: {
+ if ((st.max)<256) { // Binary PPM 8 bits
+ unsigned char *ptrd = new unsigned char[buf_size], *xptrd = ptrd;
+ cimg_mapXY(*this,x,y) {
+ *(xptrd++) = (unsigned char)*(ptrR++);
+ *(xptrd++) = (unsigned char)*(ptrG++);
+ *(xptrd++) = (unsigned char)*(ptrB++);
+ }
+ cimg::fwrite(ptrd,buf_size,file);
+ delete[] ptrd;
+ } else { // Binary PPM 16 bits
+ unsigned short *ptrd = new unsigned short[buf_size], *xptrd = ptrd;
+ cimg_mapXY(*this,x,y) {
+ *(xptrd++) = (unsigned short)*(ptrR++);
+ *(xptrd++) = (unsigned short)*(ptrG++);
+ *(xptrd++) = (unsigned short)*(ptrB++);
+ }
+ if (!cimg::endian()) cimg::endian_swap(ptrd,buf_size);
+ cimg::fwrite(ptrd,buf_size,file);
+ delete[] ptrd;
+ }
+ } break;
+ }
+ cimg::fclose(file);
+
+ return *this;
+ }
+
+ //! Save an image as a Dicom file (need '(X)Medcon' : http://xmedcon.sourceforge.net )
+ const CImg& save_dicom(const char *filename) const {
+ if (is_empty()) throw CImgInstanceException("CImg<%s>::save_dicom() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (!filename) throw CImgArgumentException("CImg<%s>::save_dicom() : Specified filename is (null).",pixel_type());
+ static bool first_time = true;
+ char command[1024], filetmp[512], body[512];
+ if (first_time) { std::srand((unsigned int)::time(NULL)); first_time = false; }
+ std::FILE *file = NULL;
+ do {
+ if (file) std::fclose(file);
+ std::sprintf(filetmp,"CImg%.4d.hdr",std::rand()%10000);
+ file = std::fopen(filetmp,"rb");
+ } while (file);
+ save_analyze(filetmp);
+ std::sprintf(command,"\"%s\" -w -c dicom -o \"%s\" -f \"%s\"",cimg::medcon_path(),filename,filetmp);
+ cimg::system(command);
+ std::remove(filetmp);
+ cimg::filename_split(filetmp,body);
+ std::sprintf(filetmp,"%s.img",body);
+ std::remove(filetmp);
+ std::sprintf(command,"m000-%s",filename);
+ file = std::fopen(command,"rb");
+ if (!file) {
+ std::fclose(cimg::fopen(filename,"r"));
+ throw CImgIOException("CImg<%s>::save_dicom() : Failed to save image '%s' with 'medcon'.\n"
+ "Check that you have installed the XMedCon package in a standard directory.",
+ pixel_type(),filename);
+ } else cimg::fclose(file);
+ std::rename(command,filename);
+ return *this;
+ }
+
+ //! Save the image as an ANALYZE7.5 file.
+ const CImg& save_analyze(const char *filename,const float *const voxsize=NULL) const {
+ if (is_empty()) throw CImgInstanceException("CImg<%s>::save_analyze() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (!filename) throw CImgArgumentException("CImg<%s>::save_analyze() : Specified filename is (null).",pixel_type());
+ std::FILE *file;
+ char header[348],hname[1024],iname[1024];
+ const char *ext = cimg::filename_split(filename);
+ short datatype=-1;
+ std::memset(header,0,348);
+ if (!ext[0]) { std::sprintf(hname,"%s.hdr",filename); std::sprintf(iname,"%s.img",filename); }
+ if (!cimg::strncasecmp(ext,"hdr",3)) {
+ std::strcpy(hname,filename); std::strcpy(iname,filename); std::sprintf(iname+cimg::strlen(iname)-3,"img");
+ }
+ if (!cimg::strncasecmp(ext,"img",3)) {
+ std::strcpy(hname,filename); std::strcpy(iname,filename); std::sprintf(hname+cimg::strlen(iname)-3,"hdr");
+ }
+ ((int*)(header))[0] = 348;
+ std::sprintf(header+4,"CImg");
+ std::sprintf(header+14," ");
+ ((short*)(header+36))[0] = 4096;
+ ((char*)(header+38))[0] = 114;
+ ((short*)(header+40))[0] = 4;
+ ((short*)(header+40))[1] = width;
+ ((short*)(header+40))[2] = height;
+ ((short*)(header+40))[3] = depth;
+ ((short*)(header+40))[4] = dim;
+ if (!cimg::strcasecmp(pixel_type(),"bool")) datatype = 2;
+ if (!cimg::strcasecmp(pixel_type(),"unsigned char")) datatype = 2;
+ if (!cimg::strcasecmp(pixel_type(),"char")) datatype = 2;
+ if (!cimg::strcasecmp(pixel_type(),"unsigned short")) datatype = 4;
+ if (!cimg::strcasecmp(pixel_type(),"short")) datatype = 4;
+ if (!cimg::strcasecmp(pixel_type(),"unsigned int")) datatype = 8;
+ if (!cimg::strcasecmp(pixel_type(),"int")) datatype = 8;
+ if (!cimg::strcasecmp(pixel_type(),"unsigned long")) datatype = 8;
+ if (!cimg::strcasecmp(pixel_type(),"long")) datatype = 8;
+ if (!cimg::strcasecmp(pixel_type(),"float")) datatype = 16;
+ if (!cimg::strcasecmp(pixel_type(),"double")) datatype = 64;
+ if (datatype<0)
+ throw CImgIOException("CImg<%s>::save_analyze() : Cannot save image '%s' since pixel type (%s)"
+ "is not handled in Analyze7.5 specifications.\n",
+ pixel_type(),filename,pixel_type());
+ ((short*)(header+70))[0] = datatype;
+ ((short*)(header+72))[0] = sizeof(T);
+ ((float*)(header+112))[0] = 1;
+ ((float*)(header+76))[0] = 0;
+ if (voxsize) {
+ ((float*)(header+76))[1] = voxsize[0];
+ ((float*)(header+76))[2] = voxsize[1];
+ ((float*)(header+76))[3] = voxsize[2];
+ } else ((float*)(header+76))[1] = ((float*)(header+76))[2] = ((float*)(header+76))[3] = 1;
+ file = cimg::fopen(hname,"wb");
+ cimg::fwrite(header,348,file);
+ cimg::fclose(file);
+ file = cimg::fopen(iname,"wb");
+ cimg::fwrite(data,size(),file);
+ cimg::fclose(file);
+ return *this;
+ }
+
+ //! Save the image as a CImg RAW file
+ const CImg& save_cimg(const char *filename) const {
+ if (is_empty()) throw CImgInstanceException("CImg<%s>::save_cimg() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (!filename) throw CImgArgumentException("CImg<%s>::save_cimg() : Specified filename is (null).",pixel_type());
+ CImgl<T> tmp(1);
+ tmp[0].width = width;
+ tmp[0].height = height;
+ tmp[0].depth = depth;
+ tmp[0].dim = dim;
+ tmp[0].data = data;
+ tmp.save_cimg(filename);
+ tmp[0].width = tmp[0].height = tmp[0].depth = tmp[0].dim = 0;
+ tmp[0].data = NULL;
+ return *this;
+ }
+
+ //! Save the image as a RAW file
+ const CImg& save_raw(const char *filename, const bool multiplexed=false) const {
+ if (is_empty()) throw CImgInstanceException("CImg<%s>::save_raw() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (!filename) throw CImgArgumentException("CImg<%s>::save_raw() : Specified filename is (null).",pixel_type());
+ std::FILE *file = cimg::fopen(filename,"wb");
+ if (!multiplexed) cimg::fwrite(data,size(),file);
+ else {
+ CImg<T> buf(dim);
+ cimg_mapXYZ(*this,x,y,z) {
+ cimg_mapV(*this,k) buf[k] = (*this)(x,y,z,k);
+ cimg::fwrite(buf.data,dim,file);
+ }
+ }
+ cimg::fclose(file);
+ return *this;
+ }
+
+ //! Save the image using ImageMagick's convert.
+ /** Function that saves the image for other file formats that are not natively handled by CImg,
+ using the tool 'convert' from the ImageMagick package.\n
+ This is the case for all compressed image formats (GIF,PNG,JPG,TIF,...). You need to install
+ the ImageMagick package in order to get
+ this function working properly (see http://www.imagemagick.org ).
+ **/
+ const CImg& save_convert(const char *filename) const {
+ if (is_empty()) throw CImgInstanceException("CImg<%s>::save_convert() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (!filename) throw CImgArgumentException("CImg<%s>::save_convert() : Specified filename is (null).",pixel_type());
+ static bool first_time = true;
+ char command[512],filetmp[512];
+ if (first_time) { std::srand((unsigned int)::time(NULL)); first_time = false; }
+ std::FILE *file = NULL;
+ do {
+ if (file) std::fclose(file);
+ std::sprintf(filetmp,"%s/CImg%.4d.ppm",cimg::temporary_path(),std::rand()%10000);
+ file = std::fopen(filetmp,"rb");
+ } while (file);
+ save_pnm(filetmp);
+ std::sprintf(command,"\"%s\" -quality 100%% %s \"%s\"",cimg::convert_path(),filetmp,filename);
+ cimg::system(command);
+ file = std::fopen(filename,"rb");
+ if (!file) throw CImgIOException("CImg<%s>::save_convert() : Failed to save image '%s' with 'convert'.\n"
+ "Check that you have installed the ImageMagick package in a standard directory.",
+ pixel_type(),filename);
+ if (file) cimg::fclose(file);
+ std::remove(filetmp);
+ return *this;
+ }
+
+ //! Save the image as an INRIMAGE-4 file.
+ const CImg& save_inr(const char *filename,const float *const voxsize = NULL) const {
+ if (is_empty()) throw CImgInstanceException("CImg<%s>::save_inr() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (!filename) throw CImgArgumentException("CImg<%s>::save_inr() : Specified filename is (null).",pixel_type());
+ int inrpixsize=-1;
+ const char *inrtype = "unsigned fixed\nPIXSIZE=8 bits\nSCALE=2**0";
+ if (!cimg::strcasecmp(pixel_type(),"unsigned char")) { inrtype = "unsigned fixed\nPIXSIZE=8 bits\nSCALE=2**0"; inrpixsize = 1; }
+ if (!cimg::strcasecmp(pixel_type(),"char")) { inrtype = "fixed\nPIXSIZE=8 bits\nSCALE=2**0"; inrpixsize = 1; }
+ if (!cimg::strcasecmp(pixel_type(),"unsigned short")) { inrtype = "unsigned fixed\nPIXSIZE=16 bits\nSCALE=2**0";inrpixsize = 2; }
+ if (!cimg::strcasecmp(pixel_type(),"short")) { inrtype = "fixed\nPIXSIZE=16 bits\nSCALE=2**0"; inrpixsize = 2; }
+ if (!cimg::strcasecmp(pixel_type(),"unsigned int")) { inrtype = "unsigned fixed\nPIXSIZE=32 bits\nSCALE=2**0";inrpixsize = 4; }
+ if (!cimg::strcasecmp(pixel_type(),"int")) { inrtype = "fixed\nPIXSIZE=32 bits\nSCALE=2**0"; inrpixsize = 4; }
+ if (!cimg::strcasecmp(pixel_type(),"float")) { inrtype = "float\nPIXSIZE=32 bits"; inrpixsize = 4; }
+ if (!cimg::strcasecmp(pixel_type(),"double")) { inrtype = "float\nPIXSIZE=64 bits"; inrpixsize = 8; }
+ if (inrpixsize<=0) throw CImgIOException("CImg<%s>::save_inr() : Don't know how to save images of '%s'",pixel_type(),pixel_type());
+ std::FILE *file = cimg::fopen(filename,"wb");
+ char header[257];
+ int err = std::sprintf(header,"#INRIMAGE-4#{\nXDIM=%u\nYDIM=%u\nZDIM=%u\nVDIM=%u\n",width,height,depth,dim);
+ if (voxsize) err += std::sprintf(header+err,"VX=%g\nVY=%g\nVZ=%g\n",voxsize[0],voxsize[1],voxsize[2]);
+ err += std::sprintf(header+err,"TYPE=%s\nCPU=%s\n",inrtype,cimg::endian()?"sun":"decm");
+ std::memset(header+err,'\n',252-err);
+ std::memcpy(header+252,"##}\n",4);
+ cimg::fwrite(header,256,file);
+ cimg_mapXYZ(*this,x,y,z) cimg_mapV(*this,k) cimg::fwrite(&((*this)(x,y,z,k)),1,file);
+ cimg::fclose(file);
+ return *this;
+ }
+
+#define cimg_save_pandore_case(sy,sz,sv,stype,id) \
+ if (!saved && (sy?(sy==height):true) && (sz?(sz==depth):true) && (sv?(sv==dim):true) && !strcmp(stype,pixel_type())) { \
+ unsigned int *iheader = (unsigned int*)(header+12); \
+ nbdims = _save_pandore_header_length((*iheader=id),dims,colorspace); \
+ cimg::fwrite(header,36,file); \
+ cimg::fwrite(dims,nbdims,file); \
+ if (id==2 || id==5 || id==8 || id==16 || id==19 || id==22 || id==26 || id==30) { \
+ unsigned char *buffer = new unsigned char[size()]; \
+ const T *ptrs = ptr(); \
+ cimg_mapoff(*this,off) *(buffer++)=(unsigned char)(*(ptrs++)); \
+ buffer-=size(); \
+ cimg::fwrite(buffer,size(),file); \
+ delete[] buffer; \
+ } \
+ if (id==3 || id==6 || id==9 || id==17 || id==20 || id==23 || id==27 || id==31) { \
+ unsigned long *buffer = new unsigned long[size()]; \
+ const T *ptrs = ptr(); \
+ cimg_mapoff(*this,off) *(buffer++)=(long)(*(ptrs++)); \
+ buffer-=size(); \
+ cimg::fwrite(buffer,size(),file); \
+ delete[] buffer; \
+ } \
+ if (id==4 || id==7 || id==10 || id==18 || id==21 || id==25 || id==29 || id==33) { \
+ float *buffer = new float[size()]; \
+ const T *ptrs = ptr(); \
+ cimg_mapoff(*this,off) *(buffer++)=(float)(*(ptrs++)); \
+ buffer-=size(); \
+ cimg::fwrite(buffer,size(),file); \
+ delete[] buffer; \
+ } \
+ saved = true; \
+ }
+
+ unsigned int _save_pandore_header_length(unsigned int id,unsigned int *dims,const unsigned int colorspace=0) const {
+ unsigned int nbdims=0;
+ if (id==2 || id==3 || id==4) { dims[0]=1; dims[1]=width; nbdims=2; }
+ if (id==5 || id==6 || id==7) { dims[0]=1; dims[1]=height; dims[2]=width; nbdims=3; }
+ if (id==8 || id==9 || id==10) { dims[0]=dim; dims[1]=depth; dims[2]=height; dims[3]=width; nbdims=4; }
+ if (id==16 || id==17 || id==18) { dims[0]=3; dims[1]=height; dims[2]=width; dims[3]=colorspace; nbdims=4; }
+ if (id==19 || id==20 || id==21) { dims[0]=3; dims[1]=depth; dims[2]=height; dims[3]=width; dims[4]=colorspace; nbdims=5; }
+ if (id==22 || id==23 || id==25) { dims[0]=dim; dims[1]=width; nbdims=2; }
+ if (id==26 || id==27 || id==29) { dims[0]=dim; dims[1]=height; dims[2]=width; nbdims=3; }
+ if (id==30 || id==31 || id==33) { dims[0]=dim; dims[1]=depth; dims[2]=height; dims[3]=width; nbdims=4; }
+ return nbdims;
+ }
+
+ //! Save the image as a PANDORE-5 file.
+ const CImg& save_pandore(const char* filename, const unsigned int colorspace=0) const {
+ if (is_empty()) throw CImgInstanceException("CImg<%s>::save_pandore() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (!filename) throw CImgArgumentException("CImg<%s>::save_pandore() : Specified filename is (null).",pixel_type());
+ std::FILE *file = cimg::fopen(filename,"wb");
+ unsigned char header[36] = { 'P','A','N','D','O','R','E','0','4',0,0,0,
+ 0,0,0,0,
+ 'C','I','m','g',0,0,0,0,0,
+ 'N','o',' ','d','a','t','e',0,0,0,
+ 0 };
+ unsigned int nbdims,dims[5];
+ bool saved=false;
+ cimg_save_pandore_case(1,1,1,"unsigned char",2);
+ cimg_save_pandore_case(1,1,1,"char",3);
+ cimg_save_pandore_case(1,1,1,"short",3);
+ cimg_save_pandore_case(1,1,1,"unsigned short",3);
+ cimg_save_pandore_case(1,1,1,"unsigned int",3);
+ cimg_save_pandore_case(1,1,1,"int",3);
+ cimg_save_pandore_case(1,1,1,"unsigned long",4);
+ cimg_save_pandore_case(1,1,1,"long",3);
+ cimg_save_pandore_case(1,1,1,"float",4);
+ cimg_save_pandore_case(1,1,1,"double",4);
+
+ cimg_save_pandore_case(0,1,1,"unsigned char",5);
+ cimg_save_pandore_case(0,1,1,"char",6);
+ cimg_save_pandore_case(0,1,1,"short",6);
+ cimg_save_pandore_case(0,1,1,"unsigned short",6);
+ cimg_save_pandore_case(0,1,1,"unsigned int",6);
+ cimg_save_pandore_case(0,1,1,"int",6);
+ cimg_save_pandore_case(0,1,1,"unsigned long",7);
+ cimg_save_pandore_case(0,1,1,"long",6);
+ cimg_save_pandore_case(0,1,1,"float",7);
+ cimg_save_pandore_case(0,1,1,"double",7);
+
+ cimg_save_pandore_case(0,0,1,"unsigned char",8);
+ cimg_save_pandore_case(0,0,1,"char",9);
+ cimg_save_pandore_case(0,0,1,"short",9);
+ cimg_save_pandore_case(0,0,1,"unsigned short",9);
+ cimg_save_pandore_case(0,0,1,"unsigned int",9);
+ cimg_save_pandore_case(0,0,1,"int",9);
+ cimg_save_pandore_case(0,0,1,"unsigned long",10);
+ cimg_save_pandore_case(0,0,1,"long",9);
+ cimg_save_pandore_case(0,0,1,"float",10);
+ cimg_save_pandore_case(0,0,1,"double",10);
+
+ cimg_save_pandore_case(0,1,3,"unsigned char",16);
+ cimg_save_pandore_case(0,1,3,"char",17);
+ cimg_save_pandore_case(0,1,3,"short",17);
+ cimg_save_pandore_case(0,1,3,"unsigned short",17);
+ cimg_save_pandore_case(0,1,3,"unsigned int",17);
+ cimg_save_pandore_case(0,1,3,"int",17);
+ cimg_save_pandore_case(0,1,3,"unsigned long",18);
+ cimg_save_pandore_case(0,1,3,"long",17);
+ cimg_save_pandore_case(0,1,3,"float",18);
+ cimg_save_pandore_case(0,1,3,"double",18);
+
+ cimg_save_pandore_case(0,0,3,"unsigned char",19);
+ cimg_save_pandore_case(0,0,3,"char",20);
+ cimg_save_pandore_case(0,0,3,"short",20);
+ cimg_save_pandore_case(0,0,3,"unsigned short",20);
+ cimg_save_pandore_case(0,0,3,"unsigned int",20);
+ cimg_save_pandore_case(0,0,3,"int",20);
+ cimg_save_pandore_case(0,0,3,"unsigned long",21);
+ cimg_save_pandore_case(0,0,3,"long",20);
+ cimg_save_pandore_case(0,0,3,"float",21);
+ cimg_save_pandore_case(0,0,3,"double",21);
+
+ cimg_save_pandore_case(1,1,0,"unsigned char",22);
+ cimg_save_pandore_case(1,1,0,"char",23);
+ cimg_save_pandore_case(1,1,0,"short",23);
+ cimg_save_pandore_case(1,1,0,"unsigned short",23);
+ cimg_save_pandore_case(1,1,0,"unsigned int",23);
+ cimg_save_pandore_case(1,1,0,"int",23);
+ cimg_save_pandore_case(1,1,0,"unsigned long",25);
+ cimg_save_pandore_case(1,1,0,"long",23);
+ cimg_save_pandore_case(1,1,0,"float",25);
+ cimg_save_pandore_case(1,1,0,"double",25);
+
+ cimg_save_pandore_case(0,1,0,"unsigned char",26);
+ cimg_save_pandore_case(0,1,0,"char",27);
+ cimg_save_pandore_case(0,1,0,"short",27);
+ cimg_save_pandore_case(0,1,0,"unsigned short",27);
+ cimg_save_pandore_case(0,1,0,"unsigned int",27);
+ cimg_save_pandore_case(0,1,0,"int",27);
+ cimg_save_pandore_case(0,1,0,"unsigned long",29);
+ cimg_save_pandore_case(0,1,0,"long",27);
+ cimg_save_pandore_case(0,1,0,"float",29);
+ cimg_save_pandore_case(0,1,0,"double",29);
+
+ cimg_save_pandore_case(0,0,0,"unsigned char",30);
+ cimg_save_pandore_case(0,0,0,"char",31);
+ cimg_save_pandore_case(0,0,0,"short",31);
+ cimg_save_pandore_case(0,0,0,"unsigned short",31);
+ cimg_save_pandore_case(0,0,0,"unsigned int",31);
+ cimg_save_pandore_case(0,0,0,"int",31);
+ cimg_save_pandore_case(0,0,0,"unsigned long",33);
+ cimg_save_pandore_case(0,0,0,"long",31);
+ cimg_save_pandore_case(0,0,0,"float",33);
+ cimg_save_pandore_case(0,0,0,"double",33);
+
+ cimg::fclose(file);
+ return *this;
+ }
+
+ //! Save the image as a YUV file
+ const CImg& save_yuv(const char *filename, const bool rgb2yuv=true) const {
+ CImgl<T>(*this).save_yuv(filename,rgb2yuv);
+ return *this;
+ }
+
+ //! Save the image as a BMP file
+ const CImg& save_bmp(const char* filename) const {
+ if (is_empty()) throw CImgInstanceException("CImg<%s>::save_bmp() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (!filename) throw CImgArgumentException("CImg<%s>::save_bmp() : Specified filename is (null).",pixel_type());
+
+ std::FILE *file = cimg::fopen(filename,"wb");
+ unsigned char header[54]={0}, align_buf[4]={0};
+ const unsigned int
+ align = (4-(3*width)%4)%4,
+ buf_size = (3*width+align)*dimy(),
+ file_size = 54+buf_size;
+ header[0] = 'B'; header[1] = 'M';
+ header[0x02]=file_size&0xFF; header[0x03]=(file_size>>8)&0xFF;
+ header[0x04]=(file_size>>16)&0xFF; header[0x05]=(file_size>>24)&0xFF;
+ header[0x0A]=0x36;
+ header[0x0E]=0x28;
+ header[0x12]=width&0xFF; header[0x13]=(width>>8)&0xFF;
+ header[0x14]=(width>>16)&0xFF; header[0x15]=(width>>24)&0xFF;
+ header[0x16]=height&0xFF; header[0x17]=(height>>8)&0xFF;
+ header[0x18]=(height>>16)&0xFF; header[0x19]=(height>>24)&0xFF;
+ header[0x1A]=1; header[0x1B]=0;
+ header[0x1C]=24; header[0x1D]=0;
+ header[0x22]=buf_size&0xFF; header[0x23]=(buf_size>>8)&0xFF;
+ header[0x24]=(buf_size>>16)&0xFF; header[0x25]=(buf_size>>24)&0xFF;
+ header[0x27]=0x1; header[0x2B]=0x1;
+ cimg::fwrite(header,54,file);
+
+ const T
+ *pR = ptr(0,height-1,0,0),
+ *pG = (dim>=2)?ptr(0,height-1,0,1):pR,
+ *pB = (dim>=3)?ptr(0,height-1,0,2):pR;
+
+ cimg_mapY(*this,y) {
+ cimg_mapX(*this,x) {
+ std::fputc((unsigned char)(*(pB++)),file);
+ std::fputc((unsigned char)(*(pG++)),file);
+ std::fputc((unsigned char)(*(pR++)),file);
+ }
+ std::fwrite(align_buf,1,align,file);
+ pR-=2*width; pG-=2*width; pB-=2*width;
+ }
+ cimg::fclose(file);
+ return *this;
+ }
+
+ //! Save an image to a PNG file.
+ // Most of this function has been written by Eric Fausett
+ /**
+ \param filename = name of the png image file to load
+ \return *this
+ \note The png format specifies a variety of possible data formats. Grey scale, Grey
+ scale with Alpha, RGB color, RGB color with Alpha, and Palletized color are supported.
+ Per channel bit depths of 1, 2, 4, 8, and 16 are natively supported. The
+ type of file saved depends on the number of channels in the CImg file. If there is 4 or more
+ channels, the image will be saved as an RGB color with Alpha image using the bottom 4 channels.
+ If there are 3 channels, the saved image will be an RGB color image. If 2 channels then the
+ image saved will be Grey scale with Alpha, and if 1 channel will be saved as a Grey scale
+ image.
+ **/
+ const CImg& save_png(const char* filename) const {
+ if (is_empty()) throw CImgInstanceException("CImg<%s>::save_png() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (!filename) throw CImgArgumentException("CImg<%s>::save_png() : Specified filename is (null).",pixel_type());
+#ifndef cimg_use_png
+ return save_convert(filename);
+#else
+ std::FILE *file = cimg::fopen(filename,"wb");
+
+ // Setup PNG structures for write
+ png_voidp user_error_ptr=0;
+ png_error_ptr user_error_fn=0, user_warning_fn=0;
+ png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
+ user_error_ptr, user_error_fn, user_warning_fn);
+ if(!png_ptr){
+ cimg::fclose(file);
+ throw CImgIOException("CImg<%s>::save_png() : trouble initializing 'png_ptr' data structure",pixel_type());
+ }
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if(!info_ptr){
+ png_destroy_write_struct(&png_ptr,(png_infopp)NULL);
+ cimg::fclose(file);
+ throw CImgIOException("CImg<%s>::save_png() : trouble initializing 'info_ptr' data structure",pixel_type());
+ }
+ if (setjmp(png_jmpbuf(png_ptr))){
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ cimg::fclose(file);
+ throw CImgIOException("CImg<%s>::save_png() : unspecified error reading PNG file '%s'",pixel_type(),filename);
+ }
+
+ png_init_io(png_ptr, file);
+ png_uint_32 width = dimx();
+ png_uint_32 height = dimy();
+ CImgStats stats(*this,false);
+ const int bit_depth = (stats.min<0 || stats.max>=256)?16:8;
+ int color_type;
+ switch (dimv()) {
+ case 1: color_type = PNG_COLOR_TYPE_GRAY; break;
+ case 2: color_type = PNG_COLOR_TYPE_GRAY_ALPHA; break;
+ case 3: color_type = PNG_COLOR_TYPE_RGB; break;
+ default: color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ }
+ const int interlace_type = PNG_INTERLACE_NONE;
+ const int compression_type = PNG_COMPRESSION_TYPE_DEFAULT;
+ const int filter_method = PNG_FILTER_TYPE_DEFAULT;
+ png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, interlace_type,
+ compression_type, filter_method);
+ png_write_info(png_ptr, info_ptr);
+ const int byte_depth = bit_depth>>3;
+ const int numChan = dimv()>4?4:dimv();
+ const int pixel_bit_depth_flag = numChan * (bit_depth-1);
+
+ // Allocate Memory for Image Save and Fill pixel data
+ png_bytep *imgData = new png_byte*[height];
+ for(unsigned int row=0; row<height; row++) imgData[row] = new png_byte[byte_depth * numChan * width];
+ const T *pC0 = ptr(0,0,0,0);
+ switch(pixel_bit_depth_flag) {
+ case 7 : { // Gray 8-bit
+ cimg_mapY(*this,y) {
+ unsigned char *ptrs = imgData[y];
+ cimg_mapX(*this,x) *(ptrs++) = (unsigned char)*(pC0++);
+ }
+ } break;
+ case 14: { // Gray w/ Alpha 8-bit
+ const T *pC1 = ptr(0,0,0,1);
+ cimg_mapY(*this,y) {
+ unsigned char *ptrs = imgData[y];
+ cimg_mapX(*this,x) {
+ *(ptrs++) = (unsigned char)*(pC0++);
+ *(ptrs++) = (unsigned char)*(pC1++);
+ }
+ }
+ } break;
+ case 21: { // RGB 8-bit
+ const T *pC1 = ptr(0,0,0,1);
+ const T *pC2 = ptr(0,0,0,2);
+ cimg_mapY(*this,y) {
+ unsigned char *ptrs = imgData[y];
+ cimg_mapX(*this,x) {
+ *(ptrs++) = (unsigned char)*(pC0++);
+ *(ptrs++) = (unsigned char)*(pC1++);
+ *(ptrs++) = (unsigned char)*(pC2++);
+ }
+ }
+ } break;
+ case 28: { // RGB x/ Alpha 8-bit
+ const T *pC1 = ptr(0,0,0,1);
+ const T *pC2 = ptr(0,0,0,2);
+ const T *pC3 = ptr(0,0,0,3);
+ cimg_mapY(*this,y){
+ unsigned char *ptrs = imgData[y];
+ cimg_mapX(*this,x){
+ *(ptrs++) = (unsigned char)*(pC0++);
+ *(ptrs++) = (unsigned char)*(pC1++);
+ *(ptrs++) = (unsigned char)*(pC2++);
+ *(ptrs++) = (unsigned char)*(pC3++);
+ }
+ }
+ } break;
+ case 15: { // Gray 16-bit
+ cimg_mapY(*this,y){
+ unsigned short *ptrs = reinterpret_cast<unsigned short*>(imgData[y]);
+ cimg_mapX(*this,x) *(ptrs++) = (unsigned short)*(pC0++);
+ }
+ } break;
+ case 30: { // Gray w/ Alpha 16-bit
+ const T *pC1 = ptr(0,0,0,1);
+ cimg_mapY(*this,y){
+ unsigned short *ptrs = reinterpret_cast<unsigned short*>(imgData[y]);
+ cimg_mapX(*this,x) {
+ *(ptrs++) = (unsigned short)*(pC0++);
+ *(ptrs++) = (unsigned short)*(pC1++);
+ }
+ }
+ } break;
+ case 45: { // RGB 16-bit
+ const T *pC1 = ptr(0,0,0,1);
+ const T *pC2 = ptr(0,0,0,2);
+ cimg_mapY(*this,y) {
+ unsigned short *ptrs = reinterpret_cast<unsigned short*>(imgData[y]);
+ cimg_mapX(*this,x) {
+ *(ptrs++) = (unsigned short)*(pC0++);
+ *(ptrs++) = (unsigned short)*(pC1++);
+ *(ptrs++) = (unsigned short)*(pC2++);
+ }
+ }
+ } break;
+ case 60: { // RGB w/ Alpha 16-bit
+ const T *pC1 = ptr(0,0,0,1);
+ const T *pC2 = ptr(0,0,0,2);
+ const T *pC3 = ptr(0,0,0,3);
+ cimg_mapY(*this,y) {
+ unsigned short *ptrs = reinterpret_cast<unsigned short*>(imgData[y]);
+ cimg_mapX(*this,x) {
+ *(ptrs++) = (unsigned short)*(pC0++);
+ *(ptrs++) = (unsigned short)*(pC1++);
+ *(ptrs++) = (unsigned short)*(pC2++);
+ *(ptrs++) = (unsigned short)*(pC3++);
+ }
+ }
+ } break;
+ default:
+ throw CImgIOException("CImg<%s>::save_png() : unspecified error reading PNG file '%s'",pixel_type(),filename);
+ break;
+ }
+ png_write_image(png_ptr, imgData);
+ png_write_end(png_ptr, info_ptr);
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ // Deallocate Image Write Memory
+ for (unsigned int n=0; n<height; n++) delete[] imgData[n];
+ delete[] imgData;
+ cimg::fclose(file);
+ return *this;
+#endif
+ }
+
+ //! Save a file in JPEG format.
+ const CImg<T>& save_jpeg(const char *filename,const unsigned int quality=100) const {
+ if (is_empty()) throw CImgInstanceException("CImg<%s>::save_jpeg() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (!filename) throw CImgArgumentException("CImg<%s>::save_jpeg() : Specified filename is (null).",pixel_type());
+#ifndef cimg_use_jpeg
+ return save_convert(filename);
+#else
+
+ // Fill pixel buffer
+ unsigned char *buf;
+ unsigned int dimbuf=0;
+ J_COLOR_SPACE colortype=JCS_RGB;
+ switch (dim) {
+ case 1: { // Greyscale images
+ unsigned char *buf2 = buf = new unsigned char[width*height*(dimbuf=1)];
+ colortype = JCS_GRAYSCALE;
+ const T *ptr_g = ptr();
+ cimg_mapXY(*this,x,y) *(buf2++) = (unsigned char)*(ptr_g++);
+ } break;
+ case 2:
+ case 3: { // RGB images
+ unsigned char *buf2 = buf = new unsigned char[width*height*(dimbuf=3)];
+ const T *ptr_r = ptr(0,0,0,0), *ptr_g = ptr(0,0,0,1), *ptr_b = ptr(0,0,0,dim>2?2:0);
+ colortype = JCS_RGB;
+ cimg_mapXY(*this,x,y) {
+ *(buf2++) = (unsigned char)*(ptr_r++);
+ *(buf2++) = (unsigned char)*(ptr_g++);
+ *(buf2++) = (unsigned char)*(ptr_b++);
+ }
+ } break;
+ default: { // YCMYK images
+ unsigned char *buf2 = buf = new unsigned char[width*height*(dimbuf=4)];
+ const T *ptr_r = ptr(0,0,0,0), *ptr_g = ptr(0,0,0,1), *ptr_b = ptr(0,0,0,2), *ptr_a = ptr(0,0,0,3);
+ colortype = JCS_CMYK;
+ cimg_mapXY(*this,x,y) {
+ *(buf2++) = (unsigned char)*(ptr_r++);
+ *(buf2++) = (unsigned char)*(ptr_g++);
+ *(buf2++) = (unsigned char)*(ptr_b++);
+ *(buf2++) = (unsigned char)*(ptr_a++);
+ }
+ } break;
+ }
+
+ // Call libjpeg functions
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+ std::FILE *file = cimg::fopen(filename,"wb");
+ jpeg_stdio_dest(&cinfo,file);
+ cinfo.image_width = width;
+ cinfo.image_height = height;
+ cinfo.input_components = dimbuf;
+ cinfo.in_color_space = colortype;
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo,quality<100?quality:100,TRUE);
+ jpeg_start_compress(&cinfo,TRUE);
+
+ const unsigned int row_stride = width*dimbuf;
+ JSAMPROW row_pointer[1];
+ while (cinfo.next_scanline < cinfo.image_height) {
+ row_pointer[0] = &buf[cinfo.next_scanline*row_stride];
+ jpeg_write_scanlines(&cinfo,row_pointer,1);
+ }
+ jpeg_finish_compress(&cinfo);
+
+ delete[] buf;
+ cimg::fclose(file);
+ jpeg_destroy_compress(&cinfo);
+ return *this;
+#endif
+ }
+
+ //! Save the image as a RGBA file
+ const CImg& save_rgba(const char *filename) const {
+ if (is_empty()) throw CImgInstanceException("CImg<%s>::save_rgba() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (!filename) throw CImgArgumentException("CImg<%s>::save_rgba() : Specified filename is (null).",pixel_type());
+ std::FILE *file = cimg::fopen(filename,"wb");
+ const unsigned int wh = width*height;
+ unsigned char *buffer = new unsigned char[4*wh], *nbuffer=buffer;
+ const T
+ *ptr1 = ptr(0,0,0,0),
+ *ptr2 = dim>1?ptr(0,0,0,1):ptr1,
+ *ptr3 = dim>2?ptr(0,0,0,2):ptr1,
+ *ptr4 = dim>3?ptr(0,0,0,3):NULL;
+ for (unsigned int k=0; k<wh; k++) {
+ *(nbuffer++) = (unsigned char)(*(ptr1++));
+ *(nbuffer++) = (unsigned char)(*(ptr2++));
+ *(nbuffer++) = (unsigned char)(*(ptr3++));
+ *(nbuffer++) = (unsigned char)(ptr4?(*(ptr4++)):255);
+ }
+ cimg::fwrite(buffer,4*wh,file);
+ cimg::fclose(file);
+ delete[] buffer;
+ return *this;
+ }
+
+
+ //! Save the image as a RGB file
+ const CImg& save_rgb(const char *filename) const {
+ if (is_empty()) throw CImgInstanceException("CImg<%s>::save_rgb() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (!filename) throw CImgArgumentException("CImg<%s>::save_rgb() : Specified filename is (null).",pixel_type());
+ std::FILE *file = cimg::fopen(filename,"wb");
+ const unsigned int wh = width*height;
+ unsigned char *buffer = new unsigned char[3*wh], *nbuffer=buffer;
+ const T
+ *ptr1 = ptr(0,0,0,0),
+ *ptr2 = dim>1?ptr(0,0,0,1):ptr1,
+ *ptr3 = dim>2?ptr(0,0,0,2):ptr1;
+ for (unsigned int k=0; k<wh; k++) {
+ *(nbuffer++) = (unsigned char)(*(ptr1++));
+ *(nbuffer++) = (unsigned char)(*(ptr2++));
+ *(nbuffer++) = (unsigned char)(*(ptr3++));
+ }
+ cimg::fwrite(buffer,3*wh,file);
+ cimg::fclose(file);
+ delete[] buffer;
+ return *this;
+ }
+
+ //! Get a 40x38 color logo of a 'danger' item
+ static CImg get_logo40x38() {
+ static bool first_time = true;
+ static CImg<T> res(40,38,1,3);
+ if (first_time) {
+ const unsigned char *ptrs = cimg::logo40x38;
+ T *ptr1 = res.ptr(0,0,0,0), *ptr2 = res.ptr(0,0,0,1), *ptr3 = res.ptr(0,0,0,2);
+ for (unsigned int off = 0; off<res.width*res.height;) {
+ const unsigned char n = *(ptrs++), r = *(ptrs++), g = *(ptrs++), b = *(ptrs++);
+ for (unsigned int l=0; l<n; off++,l++) { *(ptr1++) = (T)r; *(ptr2++) = (T)g; *(ptr3++) = (T)b; }
+ }
+ first_time = false;
+ }
+ return res;
+ }
+
+ //! Save OFF files (GeomView 3D object files)
+ template<typename tf, typename tc>
+ const CImg& save_off(const char *filename, const CImgl<tf>& primitives, const CImgl<tc>& colors, const bool invert_faces=false) const {
+ if (is_empty()) throw CImgInstanceException("CImg<%s>::save_off() : Instance image (%u,%u,%u,%u,%p) is empty.",
+ pixel_type(),width,height,depth,dim,data);
+ if (!filename) throw CImgArgumentException("CImg<%s>::save_off() : Specified filename is (null).",pixel_type());
+ std::FILE *file=cimg::fopen(filename,"w");
+ std::fprintf(file,"OFF\n%u %u %u\n",width,primitives.size,3*primitives.size);
+ cimg_mapX(*this,i) std::fprintf(file,"%f %f %f\n",(float)((*this)(i,0)),(float)((*this)(i,1)),(float)((*this)(i,2)));
+ cimgl_map(primitives,l) {
+ const unsigned int prim = primitives[l].size();
+ switch (prim) {
+ case 3: {
+ if (invert_faces)
+ std::fprintf(file,"3 %u %u %u %f %f %f\n",
+ (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),(unsigned int)primitives(l,2),
+ (float)(colors(l,0)/255.0f),(float)(colors(l,1)/255.0f),(float)(colors(l,2)/255.0f));
+ else
+ std::fprintf(file,"3 %u %u %u %f %f %f\n",
+ (unsigned int)primitives(l,0),(unsigned int)primitives(l,2),(unsigned int)primitives(l,1),
+ (float)(colors(l,0)/255.0f),(float)(colors(l,1)/255.0f),(float)(colors(l,2)/255.0f));
+ } break;
+ case 4: {
+ if (invert_faces)
+ std::fprintf(file,"4 %u %u %u %u %f %f %f\n",
+ (unsigned int)primitives(l,0),(unsigned int)primitives(l,1),(unsigned int)primitives(l,2),(unsigned int)primitives(l,3),
+ (float)(colors(l,0)/255.0f),(float)(colors(l,1)/255.0f),(float)(colors(l,2)/255.0f));
+ else
+ std::fprintf(file,"4 %u %u %u %u %f %f %f\n",
+ (unsigned int)primitives(l,0),(unsigned int)primitives(l,3),(unsigned int)primitives(l,2),(unsigned int)primitives(l,1),
+ (float)(colors(l,0)/255.0f),(float)(colors(l,1)/255.0f),(float)(colors(l,2)/255.0f));
+ } break;
+ }
+ }
+ cimg::fclose(file);
+ return *this;
+ }
+
+ //@}
+ //---------------------------
+ //
+ //! \name Plugins functions
+ //@{
+ //---------------------------
+#ifdef cimg_plugin
+#include cimg_plugin
+#endif
+ //@}
+ };
+
+
+ /*
+ #-----------------------------------------
+ #
+ #
+ #
+ # Definition of the CImgl<> structure
+ #
+ #
+ #
+ #------------------------------------------
+ */
+
+ //! Class representing list of images CImg<T>.
+ template<typename T> struct CImgl {
+
+ //! This variable represents the number of images in the image list.
+ /**
+ \note if \c size==0, the image list is empty.
+ **/
+ unsigned int size;
+
+ // This variable represents the size of the allocated block for the list.
+ unsigned int allocsize;
+
+ //! This variable defines if the instance list uses shared memory.
+ const bool shared;
+
+ //! This variable represents a pointer to the first \c CImg<T> image of the list.
+ CImg<T> *data;
+
+ //! Define a CImgl<T>::iterator
+ typedef CImg<T>* iterator;
+
+ //! Define a CImgl<T>::const_iterator
+ typedef const CImg<T>* const_iterator;
+
+ //------------------------------------------
+ //
+ //! \name Constructors - Destructor - Copy
+ //@{
+ //------------------------------------------
+
+ //! Return a string describing the type of the image pixels in the list (template parameter \p T).
+ static const char* pixel_type() { T val; return cimg::get_type(val); }
+
+ //! Create a list of \p n new images, each having size (\p width,\p height,\p depth,\p dim).
+ CImgl(const unsigned int n=0, const unsigned int width=0, const unsigned int height=1,
+ const unsigned int depth=1, const unsigned int dim=1):shared(false) {
+ if (n) {
+ data = new CImg<T>[allocsize=cimg::nearest_pow2(n)];
+ size = n;
+ cimgl_map(*this,l) data[l].assign(width,height,depth,dim);
+ } else { size = allocsize = 0; data = 0; }
+ }
+
+ //! In-place version of the previous constructor.
+ CImgl& assign(const unsigned int n=0, const unsigned int width=0, const unsigned int height=1,
+ const unsigned int depth=1, const unsigned int dim=1) {
+ return CImgl<T>(n,width,height,depth,dim).swap(*this);
+ }
+
+ //! Create a list of \p n new images, each having size (\p width,\p height,\p depth,\p dim).
+ CImgl(const unsigned int n, const unsigned int width, const unsigned int height,
+ const unsigned int depth, const unsigned int dim, const T& val):shared(false) {
+ if (n) {
+ data = new CImg<T>[allocsize=cimg::nearest_pow2(n)];
+ size = n;
+ cimgl_map(*this,l) data[l].assign(width,height,depth,dim,val);
+ } else { size = allocsize = 0; data = 0; }
+ }
+
+ //! In-place version of previous constructor.
+ CImgl& assign(const unsigned int n,const unsigned int width,const unsigned int height,
+ const unsigned int depth, const unsigned int dim,const T& val) {
+ return CImgl<T>(n,width,height,depth,dim,val).swap(*this);
+ }
+
+ // ! Create a list of \p n copies of the input image.
+ template<typename t> CImgl(const unsigned int n, const CImg<t>& img):shared(false) {
+ if (n) {
+ data = new CImg<T>[allocsize=cimg::nearest_pow2(n)];
+ size = n;
+ cimgl_map(*this,l) data[l]=img;
+ } else { size = allocsize = 0; data = 0; }
+ }
+
+ //! In-place version of previous constructor.
+ template<typename t> CImgl& assign(const unsigned int n, const CImg<t>& img) {
+ return CImgl<T>(n,img).swap(*this);
+ }
+
+ //! Copy constructor.
+ template<typename t> CImgl(const CImgl<t>& list):shared(false) {
+ if (list.data && list.size) {
+ data = new CImg<T>[allocsize=cimg::nearest_pow2(list.size)];
+ size = list.size;
+ cimgl_map(*this,l) data[l] = list[l];
+ } else { size = allocsize = 0; data = 0; }
+ }
+
+ //! Copy constructor (fast version).
+ CImgl(const CImgl<T>& list):shared(list.shared) {
+ if (list.data && list.size) {
+ if (shared) {
+ data = list.data;
+ size = list.size;
+ allocsize = 0;
+ } else {
+ data = new CImg<T>[allocsize=cimg::nearest_pow2(list.size)];
+ size = list.size;
+ cimgl_map(*this,l) data[l] = list[l];
+ }
+ } else { size = allocsize = 0; data = 0; }
+ }
+
+ //! In-place version of previous constructor.
+ template<typename t> CImgl& assign(const CImgl<t>& list) {
+ return CImgl<T>(list).swap(*this);
+ }
+
+ //! Create a list by loading a file.
+ CImgl(const char* filename):size(0),shared(false),data(0) {
+ load(filename);
+ }
+
+ //! Create a list from a single image \p img.
+ CImgl(const CImg<T>& img):size(0),shared(false),data(0) {
+ CImgl<T>(1,img).swap(*this);
+ }
+
+ //! In-place version of previous constructor.
+ CImgl assign(const CImg<T>& img) {
+ return CImgl<T>(1,img).swap(*this);
+ }
+
+ //! Create a list from two images \p img1 and \p img2 (images are copied).
+ CImgl(const CImg<T>& img1, const CImg<T>& img2):size(2),shared(false) {
+ data = new CImg<T>[allocsize=2];
+ data[0] = img1; data[1] = img2;
+ }
+
+ //! In-place version of previous constructor.
+ CImgl& assign(const CImg<T>& img1, const CImg<T>& img2) {
+ return CImgl<T>(img1,img2).swap(*this);
+ }
+
+ //! Create a list from three images \p img1,\p img2 and \p img3 (images are copied).
+ CImgl(const CImg<T>& img1, const CImg<T>& img2, const CImg<T>& img3):size(3),shared(false) {
+ data = new CImg<T>[allocsize=4];
+ data[0] = img1; data[1] = img2; data[2] = img3;
+ }
+
+ //! In-place version of previous constructor.
+ CImgl& assign(const CImg<T>& img1, const CImg<T>& img2, const CImg<T>& img3) {
+ return CImgl<T>(img1,img2,img3).swap(*this);
+ }
+
+ //! Create a list from four images \p img1,\p img2,\p img3 and \p img4 (images are copied).
+ CImgl(const CImg<T>& img1, const CImg<T>& img2, const CImg<T>& img3, const CImg<T>& img4):size(4),shared(false) {
+ data = new CImg<T>[allocsize=4];
+ data[0] = img1; data[1] = img2; data[2] = img3; data[3] = img4;
+ }
+
+ //! In-place version of previous constructor.
+ CImgl& assign(const CImg<T>& img1, const CImg<T>& img2, const CImg<T>& img3, const CImg<T>& img4) {
+ return CImgl<T>(img1,img2,img3,img4).swap(*this);
+ }
+
+ //! Create a list from five images.
+ CImgl(const CImg<T>& img1, const CImg<T>& img2, const CImg<T>& img3, const CImg<T>& img4,
+ const CImg<T>& img5):size(5),shared(false) {
+ data = new CImg<T>[allocsize=8];
+ data[0] = img1; data[1] = img2; data[2] = img3; data[3] = img4;
+ data[4] = img5;
+ }
+
+ //! In-place version of previous constructor.
+ CImgl& assign(const CImg<T>& img1, const CImg<T>& img2, const CImg<T>& img3, const CImg<T>& img4,
+ const CImg<T>& img5) {
+ return CImgl<T>(img1,img2,img3,img4,img5).swap(*this);
+ }
+
+ //! Create a list from six images.
+ CImgl(const CImg<T>& img1, const CImg<T>& img2, const CImg<T>& img3, const CImg<T>& img4,
+ const CImg<T>& img5, const CImg<T>& img6):size(6),shared(false) {
+ data = new CImg<T>[allocsize=8];
+ data[0] = img1; data[1] = img2; data[2] = img3; data[3] = img4;
+ data[4] = img5; data[5] = img6;
+ }
+
+ //! In-place version of previous constructor.
+ CImgl& assign(const CImg<T>& img1, const CImg<T>& img2, const CImg<T>& img3, const CImg<T>& img4,
+ const CImg<T>& img5, const CImg<T>& img6) {
+ return CImgl<T>(img1,img2,img3,img4,img5,img6).swap(*this);
+ }
+
+ //! Create a list from seven images.
+ CImgl(const CImg<T>& img1, const CImg<T>& img2, const CImg<T>& img3, const CImg<T>& img4,
+ const CImg<T>& img5, const CImg<T>& img6, const CImg<T>& img7):size(7),shared(false) {
+ data = new CImg<T>[allocsize=8];
+ data[0] = img1; data[1] = img2; data[2] = img3; data[3] = img4;
+ data[4] = img5; data[5] = img6; data[6] = img7;
+ }
+
+ //! In-place version of previous constructor.
+ CImgl& assign(const CImg<T>& img1, const CImg<T>& img2, const CImg<T>& img3, const CImg<T>& img4,
+ const CImg<T>& img5, const CImg<T>& img6, const CImg<T>& img7) {
+ return CImgl<T>(img1,img2,img3,img4,img5,img6,img7).swap(*this);
+ }
+
+ //! Create a list from eight images.
+ CImgl(const CImg<T>& img1, const CImg<T>& img2, const CImg<T>& img3, const CImg<T>& img4,
+ const CImg<T>& img5, const CImg<T>& img6, const CImg<T>& img7, const CImg<T>& img8):size(8),shared(false) {
+ data = new CImg<T>[allocsize=8];
+ data[0] = img1; data[1] = img2; data[2] = img3; data[3] = img4;
+ data[4] = img5; data[5] = img6; data[6] = img7; data[7] = img8;
+ }
+
+ //! In-place version of previous constructor.
+ CImgl& assign(const CImg<T>& img1, const CImg<T>& img2, const CImg<T>& img3, const CImg<T>& img4,
+ const CImg<T>& img5, const CImg<T>& img6, const CImg<T>& img7, const CImg<T>& img8) {
+ return CImgl<T>(img1,img2,img3,img4,img5,img6,img7,img8).swap(*this);
+ }
+
+ //! Create a list from nine images.
+ CImgl(const CImg<T>& img1, const CImg<T>& img2, const CImg<T>& img3, const CImg<T>& img4,
+ const CImg<T>& img5, const CImg<T>& img6, const CImg<T>& img7, const CImg<T>& img8,
+ const CImg<T>& img9):size(9),shared(false) {
+ data = new CImg<T>[allocsize=16];
+ data[0] = img1; data[1] = img2; data[2] = img3; data[3] = img4;
+ data[4] = img5; data[5] = img6; data[6] = img7; data[7] = img8;
+ data[8] = img9;
+ }
+
+ //! In-place version of previous constructor.
+ CImgl& assign(const CImg<T>& img1, const CImg<T>& img2, const CImg<T>& img3, const CImg<T>& img4,
+ const CImg<T>& img5, const CImg<T>& img6, const CImg<T>& img7, const CImg<T>& img8,
+ const CImg<T>& img9) {
+ return CImgl<T>(img1,img2,img3,img4,img5,img6,img7,img8,img9).swap(*this);
+ }
+
+ //! Create a list from ten images.
+ CImgl(const CImg<T>& img1, const CImg<T>& img2, const CImg<T>& img3, const CImg<T>& img4,
+ const CImg<T>& img5, const CImg<T>& img6, const CImg<T>& img7, const CImg<T>& img8,
+ const CImg<T>& img9, const CImg<T>& img10):size(10),shared(false) {
+ data = new CImg<T>[allocsize=16];
+ data[0] = img1; data[1] = img2; data[2] = img3; data[3] = img4;
+ data[4] = img5; data[5] = img6; data[6] = img7; data[7] = img8;
+ data[8] = img9; data[9] = img10;
+ }
+
+ //! In-place version of previous constructor.
+ CImgl& assign(const CImg<T>& img1, const CImg<T>& img2, const CImg<T>& img3, const CImg<T>& img4,
+ const CImg<T>& img5, const CImg<T>& img6, const CImg<T>& img7, const CImg<T>& img8,
+ const CImg<T>& img9, const CImg<T>& img10) {
+ return CImgl<T>(img1,img2,img3,img4,img5,img6,img7,img8,img9,img10).swap(*this);
+ }
+
+ //! Create a list from an array of CImg<t>
+ template<typename t> CImgl(const CImg<t> *const list, const unsigned int nb):shared(false) {
+ if (list && nb) {
+ data = new CImg<T>[allocsize=cimg::nearest_pow2(nb)];
+ size = nb;
+ cimgl_map(*this,l) data[l]=list[l];
+ } else { size = allocsize = 0; data = 0; }
+ }
+
+ // In-place version of the previous constructor.
+ template<typename t> CImgl& assign(const CImg<t> *const list, const unsigned int nb) {
+ return CImgl<T>(list,nb).swap(*this);
+ }
+
+ //! Create a list from an array of CImg<T>
+ CImgl(const CImg<T> *const list, const unsigned int nb, const bool shared_memory):shared(shared_memory) {
+ if (list && nb) {
+ size = nb;
+ if (shared) { data = const_cast<CImg<T>*>(list); allocsize = 0; }
+ else {
+ data = new CImg<T>[allocsize=cimg::nearest_pow2(nb)];
+ cimgl_map(*this,l) (*this)[l]=list[l];
+ }
+ } else { size = allocsize = 0; data = 0; }
+ }
+
+ // In-place version of the previous constructor.
+ template<typename t> CImgl& assign(const CImg<t> *const list, const unsigned int nb, const bool shared_memory) {
+ return CImgl<T>(list,nb,shared_memory).swap(*this);
+ }
+
+ //! Copy constructor.
+ template<typename t> CImgl& operator=(const CImgl<t>& list) {
+ if (list.data && list.size) {
+ if (shared) {
+ if (list.size==size) cimgl_map(*this,l) data[l]=list[l];
+ else throw CImgArgumentException("CImgl<%s>::operator=() : Given list (size=%u) and instance list (size=%u) must have same dimensions, "
+ "since instance list has shared-memory.",
+ pixel_type(),list.size,size);
+ } else {
+ if (list.allocsize!=allocsize) { if (data) delete[] data; data = new CImg<T>[allocsize=cimg::nearest_pow2(list.size)]; }
+ size = list.size;
+ cimgl_map(*this,l) data[l]=list[l];
+ }
+ } else {
+ if (data) delete[] data;
+ size = allocsize = 0; data = 0;
+ }
+ return *this;
+ }
+
+ //! Assignment constructor (fast version)
+ CImgl& operator=(const CImgl<T>& list) {
+ if (this!=&list) {
+ if (list.data && list.size) {
+ if (shared) {
+ if (list.size==size) cimgl_map(*this,l) data[l]=list[l];
+ else throw CImgArgumentException("CImgl<%s>::operator=() : Given list (size=%u) and instance list (size=%u) must have same dimensions, "
+ "since instance list has shared-memory.",
+ pixel_type(),list.size,size);
+ } else {
+ if (list.allocsize!=allocsize) { if (data) delete[] data; data = new CImg<T>[allocsize=cimg::nearest_pow2(list.size)]; }
+ size = list.size;
+ cimgl_map(*this,l) data[l]=list[l];
+ }
+ } else {
+ if (data) delete[] data;
+ size = allocsize = 0; data = 0;
+ }
+ }
+ return *this;
+ }
+
+ //! Destructor
+ ~CImgl() {
+ if (data && !shared) delete[] data;
+ }
+
+ //! Empty list
+ CImgl& empty() {
+ return CImgl<T>().swap(*this);
+ }
+
+ //! same as empty()
+ CImgl& clear() {
+ return empty();
+ }
+
+ //! Get an empty list
+ static CImgl get_empty() {
+ return CImgl<T>();
+ }
+
+ //@}
+ //------------------------------
+ //
+ //! \name Arithmetics operators
+ //@{
+ //------------------------------
+
+ //! Return \p true if list is empty
+ bool is_empty() const { return (!data || !size); }
+
+ //! Add each image of the current list with the corresponding image in the list \p list.
+ template<typename t> CImgl& operator+=(const CImgl<t>& list) {
+ const unsigned int sizemax = min(size,list.size);
+ for (unsigned int l=0; l<sizemax; l++) (*this)[l]+=list[l];
+ return *this;
+ }
+
+ //! Subtract each image of the current list with the corresponding image in the list \p list.
+ template<typename t> CImgl& operator-=(const CImgl<t>& list) {
+ const unsigned int sizemax = min(size,list.size);
+ for (unsigned int l=0; l<sizemax; l++) (*this)[l]-=list[l];
+ return *this;
+ }
+
+ //! Add each image of the current list with a value \p val.
+ CImgl& operator+=(const T& val) { cimgl_map(*this,l) (*this)[l]+=val; return *this; }
+
+ //! Substract each image of the current list with a value \p val.
+ CImgl& operator-=(const T& val) { cimgl_map(*this,l) (*this)[l]-=val; return *this; }
+
+ //! Multiply each image of the current list by a value \p val.
+ CImgl& operator*=(const double val) { cimgl_map(*this,l) (*this)[l]*=val; return *this; }
+
+ //! Divide each image of the current list by a value \p val.
+ CImgl& operator/=(const double val) { cimgl_map(*this,l) (*this)[l]/=val; return *this; }
+
+ //! Return a new image list corresponding to the addition of each image of the current list with a value \p val.
+ CImgl operator+(const T& val) const { return CImgl<T>(*this)+=val; }
+
+ //! Return a new image list corresponding to the multiplication of each image of the current list by a value \p val.
+ CImgl operator*(const double val) const { return CImgl<T>(*this)*=val; }
+
+ //! Return a new image list corresponding to the substraction of each image of the current list with a value \p val.
+ CImgl operator-(const T& val) const { return CImgl<T>(*this)-=val; }
+
+ //! Return a new image list corresponding to the division of each image of the current list by a value \p val.
+ CImgl operator/(const double val) const { return CImgl<T>(*this)/=val; }
+
+ //! Return a new image list corresponding to the addition of each image of the current list with the corresponding image in the list \p list.
+ CImgl operator+(const CImgl& list) const { return CImgl<T>(*this)+=list; }
+
+ //! Return a new image list corresponding to the substraction of each image of the current list with the corresponding image in the list \p list.
+ CImgl operator-(const CImgl& list) const { return CImgl<T>(*this)-=list; }
+
+ //! Return a new image list corresponding to the addition of each image of the current list with a value \p val;
+ friend CImgl operator+(const T& val, const CImgl& list) { return CImgl<T>(list)+=val; }
+
+ //! Return a new image list corresponding to the scalar multiplication of each image of the current list by a value \p val.
+ friend CImgl operator*(const double val, const CImgl& list) { return CImgl<T>(list)*=val; }
+
+ //@}
+ //-------------------------
+ //
+ //! \name List operations
+ //@{
+ //-------------------------
+
+ //! Return a reference to the i-th element of the image list.
+ CImg<T>& operator[](const unsigned int pos) {
+#if cimg_debug>1
+ if (pos>=size) {
+ cimg::warn(true,"CImgl<%s>::operator[] : bad list position %u, in a list of %u images",pixel_type(),pos,size);
+ return *data;
+ }
+#endif
+ return data[pos];
+ }
+
+ const CImg<T>& operator[](const unsigned int pos) const {
+#if cimg_debug>1
+ if (pos>=size) {
+ cimg::warn(true,"CImgl<%s>::operator[] : bad list position %u, in a list of %u images",pixel_type(),pos,size);
+ return *data;
+ }
+#endif
+ return data[pos];
+ }
+
+ //! Equivalent to CImgl<T>::operator[]
+ CImg<T>& operator()(const unsigned int pos) { return (*this)[pos]; }
+ const CImg<T>& operator()(const unsigned int pos) const { return (*this)[pos]; }
+
+ //! Return a reference to (x,y,z,v) pixel of the pos-th image of the list
+ T& operator()(const unsigned int pos, const unsigned int x, const unsigned int y=0,
+ const unsigned int z=0, const unsigned int v=0) {
+ return (*this)[pos](x,y,z,v);
+ }
+ const T& operator()(const unsigned int pos, const unsigned int x, const unsigned int y=0,
+ const unsigned int z=0, const unsigned int v=0) const {
+ return (*this)[pos](x,y,z,v);
+ }
+
+ //! Equivalent to CImgl<T>::operator[], with boundary checking
+ CImg<T>& at(const unsigned int pos) {
+ if (pos>=size)
+ throw CImgArgumentException("CImgl<%s>::at() : bad list position %u, in a list of %u images",
+ pixel_type(),pos,size);
+ return data[pos];
+ }
+
+ const CImg<T>& at(const unsigned int pos) const {
+ if (pos>=size)
+ throw CImgArgumentException("CImgl<%s>::at() : bad list position %u, in a list of %u images",
+ pixel_type(),pos,size);
+ return data[pos];
+ }
+
+ //! Returns a reference to last element
+ CImg<T>& back() { return (*this)(size-1); }
+ const CImg<T>& back() const { return (*this)(size-1); }
+
+ //! Returns a reference to the first element
+ CImg<T>& front() { return *data; }
+ const CImg<T>& front() const { return *data; }
+
+ //! Returns an iterator to the beginning of the vector.
+ iterator begin() { return data; }
+ const_iterator begin() const { return data; }
+
+ //! Returns an iterator just past the last element.
+ iterator end() { return data + size; }
+ const_iterator end() const { return data + size; }
+
+ //! Insert a copy of the image \p img into the current image list, at position \p pos.
+ CImgl& insert(const CImg<T>& img,const unsigned int pos) {
+ if (shared)
+ throw CImgInstanceException("CImgl<%s>::insert() : Insertion in a shared list is not possible",pixel_type());
+ if (pos>size)
+ throw CImgArgumentException("CImgl<%s>::insert() : Can't insert at position %u into a list with %u elements",
+ pixel_type(),pos,size);
+ CImg<T> *new_data = (++size>allocsize)?new CImg<T>[allocsize?(allocsize<<=1):(allocsize=1)]:NULL;
+ if (!size || !data) { data=new_data; *data=img; }
+ else {
+ if (new_data) { // Insert with reallocation
+ if (pos) std::memcpy(new_data,data,sizeof(CImg<T>)*pos);
+ if (pos!=size-1) std::memcpy(new_data+pos+1,data+pos,sizeof(CImg<T>)*(size-1-pos));
+ std::memset(data,0,sizeof(CImg<T>)*(size-1));
+ delete[] data;
+ data = new_data;
+ }
+ else if (pos!=size-1) memmove(data+pos+1,data+pos,sizeof(CImg<T>)*(size-1-pos));
+ data[pos].width = data[pos].height = data[pos].depth = data[pos].dim = 0; data[pos].data = NULL;
+ data[pos] = img;
+ }
+ return *this;
+ }
+
+ //! Insert n copies of the image \p img into the current image list, at position \p pos.
+ CImgl& insert(const unsigned int n, const CImg<T>& img, const unsigned int pos) {
+ for (unsigned int i=0; i<n; i++) insert(img,pos);
+ return *this;
+ }
+
+ //! Insert a copy of the image \p img at the current image list.
+ CImgl& insert(const CImg<T>& img) { return insert(img,size); }
+
+ //! Insert n copies of the image \p img at the end of the list.
+ CImgl& insert(const unsigned int n, const CImg<T>& img) {
+ for (unsigned int i=0; i<n; i++) insert(img);
+ return *this;
+ }
+
+ //! Insert image \p img at the end of the list.
+ CImgl& push_back(const CImg<T>& img) { return insert(img); }
+
+ //! Insert image \p img at the front of the list.
+ CImgl& push_front(const CImg<T>& img) { return insert(img,0); }
+
+ //! Insert a copy of the image list \p list into the current image list, starting from position \p pos.
+ CImgl& insert(const CImgl<T>& list,const unsigned int pos) {
+ if (this!=&list) cimgl_map(list,l) insert(list[l],pos+l);
+ else insert(CImgl<T>(list),pos);
+ return *this;
+ }
+
+ //! Insert n copies of the list \p list at position \p pos of the current list.
+ CImgl& insert(const unsigned int n, const CImgl<T>& list, const unsigned int pos) {
+ for (unsigned int i=0; i<n; i++) insert(list,pos);
+ return *this;
+ }
+
+ //! Append a copy of the image list \p list at the current image list.
+ CImgl& insert(const CImgl<T>& list) { return insert(list,size); }
+
+ //! Insert n copies of the list at the end of the current list
+ CImgl& insert(const unsigned int n, const CImgl<T>& list) {
+ for (unsigned int i=0; i<n; i++) insert(list);
+ return *this;
+ }
+
+ //! Insert list \p list at the end of the current list.
+ CImgl& push_back(const CImgl<T>& list) { return insert(list); }
+
+ //! Insert list \p list at the front of the current list.
+ CImgl& push_front(const CImgl<T>& list) { return insert(list,0); }
+
+ //! Remove the image at position \p pos from the image list.
+ CImgl& remove(const unsigned int pos) {
+ if (shared)
+ throw CImgInstanceException("CImgl<%s>::remove() : Removing from a shared list is not allowed.",pixel_type());
+ if (pos>=size)
+ cimg::warn(true,"CImgl<%s>::remove() : Cannot remove an image from a list (%p,%u), at position %u.",
+ pixel_type(),data,size,pos);
+ else {
+ data[pos].empty();
+ if (!(--size)) return empty();
+ if (size<8 || size>(allocsize>>2)) { // Removing item without reallocation.
+ if (pos!=size) {
+ std::memmove(data+pos,data+pos+1,sizeof(CImg<T>)*(size-pos));
+ CImg<T> &tmp = data[size];
+ tmp.width = tmp.height = tmp.depth = tmp.dim = 0; tmp.data = 0;
+ }
+ } else { // Removing item with reallocation.
+ allocsize>>=2;
+ CImg<T> *new_data = new CImg<T>[allocsize];
+ if (pos) std::memcpy(new_data,data,sizeof(CImg<T>)*pos);
+ if (pos!=size) std::memcpy(new_data+pos,data+pos+1,sizeof(CImg<T>)*(size-pos));
+ std::memset(data,0,sizeof(CImg<T>)*(size+1));
+ delete[] data;
+ data = new_data;
+ }
+ }
+ return *this;
+ }
+
+ //! Remove last element of the list;
+ CImgl& pop_back() { return remove(size-1); }
+
+ //! Remove first element of the list;
+ CImgl& pop_front() { return remove(0); }
+
+ //! Remove the element pointed by iterator \p iter;
+ CImgl& erase(const iterator iter) { return remove(iter-data); }
+
+ //! Remove the last image from the image list.
+ CImgl& remove() {
+ if (size) return remove(size-1);
+ else cimg::warn(true,"CImgl<%s>::remove() : List is empty",pixel_type());
+ return *this;
+ }
+
+ //! Reverse list order
+ CImgl& reverse() {
+ for (unsigned int l=0; l<size/2; l++) (*this)[l].swap((*this)[size-1-l]);
+ return *this;
+ }
+
+ //! Get reversed list
+ CImgl& get_reverse() const { return CImgl<T>(*this).reverse(); }
+
+ //! Insert image at the end of the list
+ CImgl& operator<<(const CImg<T>& img) {
+ return insert(img);
+ }
+
+ //! Remove last image of the list
+ CImgl& operator>>(CImg<T>& img) {
+ if (size) { img = (*this)[size-1]; return remove(size-1); }
+ cimg::warn(true,"CImgl<%s>::operator>>() : List is empty",pixel_type());
+ img.empty();
+ return *this;
+ }
+
+ //@}
+ //----------------------------
+ //
+ //! \name Fourier transforms
+ //@{
+ //----------------------------
+
+ //! Compute the Fast Fourier Transform (along the specified axis).
+ CImgl& FFT(const char axe, const bool inverse=false) {
+ if (size<2) throw CImgInstanceException("CImg<%s>::FFT() : Instance list have less than 2 images",pixel_type());
+ CImg<T> &Ir = data[0], &Ii = data[1];
+ if (Ir.is_empty())
+ throw CImgInstanceException("CImg<%s>::FFT() : Real part (first image of the instance list) is empty.",pixel_type());
+ if (Ii.is_empty())
+ throw CImgInstanceException("CImg<%s>::FFT() : Imaginary part (second image of the instance list) is empty.",pixel_type());
+ if (Ir.width!=Ii.width || Ir.height!=Ii.height || Ir.depth!=Ii.depth || Ir.dim!=Ii.dim)
+ throw CImgInstanceException("CImg<%s>::FFT() : Real and Imaginary parts of the instance have different dimensions",pixel_type());
+
+ switch (cimg::uncase(axe)) {
+ case 'x': { // Fourier along X
+ const unsigned int N = Ir.width, N2 = (N>>1);
+ if (((N-1)&N) && N!=1) throw CImgInstanceException("CImg<%s>::FFT() : Dimension of instance image along 'x' is %d != 2^N",
+ pixel_type(),N);
+ for (unsigned int i=0,j=0; i<N2; i++) {
+ if (j>i) cimg_mapYZV(Ir,y,z,v) { cimg::swap(Ir(i,y,z,v),Ir(j,y,z,v)); cimg::swap(Ii(i,y,z,v),Ii(j,y,z,v));
+ if (j<N2) {
+ const unsigned int ri = N-1-i, rj = N-1-j;
+ cimg::swap(Ir(ri,y,z,v),Ir(rj,y,z,v)); cimg::swap(Ii(ri,y,z,v),Ii(rj,y,z,v));
+ }}
+ for (unsigned int m=N, n=N2; (j+=n)>=m; j-=m, m=n, n>>=1);
+ }
+ for (unsigned int delta=2; delta<=N; delta<<=1) {
+ const unsigned int delta2 = (delta>>1);
+ for (unsigned int i=0; i<N; i+=delta) {
+ float wr = 1, wi = 0;
+ const float angle = (float)((inverse?+1:-1)*2*cimg::PI/delta),
+ ca = (float)std::cos(angle),
+ sa = (float)std::sin(angle);
+ for (unsigned int k=0; k<delta2; k++) {
+ const unsigned int j = i + k, nj = j + delta2;
+ cimg_mapYZV(Ir,y,z,k) {
+ T &ir = Ir(j,y,z,k), &ii = Ii(j,y,z,k), &nir = Ir(nj,y,z,k), &nii = Ii(nj,y,z,k);
+ const T tmpr = wr*nir - wi*nii, tmpi = wr*nii + wi*nir;
+ nir = ir - tmpr; nii = ii - tmpi;
+ ir += tmpr; ii += tmpi;
+ }
+ const float nwr = wr*ca-wi*sa;
+ wi = wi*ca + wr*sa;
+ wr = nwr;
+ }
+ }
+ }
+ if (inverse) (*this)/=N;
+ } break;
+
+ case 'y': { // Fourier along Y
+ const unsigned int N = Ir.height, N2 = (N>>1);
+ if (((N-1)&N) && N!=1) throw CImgInstanceException("CImg<%s>::FFT() : Dimension of instance image(s) along 'y' is %d != 2^N",
+ pixel_type(),N);
+ for (unsigned int i=0,j=0; i<N2; i++) {
+ if (j>i) cimg_mapXZV(Ir,x,z,v) { cimg::swap(Ir(x,i,z,v),Ir(x,j,z,v)); cimg::swap(Ii(x,i,z,v),Ii(x,j,z,v));
+ if (j<N2) {
+ const unsigned int ri = N-1-i, rj = N-1-j;
+ cimg::swap(Ir(x,ri,z,v),Ir(x,rj,z,v)); cimg::swap(Ii(x,ri,z,v),Ii(x,rj,z,v));
+ }}
+ for (unsigned int m=N, n=N2; (j+=n)>=m; j-=m, m=n, n>>=1);
+ }
+ for (unsigned int delta=2; delta<=N; delta<<=1) {
+ const unsigned int delta2 = (delta>>1);
+ for (unsigned int i=0; i<N; i+=delta) {
+ float wr = 1, wi = 0;
+ const float angle = (float)((inverse?+1:-1)*2*cimg::PI/delta),
+ ca = (float)std::cos(angle), sa = (float)std::sin(angle);
+ for (unsigned int k=0; k<delta2; k++) {
+ const unsigned int j = i + k, nj = j + delta2;
+ cimg_mapXZV(Ir,x,z,k) {
+ T &ir = Ir(x,j,z,k), &ii = Ii(x,j,z,k), &nir = Ir(x,nj,z,k), &nii = Ii(x,nj,z,k);
+ const T tmpr = wr*nir - wi*nii, tmpi = wr*nii + wi*nir;
+ nir = ir - tmpr; nii = ii - tmpi;
+ ir += tmpr; ii += tmpi;
+ }
+ const float nwr = wr*ca-wi*sa;
+ wi = wi*ca + wr*sa;
+ wr = nwr;
+ }
+ }
+ }
+ if (inverse) (*this)/=N;
+ } break;
+
+ case 'z': { // Fourier along Z
+ const unsigned int N = Ir.depth, N2 = (N>>1);
+ if (((N-1)&N) && N!=1) throw CImgInstanceException("CImg<%s>::FFT() : Dimension of instance image(s) along 'z' is %d != 2^N",
+ pixel_type(),N);
+ for (unsigned int i=0,j=0; i<N2; i++) {
+ if (j>i) cimg_mapXYV(Ir,x,y,v) { cimg::swap(Ir(x,y,i,v),Ir(x,y,j,v)); cimg::swap(Ii(x,y,i,v),Ii(x,y,j,v));
+ if (j<N2) {
+ const unsigned int ri = N-1-i, rj = N-1-j;
+ cimg::swap(Ir(x,y,ri,v),Ir(x,y,rj,v)); cimg::swap(Ii(x,y,ri,v),Ii(x,y,rj,v));
+ }}
+ for (unsigned int m=N, n=N2; (j+=n)>=m; j-=m, m=n, n>>=1);
+ }
+ for (unsigned int delta=2; delta<=N; delta<<=1) {
+ const unsigned int delta2 = (delta>>1);
+ for (unsigned int i=0; i<N; i+=delta) {
+ float wr = 1, wi = 0;
+ const float angle = (float)((inverse?+1:-1)*2*cimg::PI/delta),
+ ca = (float)std::cos(angle), sa = (float)std::sin(angle);
+ for (unsigned int k=0; k<delta2; k++) {
+ const unsigned int j = i + k, nj = j + delta2;
+ cimg_mapXYV(Ir,x,y,k) {
+ T &ir = Ir(x,y,j,k), &ii = Ii(x,y,j,k), &nir = Ir(x,y,nj,k), &nii = Ii(x,y,nj,k);
+ const T tmpr = wr*nir - wi*nii, tmpi = wr*nii + wi*nir;
+ nir = ir - tmpr; nii = ii - tmpi;
+ ir += tmpr; ii += tmpi;
+ }
+ const float nwr = wr*ca-wi*sa;
+ wi = wi*ca + wr*sa;
+ wr = nwr;
+ }
+ }
+ }
+ if (inverse) (*this)/=N;
+ } break;
+
+ default: throw CImgArgumentException("CImg<%s>::FFT() : unknown axe '%c', must be 'x','y' or 'z'");
+ }
+ return *this;
+ }
+
+ //! Compute the Fast Fourier Transform of a complex image.
+ CImgl& FFT(const bool inverse=false) {
+ if (size<2) throw CImgInstanceException("CImg<%s>::FFT() : Instance have less than 2 images",pixel_type());
+ CImg<T> &Ir = data[0];
+ if (Ir.depth>1) FFT('z',inverse);
+ if (Ir.height>1) FFT('y',inverse);
+ if (Ir.width>1) FFT('x',inverse);
+ return *this;
+ }
+
+ //! Return the Fast Fourier Transform of a complex image
+ CImgl<typename cimg::largest<T,float>::type> get_FFT(const bool inverse=false) const {
+ typedef typename cimg::largest<T,float>::type restype;
+ return CImgl<restype>(*this).FFT(inverse);
+ }
+
+ //! Return the Fast Fourier Transform of a complex image (along a specified axis).
+ CImgl<typename cimg::largest<T,float>::type> get_FFT(const char axe,const bool inverse=false) const {
+ typedef typename cimg::largest<T,float>::type restype;
+ return CImgl<restype>(*this).FFT(axe,inverse);
+ }
+
+ //@}
+ //----------------------------------
+ //
+ //! \name IO and display functions
+ //@{
+ //----------------------------------
+
+ //! Print informations about the list on the standard error stream.
+ const CImgl& print(const char* title=NULL,const int print_flag=1) const {
+ char tmp[1024];
+ std::fprintf(stderr,"%-8s(this=%p) : { size=%u, data=%p (%s) }\n",title?title:"CImgl",
+ (void*)this,size,(void*)data,shared?"shared":"not shared");
+ if (print_flag>0) cimgl_map(*this,l) {
+ std::sprintf(tmp,"%s[%d]",title?title:"CImgl",l);
+ data[l].print(tmp,print_flag);
+ }
+ return *this;
+ }
+
+ //! Load an image list from a file.
+ static CImgl get_load(const char *filename) {
+ CImgl res;
+ const char *ext = cimg::filename_split(filename);
+ if (!cimg::strcasecmp(ext,"cimg") || !ext[0]) return get_load_cimg(filename);
+ if (!cimg::strcasecmp(ext,"rec") || !cimg::strcasecmp(ext,"par")) return get_load_parrec(filename);
+ return CImg<T>(filename);
+ }
+
+ //! In-place version of load().
+ CImgl& load(const char* filename) { return get_load(filename).swap(*this); }
+
+#define cimg_load_cimg_case(Ts,Tss) \
+ if (!loaded && !cimg::strcasecmp(Ts,tmp2)) for (unsigned int l=0; l<n; l++) { \
+ const bool endian = cimg::endian(); \
+ j=0; while((i=std::fgetc(file))!='\n') tmp[j++]=(char)i; tmp[j]='\0'; \
+ std::sscanf(tmp,"%u %u %u %u",&w,&h,&z,&k);\
+ if (w*h*z*k>0) { \
+ Tss *buf = new Tss[w*h*z*k]; cimg::fread(buf,w*h*z*k,file); \
+ if (endian) cimg::endian_swap(buf,w*h*z*k); \
+ CImg<T> idest(w,h,z,k); cimg_mapoff(idest,off) \
+ idest[off] = (T)(buf[off]); idest.swap(res[l]); \
+ delete[] buf; \
+ } \
+ loaded = true; \
+ }
+
+ //! Load an image list from a file (.raw format).
+ static CImgl get_load_cimg(const char *filename) {
+ typedef unsigned char uchar;
+ typedef unsigned short ushort;
+ typedef unsigned int uint;
+ typedef unsigned long ulong;
+ std::FILE *file = cimg::fopen(filename,"rb");
+ char tmp[256],tmp2[256];
+ int i;
+ bool loaded = false;
+ unsigned int n,j,w,h,z,k,err;
+ j=0; while((i=std::fgetc(file))!='\n' && i!=EOF && j<256) tmp[j++]=i; tmp[j]='\0';
+ err=std::sscanf(tmp,"%u%*c%255[A-Za-z ]",&n,tmp2);
+ if (err!=2) throw CImgIOException("CImgl<%s>::get_load_cimg() : file '%s', Unknow CImg RAW header",pixel_type(),filename);
+ CImgl<T> res(n);
+ cimg_load_cimg_case("unsigned char",uchar);
+ cimg_load_cimg_case("uchar",uchar);
+ cimg_load_cimg_case("char",char);
+ cimg_load_cimg_case("unsigned short",ushort);
+ cimg_load_cimg_case("ushort",ushort);
+ cimg_load_cimg_case("short",short);
+ cimg_load_cimg_case("unsigned int",uint);
+ cimg_load_cimg_case("uint",uint);
+ cimg_load_cimg_case("int",int);
+ cimg_load_cimg_case("unsigned long",ulong);
+ cimg_load_cimg_case("ulong",ulong);
+ cimg_load_cimg_case("long",long);
+ cimg_load_cimg_case("float",float);
+ cimg_load_cimg_case("double",double);
+ if (!loaded) throw CImgIOException("CImgl<%s>::get_load_cimg() : file '%s', can't read images of %s",
+ pixel_type(),filename,tmp2);
+ cimg::fclose(file);
+ return res;
+ }
+
+ //! In-place version of get_load_cimg().
+ CImgl& load_cimg(const char *filename) { return get_load_cimg(filename).swap(*this); }
+
+ //! Load PAR-REC (Philips) image file
+ static CImgl get_load_parrec(const char *filename) {
+ char body[1024], filenamepar[1024], filenamerec[1024];
+ const char *ext = cimg::filename_split(filename,body);
+ if (!cimg::strncmp(ext,"par",3)) { std::strcpy(filenamepar,filename); std::sprintf(filenamerec,"%s.rec",body); }
+ if (!cimg::strncmp(ext,"PAR",3)) { std::strcpy(filenamepar,filename); std::sprintf(filenamerec,"%s.REC",body); }
+ if (!cimg::strncmp(ext,"rec",3)) { std::strcpy(filenamerec,filename); std::sprintf(filenamepar,"%s.par",body); }
+ if (!cimg::strncmp(ext,"REC",3)) { std::strcpy(filenamerec,filename); std::sprintf(filenamepar,"%s.PAR",body); }
+ std::FILE *file = cimg::fopen(filenamepar,"r");
+
+ // Parse header file
+ CImgl<float> st_slices;
+ CImgl<unsigned int> st_global;
+ int err;
+ char line[256]={0};
+ do { err=std::fscanf(file,"%255[^\n]%*c",line); } while (err!=EOF && (line[0]=='#' || line[0]=='.'));
+ do {
+ unsigned int sn,sizex,sizey,pixsize;
+ float rs,ri,ss;
+ err=std::fscanf(file,"%u%*u%*u%*u%*u%*u%*u%u%*u%u%u%g%g%g%*[^\n]",&sn,&pixsize,&sizex,&sizey,&ri,&rs,&ss);
+ if (err==7) {
+ st_slices.insert(CImg<float>::vector((float)sn,(float)pixsize,(float)sizex,(float)sizey,ri,rs,ss,0));
+ unsigned int i; for (i=0; i<st_global.size && sn<=st_global[i][2]; i++);
+ if (i==st_global.size) st_global.insert(CImg<unsigned int>::vector(sizex,sizey,sn));
+ else {
+ CImg<unsigned int> &vec = st_global[i];
+ if (sizex>vec[0]) vec[0] = sizex;
+ if (sizey>vec[1]) vec[1] = sizey;
+ vec[2] = sn;
+ }
+ st_slices[st_slices.size-1][7] = (float)i;
+ }
+ } while (err==7);
+
+ // Read data
+ std::FILE *file2 = cimg::fopen(filenamerec,"rb");
+ CImgl<T> dest;
+ { cimgl_map(st_global,l) {
+ const CImg<unsigned int>& vec = st_global[l];
+ dest.insert(CImg<T>(vec[0],vec[1],vec[2]));
+ }}
+
+ cimgl_map(st_slices,l) {
+ const CImg<float>& vec = st_slices[l];
+ const unsigned int
+ sn = (unsigned int)vec[0]-1,
+ pixsize = (unsigned int)vec[1],
+ sizex = (unsigned int)vec[2],
+ sizey = (unsigned int)vec[3],
+ imn = (unsigned int)vec[7];
+ const float ri = vec[4], rs = vec[5], ss = vec[6];
+ switch (pixsize) {
+ case 8: {
+ CImg<unsigned char> buf(sizex,sizey);
+ cimg::fread(buf.data,sizex*sizey,file2);
+ if (cimg::endian()) cimg::endian_swap(buf.data,sizex*sizey);
+ CImg<T>& img = dest[imn];
+ cimg_mapXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss));
+ } break;
+ case 16: {
+ CImg<unsigned short> buf(sizex,sizey);
+ cimg::fread(buf.data,sizex*sizey,file2);
+ if (cimg::endian()) cimg::endian_swap(buf.data,sizex*sizey);
+ CImg<T>& img = dest[imn];
+ cimg_mapXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss));
+ } break;
+ case 32: {
+ CImg<unsigned int> buf(sizex,sizey);
+ cimg::fread(buf.data,sizex*sizey,file2);
+ if (cimg::endian()) cimg::endian_swap(buf.data,sizex*sizey);
+ CImg<T>& img = dest[imn];
+ cimg_mapXY(img,x,y) img(x,y,sn) = (T)(( buf(x,y)*rs + ri )/(rs*ss));
+ } break;
+ default:
+ throw CImgIOException("CImg<%s>::get_load_parrec() : Cannot handle image with pixsize = %d bits\n",
+ pixel_type(),pixsize);
+
+ }
+ }
+
+ cimg::fclose(file);
+ cimg::fclose(file2);
+ if (!dest.size)
+ throw CImgIOException("CImg<%s>::get_load_parrec() : filename '%s' does not appear to be a valid PAR-REC file",
+ pixel_type(),filename);
+ return dest;
+ }
+
+ //! In-place version of get_load_parrec().
+ CImgl& load_parrec(const char *filename) { return get_load_parrec(filename).swap(*this); }
+
+ //! Load YUV image sequence.
+ static CImgl get_load_yuv(const char *filename,
+ const unsigned int sizex, const unsigned int sizey,
+ const unsigned int first_frame=0, const int last_frame=-1,
+ const bool yuv2rgb=true) {
+
+ if (sizex%2 || sizey%2)
+ throw CImgArgumentException("CImgl<%s>::get_load_yuv() : Image dimensions along X and Y must be even (given are %ux%u)\n",
+ pixel_type(),sizex,sizey);
+ if (!sizex || !sizey)
+ throw CImgArgumentException("CImgl<%s>::get_load_yuv() : Given image sequence size (%u,%u) is invalid",
+ pixel_type(),sizex,sizey);
+ if (last_frame>0 && first_frame>(unsigned int)last_frame)
+ throw CImgArgumentException("CImgl<%s>::get_load_yuv() : Given first frame %u is posterior to last frame %d.",
+ pixel_type(),first_frame,last_frame);
+ if (!sizex || !sizey)
+ throw CImgArgumentException("CImgl<%s>::get_load_yuv() : Given frame size (%u,%u) is invalid.",
+ pixel_type(),sizex,sizey);
+ CImgl<T> res;
+ CImg<unsigned char> tmp(sizex,sizey,1,3), UV(sizex/2,sizey/2,1,2);
+ std::FILE *file = cimg::fopen(filename,"rb");
+ bool stopflag = false;
+ int err;
+ if (first_frame) {
+ err = std::fseek(file,first_frame*(sizex*sizey + sizex*sizey/2),SEEK_CUR);
+ if (err) throw CImgIOException("CImgl<%s>::get_load_yuv() : File '%s' doesn't contain frame number %u "
+ "(out of range error).",pixel_type(),filename,first_frame);
+ }
+ unsigned int frame;
+ for (frame = first_frame; !stopflag && (last_frame<0 || frame<=(unsigned int)last_frame); frame++) {
+ tmp.fill(0);
+ // TRY to read the luminance, don't replace by cimg::fread !
+ err = (int)std::fread((void*)(tmp.ptr()),1,(size_t)(tmp.width*tmp.height),file);
+ if (err!=(int)(tmp.width*tmp.height)) {
+ stopflag = true;
+ cimg::warn(err>0,"CImgl<%s>::get_load_yuv() : File '%s' contains incomplete data,"
+ " or given image dimensions (%u,%u) are incorrect.",pixel_type(),filename,sizex,sizey);
+ } else {
+ UV.fill(0);
+ // TRY to read the luminance, don't replace by cimg::fread !
+ err = (int)std::fread((void*)(UV.ptr()),1,(size_t)(UV.size()),file);
+ if (err!=(int)(UV.size())) {
+ stopflag = true;
+ cimg::warn(err>0,"CImgl<%s>::get_load_yuv() : File '%s' contains incomplete data,"
+ " or given image dimensions (%u,%u) are incorrect.",pixel_type(),filename,sizex,sizey);
+ } else {
+ cimg_mapXY(UV,x,y) {
+ const int x2=2*x, y2=2*y;
+ tmp(x2,y2,1) = tmp(x2+1,y2,1) = tmp(x2,y2+1,1) = tmp(x2+1,y2+1,1) = UV(x,y,0);
+ tmp(x2,y2,2) = tmp(x2+1,y2,2) = tmp(x2,y2+1,2) = tmp(x2+1,y2+1,2) = UV(x,y,1);
+ }
+ if (yuv2rgb) tmp.YCbCrtoRGB();
+ res.insert(tmp);
+ }
+ }
+ }
+ cimg::warn(stopflag && last_frame>=0 && frame!=(unsigned int)last_frame,
+ "CImgl<%s>::get_load_yuv() : Frame %d not reached, only %u frames found in the file '%s'.",
+ pixel_type(),last_frame,frame-1,filename);
+ return res;
+ }
+
+ //! In-place version of get_load_yuv().
+ CImgl& load_yuv(const char *filename,
+ const unsigned int sizex, const unsigned int sizey,
+ const unsigned int first_frame=0, const int last_frame=-1,
+ const bool yuv2rgb=true) {
+ return get_load_yuv(filename,sizex,sizey,first_frame,last_frame,yuv2rgb).swap(*this);
+ }
+
+ //! Save an image sequence into a YUV file
+ const CImgl& save_yuv(const char *filename, const bool rgb2yuv=true) const {
+ if (is_empty())
+ throw CImgInstanceException("CImgl<%s>::save_yuv() : Instance list (%u,%p) is empty.",
+ pixel_type(),size,data);
+ if (!filename)
+ throw CImgArgumentException("CImgl<%s>::save_yuv() : Specified filename is (null).",
+ pixel_type());
+ if ((*this)[0].dimx()%2 || (*this)[0].dimy()%2)
+ throw CImgInstanceException("CImgl<%s>::save_yuv() : Image dimensions along X and Y must be even (current are %ux%u)\n",
+ pixel_type(),(*this)[0].dimx(),(*this)[0].dimy());
+
+ std::FILE *file = cimg::fopen(filename,"wb");
+ cimgl_map(*this,l) {
+ CImg<unsigned char> YCbCr((*this)[l]);
+ if (rgb2yuv) YCbCr.RGBtoYCbCr();
+ cimg::fwrite(YCbCr.ptr(),YCbCr.width*YCbCr.height,file);
+ cimg::fwrite(YCbCr.get_resize(YCbCr.width/2, YCbCr.height/2,1,3,3).ptr(0,0,0,1),
+ YCbCr.width*YCbCr.height/2,file);
+ }
+ cimg::fclose(file);
+ return *this;
+ }
+
+ //! Save an image list into a file.
+ /**
+ Depending on the extension of the given filename, a file format is chosen for the output file.
+ **/
+ const CImgl& save(const char *filename) const {
+ if (is_empty()) throw CImgInstanceException("CImgl<%s>::save() : Instance list (%u,%p) is empty.",
+ pixel_type(),size,data);
+ if (!filename) throw CImgArgumentException("CImgl<%s>::save() : Specified filename is (null).",pixel_type());
+ const char *ext = cimg::filename_split(filename);
+ if (!cimg::strcasecmp(ext,"cimg") || !ext[0]) return save_cimg(filename);
+ if (!cimg::strcasecmp(ext,"yuv")) return save_yuv(filename,true);
+ if (size==1) data[0].save(filename,-1);
+ else cimgl_map(*this,l) data[l].save(filename,l);
+ return *this;
+ }
+
+ //! Save an image list into a CImg RAW file.
+ /**
+ A CImg RAW file is a simple uncompressed binary file that may be used to save list of CImg<T> images.
+ \param filename : name of the output file.
+ \return A reference to the current CImgl instance is returned.
+ **/
+ const CImgl& save_cimg(const char *filename) const {
+ if (is_empty()) throw CImgInstanceException("CImgl<%s>::save_cimg() : Instance list (%u,%p) is empty.",
+ pixel_type(),size,data);
+ if (!filename) throw CImgArgumentException("CImgl<%s>::save_cimg() : Specified filename is (null).",
+ pixel_type());
+ std::FILE *file = cimg::fopen(filename,"wb");
+ std::fprintf(file,"%u %s\n",size,pixel_type());
+ cimgl_map(*this,l) {
+ const CImg<T>& img = data[l];
+ std::fprintf(file,"%u %u %u %u\n",img.width,img.height,img.depth,img.dim);
+ if (img.data) {
+ if (cimg::endian()) {
+ CImg<T> tmp(img);
+ cimg::endian_swap(tmp.data,tmp.size());
+ cimg::fwrite(tmp.data,img.width*img.height*img.depth*img.dim,file);
+ } else cimg::fwrite(img.data,img.width*img.height*img.depth*img.dim,file);
+ }
+ }
+ cimg::fclose(file);
+ return *this;
+ }
+
+
+ //! Load from OFF file format
+ template<typename tf,typename tc>
+ static CImgl<T> get_load_off(const char *filename, CImgl<tf>& primitives, CImgl<tc>& colors, const bool invert_faces=false) {
+ return CImg<T>::get_load_off(filename,primitives,colors,invert_faces).get_split('x');
+ }
+
+ //! In-place version of get_load_off()
+ template<typename tf,typename tc>
+ CImgl& load_off(const char *filename, CImgl<tf>& primitives, CImgl<tc>& colors, const bool invert_faces=false) {
+ return get_load_off(filename,primitives,colors,invert_faces).swap(*this);
+ }
+
+ //! Save an image list into a OFF file.
+ template<typename tf, typename tc>
+ const CImgl& save_off(const char *filename, const CImgl<tf>& primitives, const CImgl<tc>& colors, const bool invert_faces=false) const {
+ get_append('x').save_off(filename,primitives,colors,invert_faces);
+ return *this;
+ }
+
+ //! Return a single image which is the concatenation of all images of the current CImgl instance.
+ /**
+ \param axe : specify the axe for image concatenation. Can be 'x','y','z' or 'v'.
+ \param align : specify the tqalignment for image concatenation. Can be 'p' (top), 'c' (center) or 'n' (bottom).
+ \return A CImg<T> image corresponding to the concatenation is returned.
+ **/
+ CImg<T> get_append(const char axe='x',const char align='c') const {
+ if (is_empty()) return CImg<T>();
+ unsigned int dx=0,dy=0,dz=0,dv=0,pos=0;
+ CImg<T> res;
+ switch(cimg::uncase(axe)) {
+ case 'x': {
+ cimgl_map(*this,l) {
+ const CImg<T>& img = (*this)[l];
+ dx += img.width;
+ dy = cimg::max(dy,img.height);
+ dz = cimg::max(dz,img.depth);
+ dv = cimg::max(dv,img.dim);
+ }
+ res.assign(dx,dy,dz,dv,0);
+ switch (cimg::uncase(align)) {
+ case 'p' : { cimgl_map(*this,ll) { res.draw_image((*this)[ll],pos,0,0,0); pos+=(*this)[ll].width; }} break;
+ case 'n' : { cimgl_map(*this,ll) {
+ res.draw_image((*this)[ll],pos,dy-(*this)[ll].height,dz-(*this)[ll].depth,dv-(*this)[ll].dim); pos+=(*this)[ll].width;
+ }} break;
+ default : { cimgl_map(*this,ll) {
+ res.draw_image((*this)[ll],pos,(dy-(*this)[ll].height)/2,(dz-(*this)[ll].depth)/2,(dv-(*this)[ll].dim)/2);
+ pos+=(*this)[ll].width;
+ }} break;
+ }
+ } break;
+ case 'y': {
+ cimgl_map(*this,l) {
+ const CImg<T>& img = (*this)[l];
+ dx = cimg::max(dx,img.width);
+ dy += img.height;
+ dz = cimg::max(dz,img.depth);
+ dv = cimg::max(dv,img.dim);
+ }
+ res.assign(dx,dy,dz,dv,0);
+ switch (cimg::uncase(align)) {
+ case 'p': { cimgl_map(*this,ll) { res.draw_image((*this)[ll],0,pos,0,0); pos+=(*this)[ll].height; }} break;
+ case 'n': { cimgl_map(*this,ll) {
+ res.draw_image((*this)[ll],dx-(*this)[ll].width,pos,dz-(*this)[ll].depth,dv-(*this)[ll].dim); pos+=(*this)[ll].height;
+ }} break;
+ default : { cimgl_map(*this,ll) {
+ res.draw_image((*this)[ll],(dx-(*this)[ll].width)/2,pos,(dz-(*this)[ll].depth)/2,(dv-(*this)[ll].dim)/2);
+ pos+=(*this)[ll].height;
+ }} break;
+ }
+ } break;
+ case 'z': {
+ cimgl_map(*this,l) {
+ const CImg<T>& img = (*this)[l];
+ dx = cimg::max(dx,img.width);
+ dy = cimg::max(dy,img.height);
+ dz += img.depth;
+ dv = cimg::max(dv,img.dim);
+ }
+ res.assign(dx,dy,dz,dv,0);
+ switch (cimg::uncase(align)) {
+ case 'p': { cimgl_map(*this,ll) { res.draw_image((*this)[ll],0,0,pos,0); pos+=(*this)[ll].depth; }} break;
+ case 'n': { cimgl_map(*this,ll) {
+ res.draw_image((*this)[ll],dx-(*this)[ll].width,dy-(*this)[ll].height,pos,dv-(*this)[ll].dim); pos+=(*this)[ll].depth;
+ }} break;
+ case 'c': { cimgl_map(*this,ll) {
+ res.draw_image((*this)[ll],(dx-(*this)[ll].width)/2,(dy-(*this)[ll].height)/2,pos,(dv-(*this)[ll].dim)/2);
+ pos+=(*this)[ll].depth;
+ }} break;
+ }
+ } break;
+ case 'v': {
+ cimgl_map(*this,l) {
+ const CImg<T>& img = (*this)[l];
+ dx = cimg::max(dx,img.width);
+ dy = cimg::max(dy,img.height);
+ dz = cimg::max(dz,img.depth);
+ dv += img.dim;
+ }
+ res.assign(dx,dy,dz,dv,0);
+ switch (cimg::uncase(align)) {
+ case 'p': { cimgl_map(*this,ll) { res.draw_image((*this)[ll],0,0,0,pos); pos+=(*this)[ll].dim; }} break;
+ case 'n': { cimgl_map(*this,ll) {
+ res.draw_image((*this)[ll],dx-(*this)[ll].width,dy-(*this)[ll].height,dz-(*this)[ll].depth,pos); pos+=(*this)[ll].dim;
+ }} break;
+ case 'c': { cimgl_map(*this,ll) {
+ res.draw_image((*this)[ll],(dx-(*this)[ll].width)/2,(dy-(*this)[ll].height)/2,(dz-(*this)[ll].depth)/2,pos);
+ pos+=(*this)[ll].dim;
+ }} break;
+ }
+ } break;
+ default: throw CImgArgumentException("CImg<%s>::get_append() : unknow axe '%c', must be 'x','y','z' or 'v'",pixel_type(),axe);
+ }
+ return res;
+ }
+
+ // Create an auto-cropped font (along the X axis) from a input font \p font.
+ CImgl<T> get_crop_font() const {
+ CImgl<T> res;
+ cimgl_map(*this,l) {
+ const CImg<T>& letter = (*this)[l];
+ int xmin=letter.width, xmax = 0;
+ cimg_mapXY(letter,x,y) if (letter(x,y)) { if (x<xmin) xmin=x; if (x>xmax) xmax=x; }
+ if (xmin>xmax) res.insert(CImg<T>(letter.width,letter.height,1,letter.dim,0));
+ else res.insert(letter.get_crop(xmin,0,xmax,letter.height));
+ }
+ res[' '].resize(res['f'].width);
+ res[' '+256].resize(res['f'].width);
+ return res;
+ }
+
+ CImgl<T>& crop_font() {
+ return get_crop_font().swap(*this);
+ }
+
+ static CImgl<T> get_font(const unsigned int *const font,const unsigned int w,const unsigned int h,
+ const unsigned int paddingx, const unsigned int paddingy, const bool variable_size=true) {
+ CImgl<T> res = CImgl<T>(256,w,h,1,3).insert(CImgl<T>(256,w,h,1,1));
+ const unsigned int *ptr = font;
+ unsigned int m = 0, val = 0;
+ for (unsigned int y=0; y<h; y++)
+ for (unsigned int x=0; x<256*w; x++) {
+ m>>=1; if (!m) { m=0x80000000; val = *(ptr++); }
+ CImg<T>& img = res[x/w], &tqmask = res[x/w+256];
+ unsigned int xm = x%w;
+ img(xm,y,0) = img(xm,y,1) = img(xm,y,2) = tqmask(xm,y,0) = (T)((val&m)?1:0);
+ }
+ if (variable_size) res.crop_font();
+ if (paddingx || paddingy) cimgl_map(res,l) res[l].resize(res[l].dimx()+paddingx, res[l].dimy()+paddingy,1,-100,0);
+ return res;
+ }
+
+ //! Return a CImg pre-defined font with desired size
+ /**
+ \param font_height = height of the desired font (can be 11,13,24,38 or 57)
+ \param fixed_size = tell if the font has a fixed or variable width.
+ **/
+ static CImgl<T> get_font(const unsigned int font_width, const bool variable_size=true) {
+ if (font_width<=11) {
+ static CImgl<T> font7x11, nfont7x11;
+ if (!variable_size && font7x11.is_empty()) font7x11 = get_font(cimg::font7x11,7,11,1,0,false);
+ if (variable_size && nfont7x11.is_empty()) nfont7x11 = get_font(cimg::font7x11,7,11,1,0,true);
+ return variable_size?nfont7x11:font7x11;
+ }
+ if (font_width<=13) {
+ static CImgl<T> font10x13, nfont10x13;
+ if (!variable_size && font10x13.is_empty()) font10x13 = get_font(cimg::font10x13,10,13,1,0,false);
+ if (variable_size && nfont10x13.is_empty()) nfont10x13 = get_font(cimg::font10x13,10,13,1,0,true);
+ return variable_size?nfont10x13:font10x13;
+ }
+ if (font_width<=17) {
+ static CImgl<T> font8x17, nfont8x17;
+ if (!variable_size && font8x17.is_empty()) font8x17 = get_font(cimg::font8x17,8,17,1,0,false);
+ if (variable_size && nfont8x17.is_empty()) nfont8x17 = get_font(cimg::font8x17,8,17,1,0,true);
+ return variable_size?nfont8x17:font8x17;
+ }
+ if (font_width<=19) {
+ static CImgl<T> font10x19, nfont10x19;
+ if (!variable_size && font10x19.is_empty()) font10x19 = get_font(cimg::font10x19,10,19,2,0,false);
+ if (variable_size && nfont10x19.is_empty()) nfont10x19 = get_font(cimg::font10x19,10,19,2,0,true);
+ return variable_size?nfont10x19:font10x19;
+ }
+ if (font_width<=24) {
+ static CImgl<T> font12x24, nfont12x24;
+ if (!variable_size && font12x24.is_empty()) font12x24 = get_font(cimg::font12x24,12,24,2,0,false);
+ if (variable_size && nfont12x24.is_empty()) nfont12x24 = get_font(cimg::font12x24,12,24,2,0,true);
+ return variable_size?nfont12x24:font12x24;
+ }
+ if (font_width<=32) {
+ static CImgl<T> font16x32, nfont16x32;
+ if (!variable_size && font16x32.is_empty()) font16x32 = get_font(cimg::font16x32,16,32,2,0,false);
+ if (variable_size && nfont16x32.is_empty()) nfont16x32 = get_font(cimg::font16x32,16,32,2,0,true);
+ return variable_size?nfont16x32:font16x32;
+ }
+ if (font_width<=38) {
+ static CImgl<T> font19x38, nfont19x38;
+ if (!variable_size && font19x38.is_empty()) font19x38 = get_font(cimg::font19x38,19,38,3,0,false);
+ if (variable_size && nfont19x38.is_empty()) nfont19x38 = get_font(cimg::font19x38,19,38,3,0,true);
+ return variable_size?nfont19x38:font19x38;
+ }
+ static CImgl<T> font29x57, nfont29x57;
+ if (!variable_size && font29x57.is_empty()) font29x57 = get_font(cimg::font29x57,29,57,5,0,false);
+ if (variable_size && nfont29x57.is_empty()) nfont29x57 = get_font(cimg::font29x57,29,57,5,0,true);
+ return variable_size?nfont29x57:font29x57;
+ }
+
+ //! Display the current CImgl instance in an existing CImgDisplay window (by reference).
+ /**
+ This function displays the list images of the current CImgl instance into an existing CImgDisplay window.
+ Images of the list are concatenated in a single temporarly image for visualization purposes.
+ The function returns immediately.
+ \param disp : reference to an existing CImgDisplay instance, where the current image list will be displayed.
+ \param axe : specify the axe for image concatenation. Can be 'x','y','z' or 'v'.
+ \param align : specify the tqalignment for image concatenation. Can be 'p' (top), 'c' (center) or 'n' (bottom).
+ \return A reference to the current CImgl instance is returned.
+ **/
+ const CImgl& display(CImgDisplay& disp,const char axe='x',const char align='c') const {
+ get_append(axe,align).display(disp);
+ return *this;
+ }
+
+ //! Display the current CImgl instance in a new display window.
+ /**
+ This function opens a new window with a specific title and displays the list images of the current CImgl instance into it.
+ Images of the list are concatenated in a single temporarly image for visualization purposes.
+ The function returns when a key is pressed or the display window is closed by the user.
+ \param title : specify the title of the opening display window.
+ \param axe : specify the axe for image concatenation. Can be 'x','y','z' or 'v'.
+ \param align : specify the tqalignment for image concatenation. Can be 'p' (top), 'c' (center) or 'n' (bottom).
+ \param min_size : specify the minimum size of the opening display window. Images having dimensions below this
+ size will be upscaled.
+ \param max_size : specify the maximum size of the opening display window. Images having dimensions above this
+ size will be downscaled.
+ \return A reference to the current CImgl instance is returned.
+ **/
+ const CImgl& display(const char* title,const char axe='x',const char align='c',
+ const int min_size=128,const int max_size=1024) const {
+ get_append(axe,align).display(title,min_size,max_size);
+ return *this;
+ }
+
+ //! Display the current CImgl instance in a new display window.
+ /**
+ This function opens a new window and displays the list images of the current CImgl instance into it.
+ Images of the list are concatenated in a single temporarly image for visualization purposes.
+ The function returns when a key is pressed or the display window is closed by the user.
+ \param axe : specify the axe for image concatenation. Can be 'x','y','z' or 'v'.
+ \param align : specify the tqalignment for image concatenation. Can be 'p' (top), 'c' (center) or 'n' (bottom).
+ \param min_size : specify the minimum size of the opening display window. Images having dimensions below this
+ size will be upscaled.
+ \param max_size : specify the maximum size of the opening display window. Images having dimensions above this
+ size will be downscaled.
+ \return A reference to the current CImgl instance is returned.
+ **/
+ const CImgl& display(const char axe='x',const char align='c',
+ const int min_size=128,const int max_size=1024) const {
+ return display(" ",axe,align,min_size,max_size);
+ }
+
+ //! Same as \ref cimg::wait()
+ /**
+ \see cimg::wait().
+ **/
+ const CImgl& wait(const unsigned int milliseconds) const { cimg::wait(milliseconds); return *this; }
+
+ // Swap fields of two CImgl instances.
+ CImgl& swap(CImgl& list) {
+ if (list.shared==shared) {
+ cimg::swap(size,list.size);
+ cimg::swap(allocsize,list.allocsize);
+ cimg::swap(data,list.data);
+ } else {
+ if (list.shared) list=*this;
+ if (shared) *this=list;
+ }
+ return list;
+ }
+
+ //! Return a reference to a set of images (I0->I1) of the list.
+ const CImgl get_shared_images(const unsigned int i0, const unsigned int i1) const {
+ if (i0>i1 || i0>=size || i1>=size)
+ throw CImgArgumentException("CImgl<%s>::get_shared_images() : Cannot get a subset (%u->%u) from a list of size %u",
+ pixel_type(),i0,i1,size);
+ return CImgl<T>(data+i0,i1-i0+1,true);
+ }
+
+ CImgl get_shared_images(const unsigned int i0, const unsigned int i1) {
+ if (i0>i1 || i0>=size || i1>=size)
+ throw CImgArgumentException("CImgl<%s>::get_shared_images() : Cannot get a subset (%u->%u) from a list of size %u",
+ pixel_type(),i0,i1,size);
+ return CImgl<T>(data+i0,i1-i0+1,true);
+ }
+
+ //! Return a sublist
+ CImgl get_images(const unsigned int i0, const unsigned int i1) const {
+ const CImgl<T> sh = get_shared_images(i0,i1);
+ return CImgl<T>(data,sh.size);
+ }
+
+ //@}
+ //---------------------------
+ //
+ //! \name Plugins functions
+ //@{
+ //---------------------------
+#ifdef cimgl_plugin
+#include cimgl_plugin
+#endif
+ //@}
+ };
+
+ /*
+ #-----------------------------------------
+ #
+ #
+ #
+ # Complete some already defined functions
+ #
+ #
+ #
+ #------------------------------------------
+ */
+
+namespace cimg {
+
+ //! Display a dialog box, where a user can click standard buttons.
+ /**
+ Up to 6 buttons can be defined in the dialog window.
+ This function returns when a user clicked one of the button or closed the dialog window.
+ \param title = Title of the dialog window.
+ \param msg = Main message displayed inside the dialog window.
+ \param button1_txt = Label of the 1st button.
+ \param button2_txt = Label of the 2nd button.
+ \param button3_txt = Label of the 3rd button.
+ \param button4_txt = Label of the 4th button.
+ \param button5_txt = Label of the 5th button.
+ \param button6_txt = Label of the 6th button.
+ \param logo = Logo image displayed at the left of the main message. This parameter is optional.
+ \param centering = Tell to center the dialog window on the screen.
+ \return The button number (from 0 to 5), or -1 if the dialog window has been closed by the user.
+ \note If a button text is set to NULL, then the corresponding button (and the followings) won't appear in
+ the dialog box. At least one button is necessary.
+ **/
+
+ template<typename t>
+ inline int dialog(const char *title,const char *msg,
+ const char *button1_txt,const char *button2_txt,
+ const char *button3_txt,const char *button4_txt,
+ const char *button5_txt,const char *button6_txt,
+ const CImg<t>& logo, const bool centering = false) {
+#if cimg_display_type!=0
+ const unsigned char
+ black[3]={0,0,0}, white[3]={255,255,255}, gray[3]={200,200,200}, gray2[3]={150,150,150};
+
+ // Create buttons and canvas graphics
+ CImgl<unsigned char> buttons, cbuttons, sbuttons;
+ if (button1_txt) { buttons.insert(CImg<unsigned char>().draw_text(button1_txt,0,0,black,gray,13));
+ if (button2_txt) { buttons.insert(CImg<unsigned char>().draw_text(button2_txt,0,0,black,gray,13));
+ if (button3_txt) { buttons.insert(CImg<unsigned char>().draw_text(button3_txt,0,0,black,gray,13));
+ if (button4_txt) { buttons.insert(CImg<unsigned char>().draw_text(button4_txt,0,0,black,gray,13));
+ if (button5_txt) { buttons.insert(CImg<unsigned char>().draw_text(button5_txt,0,0,black,gray,13));
+ if (button6_txt) { buttons.insert(CImg<unsigned char>().draw_text(button6_txt,0,0,black,gray,13));
+ }}}}}}
+ if (!buttons.size) throw CImgArgumentException("cimg::dialog() : No buttons have been defined. At least one is necessary");
+
+ unsigned int bw=0, bh=0;
+ cimgl_map(buttons,l) { bw = cimg::max(bw,buttons[l].width); bh = cimg::max(bh,buttons[l].height); }
+ bw+=8; bh+=8;
+ if (bw<64) bw=64;
+ if (bw>128) bw=128;
+ if (bh<24) bh=24;
+ if (bh>48) bh=48;
+
+ CImg<unsigned char> button = CImg<unsigned char>(bw,bh,1,3).
+ draw_rectangle(0,0,bw-1,bh-1,gray).
+ draw_line(0,0,bw-1,0,white).draw_line(0,bh-1,0,0,white).
+ draw_line(bw-1,0,bw-1,bh-1,black).draw_line(bw-1,bh-1,0,bh-1,black).
+ draw_line(1,bh-2,bw-2,bh-2,gray2).draw_line(bw-2,bh-2,bw-2,1,gray2);
+ CImg<unsigned char> sbutton = CImg<unsigned char>(bw,bh,1,3).
+ draw_rectangle(0,0,bw-1,bh-1,gray).
+ draw_line(0,0,bw-1,0,black).draw_line(bw-1,0,bw-1,bh-1,black).
+ draw_line(bw-1,bh-1,0,bh-1,black).draw_line(0,bh-1,0,0,black).
+ draw_line(1,1,bw-2,1,white).draw_line(1,bh-2,1,1,white).
+ draw_line(bw-2,1,bw-2,bh-2,black).draw_line(bw-2,bh-2,1,bh-2,black).
+ draw_line(2,bh-3,bw-3,bh-3,gray2).draw_line(bw-3,bh-3,bw-3,2,gray2).
+ draw_line(4,4,bw-5,4,black,0xAAAAAAAA).draw_line(bw-5,4,bw-5,bh-5,black,0xAAAAAAAA).
+ draw_line(bw-5,bh-5,4,bh-5,black,0xAAAAAAAA).draw_line(4,bh-5,4,4,black,0xAAAAAAAA);
+ CImg<unsigned char> cbutton = CImg<unsigned char>(bw,bh,1,3).
+ draw_rectangle(0,0,bw-1,bh-1,black).draw_rectangle(1,1,bw-2,bh-2,gray2).draw_rectangle(2,2,bw-3,bh-3,gray).
+ draw_line(4,4,bw-5,4,black,0xAAAAAAAA).draw_line(bw-5,4,bw-5,bh-5,black,0xAAAAAAAA).
+ draw_line(bw-5,bh-5,4,bh-5,black,0xAAAAAAAA).draw_line(4,bh-5,4,4,black,0xAAAAAAAA);
+
+ cimgl_map(buttons,ll) {
+ cbuttons.insert(CImg<unsigned char>(cbutton).draw_image(buttons[ll],1+(bw-buttons[ll].dimx())/2,1+(bh-buttons[ll].dimy())/2));
+ sbuttons.insert(CImg<unsigned char>(sbutton).draw_image(buttons[ll],(bw-buttons[ll].dimx())/2,(bh-buttons[ll].dimy())/2));
+ buttons[ll] = CImg<unsigned char>(button).draw_image(buttons[ll],(bw-buttons[ll].dimx())/2,(bh-buttons[ll].dimy())/2);
+ }
+
+ CImg<unsigned char> canvas;
+ if (msg) canvas = CImg<unsigned char>().draw_text(msg,0,0,black,gray,13);
+ const unsigned int
+ bwall = (buttons.size-1)*(12+bw) + bw,
+ w = cimg::max(196U,36+logo.width+canvas.width, 24+bwall),
+ h = cimg::max(96U,36+canvas.height+bh,36+logo.height+bh),
+ lx = 12 + (canvas.data?0:((w-24-logo.width)/2)),
+ ly = (h-12-bh-logo.height)/2,
+ tx = lx+logo.width+12,
+ ty = (h-12-bh-canvas.height)/2,
+ bx = (w-bwall)/2,
+ by = h-12-bh;
+
+ if (canvas.data)
+ canvas = CImg<unsigned char>(w,h,1,3).
+ draw_rectangle(0,0,w-1,h-1,gray).
+ draw_line(0,0,w-1,0,white).draw_line(0,h-1,0,0,white).
+ draw_line(w-1,0,w-1,h-1,black).draw_line(w-1,h-1,0,h-1,black).
+ draw_image(canvas,tx,ty);
+ else
+ canvas = CImg<unsigned char>(w,h,1,3).
+ draw_rectangle(0,0,w-1,h-1,gray).
+ draw_line(0,0,w-1,0,white).draw_line(0,h-1,0,0,white).
+ draw_line(w-1,0,w-1,h-1,black).draw_line(w-1,h-1,0,h-1,black);
+ if (logo.data) canvas.draw_image(logo,lx,ly);
+
+ unsigned int xbuttons[6];
+ cimgl_map(buttons,lll) { xbuttons[lll] = bx+(bw+12)*lll; canvas.draw_image(buttons[lll],xbuttons[lll],by); }
+
+ // Open window and enter events loop
+ CImgDisplay disp(canvas,title?title:" ",0,3,false,centering?true:false);
+ if (centering) disp.move((CImgDisplay::screen_dimx()-disp.dimx())/2,
+ (CImgDisplay::screen_dimy()-disp.dimy())/2);
+ bool stopflag = false, refresh = false;
+ int oselected = -1, oclicked = -1, selected = -1, clicked = -1;
+ while (!disp.closed && !stopflag) {
+ if (refresh) {
+ if (clicked>=0) CImg<unsigned char>(canvas).draw_image(cbuttons[clicked],xbuttons[clicked],by).display(disp);
+ else {
+ if (selected>=0) CImg<unsigned char>(canvas).draw_image(sbuttons[selected],xbuttons[selected],by).display(disp);
+ else canvas.display(disp);
+ }
+ refresh = false;
+ }
+ disp.wait(40);
+ if (disp.resized) disp.resize(disp);
+
+ if (disp.button&1) {
+ oclicked = clicked;
+ clicked = -1;
+ cimgl_map(buttons,l)
+ if (disp.mouse_y>=(int)by && disp.mouse_y<(int)(by+bh) &&
+ disp.mouse_x>=(int)xbuttons[l] && disp.mouse_x<(int)(xbuttons[l]+bw)) {
+ clicked = selected = l;
+ refresh = true;
+ }
+ if (clicked!=oclicked) refresh = true;
+ } else if (clicked>=0) stopflag = true;
+
+ if (disp.key) {
+ oselected = selected;
+ switch (disp.key) {
+ case cimg::keyESC: selected=-1; stopflag=true; break;
+ case cimg::keyENTER: if (selected<0) selected=0; stopflag = true; break;
+ case cimg::keyTAB:
+ case cimg::keyARROWRIGHT:
+ case cimg::keyARROWDOWN: selected = (selected+1)%buttons.size; break;
+ case cimg::keyARROWLEFT:
+ case cimg::keyARROWUP: selected = (selected+buttons.size-1)%buttons.size; break;
+ }
+ disp.key=0;
+ if (selected!=oselected) refresh = true;
+ }
+ }
+ if (disp.closed) selected = -1;
+ return selected;
+#else
+ std::fprintf(stderr,"<%s>\n\n%s\n\n",title,msg);
+ return -1;
+#endif
+ }
+
+ inline int dialog(const char *title,const char *msg,
+ const char *button1_txt,const char *button2_txt,const char *button3_txt,
+ const char *button4_txt,const char *button5_txt,const char *button6_txt,
+ const bool centering) {
+ return dialog(title,msg,button1_txt,button2_txt,button3_txt,button4_txt,button5_txt,button6_txt,
+ CImg<unsigned char>::get_logo40x38(),centering);
+ }
+
+
+ // Inner routine used by the Marching cube algorithm
+ template<typename t> inline int _marching_cubes_indice(const unsigned int edge, const CImg<t>& indices1, const CImg<t>& indices2,
+ const unsigned int x, const unsigned int y, const unsigned int nx, const unsigned int ny) {
+ switch (edge) {
+ case 0: return indices1(x,y,0);
+ case 1: return indices1(nx,y,1);
+ case 2: return indices1(x,ny,0);
+ case 3: return indices1(x,y,1);
+ case 4: return indices2(x,y,0);
+ case 5: return indices2(nx,y,1);
+ case 6: return indices2(x,ny,0);
+ case 7: return indices2(x,y,1);
+ case 8: return indices1(x,y,2);
+ case 9: return indices1(nx,y,2);
+ case 10: return indices1(nx,ny,2);
+ case 11: return indices1(x,ny,2);
+ }
+ return 0;
+ }
+
+ //! Polygonize an implicit function
+ // This function uses the Marching Cubes Tables published on the web page :
+ // http://astronomy.swin.edu.au/~pbourke/modelling/polygonise/
+ template<typename tfunc, typename tp, typename tf>
+ inline void marching_cubes(const tfunc& func, const float isovalue,
+ const float x0,const float y0,const float z0,
+ const float x1,const float y1,const float z1,
+ const float resx,const float resy,const float resz,
+ CImgl<tp>& points, CImgl<tf>& primitives,
+ const bool invert_faces) {
+
+ static unsigned int edges[256]={
+ 0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c, 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
+ 0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c, 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
+ 0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c, 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
+ 0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac, 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
+ 0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c, 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
+ 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc, 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
+ 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c, 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
+ 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc , 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
+ 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc, 0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
+ 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c, 0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
+ 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc, 0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
+ 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c, 0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460,
+ 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac, 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0,
+ 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c, 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230,
+ 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c, 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190,
+ 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c, 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000 };
+
+ static int triangles[256][16] =
+ {{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1},
+ {3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1},
+ {3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1},
+ {3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1}, {9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1},
+ {1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1},
+ {9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, {2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1},
+ {8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1},
+ {9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1}, {4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1},
+ {3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1}, {1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1},
+ {4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1}, {4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1},
+ {9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1},
+ {1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
+ {5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1}, {2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1},
+ {9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
+ {0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1}, {2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1},
+ {10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1}, {4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1},
+ {5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1}, {5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1},
+ {9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1},
+ {0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1}, {1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1}, {10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1},
+ {8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1}, {2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1},
+ {7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1}, {9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1},
+ {2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1}, {11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1},
+ {9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1}, {5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1},
+ {11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1}, {11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
+ {1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1},
+ {9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1}, {5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1},
+ {2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
+ {0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1}, {5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1},
+ {6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1},
+ {3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1}, {6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1},
+ {5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1},
+ {1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1}, {10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1},
+ {6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1},
+ {8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1}, {7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1},
+ {3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1}, {5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1},
+ {0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1}, {9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1},
+ {8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1}, {5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1},
+ {0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1}, {6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1},
+ {10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1},
+ {10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1}, {8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1},
+ {1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1}, {3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1},
+ {0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1},
+ {10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1},
+ {3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1}, {6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1},
+ {9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1}, {8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1},
+ {3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1}, {6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1}, {0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1},
+ {10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1}, {10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1},
+ {1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1}, {2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1},
+ {7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1}, {7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1}, {2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1},
+ {1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1}, {11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1},
+ {8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1}, {0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1}, {7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
+ {10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
+ {2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1}, {6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1},
+ {7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1},
+ {2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1}, {1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1},
+ {10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1}, {10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1},
+ {0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1}, {7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1},
+ {6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1},
+ {8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1}, {9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1},
+ {6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1}, {1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1},
+ {4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1}, {10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1},
+ {8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1}, {0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1}, {1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1},
+ {8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1}, {10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1},
+ {4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1}, {10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
+ {5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}, {11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1},
+ {9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1}, {6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1},
+ {7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1}, {3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1},
+ {7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1}, {9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1},
+ {3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1}, {6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1},
+ {9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1}, {1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1},
+ {4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1}, {7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1},
+ {6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1}, {3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1},
+ {0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1}, {6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1},
+ {1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1}, {0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1},
+ {11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1}, {6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1},
+ {5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1}, {9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1},
+ {1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1}, {1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1}, {10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1},
+ {0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1},
+ {5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1}, {10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1},
+ {11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1},
+ {9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1}, {7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1},
+ {2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1}, {8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1},
+ {9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1}, {9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1},
+ {1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1},
+ {9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1}, {9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1}, {5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1},
+ {0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1}, {10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1},
+ {2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1}, {0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1},
+ {0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1}, {9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1}, {5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1},
+ {3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1}, {5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1},
+ {8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1}, {0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1}, {9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1}, {0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1},
+ {1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1}, {3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1},
+ {4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1}, {9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1},
+ {11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1}, {11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1},
+ {2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1}, {9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1},
+ {3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1}, {1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1}, {4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1},
+ {4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1},
+ {0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1}, {3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1}, {3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1},
+ {0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1}, {9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1}, {1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
+ {0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}};
+
+ const unsigned int
+ nx = (unsigned int)((x1-x0+1)/resx), nxm1 = nx-1,
+ ny = (unsigned int)((y1-y0+1)/resy), nym1 = ny-1,
+ nz = (unsigned int)((z1-z0+1)/resz), nzm1 = nz-1;
+
+ if (!nxm1 || !nym1 || !nzm1) return;
+
+ CImg<int> indices1(nx,ny,1,3,-1), indices2(indices1);
+ CImg<float> values1(nx,ny), values2(nx,ny);
+ float X=0, Y=0, Z=0, nX=0, nY=0, nZ=0;
+
+ // Fill the first plane with function values
+ Y=y0;
+ cimg_mapY(values1,y) {
+ X = x0;
+ cimg_mapX(values1,x) { values1(x,y) = (float)func(X,Y,z0); X+=resx; }
+ Y+=resy;
+ }
+
+ // Run Marching Cubes algorithm
+ Z = z0; nZ = Z + resz;
+ for (unsigned int zi=0; zi<nzm1; ++zi, Z=nZ, nZ+=resz) {
+ Y = y0; nY = Y + resy;
+ indices2.fill(-1);
+ for (unsigned int yi=0, nyi=1; yi<nym1; ++yi, ++nyi, Y=nY, nY+=resy) {
+ X = x0; nX = X + resx;
+ for (unsigned int xi=0, nxi=1; xi<nxm1; ++xi, ++nxi, X=nX, nX+=resx) {
+
+ // Determine cube configuration
+ const float
+ val0 = values1(xi,yi), val1 = values1(nxi,yi), val2 = values1(nxi,nyi), val3 = values1(xi,nyi),
+ val4 = values2(xi,yi) = (float)func(X,Y,nZ),
+ val5 = values2(nxi,yi) = (float)func(nX,Y,nZ),
+ val6 = values2(nxi,nyi) = (float)func(nX,nY,nZ),
+ val7 = values2(xi,nyi) = (float)func(X,nY,nZ);
+
+ const unsigned int configuration =
+ (val0<isovalue?1:0) | (val1<isovalue?2:0) | (val2<isovalue?4:0) | (val3<isovalue?8:0) |
+ (val4<isovalue?16:0) | (val5<isovalue?32:0) | (val6<isovalue?64:0) | (val7<isovalue?128:0),
+ edge = edges[configuration];
+
+ // Compute intersection points
+ if (edge) {
+ if ((edge&1) && indices1(xi,yi,0)<0) {
+ const float Xi = X + (isovalue-val0)*resx/(val1-val0);
+ indices1(xi,yi,0) = points.size;
+ points.insert(CImg<tp>::vector(Xi,Y,Z));
+ }
+ if ((edge&2) && indices1(nxi,yi,1)<0) {
+ const float Yi = Y + (isovalue-val1)*resy/(val2-val1);
+ indices1(nxi,yi,1) = points.size;
+ points.insert(CImg<tp>::vector(nX,Yi,Z));
+ }
+ if ((edge&4) && indices1(xi,nyi,0)<0) {
+ const float Xi = X + (isovalue-val3)*resx/(val2-val3);
+ indices1(xi,nyi,0) = points.size;
+ points.insert(CImg<tp>::vector(Xi,nY,Z));
+ }
+ if ((edge&8) && indices1(xi,yi,1)<0) {
+ const float Yi = Y + (isovalue-val0)*resy/(val3-val0);
+ indices1(xi,yi,1) = points.size;
+ points.insert(CImg<tp>::vector(X,Yi,Z));
+ }
+ if ((edge&16) && indices2(xi,yi,0)<0) {
+ const float Xi = X + (isovalue-val4)*resx/(val5-val4);
+ indices2(xi,yi,0) = points.size;
+ points.insert(CImg<tp>::vector(Xi,Y,nZ));
+ }
+ if ((edge&32) && indices2(nxi,yi,1)<0) {
+ const float Yi = Y + (isovalue-val5)*resy/(val6-val5);
+ indices2(nxi,yi,1) = points.size;
+ points.insert(CImg<tp>::vector(nX,Yi,nZ));
+ }
+ if ((edge&64) && indices2(xi,nyi,0)<0) {
+ const float Xi = X + (isovalue-val7)*resx/(val6-val7);
+ indices2(xi,nyi,0) = points.size;
+ points.insert(CImg<tp>::vector(Xi,nY,nZ));
+ }
+ if ((edge&128) && indices2(xi,yi,1)<0) {
+ const float Yi = Y + (isovalue-val4)*resy/(val7-val4);
+ indices2(xi,yi,1) = points.size;
+ points.insert(CImg<tp>::vector(X,Yi,nZ));
+ }
+ if ((edge&256) && indices1(xi,yi,2)<0) {
+ const float Zi = Z+ (isovalue-val0)*resz/(val4-val0);
+ indices1(xi,yi,2) = points.size;
+ points.insert(CImg<tp>::vector(X,Y,Zi));
+ }
+ if ((edge&512) && indices1(nxi,yi,2)<0) {
+ const float Zi = Z + (isovalue-val1)*resz/(val5-val1);
+ indices1(nxi,yi,2) = points.size;
+ points.insert(CImg<tp>::vector(nX,Y,Zi));
+ }
+ if ((edge&1024) && indices1(nxi,nyi,2)<0) {
+ const float Zi = Z + (isovalue-val2)*resz/(val6-val2);
+ indices1(nxi,nyi,2) = points.size;
+ points.insert(CImg<tp>::vector(nX,nY,Zi));
+ }
+ if ((edge&2048) && indices1(xi,nyi,2)<0) {
+ const float Zi = Z + (isovalue-val3)*resz/(val7-val3);
+ indices1(xi,nyi,2) = points.size;
+ points.insert(CImg<tp>::vector(X,nY,Zi));
+ }
+
+ // Create triangles
+ for (int *triangle=triangles[configuration]; *triangle!=-1; ) {
+ const unsigned int p0 = *(triangle++), p1 = *(triangle++), p2 = *(triangle++);
+ const tf
+ i0 = (tf)(_marching_cubes_indice(p0,indices1,indices2,xi,yi,nxi,nyi)),
+ i1 = (tf)(_marching_cubes_indice(p1,indices1,indices2,xi,yi,nxi,nyi)),
+ i2 = (tf)(_marching_cubes_indice(p2,indices1,indices2,xi,yi,nxi,nyi));
+ if (invert_faces) primitives.insert(CImg<tf>::vector(i0,i1,i2));
+ else primitives.insert(CImg<tf>::vector(i0,i2,i1));
+ }
+ }
+ }
+ }
+ cimg::swap(values1,values2);
+ cimg::swap(indices1,indices2);
+ }
+ }
+
+ // Inner routine used by the Marching square algorithm
+ template<typename t> inline int _marching_squares_indice(const unsigned int edge, const CImg<t>& indices1, const CImg<t>& indices2,
+ const unsigned int x, const unsigned int nx) {
+ switch (edge) {
+ case 0: return (int)indices1(x,0);
+ case 1: return (int)indices1(nx,1);
+ case 2: return (int)indices2(x,0);
+ case 3: return (int)indices1(x,1);
+ }
+ return 0;
+ }
+
+ //! Polygonize an implicit 2D function by the marching squares algorithm
+ template<typename tfunc, typename tp, typename tf>
+ inline void marching_squares(const tfunc& func, const float isovalue,
+ const float x0,const float y0,
+ const float x1,const float y1,
+ const float resx,const float resy,
+ CImgl<tp>& points, CImgl<tf>& primitives) {
+
+ static unsigned int edges[16]={ 0x0, 0x9, 0x3, 0xa, 0x6, 0xf, 0x5, 0xc, 0xc, 0x5, 0xf, 0x6, 0xa, 0x3, 0x9, 0x0 };
+ static int segments[16][4] = { { -1,-1,-1,-1 }, { 0,3,-1,-1 }, { 0,1,-1,-1 }, { 1,3,-1,-1 },
+ { 1,2,-1,-1 }, { 0,1,2,3 }, { 0,2,-1,-1 }, { 2,3,-1,-1 },
+ { 2,3,-1,-1 }, { 0,2,-1,-1}, { 0,3,1,2 }, { 1,2,-1,-1 },
+ { 1,3,-1,-1 }, { 0,1,-1,-1}, { 0,3,-1,-1}, { -1,-1,-1,-1 } };
+ const unsigned int
+ nx = (unsigned int)((x1-x0+1)/resx), nxm1 = nx-1,
+ ny = (unsigned int)((y1-y0+1)/resy), nym1 = ny-1;
+
+ if (!nxm1 || !nym1) return;
+
+ CImg<int> indices1(nx,1,1,2,-1), indices2(nx,1,1,2);
+ CImg<float> values1(nx), values2(nx);
+ float X = 0, Y = 0, nX = 0, nY = 0;
+
+ // Fill first line with values
+ cimg_mapX(values1,x) { values1(x) = (float)func(X,Y); X+=resx; }
+
+ // Run the marching squares algorithm
+ Y = y0; nY = Y + resy;
+ for (unsigned int yi=0, nyi=1; yi<nym1; ++yi, ++nyi, Y=nY, nY+=resy) {
+ X = x0; nX = X + resx;
+ indices2.fill(-1);
+ for (unsigned int xi=0, nxi=1; xi<nxm1; ++xi, ++nxi, X=nX, nX+=resx) {
+
+ // Determine cube configuration
+ const float
+ val0 = values1(xi), val1 = values1(nxi),
+ val2 = values2(nxi) = (float)func(nX,nY),
+ val3 = values2(xi) = (float)func(X,nY);
+
+ const unsigned int configuration = (val0<isovalue?1:0) | (val1<isovalue?2:0) | (val2<isovalue?4:0) | (val3<isovalue?8:0),
+ edge = edges[configuration];
+
+ // Compute intersection points
+ if (edge) {
+ if ((edge&1) && indices1(xi,0)<0) {
+ const float Xi = X + (isovalue-val0)*resx/(val1-val0);
+ indices1(xi,0) = points.size;
+ points.insert(CImg<tp>::vector(Xi,Y));
+ }
+ if ((edge&2) && indices1(nxi,1)<0) {
+ const float Yi = Y + (isovalue-val1)*resy/(val2-val1);
+ indices1(nxi,1) = points.size;
+ points.insert(CImg<tp>::vector(nX,Yi));
+ }
+ if ((edge&4) && indices2(xi,0)<0) {
+ const float Xi = X + (isovalue-val3)*resx/(val2-val3);
+ indices2(xi,0) = points.size;
+ points.insert(CImg<tp>::vector(Xi,nY));
+ }
+ if ((edge&8) && indices1(xi,1)<0) {
+ const float Yi = Y + (isovalue-val0)*resy/(val3-val0);
+ indices1(xi,1) = points.size;
+ points.insert(CImg<tp>::vector(X,Yi));
+ }
+
+ // Create segments
+ for (int *segment=segments[configuration]; *segment!=-1; ) {
+ const unsigned int p0 = *(segment++), p1 = *(segment++);
+ const tf
+ i0 = (tf)(_marching_squares_indice(p0,indices1,indices2,xi,nxi)),
+ i1 = (tf)(_marching_squares_indice(p1,indices1,indices2,xi,nxi));
+ primitives.insert(CImg<tf>::vector(i0,i1));
+ }
+ }
+ }
+ values1.swap(values2);
+ indices1.swap(indices2);
+ }
+ }
+
+ // End of cimg:: namespace
+}
+
+
+ // End of cimg_library:: namespace
+}
+
+// Overcome VisualC++ 6.0 and DMC compilers namespace bug
+#if ( defined(_MSC_VER) || defined(__DMC__) ) && defined(std)
+#undef std
+#endif
+
+/*
+ #------------------------------------------------------------------------------------
+ #
+ #
+ # Additional documentation for the generation of the reference page (using doxygen)
+ #
+ #
+ #------------------------------------------------------------------------------------
+ */
+
+/**
+ \mainpage
+
+ This is the reference documentation of <a href="http://cimg.sourceforge.net">the CImg Library</a>.
+ These HTML pages have been generated using <a href="http://www.doxygen.org">doxygen</a>.
+ It contains a detailed description of all classes and functions of the %CImg Library.
+ If you have downloaded the CImg package, you actually have a local copy of these pages in the
+ \c CImg/documentation/reference/ directory.
+
+ Use the menu above to navigate through the documentation pages.
+ As a first step, you may look at the list of <a href="modules.html">available modules</a>.
+
+ A complete PDF version of this reference documentation is
+ <a href="../CImg_reference.pdf">available here</a> for off-line reading.
+
+**/
+
+/** \addtogroup cimg_structure Introduction to the CImg Library */
+/*@{*/
+/**
+ \page foo2
+
+ The <b>CImg Library</b> is an image processing library, designed for C++ programmers.
+ It provides useful classes and functions to load/save, display and process various types of images.
+
+ \section s1 Library structure
+
+ The %CImg Library consists in a <b>single header file</b> CImg.h providing a set of C++ template classes that
+ can be used in your own sources, to load/save, process and display images or list of images.
+ Very portable (Unix/X11,Windows, MacOS X, FreeBSD,..), efficient, simple to use, it's a pleasant toolkit
+ for coding image processing stuffs in C++.
+
+ The header file CImg.h contains all the classes and functions that compose the library itself.
+ This is one originality of the %CImg Library. This particularly means that :
+ - No pre-compilation of the library is needed, since the compilation of the CImg functions is done at the same time as
+ the compilation of your own C++ code.
+ - No complex dependencies have to be handled : Just include the CImg.h file, and you get a working C++ image processing toolkit.
+ - The compilation is done on the fly : only CImg functionalities really used by your program are compiled and appear in the
+ compiled executable program. This leads to very compact code, without any unused stuffs.
+ - Class members and functions are inlined, leading to better performance during the program execution.
+
+ The %CImg Library is structured as follows :
+
+ - All library classes and functions are defined in the namespace \ref cimg_library. This namespace
+ encapsulates the library functionalities and avoid any class name collision that could happen with
+ other includes. Generally, one uses this namespace as a default namespace :
+ \code
+ #include "CImg.h"
+ using namespace cimg_library;
+ ...
+ \endcode
+
+ - The namespace \ref cimg_library::cimg defines a set of \e low-level functions and variables used by the library.
+ Documented functions in this namespace can be safely used in your own program. But, \b never use the
+ \ref cimg_library::cimg namespace as a default namespace, since it contains functions whose names are already
+ defined in the standard C/C++ library.
+
+ - The class \ref cimg_library::CImg<T> represents images up to 4-dimensions wide, containing pixels of type \c T
+ (template parameter). This is actually the main class of the library.
+
+ - The class \ref cimg_library::CImgl<T> represents lists of cimg_library::CImg<T> images. It can be used for instance
+ to store different frames of an image sequence.
+
+ - The class \ref cimg_library::CImgDisplay is able to display images or image lists into graphical display windows.
+ As you may guess, the code of this class is highly system-dependent but this is transparent for the programmer,
+ as environment variables are automatically set by the CImg library (see also \ref cimg_environment).
+
+ - The class \ref cimg_library::CImgStats represents image statistics. Use it to compute the
+ minimum, maximum, mean and variance of pixel values of images, as well as the corresponding min/max pixel location.
+
+ - The class \ref cimg_library::CImgException (and its subclasses) are used by the library to throw exceptions
+ when errors occur. Those exceptions can be catched with a bloc <tt>try { ..} catch (CImgException) { .. }</tt>.
+ Subclasses define precisely the type of encountered errors.
+
+ Knowing these five classes is \b enough to get benefit of the %CImg Library functionalities.
+
+
+ \section s2 CImg version of "Hello world".
+
+ Below is a very simple code that creates a "Hello World" image. This shows you basically how a CImg program looks like.
+
+ \code
+ #include "CImg.h"
+ using namespace cimg_library;
+
+ int main() {
+ CImg<unsigned char> img(640,400,1,3); // Define a 640x400 color image with 8 bits per color component.
+ img.fill(0); // Set pixel values to 0 (color : black)
+ unsigned char purple[3]={255,0,255}; // Define a purple color
+ img.draw_text("Hello World",100,100,purple); // Draw a purple "Hello world" at coordinates (100,100).
+ img.display("My first CImg code"); // Display the image in a display window.
+ return 0;
+ }
+ \endcode
+
+ Which can be also written in a more compact way as :
+
+ \code
+ #include "CImg.h"
+ using namespace cimg_library;
+
+ int main() {
+ const unsigned char purple[3]={255,0,255};
+ CImg<unsigned char>(640,400,1,3,0).draw_text("Hello World",100,100,purple).display("My first CImg code");
+ return 0;
+ }
+ \endcode
+
+ Generally, you can write very small code that performs complex image processing tasks. The %CImg Library is very simple
+ to use and provide a lot of interesting algorithms for image manipulation.
+
+ \section s3 How to compile ?
+
+ The CImg library is a very light and user-friendly library : only standard system libraries are used.
+ It avoid to handle complex dependancies and problems with library compatibility.
+ The only thing you need is a (quite modern) C++ compiler :
+
+ - <b>Microsoft Visual C++ 6.0 and Visual Studio.NET</b> : Use project files and solution files provided in the
+ %CImg Library package (directory 'compilation/') to see how it works.
+ - <b>Intel ICL compiler</b> : Use the following command to compile a CImg-based program with ICL :
+ \code
+ icl /Ox hello_world.cpp user32.lib gdi32.lib
+ \endcode
+ - <b>g++ (MingW windows version)</b> : Use the following command to compile a CImg-based program with g++, on Windows :
+ \code
+ g++ -o hello_word.exe hello_word.cpp -O2 -lgdi32
+ \endcode
+ - <b>g++ (Linux version)</b> : Use the following command to compile a CImg-based program with g++, on Linux :
+ \code
+ g++ -o hello_word.exe hello_world.cpp -O2 -L/usr/X11R6/lib -lm -lpthread -lX11
+ \endcode
+ - <b>g++ (Solaris version)</b> : Use the following command to compile a CImg-based program with g++, on Solaris :
+ \code
+ g++ -o hello_word.exe hello_world.cpp -O2 -lm -lpthread -R/usr/X11R6/lib -lrt -lnsl -lsocket
+ \endcode
+ - <b>g++ (Mac OS X version)</b> : Use the following command to compile a CImg-based program with g++, on Mac OS X :
+ \code
+ g++ -o hello_word.exe hello_world.cpp -O2 -lm -lpthread -L/usr/X11R6/lib -lm -lpthread -lX11
+ \endcode
+ - <b>Dev-Cpp</b> : Use the project file provided in the CImg library package to see how it works.
+
+ If you are using another compilers and encounter problems, please
+ <a href="http://www.greyc.ensicaen.fr/~dtschump">write me</a> since maintaining compatibility is one
+ of the priority of the %CImg Library. Nevertheless, old compilers that does not respect the C++ norm will not
+ support the %CImg Library.
+
+ \section s4 What's next ?
+
+ If you are ready to get more, and to start writing more serious programs
+ with CImg, you are invited to go to the \ref cimg_tutorial section.
+
+**/
+/*@}*/
+
+/** \addtogroup cimg_environment Setting Environment Variables */
+/*@{*/
+/**
+ \page foo1
+
+ The CImg library is a multiplatform library, working on a wide variety of systems.
+ This implies the existence of some \e environment \e variables that must be correctly defined
+ depending on your current system.
+ Most of the time, the %CImg Library defines these variables automatically
+ (for popular systems). Anyway, if your system is not recognized, you will have to set the environment
+ variables by hand. Here is a quick explanations of environment variables.\n
+
+ Setting the environment variables is done with the <tt>#define</tt> keyword.
+ This setting must be done <i>before including the file CImg.h</i> in your source code.
+ For instance,
+ defining the environment variable \c cimg_display_type would be done like this :
+ \code
+ #define cimg_display_type 0
+ #include "CImg.h"
+ ...
+ \endcode
+
+ Here are the different environment variables used by the %CImg Library :
+
+ - \b \c cimg_OS : This variable defines the type of your Operating System. It can be set to \b 1 (\e Unix),
+ \b 2 (\e Windows), or \b 0 (\e Other \e configuration).
+ It should be actually auto-detected by the CImg library. If this is not the case (<tt>cimg_OS=0</tt>), you
+ will probably have to tune the environment variables described below.
+
+ - \b \c cimg_display_type : This variable defines the type of graphical library used to
+ display images in windows. It can be set to 0 (no display library available), \b 1 (X11-based display) or
+ \b 2 (Windows-GDI display).
+ If you are running on a system without X11 or Windows-GDI ability, please set this variable to \c 0.
+ This will disable the display support, since the %CImg Library doesn't contain the necessary code to display
+ images on systems other than X11 or Windows GDI.
+
+ - \b \c cimg_color_terminal : This variable tells the library if the system terminal has VT100 color capabilities.
+ It can be \e defined or \e not \e defined. Define this variable to get colored output on your terminal,
+ when using the %CImg Library.
+
+ - \b \c cimg_debug : This variable defines the level of run-time debug messages that will be displayed by
+ the %CImg Library. It can be set to 0 (no debug messages), 1 (normal debug messages, which is
+ the default value), or 2 (high debug messages). Note that setting this value to 2 may slow down your
+ program since more debug tests are made by the library (particularly to check if pixel access is made outside
+ image boundaries). See also CImgException to better understand how debug messages are working.
+
+ - \b \c cimg_convert_path : This variables tells the library where the ImageMagick's \e convert tool is located.
+ Setting this variable should not be necessary if ImageMagick is installed on a standard directory, or
+ if \e convert is in your system PATH variable. This macro should be defined only if the ImageMagick's
+ \e convert tool is not found automatically, when trying to read compressed image format (GIF,PNG,...).
+ See also cimg_library::CImg::get_load_convert() and cimg_library::CImg::save_convert() for more informations.
+
+ - \b \c cimg_temporary_path : This variable tells the library where it can find a directory to store
+ temporary files. Setting this variable should not be necessary if you are running on a standard system.
+ This macro should be defined only when troubles are encountered when trying to read
+ compressed image format (GIF,PNG,...).
+ See also cimg_library::CImg::get_load_convert() and cimg_library::CImg::save_convert() for more informations.
+
+ - \b \c cimg_plugin : This variable tells the library to use a plugin file to add features to the CImg<T> class.
+ Define it with the path of your plugin file, if you want to add member functions to the CImg<T> class,
+ without having to modify directly the \c "CImg.h" file. An include of the plugin file is performed in the CImg<T>
+ class. If \c cimg_plugin if not specified (default), no include is done.
+
+ - \b \c cimgl_plugin : Same as \c cimg_plugin, but to add features to the CImgl<T> class.
+
+ - \b \c cimgdisplay_plugin : Same as \c cimg_plugin, but to add features to the CImgDisplay<T> class.
+
+ - \b \c cimgstats_plugin : Same as \c cimg_plugin, but to add features to the CImgStats<T> class.
+
+ All these compilation variables can be checked, using the function cimg_library::cimg::info(), which
+ displays a list of the different configuration variables and their values on the standard error output.
+**/
+/*@}*/
+
+/** \addtogroup cimg_tutorial Tutorial : Getting Started. */
+/*@{*/
+/**
+ \page foo3
+
+ Let's start to write our first program to get the idea. This will demonstrate how to load and create images, as well as handle image
+ display and mouse events.
+ Assume we want to load a color image <tt>lena.jpg</tt>, smooth it, display it in a windows, and enter an event loop so that clicking a
+ point in the image with the mouse will draw the intensity profiles of (R,G,B) of the corresponding image line (in another window).
+ Yes, that sounds quite complex for a first code, but don't worry, it will be very simple using the CImg library ! Well, just look
+ at the code below, it does the task :
+
+ \code
+ #include "CImg.h"
+ using namespace cimg_library;
+
+ int main() {
+ CImg<unsigned char> image("lena.jpg"), visu(500,400,1,3,0);
+ const unsigned char red[3]={255,0,0}, green[3]={0,255,0}, blue[3]={0,0,255};
+ image.blur(2.5);
+ CImgDisplay main_disp(image,"Click a point"), draw_disp(visu,"Intensity profile");
+ while (!main_disp.closed && !draw_disp.closed) {
+ main_disp.wait();
+ if (main_disp.button && main_disp.mouse_y>=0) {
+ const int y = main_disp.mouse_y;
+ visu.fill(0).draw_graph(image.get_crop(0,y,0,0,image.dimx()-1,y,0,0),red,0,256,0);
+ visu.draw_graph(image.get_crop(0,y,0,1,image.dimx()-1,y,0,1),green,0,256,0);
+ visu.draw_graph(image.get_crop(0,y,0,2,image.dimx()-1,y,0,2),blue,0,256,0).display(draw_disp);
+ }
+ }
+ return 0;
+ }
+ \endcode
+
+ Here is a screenshot of the resulting program :
+
+ <img SRC="../img/tutorial.jpg">
+
+ And here is the detailled explanation of the source, line by line :
+
+ \code #include "CImg.h" \endcode
+ Include the main and only header file of the CImg library.
+ \code using namespace cimg_library; \endcode
+ Use the library namespace to ease the declarations afterward.
+ \code int main() { \endcode
+ Definition of the main function.
+ \code CImg<unsigned char> image("lena.jpg"), visu(500,400,1,3,0); \endcode
+ Creation of two instances of images of \c unsigned \c char pixels.
+ The first image \c image is initialized by reading an image file from the disk.
+ Here, <tt>lena.jpg</tt> must be in the same directory than the current program.
+ Note that you must also have installed the \e ImageMagick package in order to be able to read JPG images.
+ The second image \c visu is initialized as a black color image with dimension <tt>dx=500</tt>, <tt>dy=400</tt>,
+ <tt>dz=1</tt> (here, it is a 2D image, not a 3D one), and <tt>dv=3</tt> (each pixel has 3 'vector' channels R,G,B).
+ The last argument in the constructor defines the default value of the pixel values
+ (here \c 0, which means that \c visu will be initially black).
+ \code const unsigned char red[3]={255,0,0}, green[3]={0,255,0}, blue[3]={0,0,255}; \endcode
+ Definition of three different colors as array of unsigned char. This will be used to draw plots with different colors.
+ \code image.blur(2.5); \endcode
+ Blur the image, with a gaussian blur and a standard variation of 2.5. Note that most of the CImg functions have two versions :
+ one that acts in-place (which is the case of blur), and one that returns the result as a new image (the name of the function
+ begins then with <tt>get_</tt>&nbsp;). In this case, one could have also written <tt>image = image.get_blur(2.5);</tt>
+ (more expensive, since it needs an additional copy operation).
+ \code CImgDisplay main_disp(image,"Click a point"), draw_disp(visu,"Intensity profile"); \endcode
+ Creation of two display windows, one for the input image image, and one for the image visu which will be display intensity profiles.
+ By default, CImg displays handles events (mouse,keyboard,..). On Windows, there is a way to create fullscreen displays.
+ \code while (!main_disp.closed && !draw_disp.closed) { \endcode
+ Enter the event loop, the code will exit when one of the two display windows is closed.
+ \code main_disp.wait(); \endcode
+ Wait for an event (mouse, keyboard,..) in the display window \c main_disp.
+ \code if (main_disp.button && main_disp.mouse_y>=0) { \endcode
+ Test if the mouse button has been clicked on the image area.
+ One may distinguish between the 3 different mouse buttons,
+ but in this case it is not necessary
+ \code const int y = main_disp.mouse_y; \endcode
+ Get the image line y-coordinate that has been clicked.
+ \code visu.fill(0).draw_graph(image.get_crop(0,y,0,0,image.dimx()-1,y,0,0),red,0,256,0); \endcode
+ This line illustrates the pipeline property of most of the CImg class functions. The first function <tt>fill(0)</tt> simply sets
+ all pixel values with 0 (i.e. clear the image \c visu). The interesting thing is that it returns a reference to
+ \c visu and then, can be pipelined with the function \c draw_graph() which draws a plot in the image \c visu.
+ The plot data are given by another image (the first argument of \c draw_graph()). In this case, the given image is
+ the red-component of the line y of the original image, retrieved by the function \c get_crop() which returns a
+ sub-image of the image \c image. Remember that images coordinates are 4D (x,y,z,v) and for color images,
+ the R,G,B channels are respectively given by <tt>v=0, v=1</tt> and <tt>v=2</tt>.
+ \code visu.draw_graph(image.get_crop(0,y,0,1,image.dimx()-1,y,0,1),green,0,256,0); \endcode
+ Plot the intensity profile for the green channel of the clicked line.
+ \code visu.draw_graph(image.get_crop(0,y,0,2,image.dimx()-1,y,0,2),blue,0,256,0).display(draw_disp); \endcode
+ Same thing for the blue channel. Note how the function (which return a reference to \c visu) is pipelined with the function
+ \c display() that just paints the image visu in the corresponding display window.
+ \code ...till the end \endcode
+ I don't think you need more explanations !
+
+ As you have noticed, the CImg library allows to write very small and intuitive code. Note also that this source will perfectly
+ work on Unix and Windows systems. Take also a look to the examples provided in the CImg package (
+ directory \c examples/ ). It will show you how CImg-based code can be surprisingly small.
+ Moreover, there is surely one example close to what you want to do.
+ A good start will be to look at the file <tt>CImg_demo.cpp</tt> which contains small and various examples of what you can do
+ with the %CImg Library. All CImg classes are used in this source, and the code can be easily modified to see what happens.
+
+**/
+/*@}*/
+
+/** \addtogroup cimg_drawing Using Drawing Functions. */
+/*@{*/
+/**
+ \page foo5
+
+ \section s5 Using Drawing Functions.
+
+ This section tells more about drawing features in CImg images.
+ Drawing functions list can be found in <a href="structCImg.html">the CImg functions list</a>
+ (section \b Drawing Functions),
+ and are all defined on a common basis. Here are the important points to understand before using
+ drawing functions :
+
+ - Drawing is performed on the instance image. Drawing functions parameters
+ are defined as \e const variables and return a reference to the current instance <tt>(*this)</tt>,
+ so that drawing functions can be pipelined (see examples below).
+ Drawing is usually done in 2D color images but can be performed in 3D images with any vector-valued dimension,
+ and with any possible pixel type.
+
+ - A color parameter is always needed to draw features in an image. The color must be defined as a C-style array
+ whose dimension is at least
+
+**/
+/*@}*/
+
+/** \addtogroup cimg_loops Using Image Loops. */
+/*@{*/
+/**
+ \page foo_lo
+ The %CImg Library provides different macros that define useful iterative loops over an image.
+ Basically, it can be used to replace one or several <tt>for(..)</tt> instructions, but it also proposes
+ interesting extensions to classical loops.
+ Below is a list of all existing loop macros, classified in four different categories :
+ - \ref lo1
+ - \ref lo4
+ - \ref lo5
+ - \ref lo6
+
+ \section lo1 Loops over the pixel buffer
+
+ Loops over the pixel buffer are really basic loops that iterate a pointer on the pixel data buffer
+ of a \c cimg_library::CImg image. Two macros are defined for this purpose :
+
+ - \b cimg_map(img,ptr,T) :
+ This macro loops over the pixel data buffer of the image \c img, using a pointer <tt>T* ptr</tt>,
+ starting from the end of the buffer (last pixel) till the beginning of the buffer (first pixel).
+ - \c img must be a (non empty) \c cimg_library::CImg image of pixels \c T.
+ - \c ptr is a pointer of type \c T*.
+ This kind of loop should not appear a lot in your own source code, since this is a low-level loop
+ and many functions of the CImg class may be used instead. Here is an example of use :
+ \code
+ CImg<float> img(320,200);
+ cimg_map(img,ptr,float) { *ptr=0; } // Equivalent to 'img.fill(0);'
+ \endcode
+
+ - \b cimg_mapoff(img,off) :
+ This macro loops over the pixel data buffer of the image \c img, using an offset \c ,
+ starting from the beginning of the buffer (first pixel, \c off=0)
+ till the end of the buffer (last pixel value, <tt>off = img.size()-1</tt>).
+ - \c img must be a (non empty) cimg_library::CImg<T> image of pixels \c T.
+ - \c off is an inner-loop variable, only defined inside the scope of the loop.
+
+ Here is an example of use :
+ \code
+ CImg<float> img(320,200);
+ cimg_mapoff(img,off) { img[off]=0; } // Equivalent to 'img.fill(0);'
+ \endcode
+
+ \section lo4 Loops over image dimensions
+
+ The following loops are probably the most used loops in image processing programs.
+ They allow to loop over the image along one or several dimensions, along a raster scan course.
+ Here is the list of such loop macros for a single dimension :
+ - \b cimg_mapX(img,x) : equivalent to : <tt>for (int x=0; x<img.dimx(); x++)</tt>.
+ - \b cimg_mapY(img,y) : equivalent to : <tt>for (int y=0; y<img.dimy(); y++)</tt>.
+ - \b cimg_mapZ(img,z) : equivalent to : <tt>for (int z=0; z<img.dimz(); z++)</tt>.
+ - \b cimg_mapV(img,v) : equivalent to : <tt>for (int v=0; v<img.dimv(); v++)</tt>.
+
+ Combinations of these macros are also defined as other loop macros, allowing to loop directly over 2D, 3D or 4D images :
+ - \b cimg_mapXY(img,x,y) : equivalent to : \c cimg_mapY(img,y) \c cimg_mapX(img,x).
+ - \b cimg_mapXZ(img,x,z) : equivalent to : \c cimg_mapZ(img,z) \c cimg_mapX(img,x).
+ - \b cimg_mapYZ(img,y,z) : equivalent to : \c cimg_mapZ(img,z) \c cimg_mapY(img,y).
+ - \b cimg_mapXV(img,x,v) : equivalent to : \c cimg_mapV(img,v) \c cimg_mapX(img,x).
+ - \b cimg_mapYV(img,y,v) : equivalent to : \c cimg_mapV(img,v) \c cimg_mapY(img,y).
+ - \b cimg_mapZV(img,z,v) : equivalent to : \c cimg_mapV(img,v) \c cimg_mapZ(img,z).
+ - \b cimg_mapXYZ(img,x,y,z) : equivalent to : \c cimg_mapZ(img,z) \c cimg_mapXY(img,x,y).
+ - \b cimg_mapXYV(img,x,y,v) : equivalent to : \c cimg_mapV(img,v) \c cimg_mapXY(img,x,y).
+ - \b cimg_mapXZV(img,x,z,v) : equivalent to : \c cimg_mapV(img,v) \c cimg_mapXZ(img,x,z).
+ - \b cimg_mapYZV(img,y,z,v) : equivalent to : \c cimg_mapV(img,v) \c cimg_mapYZ(img,y,z).
+ - \b cimg_mapXYZV(img,x,y,z,v) : equivalent to : \c cimg_mapV(img,v) \c cimg_mapXYZ(img,x,y,z).
+
+ - For all these loops, \c x,\c y,\c z and \c v are inner-defined variables only visible inside the scope of the loop.
+ They don't have to be defined before the call of the macro.
+ - \c img must be a (non empty) cimg_library::CImg image.
+
+ Here is an example of use that creates an image with a smooth color gradient :
+ \code
+ CImg<unsigned char> img(256,256,1,3); // Define a 256x256 color image
+ cimg_mapXYV(img,x,y,v) { img(x,y,v) = (x+y)*(v+1)/6; }
+ img.display("Color gradient");
+ \endcode
+
+ \section lo5 Loops over interior regions and borders.
+
+ Similar macros are also defined to loop only on the border of an image, or inside the image (excluding the border).
+ The border may be several pixel wide :
+
+ - \b cimg_imapX(img,x,n) : Loop along the x-axis, except for pixels inside a border of \p n pixels wide.
+ - \b cimg_imapY(img,y,n) : Loop along the y-axis, except for pixels inside a border of \p n pixels wide.
+ - \b cimg_imapZ(img,z,n) : Loop along the z-axis, except for pixels inside a border of \p n pixels wide.
+ - \b cimg_imapV(img,v,n) : Loop along the v-axis, except for pixels inside a border of \p n pixels wide.
+ - \b cimg_imapXY(img,x,y,n) : Loop along the (x,y)-axes, excepted for pixels inside a border of \p n pixels wide.
+ - \b cimg_imapXYZ(img,x,y,z,n) : Loop along the (x,y,z)-axes, excepted for pixels inside a border of \p n pixels wide.
+
+ And also :
+
+ - \b cimg_bmapX(img,x,n) : Loop along the x-axis, only for pixels inside a border of \p n pixels wide.
+ - \b cimg_bmapY(img,y,n) : Loop along the y-axis, only for pixels inside a border of \p n pixels wide.
+ - \b cimg_bmapZ(img,z,n) : Loop along the z-axis, only for pixels inside a border of \p n pixels wide.
+ - \b cimg_bmapV(img,v,n) : Loop along the z-axis, only for pixels inside a border of \p n pixels wide.
+ - \b cimg_bmapXY(img,x,y,n) : Loop along the (x,y)-axes, only for pixels inside a border of \p n pixels wide.
+ - \b cimg_bmapXYZ(img,x,y,z,n) : Loop along the (x,y,z)-axes, only for pixels inside a border of \p n pixels wide.
+
+ - For all these loops, \c x,\c y,\c z and \c v are inner-defined variables only visible inside the scope of the loop.
+ They don't have to be defined before the call of the macro.
+ - \c img must be a (non empty) cimg_library::CImg image.
+ - The constant \c n stands for the size of the border.
+
+ Here is an example of use, to create a 2d grayscale image with two different intensity gradients :
+ \code
+ CImg<> img(256,256);
+ cimg_imapXY(img,x,y,50) img(x,y) = x+y;
+ cimg_bmapXY(img,x,y,50) img(x,y) = x-y;
+ img.display();
+ \endcode
+
+ \section lo6 Loops using neighborhoods.
+
+ Inside an image loop, it is often useful to get values of neighborhood pixels of the
+ current pixel at the loop location.
+ The %CImg Library provides a very smart and fast mechanism for this purpose, with the definition
+ of several loop macros that remember the neighborhood values of the pixels.
+ The use of these macros can highly optimize your code, and also simplify your program.
+
+ \subsection lo7 Neighborhood-based loops for 2D images
+
+ For 2D images, the neighborhood-based loop macros are :
+
+ - \b cimg_map2x2x1(img,x,y,z,v,I) : Loop along the (x,y)-axes using a centered 2x2 neighborhood.
+ - \b cimg_map3x3x1(img,x,y,z,v,I) : Loop along the (x,y)-axes using a centered 3x3 neighborhood.
+ - \b cimg_map4x4x1(img,x,y,z,v,I) : Loop along the (x,y)-axes using a centered 4x4 neighborhood.
+ - \b cimg_map5x5x1(img,x,y,z,v,I) : Loop along the (x,y)-axes using a centered 5x5 neighborhood.
+
+ For all these loops, \c x and \c y are inner-defined variables only visible inside the scope of the loop.
+ They don't have to be defined before the call of the macro.
+ \c img is a non empty CImg<T> image. \c z and \c v are constants that define on which image slice and
+ vector channel the loop must apply (usually both 0 for grayscale 2D images).
+ Finally, \c I is the 2x2, 3x3, 4x4 or 5x5 neighborhood that will be updated with the correct pixel values
+ during the loop (see \ref lo9).
+
+ \subsection lo8 Neighborhood-based loops for 3D images
+
+ For 3D images, the neighborhood-based loop macros are :
+
+ - \b cimg_map2x2x2(img,x,y,z,v,I) : Loop along the (x,y,z)-axes using a centered 2x2x2 neighborhood.
+ - \b cimg_map3x3x3(img,x,y,z,v,I) : Loop along the (x,y,z)-axes using a centered 3x3x3 neighborhood.
+
+ For all these loops, \c x, \c y and \c z are inner-defined variables only visible inside the scope of the loop.
+ They don't have to be defined before the call of the macro.
+ \c img is a non empty CImg<T> image. \c v is a constant that defines on which image channel
+ the loop must apply (usually 0 for grayscale 3D images).
+ Finally, \c I is the 2x2x2 or 3x3x3 neighborhood that will be updated with the correct pixel values
+ during the loop (see \ref lo9).
+
+ \subsection lo9 Defining neighborhoods
+
+ The CImg library defines a neighborhood as a set of named \e variables or \e references, declared
+ using specific CImg macros :
+
+ - \b CImg_2x2x1(I,type) : Define a 2x2 neighborhood named \c I, of type \c type.
+ - \b CImg_3x3x1(I,type) : Define a 3x3 neighborhood named \c I, of type \c type.
+ - \b CImg_4x4x1(I,type) : Define a 4x4 neighborhood named \c I, of type \c type.
+ - \b CImg_5x5x1(I,type) : Define a 5x5 neighborhood named \c I, of type \c type.
+ - \b CImg_2x2x2(I,type) : Define a 2x2x2 neighborhood named \c I, of type \c type.
+ - \b CImg_3x3x3(I,type) : Define a 3x3x3 neighborhood named \c I, of type \c type.
+
+ Actually, \c I is a \e generic \e name for the neighborhood. In fact, these macros declare
+ a \e set of new variables.
+ For instance, defining a 3x3 neighborhood \c CImg_3x3x1(I,float) declares 9 different float variables
+ \c Ipp,\c Icp,\c Inp,\c Ipc,\c Icc,\c Inc,\c Ipn,\c Icn,\c Inn which correspond to each pixel value of
+ a 3x3 neighborhood.
+ Variable indices are \c p,\c c or \c n, and stand respectively for \e 'previous', \e 'current' and \e 'next'.
+ First indice denotes the \c x-axis, second indice denotes the \c y-axis.
+ Then, the names of the variables are directly related to the position of the corresponding pixels
+ in the neighborhood. For 3D neighborhoods, a third indice denotes the \c z-axis.
+ Then, inside a neighborhood loop, you will have the following equivalence :
+ - <tt>Ipp = img(x-1,y-1)</tt>
+ - <tt>Icn = img(x,y+1)</tt>
+ - <tt>Inp = img(x+1,y-1)</tt>
+ - <tt>Inpc = img(x+1,y-1,z)</tt>
+ - <tt>Ippn = img(x-1,y-1,z+1)</tt>
+ - and so on...
+
+ For bigger neighborhoods, such as 4x4 or 5x5 neighborhoods, two additionnal indices are introduced :
+ \c a (stands for \e 'after') and \c b (stands for \e 'before'), so that :
+ - <tt>Ibb = img(x-2,y-2)</tt>
+ - <tt>Ina = img(x+1,y+2)</tt>
+ - and so on...
+
+ The value of a neighborhood pixel outside the image range (image border problem) is automatically set to the same
+ values than the nearest valid pixel in the image (this is also called the \e Neumann \e border \e condition).
+
+ \subsection lo10 Neighborhood as a reference
+ It is also possible to define neighborhood variables as references to classical C-arrays or CImg<T> images, instead of
+ allocating new variables. This is done by adding \c _ref to the macro names used for the neighborhood definition :
+
+ - \b CImg_2x2x1_ref(I,type,tab) : Define a 2x2 neighborhood named \c I, of type \c type, as a reference to \c tab.
+ - \b CImg_3x3x1_ref(I,type,tab) : Define a 3x3 neighborhood named \c I, of type \c type, as a reference to \c tab.
+ - \b CImg_4x4x1_ref(I,type,tab) : Define a 4x4 neighborhood named \c I, of type \c type, as a reference to \c tab.
+ - \b CImg_5x5x1_ref(I,type,tab) : Define a 5x5 neighborhood named \c I, of type \c type, as a reference to \c tab.
+ - \b CImg_2x2x2_ref(I,type,tab) : Define a 2x2x2 neighborhood named \c I, of type \c type, as a reference to \c tab.
+ - \b CImg_3x3x3_ref(I,type,tab) : Define a 3x3x3 neighborhood named \c I, of type \c type, as a reference to \c tab.
+
+ \c tab can be a one-dimensionnal C-style array, or a non empty \c CImg<T> image. Both objects must have
+ same sizes as the considered neighborhoods.
+
+ \subsection lo11 Example codes
+ More than a long discussion, the above example will demonstrate how to compute the gradient norm of a 3D volume
+ using the \c cimg_map3x3x3() loop macro :
+
+ \code
+ CImg<float> volume("IRM.hdr"); // Load an IRM volume from an Analyze7.5 file
+ CImg_3x3x3(I,float); // Define a 3x3x3 neighborhood
+ CImg<float> gradnorm(volume,false); // Create an image with same size as 'volume'
+ cimg_map3x3x3(volume,x,y,z,0,I) { // Loop over the volume, using the neighborhood I
+ const float ix = 0.5f*(Incc-Ipcc); // Compute the derivative along the x-axis.
+ const float iy = 0.5f*(Icnc-Icpc); // Compute the derivative along the y-axis.
+ const float iz = 0.5f*(Iccn-Iccp); // Compute the derivative along the z-axis.
+ gradnorm(x,y,z) = std::sqrt(ix*ix+iy*iy+iz*iz); // Set the gradient norm in the destination image
+ }
+ gradnorm.display("Gradient norm");
+ \endcode
+
+ And the following example shows how to deal with neighborhood references to blur a color image by averaging
+ pixel values on a 5x5 neighborhood.
+
+ \code
+ CImg<unsigned char> src("image_color.jpg"), dest(src,false), neighbor(5,5); // Image definitions.
+ typedef unsigned char uchar; // Avoid space in the second parameter of the macro CImg_5x5x1 below.
+ CImg_5x5x1_ref(N,uchar,neighbor); // Define a 5x5 neighborhood as a reference to the 5x5 image neighbor.
+ cimg_mapV(src,k) // Standard loop on color channels
+ cimg_map5x5x1(src,x,y,0,k,N) // 5x5 neighborhood loop.
+ dest(x,y,k) = neighbor.sum()/(5*5); // Averaging pixels to filter the color image.
+ CImgl<unsigned char> visu(src,dest);
+ visu.display("Original + Filtered"); // Display both original and filtered image.
+ \endcode
+
+ Note that in this example, we didn't use directly the variables Nbb,Nbp,..,Ncc,... since
+ there are only references to the neighborhood image \c neighbor. We rather used a member function of \c neighbor.
+
+ As you can see, explaining the use of the CImg neighborhood macros is actually more difficult than using them !
+
+**/
+/*@}*/
+
+/** \addtogroup cimg_displays Using Display Windows. */
+/*@{*/
+/**
+ \page foo_di
+
+ When opening a display window, you can choose the way the pixel values will be normalized
+ before being displayed on the screen. Screen displays only support color values between [0,255],
+ and some
+
+ When displaying an image into the display window using CImgDisplay::display(), values of
+ the image pixels can be eventually linearly normalized between [0,255] for visualization purposes.
+ This may be useful for instance when displaying \p CImg<double> images with pixel values
+ between [0,1].
+ The normalization behavior depends on the value of \p normalize which can be either \p 0,\p 1 or \p 2 :
+ - \p 0 : No pixel normalization is performed when displaying an image. This is the fastest
+ process, but you must be sure your displayed image have pixel values inside the range [0,255].
+ - \p 1 : Pixel value normalization is done for each new image display. Image pixels are
+ not modified themselves, only displayed pixels are normalized.
+ - \p 2 : Pixel value normalization is done for the first image display, then the
+ normalization parameters are kept and used for all the next image displays.
+
+**/
+/*@}*/
+
+/** \addtogroup cimg_storage How pixel data are stored with CImg. */
+/*@{*/
+/**
+ \page foo_store
+
+ TODO
+**/
+/*@}*/
+
+/** \addtogroup cimg_files_io Files IO in CImg. */
+/*@{*/
+/**
+ \page foo_fi
+
+ The %CImg Library can NATIVELY handle the following file formats :
+ - RAW : consists in a very simple header (in ascii), then the image data.
+ - ASC (Ascii)
+ - HDR (Analyze 7.5)
+ - INR (Inrimage)
+ - PPM/PGM (Portable Pixmap)
+ - BMP (uncompressed)
+ - PAN (Pandore-5)
+ - DLM (Matlab ASCII)
+
+ If ImageMagick is installed, The %CImg Library can save image in formats handled by ImageMagick : JPG, GIF, PNG, TIF,...
+
+**/
+/*@}*/
+
+/** \addtogroup cimg_options Retrieving Command Line Arguments. */
+/*@{*/
+/**
+ \page foo_so
+
+ The CImg library offers facilities to retrieve command line arguments in a console-based
+ program, as it is a commonly needed operation.
+ Two macros \c cimg_usage() and \c cimg_option() are defined for this purpose.
+ Using these macros allows to easily retrieve options values from the command line.
+ Moreover, invoking the corresponding executable with the option \c -h or \c --help will
+ automatically display the program usage, followed by the list of requested options.
+
+ \section so1 The cimg_usage() macro
+
+ The macro \c cimg_usage(usage) may be used to describe the program goal and usage.
+ It is generally inserted one time after the <tt>int main(int argc,char **argv)</tt> definition.
+
+ \param usage : A string describing the program goal and usage.
+ \pre The function where \c cimg_usage() is used must have correctly defined \c argc and \c argv variables.
+
+ \section so2 The cimg_option() macro
+
+ The macro \c cimg_option(name,default,usage) may be used to retrieve an option value from the command line.
+
+ \param name : The name of the option to be retrieved from the command line.
+ \param default : The default value returned by the macro if no options \p name has been specified when running the program.
+ \param usage : A brief explanation of the option. If \c usage==NULL, the option won't appear on the option list
+ when invoking the executable with options \c -h or \c --help (hidden option).
+
+ \return \c cimg_option() returns an object that has the \e same \e type than the default value \c default.
+ The return value is equal to the one specified on the command line. If no such option have been specified,
+ the return value is equal to the default value \c default.
+ Warning, this can be confusing in some situations (look at the end of the next section).
+ \pre The function where \c cimg_option() is used must have correctly defined \c argc and \c argv variables.
+
+ \section so3 Example of use
+
+ The code below uses the macros \c cimg_usage() and \c cimg_option().
+ It loads an image, smoothes it an quantifies it with a specified number of values.
+ \code
+ #include "CImg.h"
+ using namespace cimg_library;
+ int main(int argc,char **argv) {
+ cimg_usage("Retrieve command line arguments");
+ const char* filename = cimg_option("-i","image.gif","Input image file");
+ const char* output = cimg_option("-o",(const char*)NULL,"Output image file");
+ const double sigma = cimg_option("-s",1.0,"Standard variation of the gaussian smoothing");
+ const int nblevels = cimg_option("-n",16,"Number of quantification levels");
+ const bool hidden = cimg_option("-hidden",false,NULL); // This is a hidden option
+
+ CImg<unsigned char> img(filename);
+ img.blur(sigma).quantize(nblevels);
+ if (output) img.save(output); else img.display("Output image");
+ if (hidden) std::fprintf(stderr,"You found me !\n");
+ return 0;
+ }
+ \endcode
+
+ Invoking the corresponding executable with <tt>test -h -hidden -n 20 -i foo.jpg</tt> will display :
+ \verbatim
+ ./test -h -hidden -n 20 -i foo.jpg
+
+ test : Retrieve command line arguments (Oct 16 2004, 12:34:26)
+
+ -i = foo.jpg : Input image file
+ -o = NULL : Output image file
+ -s = 1 : Standard variation of the gaussian smoothing
+ -n = 20 : Number of quantification levels
+
+ You found me !
+\endverbatim
+
+ \warning As the type of object returned by the macro \c cimg_option(option,default,usage)
+ is defined by the type of \c default, undesired casts may appear when writting code such as :
+ \code
+ const double sigma = cimg_option("-val",0,"A floating point value");
+ \endcode
+ In this case, \c sigma will always be equal to an integer (since the default value \c 0 is an integer).
+ When passing a float value on the command line, a \e float \e to \e integer cast is then done,
+ truncating the given parameter to an integer value (this is surely not a desired behavior).
+ You must specify <tt>0.0</tt> as the default value in this case.
+
+ \section so4 How to learn more about command line options ?
+ You should take a look at the examples <tt>examples/inrcast.cpp</tt> provided in the %CImg Library package.
+ This is a command line based image converter which intensively uses the \c cimg_option() and \c cimg_usage()
+ macros to retrieve command line parameters.
+**/
+/*@}*/
+
+#endif
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/chalk/plugins/filters/cimg/Makefile.am b/chalk/plugins/filters/cimg/Makefile.am
new file mode 100644
index 00000000..5bedb23b
--- /dev/null
+++ b/chalk/plugins/filters/cimg/Makefile.am
@@ -0,0 +1,35 @@
+KDE_CXXFLAGS = $(USE_EXCEPTIONS) -D_GNU_SOURCE
+
+kde_services_DATA = chalkcimg.desktop
+
+# all_includes must remain last!
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkcimg_la_SOURCES = \
+ wdg_cimg.ui\
+ kis_cimg_filter.cc\
+ kis_cimg_plugin.cc\
+ kis_cimgconfig_widget.cc
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = chalkcimg.la
+
+noinst_HEADERS = \
+ CImg.h\
+ kis_cimg_filter.h\
+ kis_cimg_plugin.h\
+ kis_cimgconfig_widget.h
+
+chalkcimg_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkcimg_la_LIBADD = ../../../libchalkcommon.la
+
+chalkcimg_la_METASOURCES = AUTO
+
+
+KDE_OPTIONS = nofinal
diff --git a/chalk/plugins/filters/cimg/chalkcimg.desktop b/chalk/plugins/filters/cimg/chalkcimg.desktop
new file mode 100644
index 00000000..ae7bd2c3
--- /dev/null
+++ b/chalk/plugins/filters/cimg/chalkcimg.desktop
@@ -0,0 +1,79 @@
+[Desktop Entry]
+Name=CImg Image Restoration Filter
+Name[bg]=Филтър за възстановяване на изображение CImg
+Name[ca]=Filtre de restauració d'imatges Clmg
+Name[cy]=Hidlen adfer Delwedd CImg
+Name[da]=Cimg-billedrestaureringsfilter
+Name[de]=CImg Filter zur Bildrestauration
+Name[el]=Φίλτρο αποκατάστασης εικόνων CImg
+Name[es]=Filtro para restauración de imágenes CImg
+Name[et]=CImg pilditaastamisfilter
+Name[eu]=CImg irudiak zaharberritzeko iragazkia
+Name[fa]=پالایۀ بازگردانی تصویر CImg
+Name[fr]=Filtre de restauration d'images de CImg
+Name[fy]=CImg ôfbyldingsrestauraasjefilter
+Name[gl]=Filtro de Restauración de Imaxe CImg
+Name[hu]=CImg képhelyreállító szűrő
+Name[is]=CImg myndbjörgunarsía
+Name[it]=Filtro CImg di restauro delle immagini
+Name[ja]=Cimg 画像復元フィルタ
+Name[km]=តម្រង​សម្រាប់​ស្ដារ​រូបភាព CImg
+Name[ms]=Penapis Pemulihan Imej Clmg
+Name[nb]=CImg-filter for bilderestaurering
+Name[nds]=CImg-Filter för't Bild-Wedderherstellen
+Name[ne]=सीआईएमजी छवि आरोग्यता फिल्टर
+Name[nl]=CImg afbeeldingsrestauratiefilter
+Name[nn]=CImg-filter for biletrestaurering
+Name[pl]=Filtr CImg do restaurowania obrazków
+Name[pt]=Filtro de Restauro de Imagem CImg
+Name[pt_BR]=Filtro de Restauração de Imagens CImg
+Name[ru]=Восстановление изображения CImg
+Name[sk]=CImg filter pre obnovu obrázkov
+Name[sl]=Filter CImg za obnavljanje slik
+Name[sr]=CImg, филтер за обнову слика
+Name[sr@Latn]=CImg, filter za obnovu slika
+Name[sv]=Cimg-bildrestaureringsfilter
+Name[uk]=Фільтр (CImg) відновлення зображень
+Name[zh_CN]=CImg 图像修复滤镜
+Name[zh_TW]=CImg 圖片修復過濾器
+Comment=CImg Image restoration filter
+Comment[bg]=Филтър за възстановяване на изображение CImg
+Comment[ca]=Filtre de restauració d'imatges Clmg
+Comment[cy]=Hidlen adfer Delwedd CImg
+Comment[da]=Cimg-billedforbedringsfilter
+Comment[de]=CImg basierter Filter zur Bildrestauration
+Comment[el]=Φίλτρο αποκατάστασης εικόνων CImg
+Comment[es]=Filtro para restauración de imágenes CImg
+Comment[et]=CImg pilditaastamisfilter
+Comment[eu]=CImg irudiak zaharberritzeko iragazkia
+Comment[fa]=پالایۀ بازگردانی تصویر CImg
+Comment[fr]=Filtre de restauration d'images de CImg
+Comment[fy]=CImg ôfbyldingsrestauraasjefilter
+Comment[gl]=Filtro de restauración de imaxe CImg
+Comment[hu]=CImg képhelyreállító szűrő
+Comment[is]=CImg mynda endurheimtasía
+Comment[it]=Filtro CImg di restauro delle immagini
+Comment[ja]=Cimg 画像復元フィルタ
+Comment[km]=តម្រង​សម្រាប់​ស្ដារ​រូបភាព CImg
+Comment[ms]=Penapis pemulihan Imej Clmg
+Comment[nb]=CImg-filter for bilderestaurering
+Comment[nds]=Op CImg opbuut Filter för't Bild-Wedderherstellen
+Comment[ne]=सिआईएमजी छवि आरोग्यता फिल्टर
+Comment[nl]=CImg afbeeldingrestauratiefilter
+Comment[nn]=CImg-filter for biletrestaurering
+Comment[pl]=Filtr CImg do restaurowania obrazków
+Comment[pt]=Filtro de restauro de imagem CImg
+Comment[pt_BR]=Filtro de restauração de imagens CImg
+Comment[ru]=Восстановление изображения на основе CImg
+Comment[sk]=CImg filter pre obnovu obrázkov
+Comment[sl]=Filter CImg za obnavljanje slik
+Comment[sr]=CImg, филтер за обнову слика
+Comment[sr@Latn]=CImg, filter za obnovu slika
+Comment[sv]=Cimg-bildförbättringsfilter
+Comment[uk]=Фільтр (CImg) відновлення зображень
+Comment[zh_CN]=CImg 图像修复滤镜
+Comment[zh_TW]=CImg 圖片修復過濾器
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkcimg
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/cimg/kis_cimg_filter.cc b/chalk/plugins/filters/cimg/kis_cimg_filter.cc
new file mode 100644
index 00000000..dc074e7b
--- /dev/null
+++ b/chalk/plugins/filters/cimg/kis_cimg_filter.cc
@@ -0,0 +1,711 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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.
+ *
+ * Ported from the CImg Gimp plugin by Victor Stinner and uses CImg by David Tschumperlé.
+ * See: http://www.girouette-stinner.com/castor/gimp.html?girouette=ad761bc2f4dcfda1cb44c587da17f86c
+ */
+
+#include <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+#include <tqspinbox.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <knuminput.h>
+
+#include <kis_colorspace_factory_registry.h>
+#include <kis_doc.h>
+#include <kis_filter_registry.h>
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_meta_registry.h>
+#include <kis_painter.h>
+#include <kis_global.h>
+#include <kis_types.h>
+
+#include "kis_cimgconfig_widget.h"
+#include "kis_cimg_filter.h"
+
+#include "CImg.h"
+
+using namespace cimg_library;
+typedef unsigned char uchar;
+
+
+KisCImgFilterConfiguration::KisCImgFilterConfiguration()
+ : KisFilterConfiguration("cimg", 1)
+{
+ nb_iter = 1;
+ dt = 20.0;
+ sigma = 1.4;
+ dlength = 0.8;
+ dtheta = 45.0;
+ onormalize = false;
+ power1 = 0.1;
+ power2 = 0.9;
+ gauss_prec = 3.0;
+ linear = true;
+}
+
+void KisCImgFilterConfiguration::fromXML(const TQString & s)
+{
+ KisFilterConfiguration::fromXML( s );
+
+ nb_iter = getInt("nb_iter", 1);
+ dt = getDouble("dt", 20.0);
+ sigma = getDouble("sigma", 1.4);
+ dlength = getDouble("dlength", 0.8);
+ dtheta = getDouble("dtheta", 45.0);
+ onormalize = getBool("onormalize", false);
+ power1 = getDouble("power1", 0.1);
+ power2 = getDouble("power2", 0.9);
+ gauss_prec = getDouble("gauss_pref", 3.0);
+ linear = getBool("linear", true);
+}
+
+
+TQString KisCImgFilterConfiguration::toString()
+{
+ m_properties.clear();
+
+ setProperty("nb_iter", nb_iter);
+ setProperty("dt", dt);
+ setProperty("sigma", sigma);
+ setProperty("dlength", dlength);
+ setProperty("dtheta", dtheta);
+ setProperty("onormalize", onormalize);
+ setProperty("power1", power1);
+ setProperty("power2", power2);
+ setProperty("gauss_prec", gauss_prec);
+ setProperty("linear", linear);
+
+ return KisFilterConfiguration::toString();
+}
+
+KisCImgFilter::KisCImgFilter()
+ : KisFilter(id(), "enhance", i18n("&CImg Image Restoration...")),
+ eigen(CImg<>(2,1), CImg<>(2,2))
+{
+ restore = true;
+ inpaint = false;
+ resize = false;
+ visuflow = NULL;
+
+ /* restore */
+ nb_iter = 1;
+ dt = 20.0f;
+ sigma = 0.8f;
+ dlength = 0.8;
+ dtheta = 45.0;
+ onormalize = false;
+ power1 = 0.5;
+ power2 = 0.9;
+
+ /* inpainting *
+ nb_iter = 100;
+ dt = 50.0f;
+ sigma = 2.0;
+ power1 = 0.1;
+ power2 = 100;
+ dlength = 0.8;
+ dtheta = 45.0;
+ */
+
+ /* resize *
+ nb_iter = 1;
+ dt = 30.0f;
+ sigma = 2.0;
+ dlength = 0.8;
+ dtheta = 45.0;
+ power1 = 0.01;
+ power2 = 100.0;
+ */
+
+ /* visualflow *
+ nb_iter = 1;
+ dt = 30.0f;
+ dlength = 0.5;
+ dtheta = 20.0;
+ onormalize = false;
+ */
+
+ gauss_prec = 3.0f;
+ linear = true;
+}
+
+
+void KisCImgFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* configuration, const TQRect& rect)
+{
+ Q_UNUSED(dst);
+
+ TQ_INT32 width = rect.width();
+ TQ_INT32 height = rect.height();
+
+ // Copy the src data into a CImg type image with three channels and no alpha.
+ // XXX: This means that a CImg is always rgba; find the quickest way to get 8-bit rgb from any colorspace & find a way
+ // to warn in the gui of loss of precision. XXX: Add this to the ColorSpaceAPI doc.
+
+ img = CImg<>(width, height, 1, 3);
+
+ KisColorSpace * cs = src->colorSpace();
+ KisColorSpace* rgb16CS = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA16"),"");
+ KisPaintDeviceSP srcRGB16;
+ if(rgb16CS)
+ {
+ srcRGB16 = new KisPaintDevice(*src.data());
+ srcRGB16->convertTo(rgb16CS);
+ KisRectIteratorPixel it = srcRGB16->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), false);
+ while (!it.isDone()) {
+ TQ_UINT16* data = reinterpret_cast<TQ_UINT16*>(it.rawData());
+
+ TQ_INT32 x = it.x() - rect.x();
+ TQ_INT32 y = it.y() - rect.y();
+
+ img(x, y, 0) = data[0];
+ img(x, y, 1) = data[1];
+ img(x, y, 2) = data[2];
+
+ ++it;
+ }
+ } else {
+ kdDebug() << "The RGB16 colorspace is not available, will work in 8bit." << endl;
+ KisRectIteratorPixel it = src->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), false);
+ while (!it.isDone()) {
+
+ TQColor color;
+ cs->toTQColor(it.rawData(), &color);
+
+ TQ_INT32 x = it.x() - rect.x();
+ TQ_INT32 y = it.y() - rect.y();
+
+ img(x, y, 0) = color.red();
+ img(x, y, 1) = color.green();
+ img(x, y, 2) = color.blue();
+
+ ++it;
+ }
+ }
+
+ // Copy the config data into local variables for easy cut & pasting from the original plugin
+
+ KisCImgFilterConfiguration * cfg = (KisCImgFilterConfiguration*)configuration;
+
+ nb_iter = cfg->nb_iter;
+ dt = cfg->dt;
+ dlength = cfg->dlength;
+ dtheta = cfg->dtheta;
+ sigma = cfg->sigma;
+ power1 = cfg->power1;
+ power2 = cfg->power2;
+ gauss_prec = cfg->gauss_prec;
+ onormalize = cfg->onormalize;
+ linear = cfg->linear;
+
+ if (process() && !cancelRequested()) {
+
+
+ if(rgb16CS)
+ {
+ {
+ KisRectIteratorPixel it = srcRGB16->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true);
+ while (!it.isDone()) {
+ TQ_INT32 x = it.x() - rect.x();
+ TQ_INT32 y = it.y() - rect.y();
+
+ TQ_UINT16* data = reinterpret_cast<TQ_UINT16*>(it.rawData());
+
+ data[0] = img(x, y, 0) ;
+ data[1] = img(x, y, 1) ;
+ data[2] = img(x, y, 2) ;
+
+ ++it;
+ }
+ }
+ srcRGB16->convertTo(cs);
+ KisPainter p(dst);
+ p.bitBlt(rect.x(), rect.y(), COMPOSITE_OVER, srcRGB16, rect.x(), rect.y(), rect.width(), rect.height() );
+ } else {
+ KisRectIteratorPixel it = dst->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true);
+
+ while (!it.isDone()) {
+
+ if (it.isSelected()) {
+
+ TQ_INT32 x = it.x() - rect.x();
+ TQ_INT32 y = it.y() - rect.y();
+
+ TQColor color((int)img(x, y, 0), (int)img(x, y, 1), (int)img(x, y, 2));
+
+ cs->fromTQColor(color, it.rawData());
+ }
+
+ ++it;
+ }
+ }
+ } else {
+ // Everything went wrong; notify user and restore old state
+ }
+
+}
+
+//----------------------------------------------------------------------------
+// Cut & Pasted code starts here....
+//----------------------------------------------------------------------------
+
+void get_geom(const char *geom, int &geom_w, int &geom_h)
+{
+ char tmp[16];
+ std::sscanf(geom,"%d%7[^0-9]%d%7[^0-9]",&geom_w,tmp,&geom_h,tmp+1);
+ if (tmp[0]=='%') geom_w=-geom_w;
+ if (tmp[1]=='%') geom_h=-geom_h;
+}
+
+
+//----------------------------------------------------------------------------
+
+void KisCImgFilter::cleanup()
+{
+ img0 = flow = G = dest = sum= W = CImg<>();
+ tqmask = CImg<uchar> ();
+}
+
+//----------------------------------------------------------------------------
+
+bool KisCImgFilter::prepare()
+{
+ if (!restore && !inpaint && !resize && !visuflow)
+ {
+ // XXX: Do KDE messagebox
+ // g_message ("You must specify one of the restore, inpaint, resize or flow mode !");
+ return false;
+ }
+
+ // Init algorithm parameters
+ //---------------------------
+ if (restore) if (!prepare_restore()) return false;
+ if (inpaint) if (!prepare_inpaint()) return false;
+ if (resize) if (!prepare_resize()) return false;
+ if (visuflow) if (!prepare_visuflow()) return false;
+
+ if (!check_args()) return false;
+
+ // Init images
+ //------------
+ dest = CImg<>(img.width,img.height,1,img.dim);
+ sum = CImg<>(img.width,img.height,1);
+ W = CImg<>(img.width,img.height,1,2);
+
+ return true;
+}
+
+//----------------------------------------------------------------------------
+
+bool KisCImgFilter::check_args()
+{
+ if (power2 < power1)
+ {
+ // XXX: Do KDE messagebox
+ // g_message ("Error : p2<p1 !");
+ return false;
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+
+bool KisCImgFilter::prepare_restore()
+{
+ CImgStats stats(img, false);
+ img.normalize((float)stats.min, (float)stats.max);
+ img0 = img;
+ G = CImg<>(img.width,img.height,1,3);
+ return true;
+}
+
+//----------------------------------------------------------------------------
+
+bool KisCImgFilter::prepare_inpaint()
+{
+ const char *file_m = NULL; //cimg_option("-m",(const char*)NULL,"Input inpainting tqmask");
+ if (!file_m)
+ {
+ // XXX: Do KDE messagebox
+ // g_message ("You need to specify an inpainting tqmask (option '-m') !");
+ return false;
+ }
+
+ const unsigned int dilate = 0; //cimg_option("-dilate",0,"Inpainting tqmask dilatation");
+ const unsigned int ip_init = 3; //cimg_option("-init",3,"Inpainting init (0=black, 1=white, 2=noise, 3=unchanged, 4=interpol)");
+ if (cimg::strncasecmp("block",file_m,5))
+ tqmask = CImg<uchar>(file_m);
+ else {
+ int l=16; std::sscanf(file_m,"block%d",&l);
+ tqmask = CImg<uchar>(img.width/l,img.height/l);
+ cimg_mapXY(tqmask,x,y) tqmask(x,y)=(x+y)%2;
+ }
+ tqmask.resize(img.width,img.height,1,1);
+ if (dilate) tqmask.dilate(dilate);
+ switch (ip_init) {
+ case 0 : { cimg_mapXYV(img,x,y,k) if (tqmask(x,y)) img(x,y,k) = 0; } break;
+ case 1 : { cimg_mapXYV(img,x,y,k) if (tqmask(x,y)) img(x,y,k) = 255; } break;
+ case 2 : { cimg_mapXYV(img,x,y,k) if (tqmask(x,y)) img(x,y,k) = (float)(255*cimg::rand()); } break;
+ case 3 : break;
+ case 4 : {
+ CImg<uchar> ttqmask(tqmask),nttqmask(ttqmask);
+ CImg_3x3(M,uchar);
+ CImg_3x3(I,float);
+ while (CImgStats(nttqmask,false).max>0) {
+ cimg_map3x3(ttqmask,x,y,0,0,M) if (Mcc && (!Mpc || !Mnc || !Mcp || !Mcn)) {
+ const float ccp = Mcp?0.0f:1.0f, cpc = Mpc?0.0f:1.0f,
+ cnc = Mnc?0.0f:1.0f, ccn = Mcn?0.0f:1.0f, csum = ccp + cpc + cnc + ccn;
+ cimg_mapV(img,k) {
+ cimg_get3x3(img,x,y,0,k,I);
+ img(x,y,k) = (ccp*Icp + cpc*Ipc + cnc*Inc + ccn*Icn)/csum;
+ }
+ nttqmask(x,y) = 0;
+ }
+ ttqmask = nttqmask;
+ }
+ } break;
+ default: break;
+ }
+ img0=img;
+ G = CImg<>(img.width,img.height,1,3,0);
+ CImg_3x3(g,uchar);
+ CImg_3x3(I,float);
+ cimg_map3x3(tqmask,x,y,0,0,g) if (!gcc && !(gnc-gcc) && !(gcc-gpc) && !(gcn-gcc) && !(gcc-gcp)) cimg_mapV(img,k) {
+ cimg_get3x3(img,x,y,0,k,I);
+ const float ix = 0.5f*(Inc-Ipc), iy = 0.5f*(Icn-Icp);
+ G(x,y,0)+= ix*ix; G(x,y,1)+= ix*iy; G(x,y,2)+= iy*iy;
+ }
+ G.blur(sigma);
+ { cimg_mapXY(G,x,y)
+ {
+ G.get_tensor(x,y).symeigen(eigen(0),eigen(1));
+ const float
+ l1 = eigen(0)[0],
+ l2 = eigen(0)[1],
+ u = eigen(1)[0],
+ v = eigen(1)[1],
+ ng = (float)std::sqrt(l1+l2),
+ n1 = (float)(1.0/std::pow(1+ng,power1)),
+ n2 = (float)(1.0/std::pow(1+ng,power2)),
+ sr1 = (float)std::sqrt(n1),
+ sr2 = (float)std::sqrt(n2);
+ G(x,y,0) = sr1*u*u + sr2*v*v;
+ G(x,y,1) = u*v*(sr1-sr2);
+ G(x,y,2) = sr1*v*v + sr2*u*u;
+ }
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------
+
+bool KisCImgFilter::prepare_resize()
+{
+ const char *geom = NULL; //cimg_option("-g",(const char*)NULL,"Output image tqgeometry");
+ const bool anchor = true; //cimg_option("-anchor",true,"Anchor original pixels");
+ if (!geom) throw CImgArgumentException("You need to specify an output geomety (option -g)");
+ int w,h; get_geom(geom,w,h);
+ tqmask = CImg<uchar>(img.width,img.height,1,1,255);
+ if (!anchor) tqmask.resize(w,h,1,1,1); else tqmask = ~tqmask.resize(w,h,1,1,4);
+ img0 = img.get_resize(w,h,1,-100,1);
+ img.resize(w,h,1,-100,3);
+ G = CImg<>(img.width,img.height,1,3);
+ return true;
+}
+
+//----------------------------------------------------------------------------
+
+bool KisCImgFilter::prepare_visuflow()
+{
+ const char *geom = "100%x100%"; //cimg_option("-g","100%x100%","Output tqgeometry");
+ //const char *file_i = (const char *)NULL; //cimg_option("-i",(const char*)NULL,"Input init image");
+ const bool normalize = false; //cimg_option("-norm",false,"Normalize input flow");
+
+ int w,h; get_geom(geom,w,h);
+ if (!cimg::strcasecmp(visuflow,"circle")) { // Create a circular vector flow
+ flow = CImg<>(400,400,1,2);
+ cimg_mapXY(flow,x,y) {
+ const float ang = (float)(std::atan2(y-0.5*flow.dimy(),x-0.5*flow.dimx()));
+ flow(x,y,0) = -(float)std::sin(ang);
+ flow(x,y,1) = (float)std::cos(ang);
+ }
+ }
+ if (!cimg::strcasecmp(visuflow,"radial")) { // Create a radial vector flow
+ flow = CImg<>(400,400,1,2);
+ cimg_mapXY(flow,x,y) {
+ const float ang = (float)(std::atan2(y-0.5*flow.dimy(),x-0.5*flow.dimx()));
+ flow(x,y,0) = (float)std::cos(ang);
+ flow(x,y,1) = (float)std::sin(ang);
+ }
+ }
+ if (!flow.data) flow = CImg<>(visuflow);
+ flow.resize(w,h,1,2,3);
+ if (normalize) flow.orientation_pointwise();
+ /* if (file_i) img = CImg<>(file_i);
+ else img = CImg<>(flow.width,flow.height,1,1,0).noise(100,2); */
+ img0=img;
+ img0.fill(0);
+ float color[3]={255,255,255};
+ img0.draw_quiver(flow,color,15,-10);
+ G = CImg<>(img.width,img.height,1,3);
+ return true;
+}
+
+//----------------------------------------------------------------------------
+
+void KisCImgFilter::compute_smoothed_tensor()
+{
+ if (visuflow || inpaint) return;
+ CImg_3x3(I,float);
+ G.fill(0);
+ cimg_mapV(img,k) cimg_map3x3(img,x,y,0,k,I) {
+ const float ix = 0.5f*(Inc-Ipc), iy = 0.5f*(Icn-Icp);
+ G(x,y,0)+= ix*ix; G(x,y,1)+= ix*iy; G(x,y,2)+= iy*iy;
+ }
+ G.blur(sigma);
+}
+
+//----------------------------------------------------------------------------
+
+void KisCImgFilter::compute_normalized_tensor()
+{
+ if (restore || resize) cimg_mapXY(G,x,y) {
+ G.get_tensor(x,y).symeigen(eigen(0),eigen(1));
+ const float
+ l1 = eigen(0)[0],
+ l2 = eigen(0)[1],
+ u = eigen(1)[0],
+ v = eigen(1)[1],
+ n1 = (float)(1.0/std::pow(1.0f+l1+l2,0.5f*power1)),
+ n2 = (float)(1.0/std::pow(1.0f+l1+l2,0.5f*power2));
+ G(x,y,0) = n1*u*u + n2*v*v;
+ G(x,y,1) = u*v*(n1-n2);
+ G(x,y,2) = n1*v*v + n2*u*u;
+ }
+ if (visuflow) cimg_mapXY(G,x,y) {
+ const float
+ u = flow(x,y,0),
+ v = flow(x,y,1),
+ n = (float)std::pow(u*u+v*v,0.25f),
+ nn = n < 1e-5 ? 1 : n;
+ G(x,y,0) = u*u/nn;
+ G(x,y,1) = u*v/nn;
+ G(x,y,2) = v*v/nn;
+ }
+
+ const CImgStats stats(G,false);
+ G /= cimg::max(std::fabs(stats.max), std::fabs(stats.min));
+}
+
+//----------------------------------------------------------------------------
+
+void KisCImgFilter::compute_W(float cost, float sint)
+{
+ cimg_mapXY(W,x,y) {
+ const float
+ a = G(x,y,0),
+ b = G(x,y,1),
+ c = G(x,y,2),
+ u = a*cost + b*sint,
+ v = b*cost + c*sint;
+ W(x,y,0) = u;
+ W(x,y,1) = v;
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void KisCImgFilter::compute_LIC_back_forward(int x, int y)
+{
+ float l, X,Y, cu, cv, lsum=0;
+ const float
+ fsigma2 = 2*dt*(W(x,y,0)*W(x,y,0) + W(x,y,1)*W(x,y,1)),
+ length = gauss_prec*(float)std::sqrt(fsigma2);
+
+ if (linear) {
+
+ // Integrate with linear interpolation
+ cu = W(x,y,0); cv = W(x,y,1); X=(float)x; Y=(float)y;
+ for (l=0; l<length && X>=0 && Y>=0 && X<=W.dimx()-1 && Y<=W.dimy()-1; l+=dlength) {
+ float u = (float)(W.linear_pix2d(X,Y,0)), v = (float)(W.linear_pix2d(X,Y,1));
+ const float coef = (float)std::exp(-l*l/fsigma2);
+ if ((cu*u+cv*v)<0) { u=-u; v=-v; }
+ cimg_mapV(dest,k) dest(x,y,k)+=(float)(coef*img.linear_pix2d(X,Y,k));
+ X+=dlength*u; Y+=dlength*v; cu=u; cv=v; lsum+=coef;
+ }
+ cu = W(x,y,0); cv = W(x,y,1); X=x-dlength*cu; Y=y-dlength*cv;
+ for (l=dlength; l<length && X>=0 && Y>=0 && X<=W.dimx()-1 && Y<=W.dimy()-1; l+=dlength) {
+ float u = (float)(W.linear_pix2d(X,Y,0)), v = (float)(W.linear_pix2d(X,Y,1));
+ const float coef = (float)std::exp(-l*l/fsigma2);
+ if ((cu*u+cv*v)<0) { u=-u; v=-v; }
+ cimg_mapV(dest,k) dest(x,y,k)+=(float)(coef*img.linear_pix2d(X,Y,k));
+ X-=dlength*u; Y-=dlength*v; cu=u; cv=v; lsum+=coef;
+ }
+ } else {
+
+ // Integrate with non linear interpolation
+ cu = W(x,y,0); cv = W(x,y,1); X=(float)x; Y=(float)y;
+ for (l=0; l<length && X>=0 && Y>=0 && X<=W.dimx()-1 && Y<=W.dimy()-1; l+=dlength) {
+ float u = W((int)X,(int)Y,0), v = W((int)X,(int)Y,1);
+ const float coef = (float)std::exp(-l*l/fsigma2);
+ if ((cu*u+cv*v)<0) { u=-u; v=-v; }
+ cimg_mapV(dest,k) dest(x,y,k)+=(float)(coef*img.linear_pix2d(X,Y,k));
+ X+=dlength*u; Y+=dlength*v; cu=u; cv=v; lsum+=coef;
+ }
+ cu = W(x,y,0); cv = W(x,y,1); X=x-dlength*cu; Y=y-dlength*cv;
+ for (l=dlength; l<length && X>=0 && Y>=0 && X<=W.dimx()-1 && Y<=W.dimy()-1; l+=dlength) {
+ float u = W((int)X,(int)Y,0), v = W((int)X,(int)Y,1);
+ const float coef = (float)std::exp(-l*l/fsigma2);
+ if ((cu*u+cv*v)<0) { u=-u; v=-v; }
+ cimg_mapV(dest,k) dest(x,y,k)+=(float)(coef*img.linear_pix2d(X,Y,k));
+ X-=dlength*u; Y-=dlength*v; cu=u; cv=v; lsum+=coef;
+ }
+ }
+ sum(x,y)+=lsum;
+}
+
+//----------------------------------------------------------------------------
+
+void KisCImgFilter::compute_LIC(int &progressSteps)
+{
+ dest.fill(0);
+ sum.fill(0);
+ for (float theta=(180%(int)dtheta)/2.0f; theta<180; theta+=dtheta)
+ {
+ const float
+ rad = (float)(theta*cimg::PI/180.0),
+ cost = (float)std::cos(rad),
+ sint = (float)std::sin(rad);
+
+ // Compute vector field w = sqrt(T)*a_alpha
+ compute_W(cost, sint);
+
+ // Compute the LIC along w in backward and forward directions
+ cimg_mapXY(dest,x,y)
+ {
+ setProgress(progressSteps);
+ progressSteps++;
+
+ if (cancelRequested()) {
+ return;
+ }
+
+ if (!tqmask.data || tqmask(x,y)) compute_LIC_back_forward(x,y);
+ }
+ }
+
+}
+
+//----------------------------------------------------------------------------
+
+void KisCImgFilter::compute_average_LIC()
+{
+ cimg_mapXY(dest,x,y)
+ {
+ if (sum(x,y)>0)
+ cimg_mapV(dest,k) dest(x,y,k) /= sum(x,y);
+ else
+ cimg_mapV(dest,k) dest(x,y,k) = img(x,y,k);
+ }
+}
+
+
+bool KisCImgFilter::process()
+{
+ if (!prepare()) return false;
+
+ setProgressTotalSteps(dest.width * dest.height * nb_iter * (int)ceil(180 / dtheta));
+ setProgressStage(i18n("Applying image restoration filter..."), 0);
+
+ //-------------------------------------
+ // Begin regularization PDE iterations
+ //-------------------------------------
+ int progressSteps = 0;
+ for (unsigned int iter=0; iter<nb_iter; iter++)
+ {
+ // Compute smoothed structure tensor field G
+ compute_smoothed_tensor();
+
+ // Compute normalized tensor field sqrt(T) in G
+ compute_normalized_tensor();
+
+ // Compute LIC's along different angle projections a_\alpha
+ compute_LIC(progressSteps);
+
+ if (cancelRequested()) {
+ break;
+ }
+
+ // Average all the LIC's
+ compute_average_LIC();
+
+ // Next step
+ img = dest;
+ }
+
+ setProgressDone();
+ // Save result and end program
+ //-----------------------------
+ if (visuflow) dest.mul(flow.get_norm_pointwise()).normalize(0,255);
+ if (onormalize) dest.normalize(0,255);
+ cleanup();
+ return true;
+}
+
+KisFilterConfigWidget * KisCImgFilter::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP /*dev*/)
+{
+ return new KisCImgconfigWidget(this, tqparent);
+}
+
+KisFilterConfiguration* KisCImgFilter::configuration(TQWidget* nwidget)
+{
+ KisCImgconfigWidget * widget = (KisCImgconfigWidget *) nwidget;
+ if( widget == 0 )
+ {
+ KisCImgFilterConfiguration * cfg = new KisCImgFilterConfiguration();
+ Q_CHECK_PTR(cfg);
+ return cfg;
+
+ } else {
+ return widget->config();
+ }
+}
+
+ColorSpaceIndependence KisCImgFilter::colorSpaceIndependence()
+{
+ KisColorSpace* rgb16CS = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA16"),"");
+ if(rgb16CS)
+ {
+ return TO_RGBA16;
+ } else {
+ return TO_RGBA8;
+ }
+}
diff --git a/chalk/plugins/filters/cimg/kis_cimg_filter.h b/chalk/plugins/filters/cimg/kis_cimg_filter.h
new file mode 100644
index 00000000..3b745476
--- /dev/null
+++ b/chalk/plugins/filters/cimg/kis_cimg_filter.h
@@ -0,0 +1,124 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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_CIMG_FILTER_H_
+#define _KIS_CIMG_FILTER_H_
+
+#include "kis_filter.h"
+#include "kis_filter_config_widget.h"
+#include "CImg.h"
+
+class KisCImgFilterConfiguration : public KisFilterConfiguration
+{
+
+public:
+
+ KisCImgFilterConfiguration();
+ virtual TQString toString();
+ virtual void fromXML(const TQString & s);
+
+public:
+
+ TQ_INT32 nb_iter; // Number of smoothing iterations
+ double dt; // Time step
+ double dlength; // Integration step
+ double dtheta; // Angular step (in degrees)
+ double sigma; // Structure tensor blurring
+ double power1; // Diffusion limiter along isophote
+ double power2; // Diffusion limiter along gradient
+ double gauss_prec; // Precision of the gaussian function
+ bool onormalize; // Output image normalization (in [0,255])
+ bool linear; // Use linear interpolation for integration ?
+};
+
+
+class KisCImgFilter : public KisFilter
+{
+public:
+ KisCImgFilter();
+public:
+ virtual void process(KisPaintDeviceSP,KisPaintDeviceSP, KisFilterConfiguration* , const TQRect&);
+ static inline KisID id() { return KisID("cimg", i18n("Image Restoration (cimg-based)")); };
+ virtual bool supportsPainting() { return false; }
+ virtual bool supportsPreview() { return false; }
+ virtual ColorSpaceIndependence colorSpaceIndependence();
+public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration * configuration(TQWidget*);
+ virtual KisFilterConfiguration * configuration() { return new KisCImgFilterConfiguration();};
+private:
+
+ bool process();
+
+ // Compute smoothed structure tensor field G
+ void compute_smoothed_tensor();
+
+ // Compute normalized tensor field sqrt(T) in G
+ void compute_normalized_tensor();
+
+ // Compute LIC's along different angle projections a_\alpha
+ void compute_LIC(int &counter);
+ void compute_LIC_back_forward(int x, int y);
+ void compute_W(float cost, float sint);
+
+ // Average all the LIC's
+ void compute_average_LIC();
+
+ // Prepare datas
+ bool prepare();
+ bool prepare_restore();
+ bool prepare_inpaint();
+ bool prepare_resize();
+ bool prepare_visuflow();
+
+ // Check arguments
+ bool check_args();
+
+ // Clean up memory (CImg datas) to save memory
+ void cleanup();
+
+private:
+ unsigned int nb_iter; // Number of smoothing iterations
+ float dt; // Time step
+ float dlength; // Integration step
+ float dtheta; // Angular step (in degrees)
+ float sigma; // Structure tensor blurring
+ float power1; // Diffusion limiter along isophote
+ float power2; // Diffusion limiter along gradient
+ float gauss_prec; // Precision of the gaussian function
+ bool onormalize; // Output image normalization (in [0,255])
+ bool linear; // Use linear interpolation for integration
+
+
+ // internal use
+ bool restore;
+ bool inpaint;
+ bool resize;
+ const char* visuflow;
+ cimg_library::CImg<> dest, sum, W;
+ cimg_library::CImg<> img, img0, flow,G;
+ cimg_library::CImgl<> eigen;
+ cimg_library::CImg<unsigned char> tqmask;
+
+
+
+};
+
+#endif
diff --git a/chalk/plugins/filters/cimg/kis_cimg_plugin.cc b/chalk/plugins/filters/cimg/kis_cimg_plugin.cc
new file mode 100644
index 00000000..6c3e9522
--- /dev/null
+++ b/chalk/plugins/filters/cimg/kis_cimg_plugin.cc
@@ -0,0 +1,44 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <kgenericfactory.h>
+
+#include <kis_filter.h>
+#include "kis_cimg_plugin.h"
+#include "kis_cimg_filter.h"
+
+
+typedef KGenericFactory<KisCImgPlugin> KisCImgPluginFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkcimg, KisCImgPluginFactory( "chalk" ) )
+
+KisCImgPlugin::KisCImgPlugin(TQObject *tqparent, const char *name, const TQStringList &) : KParts::Plugin(tqparent, name)
+{
+ setInstance(KisCImgPluginFactory::instance());
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisCImgFilter());
+ }
+}
+
+KisCImgPlugin::~KisCImgPlugin()
+{
+}
+
diff --git a/chalk/plugins/filters/cimg/kis_cimg_plugin.h b/chalk/plugins/filters/cimg/kis_cimg_plugin.h
new file mode 100644
index 00000000..2d35bff4
--- /dev/null
+++ b/chalk/plugins/filters/cimg/kis_cimg_plugin.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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_CIMG_PLUGIN_H_
+#define _KIS_CIMG_PLUGIN_H_
+
+#include <kparts/plugin.h>
+
+class KisCImgPlugin : public KParts::Plugin
+{
+public:
+ KisCImgPlugin(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~KisCImgPlugin();
+};
+
+#endif
diff --git a/chalk/plugins/filters/cimg/kis_cimgconfig_widget.cc b/chalk/plugins/filters/cimg/kis_cimgconfig_widget.cc
new file mode 100644
index 00000000..c12ebf5f
--- /dev/null
+++ b/chalk/plugins/filters/cimg/kis_cimgconfig_widget.cc
@@ -0,0 +1,94 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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.
+ *
+ * Ported from the CImg Gimp plugin by Victor Stinner and David Tschumperlé.
+ */
+#include "tqlayout.h"
+#include "tqcheckbox.h"
+#include "tqpushbutton.h"
+
+#include "knuminput.h"
+
+#include "wdg_cimg.h"
+#include "kis_cimgconfig_widget.h"
+#include "kis_cimg_filter.h"
+
+KisCImgconfigWidget::KisCImgconfigWidget(KisFilter* nfilter, TQWidget * tqparent, const char * name, WFlags f)
+ : KisFilterConfigWidget(tqparent, name, f)
+{
+ m_page = new WdgCImg(this);
+ Q_CHECK_PTR(m_page);
+
+ TQHBoxLayout * l = new TQHBoxLayout(this);
+ Q_CHECK_PTR(l);
+
+ l->add(m_page);
+ nfilter->setAutoUpdate(false);
+
+// connect( m_page->bnRefresh, TQT_SIGNAL(clicked()), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->numDetail, TQT_SIGNAL(valueChanged (double)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->numGradient, TQT_SIGNAL(valueChanged (double)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->numTimeStep, TQT_SIGNAL(valueChanged (double)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->numBlur, TQT_SIGNAL(valueChanged (double)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->numBlurIterations, TQT_SIGNAL(valueChanged (int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->numAngularStep, TQT_SIGNAL(valueChanged (double)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->numIntegralStep, TQT_SIGNAL(valueChanged (double)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->numGaussian, TQT_SIGNAL(valueChanged (double)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->chkLinearInterpolation, TQT_SIGNAL(toggled(bool)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->chkNormalize, TQT_SIGNAL(toggled(bool)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+}
+
+
+KisCImgFilterConfiguration * KisCImgconfigWidget::config()
+{
+ KisCImgFilterConfiguration * cfg = new KisCImgFilterConfiguration();
+ Q_CHECK_PTR(cfg);
+
+ cfg->power1 = m_page->numDetail->value();
+ cfg->power2 = m_page->numGradient->value();
+ cfg->dt = m_page->numTimeStep->value();
+ cfg->sigma = m_page->numBlur->value();
+ cfg->nb_iter = m_page->numBlurIterations->value();
+ cfg->dtheta = m_page->numAngularStep->value();
+ cfg->dlength = m_page->numIntegralStep->value();
+ cfg->gauss_prec = m_page->numGaussian->value();
+ cfg->linear = m_page->chkLinearInterpolation->isChecked();
+ cfg->onormalize = m_page->chkNormalize->isChecked();
+
+ return cfg;
+
+}
+
+void KisCImgconfigWidget::setConfiguration(KisFilterConfiguration * config)
+{
+ KisCImgFilterConfiguration * cfg = dynamic_cast<KisCImgFilterConfiguration*>(config);
+ if (!cfg) return;
+
+ m_page->numDetail->setValue(cfg->power1);
+ m_page->numGradient->setValue(cfg->power2);
+ m_page->numTimeStep->setValue(cfg->dt);
+ m_page->numBlur->setValue(cfg->sigma);
+ m_page->numAngularStep->setValue(cfg->nb_iter);
+ m_page->numIntegralStep->setValue(cfg->dlength);
+ m_page->numGaussian->setValue(cfg->gauss_prec);
+ m_page->chkLinearInterpolation->setChecked(cfg->linear);
+ m_page->chkNormalize->setChecked(cfg->onormalize);
+}
+
+#include "kis_cimgconfig_widget.moc"
diff --git a/chalk/plugins/filters/cimg/kis_cimgconfig_widget.h b/chalk/plugins/filters/cimg/kis_cimgconfig_widget.h
new file mode 100644
index 00000000..aba373ca
--- /dev/null
+++ b/chalk/plugins/filters/cimg/kis_cimgconfig_widget.h
@@ -0,0 +1,50 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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.
+ *
+ * Ported from the CImg Gimp plugin by Victor Stinner and David Tschumperlé.
+ */
+#ifndef _KIS_CIMGCONFIG_WIDGET_
+#define _KIS_CIMGCONFIG_WIDGET_
+
+#include "wdg_cimg.h"
+#include "kis_cimg_filter.h"
+#include "kis_filter.h"
+#include "kis_filter_config_widget.h"
+
+class KisCImgconfigWidget : public KisFilterConfigWidget {
+
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ KisCImgconfigWidget(KisFilter* nfilter, TQWidget * tqparent = 0, const char * name = 0, WFlags f = 0 );
+ virtual ~KisCImgconfigWidget() {};
+
+public:
+
+ KisCImgFilterConfiguration * config();
+ void setConfiguration(KisFilterConfiguration * config);
+
+private:
+ WdgCImg * m_page;
+
+};
+
+#endif // _KIS_CIMGCONFIG_WIDGET_
diff --git a/chalk/plugins/filters/cimg/wdg_cimg.ui b/chalk/plugins/filters/cimg/wdg_cimg.ui
new file mode 100644
index 00000000..80476616
--- /dev/null
+++ b/chalk/plugins/filters/cimg/wdg_cimg.ui
@@ -0,0 +1,298 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgCImg</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgCImg</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>249</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>CImg Configuration</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <bold>1</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>Warning: this filter may take a long time.</string>
+ </property>
+ </widget>
+ <spacer row="0" column="3">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>51</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQGroupBox" row="1" column="2" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>grpPrecision</cstring>
+ </property>
+ <property name="title">
+ <string>&amp;Mathematical Precision</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel6</cstring>
+ </property>
+ <property name="text">
+ <string>Angular step:</string>
+ </property>
+ </widget>
+ <widget class="KDoubleNumInput" row="0" column="1">
+ <property name="name">
+ <cstring>numAngularStep</cstring>
+ </property>
+ <property name="value">
+ <number>45</number>
+ </property>
+ <property name="minValue">
+ <number>5</number>
+ </property>
+ <property name="maxValue">
+ <number>90</number>
+ </property>
+ </widget>
+ <widget class="KDoubleNumInput" row="1" column="1">
+ <property name="name">
+ <cstring>numIntegralStep</cstring>
+ </property>
+ <property name="value">
+ <number>0.8</number>
+ </property>
+ <property name="minValue">
+ <number>0.1</number>
+ </property>
+ <property name="maxValue">
+ <number>10</number>
+ </property>
+ </widget>
+ <widget class="KDoubleNumInput" row="2" column="1">
+ <property name="name">
+ <cstring>numGaussian</cstring>
+ </property>
+ <property name="value">
+ <number>3</number>
+ </property>
+ <property name="minValue">
+ <number>0.1</number>
+ </property>
+ <property name="maxValue">
+ <number>10</number>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="4" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>chkNormalize</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Normalize picture</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="3" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>chkLinearInterpolation</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Use linear interpolation</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel7</cstring>
+ </property>
+ <property name="text">
+ <string>Integral step:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel8</cstring>
+ </property>
+ <property name="text">
+ <string>Gaussian:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQGroupBox" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>grpSmooth</cstring>
+ </property>
+ <property name="title">
+ <string>&amp;Smoothing</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KDoubleNumInput" row="0" column="1">
+ <property name="name">
+ <cstring>numDetail</cstring>
+ </property>
+ <property name="value">
+ <number>0.1</number>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ </widget>
+ <widget class="KDoubleNumInput" row="1" column="1">
+ <property name="name">
+ <cstring>numGradient</cstring>
+ </property>
+ <property name="value">
+ <number>0.9</number>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ </widget>
+ <widget class="KDoubleNumInput" row="2" column="1">
+ <property name="name">
+ <cstring>numTimeStep</cstring>
+ </property>
+ <property name="value">
+ <number>20</number>
+ </property>
+ <property name="maxValue">
+ <number>500</number>
+ </property>
+ </widget>
+ <widget class="KDoubleNumInput" row="3" column="1">
+ <property name="name">
+ <cstring>numBlur</cstring>
+ </property>
+ <property name="value">
+ <number>1.4</number>
+ </property>
+ <property name="maxValue">
+ <number>10</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="4" column="0">
+ <property name="name">
+ <cstring>textLabel5</cstring>
+ </property>
+ <property name="text">
+ <string>Blurring iterations:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Blur:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Time step:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Gradient factor:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Detail factor:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="4" column="1">
+ <property name="name">
+ <cstring>numBlurIterations</cstring>
+ </property>
+ <property name="value">
+ <number>1</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="maxValue">
+ <number>16</number>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>numDetail</tabstop>
+ <tabstop>numGradient</tabstop>
+ <tabstop>numTimeStep</tabstop>
+ <tabstop>numBlur</tabstop>
+ <tabstop>numAngularStep</tabstop>
+ <tabstop>numIntegralStep</tabstop>
+ <tabstop>numGaussian</tabstop>
+ <tabstop>chkLinearInterpolation</tabstop>
+ <tabstop>chkNormalize</tabstop>
+</tabstops>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/filters/colorify/Colorify.cpp b/chalk/plugins/filters/colorify/Colorify.cpp
new file mode 100644
index 00000000..0b5010cf
--- /dev/null
+++ b/chalk/plugins/filters/colorify/Colorify.cpp
@@ -0,0 +1,122 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 "Colorify.h"
+
+#include <kcolorbutton.h>
+#include <kgenericfactory.h>
+
+#include <kis_iterators_pixel.h>
+
+#include "WdgColorifyBase.h"
+#include "KisWdgColorify.h"
+
+typedef KGenericFactory<ChalkColorify> ChalkColorifyFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkcolorify, ChalkColorifyFactory( "chalk" ) )
+
+ChalkColorify::ChalkColorify(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ChalkColorifyFactory::instance());
+
+
+ kdDebug(41006) << "Colorify Filter plugin. Class: "
+ << className()
+ << ", Parent: "
+ << tqparent -> className()
+ << "\n";
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisColorify());
+ }
+}
+
+ChalkColorify::~ChalkColorify()
+{
+}
+
+
+
+KisColorify::KisColorify() : KisFilter(id(), "colors", i18n("&Colorify..."))
+{
+}
+
+KisFilterConfigWidget * KisColorify::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP )
+{
+ return new KisWdgColorify(this, tqparent, "configuration of colorify");
+}
+
+KisFilterConfiguration* KisColorify::configuration(TQWidget* w)
+{
+ KisWdgColorify * wCTA = dynamic_cast<KisWdgColorify*>(w);
+ KisFilterConfiguration* config = new KisFilterConfiguration("colorify", 1);
+ if(wCTA)
+ {
+ config->setProperty("color", wCTA->widget()->colorTarget->color() );
+ }
+ return config;
+}
+
+void KisColorify::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* config, const TQRect& rect)
+{
+ Q_ASSERT(src != 0);
+ Q_ASSERT(dst != 0);
+
+ if(config == 0) config = new KisFilterConfiguration("colorify", 1);
+
+ TQVariant value;
+ TQColor cTA = (config->getProperty("color", value)) ? value.toColor() : TQColor(200,175,125);
+
+ KisRectIteratorPixel dstIt = dst->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true );
+ KisRectIteratorPixel srcIt = src->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), false);
+
+ KisColorSpace * cs = src->colorSpace();
+ TQ_UINT8* colorpixel = new TQ_UINT8[ cs->pixelSize() ];
+
+ cs->fromTQColor(cTA, colorpixel);
+
+ TQ_UINT16 labcTA[4];
+ TQ_UINT16 lab[4];
+
+ cs->toLabA16(colorpixel, (TQ_UINT8*)labcTA, 1);
+
+ int pixelsProcessed = 0;
+ setProgressTotalSteps(rect.width() * rect.height());
+
+ //TQ_INT32 pixelsize = cs->pixelSize();
+
+ while( ! srcIt.isDone() )
+ {
+ if(srcIt.isSelected())
+ {
+ cs->toLabA16(srcIt.oldRawData(), (TQ_UINT8*)lab, 1);
+ labcTA[0] = lab[0];
+ cs->fromLabA16((TQ_UINT8*)labcTA, dstIt.rawData(), 1);
+ }
+ setProgress(++pixelsProcessed);
+ ++srcIt;
+ ++dstIt;
+ }
+ delete[] colorpixel;
+ setProgressDone(); // Must be called even if you don't really support progression
+}
+
+
diff --git a/chalk/plugins/filters/colorify/Colorify.h b/chalk/plugins/filters/colorify/Colorify.h
new file mode 100644
index 00000000..36378505
--- /dev/null
+++ b/chalk/plugins/filters/colorify/Colorify.h
@@ -0,0 +1,56 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 COLORIFY_H
+#define COLORIFY_H
+
+// TODO: remove that
+#define LCMS_HEADER <lcms.h>
+// TODO: remove it !
+
+#include <kparts/plugin.h>
+
+#include "kis_filter.h"
+
+class ChalkColorify : public KParts::Plugin
+{
+public:
+ ChalkColorify(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ChalkColorify();
+};
+
+
+class KisColorify : public KisFilter {
+ public:
+ KisColorify();
+ public:
+ virtual void process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration*, const TQRect&);
+ static inline KisID id() { return KisID("colorify", i18n("Colorify...")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ virtual bool supportsAdjustmentLayers() { return false; }
+ virtual ColorSpaceIndependence colorSpaceIndendendence() { return TO_LAB16; };
+ public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration* configuration(TQWidget*);
+};
+
+#endif
diff --git a/chalk/plugins/filters/colorify/KisWdgColorify.cpp b/chalk/plugins/filters/colorify/KisWdgColorify.cpp
new file mode 100644
index 00000000..3d1e2413
--- /dev/null
+++ b/chalk/plugins/filters/colorify/KisWdgColorify.cpp
@@ -0,0 +1,50 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 "KisWdgColorify.h"
+
+#include <tqcheckbox.h>
+#include <tqlayout.h>
+#include <tqspinbox.h>
+
+#include <kcolorbutton.h>
+
+#include <kis_filter.h>
+
+#include "WdgColorifyBase.h"
+
+KisWdgColorify::KisWdgColorify( KisFilter* nfilter, TQWidget * tqparent, const char * name) : KisFilterConfigWidget ( tqparent, name )
+{
+ TQGridLayout *widgetLayout = new TQGridLayout(this, 1, 1);
+ m_widget = new WdgColorifyBase(this);
+ widgetLayout -> addWidget(m_widget,0,0);
+ connect( m_widget->colorTarget, TQT_SIGNAL( changed(const TQColor&)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+}
+
+void KisWdgColorify::setConfiguration(KisFilterConfiguration* config)
+{
+ TQVariant value;
+ if(config->getProperty("color", value))
+ {
+ m_widget->colorTarget->setColor( value.toColor() );
+ }
+}
+
+#include "KisWdgColorify.moc"
diff --git a/chalk/plugins/filters/colorify/KisWdgColorify.h b/chalk/plugins/filters/colorify/KisWdgColorify.h
new file mode 100644
index 00000000..662a24cd
--- /dev/null
+++ b/chalk/plugins/filters/colorify/KisWdgColorify.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_WDG_COLORIFY_H_
+#define _KIS_WDG_COLORIFY_H_
+
+// TODO: remove that
+#define LCMS_HEADER <lcms.h>
+// TODO: remove it !
+
+#include <kis_filter_config_widget.h>
+
+class KisFilter;
+class WdgColorifyBase;
+
+class KisWdgColorify : public KisFilterConfigWidget
+{
+ Q_OBJECT
+ TQ_OBJECT
+ public:
+ KisWdgColorify( KisFilter* nfilter, TQWidget * tqparent, const char * name);
+ inline WdgColorifyBase* widget() { return m_widget; };
+ virtual void setConfiguration(KisFilterConfiguration*);
+ private:
+ WdgColorifyBase* m_widget;
+};
+
+#endif
diff --git a/chalk/plugins/filters/colorify/Makefile.am b/chalk/plugins/filters/colorify/Makefile.am
new file mode 100644
index 00000000..d3e348e9
--- /dev/null
+++ b/chalk/plugins/filters/colorify/Makefile.am
@@ -0,0 +1,23 @@
+chalkrcdir = $(kde_datadir)/chalk/chalkplugins
+
+kde_services_DATA = chalkcolorifyfilter.desktop
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+
+
+kde_module_LTLIBRARIES = chalkcolorify.la
+
+
+chalkcolorify_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkcolorify_la_LIBADD = ../../../libchalkcommon.la
+
+METASOURCES = AUTO
+chalkcolorify_la_SOURCES = Colorify.cpp KisWdgColorify.cpp\
+ WdgColorifyBase.ui
diff --git a/chalk/plugins/filters/colorify/WdgColorifyBase.ui b/chalk/plugins/filters/colorify/WdgColorifyBase.ui
new file mode 100644
index 00000000..a5fcebf9
--- /dev/null
+++ b/chalk/plugins/filters/colorify/WdgColorifyBase.ui
@@ -0,0 +1,97 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgColorifyBase</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgColorifyBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>133</width>
+ <height>63</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <spacer row="1" column="2">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>61</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLayoutWidget" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>tqlayout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Color:</string>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>colorTarget</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>50</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcolorbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/filters/colorify/chalkcolorifyfilter.desktop b/chalk/plugins/filters/colorify/chalkcolorifyfilter.desktop
new file mode 100644
index 00000000..78aa2b93
--- /dev/null
+++ b/chalk/plugins/filters/colorify/chalkcolorifyfilter.desktop
@@ -0,0 +1,42 @@
+[Desktop Entry]
+Icon=
+Name=Color Filters (Extension)
+Name[bg]=Цветови филтри (разширения)
+Name[ca]=Filtres de color (Extensió)
+Name[da]=Farvefiltre (Udvidelse)
+Name[de]=Farbfilter (Erweiterung)
+Name[el]=Χρωματικά φίλτρα (Επέκταση)
+Name[eo]=Kolorfiltriloj (etendaĵo)
+Name[es]=Filtros de color (Extensión)
+Name[et]=Värvifiltrid (laiendus)
+Name[fa]=پالایه‌های رنگ )پسوند(
+Name[fr]=Filtres de couleurs (extension)
+Name[fy]=Kleurfilters (útwreiding)
+Name[ga]=Scagairí Datha (Eisínteacht)
+Name[gl]=Filtros de Cores (Extensións)
+Name[hu]=Színszűrők (kiterjesztés)
+Name[it]=Filtri dei colori (estensione)
+Name[ja]=カラーフィルタ (拡張)
+Name[km]=តម្រង​ពណ៌​ (ផ្នែក​បន្ថែម)
+Name[nb]=Fargefiltre (utvidelse)
+Name[nds]=Klörenfilters (Verwiedern)
+Name[ne]=रङ फिल्टरहरू (अपवाद)
+Name[nl]=Kleurfilters (extensie)
+Name[pl]=Filtry kolorów (rozszerzenie)
+Name[pt]=Filtros de Cores (Extensão)
+Name[pt_BR]=Filtros de Cores (Extensão)
+Name[ru]=Цвет (расширение)
+Name[se]=Ivdnesillit (viiddádus)
+Name[sk]=Farebné filtre (rozšírenie)
+Name[sl]=Barvni filtri (razširitev)
+Name[sr]=Филтери боја (проширење)
+Name[sr@Latn]=Filteri boja (proširenje)
+Name[sv]=Färgfilter (utökning)
+Name[uk]=Фільтри кольору (розширення)
+Name[uz]=Rang filterlari (kengaytma)
+Name[uz@cyrillic]=Ранг филтерлари (кенгайтма)
+Name[zh_TW]=色彩過濾器(延伸)
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkcolorify
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/colors/Makefile.am b/chalk/plugins/filters/colors/Makefile.am
new file mode 100644
index 00000000..70121166
--- /dev/null
+++ b/chalk/plugins/filters/colors/Makefile.am
@@ -0,0 +1,21 @@
+chalkrcdir = $(kde_datadir)/chalk/chalkplugins
+
+kde_services_DATA = chalkextensioncolorsfilters.desktop
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkextensioncolorsfilters_la_SOURCES = colors.cc kis_minmax_filters.cc kis_color_to_alpha.cc wdgcolortoalphabase.ui kis_wdg_color_to_alpha.cc
+
+kde_module_LTLIBRARIES = chalkextensioncolorsfilters.la
+noinst_HEADERS = colors.h
+
+chalkextensioncolorsfilters_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkextensioncolorsfilters_la_LIBADD = ../../../libchalkcommon.la
+
+METASOURCES = AUTO
diff --git a/chalk/plugins/filters/colors/chalkextensioncolorsfilters.desktop b/chalk/plugins/filters/colors/chalkextensioncolorsfilters.desktop
new file mode 100644
index 00000000..26b3adf4
--- /dev/null
+++ b/chalk/plugins/filters/colors/chalkextensioncolorsfilters.desktop
@@ -0,0 +1,42 @@
+[Desktop Entry]
+Icon=
+Name=Color Filters (Extension)
+Name[bg]=Цветови филтри (разширения)
+Name[ca]=Filtres de color (Extensió)
+Name[da]=Farvefiltre (Udvidelse)
+Name[de]=Farbfilter (Erweiterung)
+Name[el]=Χρωματικά φίλτρα (Επέκταση)
+Name[eo]=Kolorfiltriloj (etendaĵo)
+Name[es]=Filtros de color (Extensión)
+Name[et]=Värvifiltrid (laiendus)
+Name[fa]=پالایه‌های رنگ )پسوند(
+Name[fr]=Filtres de couleurs (extension)
+Name[fy]=Kleurfilters (útwreiding)
+Name[ga]=Scagairí Datha (Eisínteacht)
+Name[gl]=Filtros de Cores (Extensións)
+Name[hu]=Színszűrők (kiterjesztés)
+Name[it]=Filtri dei colori (estensione)
+Name[ja]=カラーフィルタ (拡張)
+Name[km]=តម្រង​ពណ៌​ (ផ្នែក​បន្ថែម)
+Name[nb]=Fargefiltre (utvidelse)
+Name[nds]=Klörenfilters (Verwiedern)
+Name[ne]=रङ फिल्टरहरू (अपवाद)
+Name[nl]=Kleurfilters (extensie)
+Name[pl]=Filtry kolorów (rozszerzenie)
+Name[pt]=Filtros de Cores (Extensão)
+Name[pt_BR]=Filtros de Cores (Extensão)
+Name[ru]=Цвет (расширение)
+Name[se]=Ivdnesillit (viiddádus)
+Name[sk]=Farebné filtre (rozšírenie)
+Name[sl]=Barvni filtri (razširitev)
+Name[sr]=Филтери боја (проширење)
+Name[sr@Latn]=Filteri boja (proširenje)
+Name[sv]=Färgfilter (utökning)
+Name[uk]=Фільтри кольору (розширення)
+Name[uz]=Rang filterlari (kengaytma)
+Name[uz@cyrillic]=Ранг филтерлари (кенгайтма)
+Name[zh_TW]=色彩過濾器(延伸)
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkextensioncolorsfilters
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/colors/colors.cc b/chalk/plugins/filters/colors/colors.cc
new file mode 100644
index 00000000..d9a42134
--- /dev/null
+++ b/chalk/plugins/filters/colors/colors.cc
@@ -0,0 +1,53 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 "colors.h"
+
+#include <kgenericfactory.h>
+
+#include "kis_minmax_filters.h"
+#include "kis_color_to_alpha.h"
+
+typedef KGenericFactory<ChalkExtensionsColors> ChalkExtensionsColorsFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkextensioncolorsfilters, ChalkExtensionsColorsFactory( "chalk" ) )
+
+ChalkExtensionsColors::ChalkExtensionsColors(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ChalkExtensionsColorsFactory::instance());
+
+
+ kdDebug(41006) << "Extensions Colors Filter plugin. Class: "
+ << className()
+ << ", Parent: "
+ << tqparent -> className()
+ << "\n";
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisFilterMax());
+ manager->add(new KisFilterMin());
+ manager->add(new KisFilterColorToAlpha());
+ }
+}
+
+ChalkExtensionsColors::~ChalkExtensionsColors()
+{
+}
diff --git a/chalk/plugins/filters/colors/colors.h b/chalk/plugins/filters/colors/colors.h
new file mode 100644
index 00000000..d93ae1cc
--- /dev/null
+++ b/chalk/plugins/filters/colors/colors.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 COLORS_H
+#define COLORS_H
+
+// TODO: remove that
+#define LCMS_HEADER <lcms.h>
+// TODO: remove it !
+
+#include <kparts/plugin.h>
+
+class ChalkExtensionsColors : public KParts::Plugin
+{
+public:
+ ChalkExtensionsColors(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ChalkExtensionsColors();
+};
+
+#endif
diff --git a/chalk/plugins/filters/colors/kis_color_to_alpha.cc b/chalk/plugins/filters/colors/kis_color_to_alpha.cc
new file mode 100644
index 00000000..28814910
--- /dev/null
+++ b/chalk/plugins/filters/colors/kis_color_to_alpha.cc
@@ -0,0 +1,95 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <tqcheckbox.h>
+#include <tqspinbox.h>
+
+#include <kcolorbutton.h>
+
+#include <kis_iterators_pixel.h>
+
+#include "wdgcolortoalphabase.h"
+#include "kis_wdg_color_to_alpha.h"
+
+KisFilterColorToAlpha::KisFilterColorToAlpha() : KisFilter(id(), "colors", i18n("&Color to Alpha..."))
+{
+}
+
+KisFilterConfigWidget * KisFilterColorToAlpha::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP )
+{
+ return new KisWdgColorToAlpha(this, tqparent, "configuration of color to alpha");
+}
+
+KisFilterConfiguration* KisFilterColorToAlpha::configuration(TQWidget* w)
+{
+ KisWdgColorToAlpha * wCTA = dynamic_cast<KisWdgColorToAlpha*>(w);
+ KisFilterConfiguration* config = new KisFilterConfiguration("colortoalpha", 1);
+ if(wCTA)
+ {
+ config->setProperty("targetcolor", wCTA->widget()->colorTarget->color() );
+ config->setProperty("threshold", wCTA->widget()->intThreshold->value());
+ }
+ return config;
+}
+
+void KisFilterColorToAlpha::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* config, const TQRect& rect)
+{
+ Q_ASSERT(src != 0);
+ Q_ASSERT(dst != 0);
+
+ if(config == 0) config = new KisFilterConfiguration("colortoalpha", 1);
+
+ TQVariant value;
+ TQColor cTA = (config->getProperty("targetcolor", value)) ? value.toColor() : TQColor(255,255,255);
+ int threshold = (config->getProperty("threshold", value)) ? value.toInt() : 0;
+
+ KisRectIteratorPixel dstIt = dst->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true );
+ KisRectIteratorPixel srcIt = src->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), false);
+
+ int pixelsProcessed = 0;
+ setProgressTotalSteps(rect.width() * rect.height());
+
+ KisColorSpace * cs = src->colorSpace();
+ TQ_INT32 pixelsize = cs->pixelSize();
+
+ TQ_UINT8* color = new TQ_UINT8[pixelsize];
+ cs->fromTQColor(cTA, color);
+
+ while( ! srcIt.isDone() )
+ {
+ if(srcIt.isSelected())
+ {
+ TQ_UINT8 d = cs->difference(color, srcIt.oldRawData());
+ if( d >= threshold )
+ {
+ cs->setAlpha(dstIt.rawData(), 255, 1);
+ } else {
+ cs->setAlpha(dstIt.rawData(), (255 * d ) / threshold, 1 );
+ }
+ }
+ setProgress(++pixelsProcessed);
+ ++srcIt;
+ ++dstIt;
+ }
+ delete[] color;
+ setProgressDone(); // Must be called even if you don't really support progression
+}
diff --git a/chalk/plugins/filters/colors/kis_color_to_alpha.h b/chalk/plugins/filters/colors/kis_color_to_alpha.h
new file mode 100644
index 00000000..9161b38e
--- /dev/null
+++ b/chalk/plugins/filters/colors/kis_color_to_alpha.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_COLOR_TO_ALPHA_H_
+#define KIS_COLOR_TO_ALPHA_H_
+
+// TODO: remove that
+#define LCMS_HEADER <lcms.h>
+// TODO: remove it !
+
+#include "kis_filter.h"
+
+class KisFilterColorToAlpha : public KisFilter {
+ public:
+ KisFilterColorToAlpha();
+ public:
+ virtual void process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration*, const TQRect&);
+ static inline KisID id() { return KisID("colortoalpha", i18n("Color to Alpha")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ virtual bool supportsAdjustmentLayers() { return false; }
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return FULLY_INDEPENDENT; };
+ public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration* configuration(TQWidget*);
+};
+
+
+#endif
diff --git a/chalk/plugins/filters/colors/kis_minmax_filters.cc b/chalk/plugins/filters/colors/kis_minmax_filters.cc
new file mode 100644
index 00000000..eac48ad3
--- /dev/null
+++ b/chalk/plugins/filters/colors/kis_minmax_filters.cc
@@ -0,0 +1,162 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <kis_iterators_pixel.h>
+
+typedef void (*funcMaxMin)(const TQ_UINT8* , TQ_UINT8* , uint );
+
+template<typename _TYPE>
+void maximize(const TQ_UINT8* s, TQ_UINT8* 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<typename _TYPE>
+ void minimize(const TQ_UINT8* s, TQ_UINT8* 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(), "colors", i18n("M&aximize Channel"))
+{
+}
+
+void KisFilterMax::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* /*config*/, const TQRect& rect)
+{
+ Q_ASSERT(src != 0);
+ Q_ASSERT(dst != 0);
+
+ KisRectIteratorPixel dstIt = dst->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true );
+ KisRectIteratorPixel srcIt = src->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), false);
+
+ int pixelsProcessed = 0;
+ setProgressTotalSteps(rect.width() * rect.height());
+
+ KisColorSpace * cs = src->colorSpace();
+ TQ_INT32 nC = cs->nColorChannels();
+
+ funcMaxMin F;
+ KisChannelInfo::enumChannelValueType cT = cs->channels()[0]->channelValueType();
+ if( cT == KisChannelInfo::UINT8 || cT == KisChannelInfo::INT8 )
+ {
+ F = & maximize<TQ_UINT8>;
+ } else if( cT == KisChannelInfo::UINT16 || cT == KisChannelInfo::INT16 )
+ {
+ F = & maximize<TQ_UINT8>;
+ } else if( cT == KisChannelInfo::FLOAT32 )
+ {
+ F = & maximize<float>;
+ } else {
+ return;
+ }
+
+ while( ! srcIt.isDone() )
+ {
+ if(srcIt.isSelected())
+ {
+ F( srcIt.oldRawData(), dstIt.rawData(), nC);
+ }
+ setProgress(++pixelsProcessed);
+ ++srcIt;
+ ++dstIt;
+ }
+ setProgressDone(); // Must be called even if you don't really support progression
+}
+
+KisFilterMin::KisFilterMin() : KisFilter(id(), "colors", i18n("M&inimize Channel"))
+{
+}
+
+void KisFilterMin::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* /*config*/, const TQRect& rect)
+{
+ Q_ASSERT(src != 0);
+ Q_ASSERT(dst != 0);
+
+ KisRectIteratorPixel dstIt = dst->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true );
+ KisRectIteratorPixel srcIt = src->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), false);
+
+ int pixelsProcessed = 0;
+ setProgressTotalSteps(rect.width() * rect.height());
+
+ KisColorSpace * cs = src->colorSpace();
+ TQ_INT32 nC = cs->nColorChannels();
+
+ funcMaxMin F;
+ KisChannelInfo::enumChannelValueType cT = cs->channels()[0]->channelValueType();
+ if( cT == KisChannelInfo::UINT8 || cT == KisChannelInfo::INT8 )
+ {
+ F = & minimize<TQ_UINT8>;
+ } else if( cT == KisChannelInfo::UINT16 || cT == KisChannelInfo::INT16 )
+ {
+ F = & minimize<TQ_UINT8>;
+ } else if( cT == KisChannelInfo::FLOAT32 )
+ {
+ F = & minimize<float>;
+ } else {
+ return;
+ }
+
+ while( ! srcIt.isDone() )
+ {
+ if(srcIt.isSelected())
+ {
+ F( srcIt.oldRawData(), dstIt.rawData(), nC);
+ }
+ setProgress(++pixelsProcessed);
+ ++srcIt;
+ ++dstIt;
+ }
+ setProgressDone(); // Must be called even if you don't really support progression
+}
+
diff --git a/chalk/plugins/filters/colors/kis_minmax_filters.h b/chalk/plugins/filters/colors/kis_minmax_filters.h
new file mode 100644
index 00000000..db95dc12
--- /dev/null
+++ b/chalk/plugins/filters/colors/kis_minmax_filters.h
@@ -0,0 +1,56 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_MINMAX_FILTERS_H
+#define KIS_MINMAX_FILTERS_H
+
+// TODO: remove that
+#define LCMS_HEADER <lcms.h>
+// TODO: remove it !
+
+#include "kis_filter.h"
+
+class KisFilterMax : public KisFilter
+{
+ public:
+ KisFilterMax();
+ public:
+ virtual void process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration*, const TQRect&);
+ static inline KisID id() { return KisID("maximize", i18n("Maximize Channel")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return FULLY_INDEPENDENT; };
+};
+
+class KisFilterMin : public KisFilter
+{
+ public:
+ KisFilterMin();
+ public:
+ virtual void process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration*, const TQRect&);
+ static inline KisID id() { return KisID("minimize", i18n("Minimize Channel")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return FULLY_INDEPENDENT; };
+};
+
+#endif
diff --git a/chalk/plugins/filters/colors/kis_wdg_color_to_alpha.cc b/chalk/plugins/filters/colors/kis_wdg_color_to_alpha.cc
new file mode 100644
index 00000000..e70fbc85
--- /dev/null
+++ b/chalk/plugins/filters/colors/kis_wdg_color_to_alpha.cc
@@ -0,0 +1,55 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_wdg_color_to_alpha.h"
+
+#include <tqcheckbox.h>
+#include <tqlayout.h>
+#include <tqspinbox.h>
+
+#include <kcolorbutton.h>
+
+#include <kis_filter.h>
+
+#include "wdgcolortoalphabase.h"
+
+KisWdgColorToAlpha::KisWdgColorToAlpha( KisFilter* nfilter, TQWidget * tqparent, const char * name) : KisFilterConfigWidget ( tqparent, name )
+{
+ TQGridLayout *widgetLayout = new TQGridLayout(this, 1, 1);
+ m_widget = new WdgColorToAlphaBase(this);
+ widgetLayout -> addWidget(m_widget,0,0);
+ connect( m_widget->colorTarget, TQT_SIGNAL( changed(const TQColor&)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_widget->intThreshold, TQT_SIGNAL( valueChanged ( int value) ), TQT_SIGNAL(sigPleaseUpdatePreview()));
+}
+
+void KisWdgColorToAlpha::setConfiguration(KisFilterConfiguration* config)
+{
+ TQVariant value;
+ if(config->getProperty("targetcolor", value))
+ {
+ m_widget->colorTarget->setColor( value.toColor() );
+ }
+ if(config->getProperty("threshold", value))
+ {
+ m_widget->intThreshold->setValue( value.toInt() );
+ }
+}
+
+#include "kis_wdg_color_to_alpha.moc"
diff --git a/chalk/plugins/filters/colors/kis_wdg_color_to_alpha.h b/chalk/plugins/filters/colors/kis_wdg_color_to_alpha.h
new file mode 100644
index 00000000..d2b5c9b9
--- /dev/null
+++ b/chalk/plugins/filters/colors/kis_wdg_color_to_alpha.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_WDG_COLOR_TO_ALPHA_H_
+#define _KIS_WDG_COLOR_TO_ALPHA_H_
+
+// TODO: remove that
+#define LCMS_HEADER <lcms.h>
+// TODO: remove it !
+
+#include <kis_filter_config_widget.h>
+
+class KisFilter;
+class WdgColorToAlphaBase;
+
+class KisWdgColorToAlpha : public KisFilterConfigWidget
+{
+ Q_OBJECT
+ TQ_OBJECT
+ public:
+ KisWdgColorToAlpha( KisFilter* nfilter, TQWidget * tqparent, const char * name);
+ inline WdgColorToAlphaBase* widget() { return m_widget; };
+ virtual void setConfiguration(KisFilterConfiguration*);
+ private:
+ WdgColorToAlphaBase* m_widget;
+};
+
+#endif
diff --git a/chalk/plugins/filters/colors/wdgcolortoalphabase.ui b/chalk/plugins/filters/colors/wdgcolortoalphabase.ui
new file mode 100644
index 00000000..f824a9ab
--- /dev/null
+++ b/chalk/plugins/filters/colors/wdgcolortoalphabase.ui
@@ -0,0 +1,113 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgColorToAlphaBase</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgColorToAlphaBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>133</width>
+ <height>63</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <spacer row="1" column="2">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>61</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLayoutWidget" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>tqlayout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Color:</string>
+ </property>
+ </widget>
+ <widget class="KColorButton">
+ <property name="name">
+ <cstring>colorTarget</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="color">
+ <color>
+ <red>255</red>
+ <green>255</green>
+ <blue>255</blue>
+ </color>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQSpinBox" row="1" column="1">
+ <property name="name">
+ <cstring>intThreshold</cstring>
+ </property>
+ <property name="maxValue">
+ <number>255</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Threshold:</string>
+ </property>
+ </widget>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>50</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcolorbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/filters/colorsfilters/Makefile.am b/chalk/plugins/filters/colorsfilters/Makefile.am
new file mode 100644
index 00000000..843402a3
--- /dev/null
+++ b/chalk/plugins/filters/colorsfilters/Makefile.am
@@ -0,0 +1,26 @@
+kde_services_DATA = chalkcolorsfilter.desktop
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkcolorsfilters_la_SOURCES = colorsfilters.cc \
+ kis_perchannel_filter.cc \
+ wdg_perchannel.ui \
+ wdg_brightness_contrast.ui \
+ kis_brightness_contrast_filter.cc
+
+noinst_HEADERS = colorsfilters.h \
+ kis_perchannel_filter.h \
+ kis_brightness_contrast_filter.h
+
+chalkcolorsfilters_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkcolorsfilters_la_LIBADD = ../../../libchalkcommon.la
+
+kde_module_LTLIBRARIES = chalkcolorsfilters.la
+
+chalkcolorsfilters_la_METASOURCES = AUTO
diff --git a/chalk/plugins/filters/colorsfilters/chalkcolorsfilter.desktop b/chalk/plugins/filters/colorsfilters/chalkcolorsfilter.desktop
new file mode 100644
index 00000000..2c2747f2
--- /dev/null
+++ b/chalk/plugins/filters/colorsfilters/chalkcolorsfilter.desktop
@@ -0,0 +1,94 @@
+[Desktop Entry]
+Name=Color Filters
+Name[bg]=Цветови филтри
+Name[br]=Siloù liv
+Name[ca]=Filtres de color
+Name[cy]=Hidlau lliw
+Name[da]=Farvefilter
+Name[de]=Farbfilter
+Name[el]=Χρωματικά φίλτρα
+Name[en_GB]=Colour Filters
+Name[eo]=Kolorfiltriloj
+Name[es]=Filtros de color
+Name[et]=Värvifiltrid
+Name[fa]=پالایه‌های رنگ
+Name[fi]=Värisuotimet
+Name[fr]=Filtres de couleurs
+Name[fy]=Kleurfilters
+Name[ga]=Scagairí Datha
+Name[gl]=Filtros de Cores
+Name[he]=מסנני צבעים
+Name[hu]=Színszűrők
+Name[is]=Litasíur
+Name[it]=Filtri dei colori
+Name[ja]=カラーフィルタ
+Name[km]=តម្រង​ពណ៌​
+Name[lt]=Spalvų filtrai
+Name[lv]=Krāsu filtri
+Name[nb]=Fargefiltre
+Name[nds]=Klörenfilters
+Name[ne]=रङ फिल्टरहरू
+Name[nl]=Kleurfilters
+Name[pl]=Filtry kolorów
+Name[pt]=Filtros de Cores
+Name[pt_BR]=Filtros de Cores
+Name[ru]=Цвет
+Name[se]=Ivdnesillit
+Name[sk]=Farebné filtre
+Name[sl]=Barvni filtri
+Name[sr]=Филтери боја
+Name[sr@Latn]=Filteri boja
+Name[sv]=Färgfilter
+Name[uk]=Фільтри кольору
+Name[uz]=Rang filterlari
+Name[uz@cyrillic]=Ранг филтерлари
+Name[zh_TW]=色彩過濾器
+Comment=Color filters
+Comment[bg]=Цветови филтри
+Comment[br]=Siloù liv
+Comment[ca]=Filtres de color
+Comment[cy]=Hidlau lliw
+Comment[da]=Farvefilter
+Comment[de]=Farbfilter
+Comment[el]=Χρωματικά φίλτρα
+Comment[en_GB]=Colour filters
+Comment[eo]=Kolorfiltriloj
+Comment[es]=Filtros de color
+Comment[et]=Värvifiltrid
+Comment[fa]=پالایه‌های رنگ
+Comment[fi]=Värisuotimet
+Comment[fr]=Filtres de couleurs
+Comment[fy]=Kleurfilters
+Comment[ga]=Scagairí datha
+Comment[gl]=Filtros de cores
+Comment[he]=מסנני צבעים
+Comment[hu]=Színszűrők
+Comment[is]=Litasíur
+Comment[it]=Filtri dei colori
+Comment[ja]=カラーフィルタ
+Comment[km]=តម្រង​ពណ៌​
+Comment[lt]=Spalvų filtrai
+Comment[lv]=Krāsu filtri
+Comment[nb]=Fargefiltre
+Comment[nds]=Klörenfilters
+Comment[ne]=रङ फिल्टरहरू
+Comment[nl]=Kleurfilters
+Comment[pl]=Filtry kolorów
+Comment[pt]=Filtros de cores
+Comment[pt_BR]=Filtros de cores
+Comment[ru]=Цвет
+Comment[se]=Ivdnesillit
+Comment[sk]=Farebné filtre
+Comment[sl]=Bravni filtri
+Comment[sr]=Филтери боја
+Comment[sr@Latn]=Filteri boja
+Comment[sv]=Färgfilter
+Comment[uk]=Фільтри кольору
+Comment[uz]=Rang filterlari
+Comment[uz@cyrillic]=Ранг филтерлари
+Comment[zh_CN]=颜色滤镜
+Comment[zh_TW]=色彩過濾器
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkcolorsfilters
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/colorsfilters/colorsfilters.cc b/chalk/plugins/filters/colorsfilters/colorsfilters.cc
new file mode 100644
index 00000000..cdc7dede
--- /dev/null
+++ b/chalk/plugins/filters/colorsfilters/colorsfilters.cc
@@ -0,0 +1,315 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <math.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <tqslider.h>
+#include <tqpoint.h>
+#include <tqcolor.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_layer.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_iterators_pixel.h>
+#include <kis_colorspace.h>
+#include <kis_painter.h>
+#include <kis_selection.h>
+#include "kis_histogram.h"
+#include "kis_basic_histogram_producers.h"
+#include "colorsfilters.h"
+#include "kis_brightness_contrast_filter.h"
+#include "kis_perchannel_filter.h"
+
+typedef KGenericFactory<ColorsFilters> ColorsFiltersFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkcolorsfilters, ColorsFiltersFactory( "chalk" ) )
+
+ColorsFilters::ColorsFilters(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ColorsFiltersFactory::instance());
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisBrightnessContrastFilter());
+ manager->add(new KisAutoContrast());
+ manager->add(new KisPerChannelFilter());
+ manager->add(new KisDesaturateFilter());
+ }
+}
+
+ColorsFilters::~ColorsFilters()
+{
+}
+
+
+//==================================================================
+
+
+KisAutoContrast::KisAutoContrast() : KisFilter(id(), "adjust", i18n("&Auto Contrast"))
+{
+}
+
+bool KisAutoContrast::workWith(KisColorSpace* cs)
+{
+ return (cs->getProfile() != 0);
+}
+
+void KisAutoContrast::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* , const TQRect& rect)
+{
+ // initialize
+ KisHistogramProducerSP producer = new KisGenericLabHistogramProducer();
+ KisHistogram histogram(src, 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;
+
+ KisBrightnessContrastFilterConfiguration * cfg = new KisBrightnessContrastFilterConfiguration();
+
+ for(int i=0; i <255; i++)
+ cfg->transfer[i] = 0xFFFF;
+
+ if (diff != 0)
+ {
+ for(int i=0; i <minvalue; i++)
+ cfg->transfer[i] = 0x0;
+ for(int i=minvalue; i <maxvalue; i++)
+ {
+ TQ_INT32 val = (i-minvalue)/diff;
+
+ val = int((0xFFFF * (i-minvalue)) / diff);
+ if(val >0xFFFF)
+ val=0xFFFF;
+ if(val <0)
+ val = 0;
+
+ cfg->transfer[i] = val;
+ }
+ for(int i=maxvalue; i <256; i++)
+ cfg->transfer[i] = 0xFFFF;
+ }
+
+ KisSelectionSP dstSel = 0;
+ if (dst != src) {
+ KisPainter gc(dst);
+ gc.bitBlt(rect.x(), rect.y(), COMPOSITE_COPY, src, rect.x(), rect.y(), rect.width(), rect.height());
+ gc.end();
+ if (src->hasSelection()) {
+ dstSel = dst->selection();
+ dst->setSelection(src->selection());
+ }
+ }
+
+ // apply
+ KisColorAdjustment *adj = src->colorSpace()->createBrightnessContrastAdjustment(cfg->transfer);
+
+ KisRectIteratorPixel iter = dst->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true );
+
+ setProgressTotalSteps(rect.width() * rect.height());
+ TQ_INT32 pixelsProcessed = 0;
+
+ while( ! iter.isDone() && !cancelRequested())
+ {
+ TQ_UINT32 npix=0, maxpix = iter.nConseqPixels();
+ TQ_UINT8 selectedness = iter.selectedness();
+ // The idea here is to handle stretches of completely selected and completely unselected pixels.
+ // Partially selected pixels are handled one pixel at a time.
+ switch(selectedness)
+ {
+ case MIN_SELECTED:
+ while(iter.selectedness()==MIN_SELECTED && maxpix)
+ {
+ --maxpix;
+ ++iter;
+ ++npix;
+ }
+ pixelsProcessed += npix;
+ break;
+
+ case MAX_SELECTED:
+ {
+ TQ_UINT8 *firstPixel = iter.rawData();
+ while(iter.selectedness()==MAX_SELECTED && maxpix)
+ {
+ --maxpix;
+ if (maxpix != 0)
+ ++iter;
+ ++npix;
+ }
+ // adjust
+ src->colorSpace()->applyAdjustment(firstPixel, firstPixel, adj, npix);
+ pixelsProcessed += npix;
+ ++iter;
+ break;
+ }
+
+ default:
+ // adjust, but since it's partially selected we also only partially adjust
+ src->colorSpace()->applyAdjustment(iter.oldRawData(), iter.rawData(), adj, 1);
+ const TQ_UINT8 *pixels[2] = {iter.oldRawData(), iter.rawData()};
+ TQ_UINT8 weights[2] = {MAX_SELECTED - selectedness, selectedness};
+ src->colorSpace()->mixColors(pixels, weights, 2, iter.rawData());
+ ++iter;
+ pixelsProcessed++;
+ break;
+ }
+ setProgress(pixelsProcessed);
+ }
+ // Restore selection
+ if (src != dst && src->hasSelection()) {
+ dst->setSelection(dstSel);
+ }
+ delete adj;
+ setProgressDone();
+}
+
+
+//==================================================================
+
+KisDesaturateFilter::KisDesaturateFilter()
+ : KisFilter(id(), "adjust", i18n("&Desaturate"))
+{
+ m_lastCS = 0;
+ m_adj = 0;
+
+}
+
+KisDesaturateFilter::~KisDesaturateFilter()
+{
+ delete m_adj;
+}
+
+bool KisDesaturateFilter::workWith(KisColorSpace* cs)
+{
+ return (cs->getProfile() != 0);
+}
+
+void KisDesaturateFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* /*config*/, const TQRect& rect)
+{
+ if (dst != src) {
+ KisPainter gc(dst);
+ gc.bitBlt(rect.x(), rect.y(), COMPOSITE_COPY, src, rect.x(), rect.y(), rect.width(), rect.height());
+ gc.end();
+ }
+
+ if (m_adj == 0 || (m_lastCS && m_lastCS != src->colorSpace())) {
+ m_adj = src->colorSpace()->createDesaturateAdjustment();
+ m_lastCS = src->colorSpace();
+ }
+
+ KisRectIteratorPixel iter = dst->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true );
+
+ setProgressTotalSteps(rect.width() * rect.height());
+ TQ_INT32 pixelsProcessed = 0;
+
+ while( ! iter.isDone() && !cancelRequested())
+ {
+ TQ_UINT32 npix=0, maxpix = iter.nConseqPixels();
+ TQ_UINT8 selectedness = iter.selectedness();
+ // The idea here is to handle stretches of completely selected and completely unselected pixels.
+ // Partially selected pixels are handled one pixel at a time.
+ switch(selectedness)
+ {
+ case MIN_SELECTED:
+ while(iter.selectedness()==MIN_SELECTED && maxpix)
+ {
+ --maxpix;
+ ++iter;
+ ++npix;
+ }
+ pixelsProcessed += npix;
+ break;
+
+ case MAX_SELECTED:
+ {
+ TQ_UINT8 *firstPixel = iter.rawData();
+ while(iter.selectedness()==MAX_SELECTED && maxpix)
+ {
+ --maxpix;
+ if (maxpix != 0)
+ ++iter;
+ ++npix;
+ }
+ // adjust
+ src->colorSpace()->applyAdjustment(firstPixel, firstPixel, m_adj, npix);
+ pixelsProcessed += npix;
+ ++iter;
+ break;
+ }
+
+ default:
+ // adjust, but since it's partially selected we also only partially adjust
+ src->colorSpace()->applyAdjustment(iter.oldRawData(), iter.rawData(), m_adj, 1);
+ const TQ_UINT8 *pixels[2] = {iter.oldRawData(), iter.rawData()};
+ TQ_UINT8 weights[2] = {MAX_SELECTED - selectedness, selectedness};
+ src->colorSpace()->mixColors(pixels, weights, 2, iter.rawData());
+ ++iter;
+ pixelsProcessed++;
+ break;
+ }
+ setProgress(pixelsProcessed);
+ }
+ setProgressDone();
+}
diff --git a/chalk/plugins/filters/colorsfilters/colorsfilters.h b/chalk/plugins/filters/colorsfilters/colorsfilters.h
new file mode 100644
index 00000000..ebf2dfeb
--- /dev/null
+++ b/chalk/plugins/filters/colorsfilters/colorsfilters.h
@@ -0,0 +1,73 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 BRIGHTNESSCONTRAST_H
+#define BRIGHTNESSCONTRAST_H
+
+#include <kparts/plugin.h>
+#include "kis_perchannel_filter.h"
+
+class KisColorSpace;
+class KisColorAdjustment;
+
+class ColorsFilters : public KParts::Plugin
+{
+ public:
+ ColorsFilters(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ColorsFilters();
+};
+
+class KisAutoContrast : public KisFilter {
+public:
+ KisAutoContrast();
+public:
+ virtual void process(KisPaintDeviceSP, KisPaintDeviceSP, KisFilterConfiguration* , const TQRect&);
+ static inline KisID id() { return KisID("autocontrast", i18n("Auto Contrast")); };
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsPainting() { return false; }
+ virtual bool supportsThreading() { return false; }
+ virtual bool supportsAdjustmentLayers() { return false; }
+
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return TO_LAB16; };
+ virtual bool workWith(KisColorSpace* cs);
+
+};
+
+
+class KisDesaturateFilter : public KisFilter {
+ public:
+ KisDesaturateFilter();
+ ~KisDesaturateFilter();
+ public:
+ virtual void process(KisPaintDeviceSP, KisPaintDeviceSP, KisFilterConfiguration* , const TQRect&);
+ static inline KisID id() { return KisID("desaturate", i18n("Desaturate")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return TO_LAB16; };
+ virtual bool workWith(KisColorSpace* cs);
+
+ private:
+
+ KisColorSpace * m_lastCS;
+ KisColorAdjustment * m_adj;
+};
+
+#endif
diff --git a/chalk/plugins/filters/colorsfilters/kis_brightness_contrast_filter.cc b/chalk/plugins/filters/colorsfilters/kis_brightness_contrast_filter.cc
new file mode 100644
index 00000000..c42223fb
--- /dev/null
+++ b/chalk/plugins/filters/colorsfilters/kis_brightness_contrast_filter.cc
@@ -0,0 +1,347 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ * Copyright (c) 2005 Casper Boemann <cbr@boemann.dk>
+*
+ * 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 <math.h>
+
+#include <klocale.h>
+
+#include <tqlayout.h>
+#include <tqpixmap.h>
+#include <tqpainter.h>
+#include <tqlabel.h>
+#include <tqdom.h>
+#include <tqstring.h>
+#include <tqstringlist.h>
+#include <tqpushbutton.h>
+
+#include "kis_filter_config_widget.h"
+#include "kis_brightness_contrast_filter.h"
+#include "wdg_brightness_contrast.h"
+#include "kis_colorspace.h"
+#include "kis_paint_device.h"
+#include "kis_iterators_pixel.h"
+#include "kis_iterator.h"
+#include "kcurve.h"
+#include "kis_histogram.h"
+#include "kis_basic_histogram_producers.h"
+#include "kis_painter.h"
+
+KisBrightnessContrastFilterConfiguration::KisBrightnessContrastFilterConfiguration()
+ : KisFilterConfiguration( "brightnesscontrast", 1 )
+{
+ for (TQ_UINT32 i = 0; i < 256; ++i) {
+ transfer[i] = i * 257;
+ }
+ curve.setAutoDelete(true);
+ m_adjustment = 0;
+}
+
+KisBrightnessContrastFilterConfiguration::~KisBrightnessContrastFilterConfiguration()
+{
+ delete m_adjustment;
+}
+
+void KisBrightnessContrastFilterConfiguration::fromXML( const TQString& s )
+{
+ TQDomDocument doc;
+ doc.setContent( s );
+ TQDomElement e = doc.documentElement();
+ TQDomNode n = e.firstChild();
+
+ while (!n.isNull()) {
+ e = n.toElement();
+ if (!e.isNull()) {
+ if (e.tagName() == "transfer") {
+ TQStringList data = TQStringList::split( ",", e.text() );
+ TQStringList::Iterator start = data.begin();
+ TQStringList::Iterator end = data.end();
+ int i = 0;
+ for ( TQStringList::Iterator it = start; it != end && i < 256; ++it ) {
+ TQString s = *it;
+ transfer[i] = s.toUShort();
+ i++;
+ }
+ }
+ else if (e.tagName() == "curve") {
+ TQStringList data = TQStringList::split( ";", e.text() );
+ TQStringList::Iterator pairStart = data.begin();
+ TQStringList::Iterator pairEnd = data.end();
+ curve.clear(); // XXX TQPtrList, sure I won't leak stuff here?
+ for (TQStringList::Iterator it = pairStart; it != pairEnd; ++it) {
+ TQString pair = * it;
+ if (pair.tqfind(",") > -1) {
+ TQPair<double,double> *p = new TQPair<double,double>;
+ p->first = pair.section(",", 0, 0).toDouble();
+ p->second = pair.section(",", 1, 1).toDouble();
+ curve.append(p);
+ }
+ }
+ }
+ }
+ n = n.nextSibling();
+ }
+ // If the adjustment was cached, it now has changed - tqinvalidate it
+ delete m_adjustment;
+ m_adjustment = 0;
+}
+
+TQString KisBrightnessContrastFilterConfiguration::toString()
+{
+ TQDomDocument doc = TQDomDocument("filterconfig");
+ TQDomElement root = doc.createElement( "filterconfig" );
+ root.setAttribute( "name", name() );
+ root.setAttribute( "version", version() );
+
+ doc.appendChild( root );
+
+ TQDomElement e = doc.createElement( "transfer" );
+ TQString sTransfer;
+ for ( uint i = 0; i < 255 ; ++i ) {
+ sTransfer += TQString::number( transfer[i] );
+ sTransfer += ",";
+ }
+ TQDomText text = doc.createCDATASection(sTransfer);
+ e.appendChild(text);
+ root.appendChild(e);
+
+ e = doc.createElement("curve");
+ TQString sCurve;
+ TQPair<double,double> * pair;
+ for ( pair = curve.first(); pair; pair = curve.next() ) {
+ sCurve += TQString::number(pair->first);
+ sCurve += ",";
+ sCurve += TQString::number(pair->second);
+ sCurve += ";";
+ }
+ text = doc.createCDATASection(sCurve);
+ e.appendChild(text);
+ root.appendChild(e);
+
+ return doc.toString();
+}
+
+KisBrightnessContrastFilter::KisBrightnessContrastFilter()
+ : KisFilter( id(), "adjust", i18n("&Brightness/Contrast..."))
+{
+
+}
+
+KisFilterConfigWidget * KisBrightnessContrastFilter::createConfigurationWidget(TQWidget *tqparent, KisPaintDeviceSP dev)
+{
+ return new KisBrightnessContrastConfigWidget(tqparent, dev);
+}
+
+KisFilterConfiguration* KisBrightnessContrastFilter::configuration(TQWidget *nwidget)
+{
+ KisBrightnessContrastConfigWidget* widget = (KisBrightnessContrastConfigWidget*)nwidget;
+
+ if ( widget == 0 )
+ {
+ return new KisBrightnessContrastFilterConfiguration();
+ } else {
+ return widget->config();
+ }
+}
+
+std::list<KisFilterConfiguration*> KisBrightnessContrastFilter::listOfExamplesConfiguration(KisPaintDeviceSP /*dev*/)
+{
+ //XXX should really come up with a list of configurations
+ std::list<KisFilterConfiguration*> list;
+ list.insert(list.begin(), new KisBrightnessContrastFilterConfiguration( ));
+ return list;
+}
+
+bool KisBrightnessContrastFilter::workWith(KisColorSpace* cs)
+{
+ return (cs->getProfile() != 0);
+}
+
+
+void KisBrightnessContrastFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* config, const TQRect& rect)
+{
+
+ if (!config) {
+ kdWarning() << "No configuration object for brightness/contrast filter\n";
+ return;
+ }
+
+ KisBrightnessContrastFilterConfiguration* configBC = (KisBrightnessContrastFilterConfiguration*) config;
+ Q_ASSERT(config);
+
+ if (src!=dst) {
+ KisPainter gc(dst);
+ gc.bitBlt(rect.x(), rect.y(), COMPOSITE_COPY, src, rect.x(), rect.y(), rect.width(), rect.height());
+ gc.end();
+ }
+
+ if (configBC->m_adjustment == 0) {
+ configBC->m_adjustment = src->colorSpace()->createBrightnessContrastAdjustment(configBC->transfer);
+ }
+
+ KisRectIteratorPixel iter = dst->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true );
+
+ setProgressTotalSteps(rect.width() * rect.height());
+ TQ_INT32 pixelsProcessed = 0;
+
+ while( ! iter.isDone() && !cancelRequested())
+ {
+ TQ_UINT32 npix=0, maxpix = iter.nConseqPixels();
+ TQ_UINT8 selectedness = iter.selectedness();
+ // The idea here is to handle stretches of completely selected and completely unselected pixels.
+ // Partially selected pixels are handled one pixel at a time.
+ switch(selectedness)
+ {
+ case MIN_SELECTED:
+ while(iter.selectedness()==MIN_SELECTED && maxpix)
+ {
+ --maxpix;
+ ++iter;
+ ++npix;
+ }
+ pixelsProcessed += npix;
+ break;
+
+ case MAX_SELECTED:
+ {
+ TQ_UINT8 *firstPixel = iter.rawData();
+ while(iter.selectedness()==MAX_SELECTED && maxpix)
+ {
+ --maxpix;
+ if (maxpix != 0)
+ ++iter;
+ ++npix;
+ }
+ // adjust
+ src->colorSpace()->applyAdjustment(firstPixel, firstPixel, configBC->m_adjustment, npix);
+ pixelsProcessed += npix;
+ ++iter;
+ break;
+ }
+
+ default:
+ // adjust, but since it's partially selected we also only partially adjust
+ src->colorSpace()->applyAdjustment(iter.oldRawData(), iter.rawData(), configBC->m_adjustment, 1);
+ const TQ_UINT8 *pixels[2] = {iter.oldRawData(), iter.rawData()};
+ TQ_UINT8 weights[2] = {MAX_SELECTED - selectedness, selectedness};
+ src->colorSpace()->mixColors(pixels, weights, 2, iter.rawData());
+ ++iter;
+ pixelsProcessed++;
+ break;
+ }
+ setProgress(pixelsProcessed);
+ }
+
+ setProgressDone();
+}
+
+KisBrightnessContrastConfigWidget::KisBrightnessContrastConfigWidget(TQWidget * tqparent, KisPaintDeviceSP dev, const char * name, WFlags f)
+ : KisFilterConfigWidget(tqparent, name, f)
+{
+ int i;
+ int height;
+ m_page = new WdgBrightnessContrast(this);
+ TQHBoxLayout * l = new TQHBoxLayout(this);
+ Q_CHECK_PTR(l);
+
+ //Hide these buttons and labels as they are not implemented in 1.5
+ m_page->pb_more_contrast->hide();
+ m_page->pb_less_contrast->hide();
+ m_page->pb_more_brightness->hide();
+ m_page->pb_less_brightness->hide();
+ m_page->textLabelBrightness->hide();
+ m_page->textLabelContrast->hide();
+
+ l->addWidget(m_page, 0, TQt::AlignTop);
+ height = 256;
+ connect( m_page->kCurve, TQT_SIGNAL(modified()), TQT_SIGNAL(sigPleaseUpdatePreview()));
+
+ // Create the horizontal gradient label
+ TQPixmap hgradientpix(256, 1);
+ TQPainter hgp(&hgradientpix);
+ hgp.setPen(TQPen::TQPen(TQColor(0,0,0),1, TQt::SolidLine));
+ for( i=0; i<256; ++i )
+ {
+ hgp.setPen(TQColor(i,i,i));
+ hgp.drawPoint(i, 0);
+ }
+ m_page->hgradient->setPixmap(hgradientpix);
+
+ // Create the vertical gradient label
+ TQPixmap vgradientpix(1, 256);
+ TQPainter vgp(&vgradientpix);
+ vgp.setPen(TQPen::TQPen(TQColor(0,0,0),1, TQt::SolidLine));
+ for( i=0; i<256; ++i )
+ {
+ vgp.setPen(TQColor(i,i,i));
+ vgp.drawPoint(0, 255-i);
+ }
+ m_page->vgradient->setPixmap(vgradientpix);
+
+ KisHistogramProducerSP producer = new KisGenericLabHistogramProducer();
+ KisHistogram histogram(dev, producer, LINEAR);
+ TQPixmap pix(256, height);
+ pix.fill();
+ TQPainter p(&pix);
+ p.setPen(TQPen::TQPen(TQt::gray,1, TQt::SolidLine));
+
+ double highest = (double)histogram.calculations().getHighest();
+ TQ_INT32 bins = histogram.producer()->numberOfBins();
+
+ if (histogram.getHistogramType() == LINEAR) {
+ double factor = (double)height / highest;
+ for( i=0; i<bins; ++i ) {
+ p.drawLine(i, height, i, height - int(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)histogram.getValue(i)) * factor));
+ }
+ }
+
+ m_page->kCurve->setPixmap(pix);
+
+}
+
+KisBrightnessContrastFilterConfiguration * KisBrightnessContrastConfigWidget::config()
+{
+ KisBrightnessContrastFilterConfiguration * cfg = new KisBrightnessContrastFilterConfiguration();
+
+ for(int i=0; i <256; i++)
+ {
+ TQ_INT32 val;
+ val = int(0xFFFF * m_page->kCurve->getCurveValue( i / 255.0));
+ if(val >0xFFFF)
+ val=0xFFFF;
+ if(val <0)
+ val = 0;
+
+ cfg->transfer[i] = val;
+ }
+ cfg->curve = m_page->kCurve->getCurve();
+ return cfg;
+}
+
+void KisBrightnessContrastConfigWidget::setConfiguration( KisFilterConfiguration * config )
+{
+ KisBrightnessContrastFilterConfiguration * cfg = dynamic_cast<KisBrightnessContrastFilterConfiguration *>(config);
+ m_page->kCurve->setCurve(cfg->curve);
+}
diff --git a/chalk/plugins/filters/colorsfilters/kis_brightness_contrast_filter.h b/chalk/plugins/filters/colorsfilters/kis_brightness_contrast_filter.h
new file mode 100644
index 00000000..598e4bcc
--- /dev/null
+++ b/chalk/plugins/filters/colorsfilters/kis_brightness_contrast_filter.h
@@ -0,0 +1,84 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_BRIGHTNESS_CONTRAST_FILTER_H_
+#define _KIS_BRIGHTNESS_CONTRAST_FILTER_H_
+
+#include "kis_filter.h"
+#include "kis_filter_config_widget.h"
+
+class WdgBrightnessContrast;
+class TQWidget;
+class KisColorAdjustment;
+
+class KisBrightnessContrastFilterConfiguration : public KisFilterConfiguration {
+
+public:
+
+ KisBrightnessContrastFilterConfiguration();
+ virtual ~KisBrightnessContrastFilterConfiguration();
+ virtual void fromXML( const TQString& );
+ virtual TQString toString();
+
+public:
+ TQ_UINT16 transfer[256];
+ TQPtrList<TQPair<double,double> > curve;
+ KisColorAdjustment * m_adjustment;
+};
+
+/**
+ * This class affect Intensity Y of the image
+ */
+class KisBrightnessContrastFilter : public KisFilter
+{
+
+public:
+
+ KisBrightnessContrastFilter();
+
+public:
+
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration * configuration(TQWidget *);
+ virtual KisFilterConfiguration * configuration() { return new KisBrightnessContrastFilterConfiguration(); };
+ virtual void process(KisPaintDeviceSP, KisPaintDeviceSP, KisFilterConfiguration* , const TQRect&);
+ static inline KisID id() { return KisID("brightnesscontrast", i18n("Brightness / Contrast")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ virtual std::list<KisFilterConfiguration*> listOfExamplesConfiguration(KisPaintDeviceSP dev);
+
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return TO_LAB16; };
+ virtual bool workWith(KisColorSpace* cs);
+};
+
+
+class KisBrightnessContrastConfigWidget : public KisFilterConfigWidget {
+
+public:
+ KisBrightnessContrastConfigWidget(TQWidget * tqparent, KisPaintDeviceSP dev, const char * name = 0, WFlags f = 0 );
+ virtual ~KisBrightnessContrastConfigWidget() {};
+
+ KisBrightnessContrastFilterConfiguration * config();
+ void setConfiguration( KisFilterConfiguration * config );
+ WdgBrightnessContrast * m_page;
+};
+
+#endif
diff --git a/chalk/plugins/filters/colorsfilters/kis_perchannel_filter.cc b/chalk/plugins/filters/colorsfilters/kis_perchannel_filter.cc
new file mode 100644
index 00000000..8d3aad84
--- /dev/null
+++ b/chalk/plugins/filters/colorsfilters/kis_perchannel_filter.cc
@@ -0,0 +1,421 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Casper Boemann <cbr@boemann.dk>
+ *
+ * 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 <tqlayout.h>
+#include <tqpixmap.h>
+#include <tqpainter.h>
+#include <tqlabel.h>
+#include <tqcombobox.h>
+#include <tqdom.h>
+
+#include "kis_filter_configuration.h"
+#include "kis_filter_config_widget.h"
+#include "kis_perchannel_filter.h"
+#include "wdg_perchannel.h"
+#include "kis_colorspace.h"
+#include "kis_paint_device.h"
+#include "kis_iterators_pixel.h"
+#include "kcurve.h"
+#include "kis_histogram.h"
+#include "kis_basic_histogram_producers.h"
+#include "kis_painter.h"
+
+KisPerChannelFilterConfiguration::KisPerChannelFilterConfiguration(int n)
+ : KisFilterConfiguration( "perchannel", 1 )
+{
+ curves = new TQSortedList<TQPair<double,double> >[n];
+ for(int i=0;i<n;i++) {
+ transfers[i] = new TQ_UINT16[256];
+
+ for (TQ_UINT32 j = 0; j < 256; ++j) {
+ transfers[i][j] = j * 257;
+ }
+ }
+ nTransfers = n;
+ dirty = true;
+ oldCs = 0;
+ adjustment = 0;
+}
+
+KisPerChannelFilterConfiguration::~KisPerChannelFilterConfiguration()
+{
+ delete [] curves;
+ for(int i=0;i<nTransfers;i++)
+ delete [] transfers[i];
+ delete adjustment;
+}
+
+void KisPerChannelFilterConfiguration::fromXML( const TQString& s )
+{
+ TQDomDocument doc;
+ doc.setContent( s );
+ TQDomElement e = doc.documentElement();
+ TQDomNode n = e.firstChild();
+
+ while (!n.isNull()) {
+ e = n.toElement();
+ if (!e.isNull()) {
+ if (e.attribute("name") == "curves") {
+ TQDomNode curvesNode = e.firstChild();
+ int count = 0;
+ nTransfers = e.attribute("number").toUShort();
+ curves = new TQSortedList<TQPair<double,double> >[nTransfers];
+ while (!curvesNode.isNull()) {
+ TQDomElement curvesElement = curvesNode.toElement();
+ if (!curvesElement.isNull() &&
+!curvesElement.text().isEmpty()) {
+ TQStringList data = TQStringList::split( ";",
+curvesElement.text() );
+ TQStringList::Iterator pairStart = data.begin();
+ TQStringList::Iterator pairEnd = data.end();
+ for (TQStringList::Iterator it = pairStart; it != pairEnd; ++it) {
+ TQString pair = * it;
+ if (pair.tqfind(",") > -1) {
+ TQPair<double,double> *p = new TQPair<double,double>;
+ p->first = pair.section(",", 0, 0).toDouble();
+ p->second = pair.section(",", 1, 1).toDouble();
+ curves[count].append(p);
+ }
+ }
+ }
+ count++;
+ curvesNode = curvesNode.nextSibling();
+ }
+ }
+ }
+ n = n.nextSibling();
+ }
+
+ for(int ch = 0; ch < nTransfers; ++ch)
+ {
+ transfers[ch] = new TQ_UINT16[256];
+ for(int i = 0; i < 256; ++i)
+ {
+ TQ_INT32 val;
+ val = int(0xFFFF * KCurve::getCurveValue(curves[ch], i /
+255.0));
+ if(val > 0xFFFF)
+ val = 0xFFFF;
+ if(val < 0)
+ val = 0;
+
+ transfers[ch][i] = val;
+ }
+ }
+ dirty = true;
+}
+
+TQString KisPerChannelFilterConfiguration::toString()
+{
+ TQDomDocument doc = TQDomDocument("filterconfig");
+ TQDomElement root = doc.createElement( "filterconfig" );
+ root.setAttribute( "name", name() );
+ root.setAttribute( "version", version() );
+
+ TQDomElement c = doc.createElement("curves");
+ c.setAttribute("number", nTransfers);
+ c.setAttribute("name", "curves");
+ for (int i = 0; i < nTransfers; ++i) {
+ TQDomElement t = doc.createElement("curve");
+ TQPtrList<TQPair<double,double> > curve = curves[i];
+ TQString sCurve;
+ TQPair<double,double> * pair;
+ for ( pair = curve.first(); pair; pair = curve.next() ) {
+ sCurve += TQString::number(pair->first);
+ sCurve += ",";
+ sCurve += TQString::number(pair->second);
+ sCurve += ";";
+ }
+ TQDomText text = doc.createCDATASection(sCurve);
+ t.appendChild(text);
+ c.appendChild(t);
+ }
+ root.appendChild(c);
+
+
+ doc.appendChild( root );
+ return doc.toString();
+}
+
+
+KisFilterConfigWidget * KisPerChannelFilter::createConfigurationWidget(TQWidget *tqparent, KisPaintDeviceSP dev)
+{
+ return new KisPerChannelConfigWidget(tqparent, dev);
+}
+
+KisFilterConfiguration* KisPerChannelFilter::configuration(TQWidget *nwidget)
+{
+ KisPerChannelConfigWidget* widget = (KisPerChannelConfigWidget*)nwidget;
+
+ if ( widget == 0 )
+ {
+ return 0;
+ } else {
+ return widget->config();
+ }
+}
+
+std::list<KisFilterConfiguration*> KisPerChannelFilter::listOfExamplesConfiguration(KisPaintDeviceSP dev)
+{
+ std::list<KisFilterConfiguration*> list;
+ list.insert(list.begin(), new KisPerChannelFilterConfiguration(dev->colorSpace()->nColorChannels()));
+ return list;
+}
+
+
+void KisPerChannelFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* config, const TQRect& rect)
+{
+ if (!config) {
+ kdWarning() << "No configuration object for per-channel filter\n";
+ return;
+ }
+
+ KisPerChannelFilterConfiguration* configBC =
+ dynamic_cast<KisPerChannelFilterConfiguration*>(config);
+ if (configBC->nTransfers != src->colorSpace()->nColorChannels()) {
+ // We got an illegal number of colorchannels.KisFilter
+ return;
+ }
+
+ if (configBC->dirty || (src->colorSpace() != configBC->oldCs)) {
+ delete configBC->adjustment;
+ configBC->adjustment =
+ src->colorSpace()->createPerChannelAdjustment(configBC->transfers);
+ kdDebug() << configBC->adjustment << endl;
+ configBC->oldCs = src->colorSpace();
+ configBC->dirty = false;
+ }
+
+ KisColorAdjustment *adj = configBC->adjustment;
+
+ if (src!=dst) {
+ KisPainter gc(dst);
+ gc.bitBlt(rect.x(), rect.y(), COMPOSITE_COPY, src, rect.x(), rect.y(), rect.width(), rect.height());
+ gc.end();
+ }
+
+ KisRectIteratorPixel iter = dst->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true );
+
+ setProgressTotalSteps(rect.width() * rect.height());
+ TQ_INT32 pixelsProcessed = 0;
+
+ while( ! iter.isDone() && !cancelRequested())
+ {
+ TQ_UINT32 npix=0, maxpix = iter.nConseqPixels();
+ TQ_UINT8 selectedness = iter.selectedness();
+ // The idea here is to handle stretches of completely selected and completely unselected pixels.
+ // Partially selected pixels are handled one pixel at a time.
+ switch(selectedness)
+ {
+ case MIN_SELECTED:
+ while(iter.selectedness()==MIN_SELECTED && maxpix)
+ {
+ --maxpix;
+ ++iter;
+ ++npix;
+ }
+ pixelsProcessed += npix;
+ break;
+
+ case MAX_SELECTED:
+ {
+ TQ_UINT8 *firstPixel = iter.rawData();
+ while(iter.selectedness()==MAX_SELECTED && maxpix)
+ {
+ --maxpix;
+ if (maxpix != 0)
+ ++iter;
+ ++npix;
+ }
+ // adjust
+ src->colorSpace()->applyAdjustment(firstPixel, firstPixel, adj, npix);
+ pixelsProcessed += npix;
+ ++iter;
+ break;
+ }
+
+ default:
+ // adjust, but since it's partially selected we also only partially adjust
+ src->colorSpace()->applyAdjustment(iter.oldRawData(), iter.rawData(), adj, 1);
+ const TQ_UINT8 *pixels[2] = {iter.oldRawData(), iter.rawData()};
+ TQ_UINT8 weights[2] = {MAX_SELECTED - selectedness, selectedness};
+ src->colorSpace()->mixColors(pixels, weights, 2, iter.rawData());
+ ++iter;
+ pixelsProcessed++;
+ break;
+ }
+ setProgress(pixelsProcessed);
+ }
+
+ setProgressDone();
+}
+
+void KisPerChannelConfigWidget::setActiveChannel(int ch)
+{
+ int i;
+ int height = 256;
+ TQPixmap pix(256, height);
+ pix.fill();
+ TQPainter p(&pix);
+ p.setPen(TQPen::TQPen(TQt::gray,1, TQt::SolidLine));
+
+ m_histogram->setChannel(ch);
+
+ double highest = (double)m_histogram->calculations().getHighest();
+ TQ_INT32 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));
+ }
+ }
+
+ m_curves[m_activeCh].setAutoDelete(true);
+ m_curves[m_activeCh] = m_page->kCurve->getCurve();
+ m_activeCh = ch;
+ m_page->kCurve->setCurve(m_curves[m_activeCh]);
+
+ m_page->kCurve->setPixmap(pix);
+}
+
+KisPerChannelConfigWidget::KisPerChannelConfigWidget(TQWidget * tqparent, KisPaintDeviceSP dev, const char * name, WFlags f)
+ : KisFilterConfigWidget(tqparent, name, f)
+{
+ int i;
+ int height;
+ m_page = new WdgPerChannel(this);
+ TQHBoxLayout * l = new TQHBoxLayout(this);
+ Q_CHECK_PTR(l);
+
+ m_dev = dev;
+ m_curves = new TQSortedList<TQPair<double,double> >[m_dev->colorSpace()->nColorChannels()];
+ m_activeCh = 0;
+ for(unsigned int ch=0; ch <m_dev->colorSpace()->nColorChannels(); ch++)
+ {
+ m_curves[ch].append(new TQPair<double,double>(0, 0));
+ m_curves[ch].append(new TQPair<double,double>(1, 1));
+ }
+
+ l->add(m_page);
+ height = 256;
+ connect( m_page->kCurve, TQT_SIGNAL(modified()), TQT_SIGNAL(sigPleaseUpdatePreview()));
+
+ // Fill in the channel chooser
+ TQValueVector<KisChannelInfo *> channels = dev->colorSpace()->channels();
+ for(unsigned int val=0; val < dev->colorSpace()->nColorChannels(); val++)
+ m_page->cmbChannel->insertItem(channels.at(val)->name());
+ connect( m_page->cmbChannel, TQT_SIGNAL(activated(int)), this, TQT_SLOT(setActiveChannel(int)));
+
+ // Create the horizontal gradient label
+ TQPixmap hgradientpix(256, 1);
+ TQPainter hgp(&hgradientpix);
+ hgp.setPen(TQPen::TQPen(TQColor(0,0,0),1, TQt::SolidLine));
+ for( i=0; i<256; ++i )
+ {
+ hgp.setPen(TQColor(i,i,i));
+ hgp.drawPoint(i, 0);
+ }
+ m_page->hgradient->setPixmap(hgradientpix);
+
+ // Create the vertical gradient label
+ TQPixmap vgradientpix(1, 256);
+ TQPainter vgp(&vgradientpix);
+ vgp.setPen(TQPen::TQPen(TQColor(0,0,0),1, TQt::SolidLine));
+ for( i=0; i<256; ++i )
+ {
+ vgp.setPen(TQColor(i,i,i));
+ vgp.drawPoint(0, 255-i);
+ }
+ m_page->vgradient->setPixmap(vgradientpix);
+
+ KisIDList keys =
+ KisHistogramProducerFactoryRegistry::instance()->listKeysCompatibleWith(m_dev->colorSpace());
+ KisHistogramProducerFactory *hpf;
+ hpf = KisHistogramProducerFactoryRegistry::instance()->get(*(keys.at(0)));
+ m_histogram = new KisHistogram(m_dev, hpf->generate(), LINEAR);
+
+ setActiveChannel(0);
+}
+
+KisPerChannelFilterConfiguration * KisPerChannelConfigWidget::config()
+{
+ int nCh = m_dev->colorSpace()->nColorChannels();
+ KisPerChannelFilterConfiguration * cfg = new KisPerChannelFilterConfiguration(nCh);
+
+ m_curves[m_activeCh].setAutoDelete(true);
+ m_curves[m_activeCh] = m_page->kCurve->getCurve();
+
+ for(int ch = 0; ch < nCh; ch++)
+ {
+ cfg->curves[ch].setAutoDelete(true);
+ cfg->curves[ch].clear();
+ TQPair<double, double> *p, *inpoint;
+ inpoint = m_curves[ch].first();
+ while(inpoint)
+ {
+ p = new TQPair<double, double>(inpoint->first, inpoint->second);
+ cfg->curves[ch].append(p);
+ inpoint = m_curves[ch].next();
+ }
+
+ for(int i=0; i <256; i++)
+ {
+ TQ_INT32 val;
+ val = int(0xFFFF * m_page->kCurve->getCurveValue(m_curves[ch], i / 255.0));
+ if ( val > 0xFFFF )
+ val = 0xFFFF;
+ if ( val < 0 )
+ val = 0;
+
+ cfg->transfers[ch][i] = val;
+ }
+ }
+ cfg->dirty = true;
+
+ return cfg;
+}
+
+void KisPerChannelConfigWidget::setConfiguration(KisFilterConfiguration * config)
+{
+ KisPerChannelFilterConfiguration * cfg = dynamic_cast<KisPerChannelFilterConfiguration *>(config);
+
+ for(unsigned int ch = 0; ch < cfg->nTransfers; ch++)
+ {
+ m_curves[ch].setAutoDelete(true);
+ m_curves[ch].clear();
+ TQPair<double, double> *p, *inpoint;
+ inpoint = cfg->curves[ch].first();
+ while(inpoint)
+ {
+ p = new TQPair<double, double>(inpoint->first, inpoint->second);
+ m_curves[ch].append(p);
+ inpoint = cfg->curves[ch].next();
+ }
+ }
+ m_page->kCurve->setCurve(m_curves[m_activeCh]);
+ setActiveChannel( 0 );
+}
+
+#include "kis_perchannel_filter.moc"
diff --git a/chalk/plugins/filters/colorsfilters/kis_perchannel_filter.h b/chalk/plugins/filters/colorsfilters/kis_perchannel_filter.h
new file mode 100644
index 00000000..6d11ab43
--- /dev/null
+++ b/chalk/plugins/filters/colorsfilters/kis_perchannel_filter.h
@@ -0,0 +1,100 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_PERCHANNEL_FILTER_H_
+#define _KIS_PERCHANNEL_FILTER_H_
+
+#include <tqpair.h>
+#include <tqptrlist.h>
+#include "kis_filter.h"
+#include "kis_filter_configuration.h"
+#include "kis_filter_config_widget.h"
+
+class WdgPerChannel;
+
+class KisPerChannelFilterConfiguration
+ : public KisFilterConfiguration
+{
+public:
+ KisPerChannelFilterConfiguration(int n);
+ ~KisPerChannelFilterConfiguration();
+
+ virtual void fromXML( const TQString& );
+ virtual TQString toString();
+
+public:
+ TQPtrList<TQPair<double,double> > *curves;
+ TQ_UINT16 *transfers[256];
+ TQ_UINT16 nTransfers;
+ // Caching of adjustment
+ bool dirty;
+ KisColorSpace* oldCs;
+ KisColorAdjustment* adjustment;
+};
+
+
+/**
+ * This class is generic for filters that affect channel separately
+ */
+class KisPerChannelFilter
+ : public KisFilter
+{
+public:
+ KisPerChannelFilter() : KisFilter( id(), "adjust", i18n("&Color Adjustment...")) {};
+public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration* configuration(TQWidget*);
+ virtual KisFilterConfiguration* configuration() { return new KisPerChannelFilterConfiguration(0); };
+ virtual void process(KisPaintDeviceSP, KisPaintDeviceSP, KisFilterConfiguration* , const TQRect&);
+ static inline KisID id() { return KisID("perchannel", i18n("Color Adjustment")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ virtual std::list<KisFilterConfiguration*> listOfExamplesConfiguration(KisPaintDeviceSP dev);
+
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return TO_LAB16; };
+private:
+};
+
+class KisPerChannelConfigWidget : public KisFilterConfigWidget {
+
+ typedef KisFilterConfigWidget super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisPerChannelConfigWidget(TQWidget * tqparent, KisPaintDeviceSP dev, const char * name = 0, WFlags f = 0 );
+ virtual ~KisPerChannelConfigWidget() {};
+
+ KisPerChannelFilterConfiguration * config();
+ void setConfiguration(KisFilterConfiguration * config);
+
+private slots:
+ virtual void setActiveChannel(int ch);
+
+private:
+ WdgPerChannel * m_page;
+ KisPaintDeviceSP m_dev;
+ KisHistogram *m_histogram;
+ TQPtrList<TQPair<double,double> > *m_curves;
+ int m_activeCh;
+};
+
+#endif
diff --git a/chalk/plugins/filters/colorsfilters/wdg_brightness_contrast.ui b/chalk/plugins/filters/colorsfilters/wdg_brightness_contrast.ui
new file mode 100644
index 00000000..9474462b
--- /dev/null
+++ b/chalk/plugins/filters/colorsfilters/wdg_brightness_contrast.ui
@@ -0,0 +1,292 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgBrightnessContrast</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgBrightnessContrast</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>284</width>
+ <height>346</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>BrightnessCon</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="TQLayoutWidget" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>tqlayout4</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="1" column="1">
+ <property name="name">
+ <cstring>hgradient</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>250</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>250</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQFrame" row="0" column="1">
+ <property name="name">
+ <cstring>frame3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>254</width>
+ <height>254</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>254</width>
+ <height>254</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>3</number>
+ </property>
+ <widget class="KCurve">
+ <property name="name">
+ <cstring>kCurve</cstring>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>250</width>
+ <height>250</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>250</width>
+ <height>250</height>
+ </size>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>vgradient</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>20</width>
+ <height>250</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>20</width>
+ <height>250</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>tqlayout7</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQPushButton" row="1" column="2">
+ <property name="name">
+ <cstring>pb_more_contrast</cstring>
+ </property>
+ <property name="text">
+ <string>+</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="1">
+ <property name="name">
+ <cstring>textLabelContrast</cstring>
+ </property>
+ <property name="text">
+ <string>Contrast</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="1" column="0">
+ <property name="name">
+ <cstring>pb_less_contrast</cstring>
+ </property>
+ <property name="text">
+ <string>-</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="0" column="0">
+ <property name="name">
+ <cstring>pb_less_brightness</cstring>
+ </property>
+ <property name="text">
+ <string>-</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="1">
+ <property name="name">
+ <cstring>textLabelBrightness</cstring>
+ </property>
+ <property name="text">
+ <string>Brightness</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="0" column="2">
+ <property name="name">
+ <cstring>pb_more_brightness</cstring>
+ </property>
+ <property name="text">
+ <string>+</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="1" column="1">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>131</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KCurve</class>
+ <header location="local">kcurve.h</header>
+ <sizehint>
+ <width>33</width>
+ <height>23</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="XBM.GZ" length="79">789c534e494dcbcc4b554829cdcdad8c2fcf4c29c95030e0524611cd48cd4ccf28010a1797249664262b2467241641a592324b8aa363156c15aab914146aadb90067111b1f</data>
+ </image>
+</images>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcurve.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/filters/colorsfilters/wdg_perchannel.ui b/chalk/plugins/filters/colorsfilters/wdg_perchannel.ui
new file mode 100644
index 00000000..243d628f
--- /dev/null
+++ b/chalk/plugins/filters/colorsfilters/wdg_perchannel.ui
@@ -0,0 +1,190 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgPerChannel</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgPerChannel</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>609</width>
+ <height>698</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>BrightnessCon</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Channel:</string>
+ </property>
+ </widget>
+ <widget class="TQComboBox">
+ <property name="name">
+ <cstring>cmbChannel</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout8</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="1" column="1">
+ <property name="name">
+ <cstring>hgradient</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>0</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>32767</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQFrame" row="0" column="1">
+ <property name="name">
+ <cstring>frame3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>3</number>
+ </property>
+ <widget class="KCurve">
+ <property name="name">
+ <cstring>kCurve</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>vgradient</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>20</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>20</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KCurve</class>
+ <header location="local">../../../ui/kcurve.h</header>
+ <sizehint>
+ <width>33</width>
+ <height>23</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data>
+ </image>
+</images>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcurve.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/filters/convolutionfilters/Makefile.am b/chalk/plugins/filters/convolutionfilters/Makefile.am
new file mode 100644
index 00000000..069ff51f
--- /dev/null
+++ b/chalk/plugins/filters/convolutionfilters/Makefile.am
@@ -0,0 +1,28 @@
+kde_services_DATA = chalkconvolutionfilters.desktop
+
+INCLUDES = \
+ -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../ui \
+ -I../../../ui/ \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalkconvolutionfilters.la
+
+chalkconvolutionfilters_la_SOURCES = kis_custom_convolution_filter_configuration_base_widget.ui \
+ kis_custom_convolution_filter_configuration_widget.cc \
+ kis_custom_convolution_filter.cc \
+ convolutionfilters.cc \
+ kis_convolution_filter.cc
+
+noinst_HEADERS = convolutionfilters.h \
+ kis_custom_convolution_filter_configuration_widget.h \
+ kis_convolution_filter.h
+
+chalkconvolutionfilters_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkconvolutionfilters_la_LIBADD = ../../../libchalkcommon.la
+
+chalkconvolutionfilters_la_METASOURCES = AUTO
diff --git a/chalk/plugins/filters/convolutionfilters/chalkconvolutionfilters.desktop b/chalk/plugins/filters/convolutionfilters/chalkconvolutionfilters.desktop
new file mode 100644
index 00000000..ee0b9842
--- /dev/null
+++ b/chalk/plugins/filters/convolutionfilters/chalkconvolutionfilters.desktop
@@ -0,0 +1,75 @@
+[Desktop Entry]
+Name=Convolution Filters
+Name[bg]=Изкривяващи филтри
+Name[ca]=Filtres de convolució
+Name[cy]=Hidlau cordeddiadau
+Name[da]=Foldningsfilter
+Name[de]=Faltungsfilter
+Name[el]=Φίλτρα περιέλιξης
+Name[eo]=Volvaĵfiltriloj
+Name[es]=Filtros de convolución
+Name[et]=Konvolutsioonifiltrid
+Name[fa]=پالایه‌های هم‌پیچش
+Name[fr]=Filtres de convolution
+Name[fy]=Verdraaïngsfilters
+Name[ga]=Scagairí Conbhlóide
+Name[gl]=Filtros de Convolución
+Name[hu]=Konvolúciószűrők
+Name[is]=Fléttunarsíur
+Name[it]=Filtri di convoluzione
+Name[ja]=コンボリューションフィルタ
+Name[km]=តម្រង​អង្កាញ់
+Name[nb]=Konvolusjonsfiltre
+Name[nds]=Fooldenfilters
+Name[ne]=कुण्डलीकरण फिल्टरहरू
+Name[nl]=Verdraaïngs
+Name[pl]=Filtry splotowe
+Name[pt]=Filtros de Convolução
+Name[pt_BR]=Filtros de Convolução
+Name[ru]=Cвёртка
+Name[sk]=Filtre zvinutia
+Name[sl]=Konvolucijski filtri
+Name[sr]=Конволуциони филтери
+Name[sr@Latn]=Konvolucioni filteri
+Name[sv]=Faltningsfilter
+Name[uk]=Фільтри згортки
+Name[zh_TW]=皺褶過濾器
+Comment=Convolution filters
+Comment[bg]=Изкривяващи филтри
+Comment[ca]=Filtres de convolució
+Comment[cy]=Hidlau cordeddiadau
+Comment[da]=Foldningsfilter
+Comment[de]=Faltungsfilter
+Comment[el]=Φίλτρα περιέλιξης
+Comment[eo]=Volvaĵfiltriloj
+Comment[es]=Filtros de convoluciones
+Comment[et]=Konvolutsioonifiltrid
+Comment[fa]=پالایه‌های هم‌پیچش
+Comment[fr]=Filtres de déformations
+Comment[fy]=Verdraaïngsfilters
+Comment[ga]=Scagairí conbhlóide
+Comment[gl]=Filtros de convolución
+Comment[hu]=CImg képhelyreállító szűrő
+Comment[is]=Fléttunarsíur
+Comment[it]=Filtri di convoluzione
+Comment[ja]=コンボリューションフィルタ
+Comment[km]=តម្រង​អង្កាញ់
+Comment[nb]=Konvolusjonsfiltre
+Comment[nds]=Fooldenfilters
+Comment[ne]=कुण्डलीकरण फिल्टरहरू
+Comment[nl]=Verdraaiingsfilters
+Comment[pl]=Filtry splotowe
+Comment[pt]=Filtros de convolução
+Comment[pt_BR]=Filtros de convolução
+Comment[ru]=Cвёртка
+Comment[sk]=Filtre zvinutia
+Comment[sl]=Konvolucijski filtri
+Comment[sr]=Конволуциони филтери
+Comment[sr@Latn]=Konvolucioni filteri
+Comment[sv]=Faltningsfilter
+Comment[uk]=Фільтри згортки
+Comment[zh_TW]=皺褶過濾器
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkconvolutionfilters
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/convolutionfilters/convolutionfilters.cc b/chalk/plugins/filters/convolutionfilters/convolutionfilters.cc
new file mode 100644
index 00000000..ddf2332f
--- /dev/null
+++ b/chalk/plugins/filters/convolutionfilters/convolutionfilters.cc
@@ -0,0 +1,176 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <stdlib.h>
+
+#include <klocale.h>
+#include <kinstance.h>
+#include <kgenericfactory.h>
+
+#include <kis_convolution_painter.h>
+#include "convolutionfilters.h"
+
+#include "kis_custom_convolution_filter.h"
+
+KisKernelSP createKernel( TQ_INT32 i0, TQ_INT32 i1, TQ_INT32 i2,
+ TQ_INT32 i3, TQ_INT32 i4, TQ_INT32 i5,
+ TQ_INT32 i6, TQ_INT32 i7, TQ_INT32 i8,
+ TQ_INT32 factor, TQ_INT32 offset )
+{
+ KisKernelSP kernel = new KisKernel();
+ kernel->width = 3;
+ kernel->height = 3;
+
+ kernel->factor = factor;
+ kernel->offset = offset;
+
+ kernel->data = new TQ_INT32[9];
+ kernel->data[0] = i0;
+ kernel->data[1] = i1;
+ kernel->data[2] = i2;
+ kernel->data[3] = i3;
+ kernel->data[4] = i4;
+ kernel->data[5] = i5;
+ kernel->data[6] = i6;
+ kernel->data[7] = i7;
+ kernel->data[8] = i8;
+
+ return kernel;
+}
+
+
+
+typedef KGenericFactory<ChalkConvolutionFilters> ChalkConvolutionFiltersFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkconvolutionfilters, ChalkConvolutionFiltersFactory( "chalk" ) )
+
+ChalkConvolutionFilters::ChalkConvolutionFilters(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ChalkConvolutionFiltersFactory::instance());
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisGaussianBlurFilter());
+ 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());
+ manager->add(new KisTopEdgeDetectionFilter());
+ manager->add(new KisRightEdgeDetectionFilter());
+ manager->add(new KisBottomEdgeDetectionFilter());
+ manager->add(new KisLeftEdgeDetectionFilter());
+ manager->add(new KisCustomConvolutionFilter());
+ }
+}
+
+ChalkConvolutionFilters::~ChalkConvolutionFilters()
+{
+}
+
+KisGaussianBlurFilter::KisGaussianBlurFilter()
+ : KisConvolutionConstFilter(id(), "blur", i18n("&Gaussian Blur"))
+{
+ m_matrix = createKernel( 1, 2, 1, 2, 4, 2, 1, 2, 1, 16, 0);
+}
+
+
+KisSharpenFilter::KisSharpenFilter()
+ : KisConvolutionConstFilter(id(), "enhance", i18n("&Sharpen"))
+{
+ m_matrix = createKernel( 0, -2, 0, -2, 11, -2, 0, -2, 0, 3, 0);
+}
+
+KisMeanRemovalFilter::KisMeanRemovalFilter()
+ : KisConvolutionConstFilter(id(), "enhance", i18n("&Mean Removal"))
+{
+ m_matrix = createKernel( -1, -1, -1, -1, 9, -1, -1, -1, -1, 1, 0);
+}
+
+KisEmbossLaplascianFilter::KisEmbossLaplascianFilter()
+ : KisConvolutionConstFilter(id(), "emboss", i18n("Emboss Laplascian"))
+{
+ m_matrix = createKernel( -1, 0, -1 , 0, 4, 0 , -1, 0, -1, 1, 127);
+ m_channelFlags = KisChannelInfo::FLAG_COLOR;
+}
+
+KisEmbossInAllDirectionsFilter::KisEmbossInAllDirectionsFilter()
+ : KisConvolutionConstFilter(id(), "emboss", i18n("Emboss in All Directions"))
+{
+ m_matrix = createKernel( -1, -1, -1 , -1, 8, -1 , -1, -1, -1, 1, 127);
+ m_channelFlags = KisChannelInfo::FLAG_COLOR;
+}
+
+KisEmbossHorizontalVerticalFilter::KisEmbossHorizontalVerticalFilter()
+ : KisConvolutionConstFilter(id(), "emboss", i18n("EmbossQt::Horizontal &&Qt::Vertical"))
+{
+ m_matrix = createKernel( 0, -1, 0 , -1, 4, -1 , 0, -1, 0, 1, 127);
+ m_channelFlags = KisChannelInfo::FLAG_COLOR;
+}
+
+KisEmbossVerticalFilter::KisEmbossVerticalFilter()
+ : KisConvolutionConstFilter(id(), "emboss", i18n("EmbossQt::Vertical Only"))
+{
+ m_matrix = createKernel( 0, -1, 0 , 0, 2, 0 , 0, -1, 0, 1, 127);
+}
+
+KisEmbossHorizontalFilter::KisEmbossHorizontalFilter() :
+ KisConvolutionConstFilter(id(), "emboss", i18n("EmbossQt::Horizontal Only"))
+{
+ m_matrix = createKernel( 0, 0, 0 , -1, 4, -1 , 0, 0, 0, 1, 127);
+
+}
+
+KisEmbossDiagonalFilter::KisEmbossDiagonalFilter()
+ : KisConvolutionConstFilter(id(), "edge", i18n("Top Edge Detection"))
+{
+ m_matrix = createKernel( -1, 0, -1 , 0, 4, 0 , -1, 0, -1, 1, 127);
+ m_channelFlags = KisChannelInfo::FLAG_COLOR;
+}
+
+
+KisTopEdgeDetectionFilter::KisTopEdgeDetectionFilter()
+ : KisConvolutionConstFilter(id(), "edge", i18n("Top Edge Detection"))
+{
+ m_matrix = createKernel( 1, 1, 1 , 0, 0, 0 , -1, -1, -1, 1, 127);
+ m_channelFlags = KisChannelInfo::FLAG_COLOR;
+
+}
+
+KisRightEdgeDetectionFilter::KisRightEdgeDetectionFilter()
+ : KisConvolutionConstFilter(id(), "edge", i18n("Right Edge Detection"))
+{
+ m_matrix = createKernel( -1, 0, 1 , -1, 0, 1 , -1, 0, 1, 1, 127);
+ m_channelFlags = KisChannelInfo::FLAG_COLOR;
+}
+
+KisBottomEdgeDetectionFilter::KisBottomEdgeDetectionFilter() : KisConvolutionConstFilter(id(), "edge", i18n("Bottom Edge Detection"))
+{
+ m_matrix = createKernel( -1, -1, -1 , 0, 0, 0 , 1, 1, 1, 1, 127);
+ m_channelFlags = KisChannelInfo::FLAG_COLOR;
+}
+
+KisLeftEdgeDetectionFilter::KisLeftEdgeDetectionFilter() : KisConvolutionConstFilter(id(), "edge", i18n("Left Edge Detection"))
+{
+ m_matrix = createKernel( 1, 0, -1 , 1, 0, -1 , 1, 0, -1, 1, 127);
+ m_channelFlags = KisChannelInfo::FLAG_COLOR;
+}
diff --git a/chalk/plugins/filters/convolutionfilters/convolutionfilters.h b/chalk/plugins/filters/convolutionfilters/convolutionfilters.h
new file mode 100644
index 00000000..94e4654c
--- /dev/null
+++ b/chalk/plugins/filters/convolutionfilters/convolutionfilters.h
@@ -0,0 +1,152 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 CONVOLUTIONFILTERS_H
+#define CONVOLUTIONFILTERS_H
+
+#include <kparts/plugin.h>
+#include "kis_convolution_filter.h"
+
+class KisGaussianBlurFilter : public KisConvolutionConstFilter {
+public:
+ KisGaussianBlurFilter();
+public:
+ static inline KisID id() { return KisID("gaussian blur", i18n("Gaussian Blur")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+};
+
+class KisSharpenFilter : public KisConvolutionConstFilter {
+public:
+ KisSharpenFilter();
+public:
+ static inline KisID id() { return KisID("sharpen", i18n("Sharpen")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+};
+
+class KisMeanRemovalFilter : public KisConvolutionConstFilter {
+public:
+ KisMeanRemovalFilter();
+public:
+ static inline KisID id() { return KisID("mean removal", i18n("Mean Removal")); };
+ virtual bool supportsPainting() { return false; }
+
+};
+
+class KisEmbossLaplascianFilter : public KisConvolutionConstFilter {
+public:
+ KisEmbossLaplascianFilter();
+public:
+ static inline KisID id() { return KisID("emboss laplascian", i18n("Emboss Laplascian")); };
+ virtual bool supportsPainting() { return false; }
+
+};
+
+class KisEmbossInAllDirectionsFilter : public KisConvolutionConstFilter {
+public:
+ KisEmbossInAllDirectionsFilter();
+public:
+ static inline KisID id() { return KisID("emboss all directions", i18n("Emboss in All Directions")); };
+ virtual bool supportsPainting() { return false; }
+
+};
+
+class KisEmbossHorizontalVerticalFilter : public KisConvolutionConstFilter {
+public:
+ KisEmbossHorizontalVerticalFilter();
+public:
+ static inline KisID id() { return KisID("", i18n("EmbossQt::Horizontal &Qt::Vertical")); };
+ virtual bool supportsPainting() { return false; }
+
+};
+
+class KisEmbossVerticalFilter : public KisConvolutionConstFilter {
+public:
+ KisEmbossVerticalFilter();
+public:
+ static inline KisID id() { return KisID("emboss vertical only", i18n("EmbossQt::Vertical Only")); };
+ virtual bool supportsPainting() { return false; }
+
+};
+
+class KisEmbossHorizontalFilter : public KisConvolutionConstFilter {
+public:
+ KisEmbossHorizontalFilter();
+public:
+ static inline KisID id() { return KisID("emboss horizontal only", i18n("EmbossQt::Horizontal Only")); };
+ virtual bool supportsPainting() { return false; }
+
+};
+
+class KisEmbossDiagonalFilter : public KisConvolutionConstFilter {
+public:
+ KisEmbossDiagonalFilter();
+public:
+ static inline KisID id() { return KisID("emboss diagonal", i18n("Emboss Diagonal")); };
+ virtual bool supportsPainting() { return false; }
+
+};
+
+class KisTopEdgeDetectionFilter : public KisConvolutionConstFilter {
+public:
+ KisTopEdgeDetectionFilter();
+public:
+ static inline KisID id() { return KisID("top edge detections", i18n("Top Edge Detection")); };
+ virtual bool supportsPainting() { return false; }
+
+};
+
+class KisRightEdgeDetectionFilter : public KisConvolutionConstFilter {
+public:
+ KisRightEdgeDetectionFilter();
+public:
+ static inline KisID id() { return KisID("right edge detections", i18n("Right Edge Detection")); };
+ virtual bool supportsPainting() { return false; }
+
+};
+
+class KisBottomEdgeDetectionFilter : public KisConvolutionConstFilter {
+public:
+ KisBottomEdgeDetectionFilter();
+public:
+ static inline KisID id() { return KisID("bottom edge detections", i18n("Bottom Edge Detection")); };
+ virtual bool supportsPainting() { return false; }
+
+};
+
+class KisLeftEdgeDetectionFilter : public KisConvolutionConstFilter {
+public:
+ KisLeftEdgeDetectionFilter();
+public:
+ static inline KisID id() { return KisID("left edge detections", i18n("Left Edge Detection")); };
+ virtual bool supportsPainting() { return false; }
+
+};
+
+
+class ChalkConvolutionFilters : public KParts::Plugin
+{
+public:
+ ChalkConvolutionFilters(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ChalkConvolutionFilters();
+};
+
+#endif
diff --git a/chalk/plugins/filters/convolutionfilters/kis_convolution_filter.cc b/chalk/plugins/filters/convolutionfilters/kis_convolution_filter.cc
new file mode 100644
index 00000000..39a395b4
--- /dev/null
+++ b/chalk/plugins/filters/convolutionfilters/kis_convolution_filter.cc
@@ -0,0 +1,138 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 "tqdom.h"
+#include "klocale.h"
+#include "kdebug.h"
+
+#include "kis_painter.h"
+#include "kis_convolution_filter.h"
+#include "kis_convolution_painter.h"
+#include "kis_progress_display_interface.h"
+#include "kis_progress_subject.h"
+
+void KisConvolutionConfiguration::fromXML(const TQString & s)
+{
+ m_matrix = new KisKernel();
+
+ TQDomDocument doc;
+ doc.setContent( s );
+ TQDomElement e = doc.documentElement();
+ TQDomNode n = e.firstChild();
+
+ m_name = e.attribute("name");
+ m_version = e.attribute("version").toInt();
+
+ TQDomElement matrix = n.toElement();
+ m_matrix->width = TQString( matrix.attribute( "width" ) ).toInt();
+ m_matrix->height = TQString( matrix.attribute( "height" ) ).toInt();
+ m_matrix->offset = TQString( matrix.attribute( "offset" ) ).toInt();
+ m_matrix->factor = TQString( matrix.attribute( "factor" ) ).toInt();
+
+ m_matrix->data = new TQ_INT32[m_matrix->width * m_matrix->height];
+
+ TQStringList data = TQStringList::split( ",", e.text() );
+ TQStringList::Iterator start = data.begin();
+ TQStringList::Iterator end = data.end();
+ int i = 0;
+ for ( TQStringList::Iterator it = start; it != end; ++it ) {
+ TQString s = *it;
+ m_matrix->data[i] = s.toInt();
+ i++;
+ }
+}
+
+TQString KisConvolutionConfiguration::toString()
+{
+ TQDomDocument doc = TQDomDocument("filterconfig");
+ TQDomElement root = doc.createElement( "filterconfig" );
+ root.setAttribute( "name", name() );
+ root.setAttribute( "version", version() );
+
+ doc.appendChild( root );
+
+ TQDomElement e = doc.createElement( "kernel" );
+ e.setAttribute( "width", m_matrix->width );
+ e.setAttribute( "height", m_matrix->height );
+ e.setAttribute( "offset", m_matrix->offset );
+ e.setAttribute( "factor", m_matrix->factor );
+
+ TQString data;
+
+ for ( uint i = 0; i < m_matrix->width * m_matrix->height; ++i ) {
+ data += TQString::number( m_matrix->data[i] );
+ data += ",";
+ }
+
+ TQDomText text = doc.createCDATASection(data);
+ e.appendChild(text);
+ root.appendChild(e);
+
+ return doc.toString();
+
+}
+
+void KisConvolutionFilter::process(KisPaintDeviceSP src,
+ KisPaintDeviceSP dst,
+ KisFilterConfiguration* configuration,
+ const TQRect& rect)
+{
+ if (!configuration) {
+ setProgressDone();
+ return;
+ }
+
+ if (dst != src) {
+ kdDebug() << "src != dst\n";
+ KisPainter gc(dst);
+ gc.bitBlt(rect.x(), rect.y(), COMPOSITE_COPY, src, rect.x(), rect.y(), rect.width(), rect.height());
+ gc.end();
+ }
+
+
+ KisConvolutionPainter painter( dst );
+ if (m_progressDisplay)
+ m_progressDisplay->setSubject( &painter, true, true );
+
+ KisKernelSP kernel = ((KisConvolutionConfiguration*)configuration)->matrix();
+ KisChannelInfo::enumChannelFlags channels = ((KisConvolutionConfiguration*)configuration)->channels();
+
+ painter.applyMatrix(kernel, rect.x(), rect.y(), rect.width(), rect.height(), BORDER_REPEAT, channels );
+
+ if (painter.cancelRequested()) {
+ cancel();
+ }
+
+ setProgressDone();
+}
+
+int KisConvolutionFilter::overlapMarginNeeded(KisFilterConfiguration* c) const {
+ KisConvolutionConfiguration* config = dynamic_cast<KisConvolutionConfiguration*>(c);
+ if (!config)
+ return 0;
+ KisKernelSP kernel = config->matrix();
+ return TQMAX(kernel->width / 2, kernel->height / 2);
+}
+
+KisFilterConfiguration* KisConvolutionConstFilter::configuration(TQWidget*)
+{
+ return new KisConvolutionConfiguration( id().id(), m_matrix, m_channelFlags);
+}
+
+#include "kis_convolution_filter.moc"
diff --git a/chalk/plugins/filters/convolutionfilters/kis_convolution_filter.h b/chalk/plugins/filters/convolutionfilters/kis_convolution_filter.h
new file mode 100644
index 00000000..87b3d2b8
--- /dev/null
+++ b/chalk/plugins/filters/convolutionfilters/kis_convolution_filter.h
@@ -0,0 +1,99 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_CONVOLUTION_FILTER_H_
+#define _KIS_CONVOLUTION_FILTER_H_
+
+#include "kis_filter.h"
+#include "kis_filter_configuration.h"
+#include "kis_convolution_painter.h"
+
+class KisConvolutionConfiguration : public KisFilterConfiguration {
+public:
+ KisConvolutionConfiguration(const TQString & name, KisKernel * matrix,
+ KisChannelInfo::enumChannelFlags channelFlags = KisChannelInfo::FLAG_COLOR_AND_ALPHA)
+ : KisFilterConfiguration( name, 1 )
+ , m_matrix(matrix)
+ , m_channelFlags(channelFlags)
+ {};
+
+ void fromXML(const TQString & s);
+ TQString toString();
+
+public:
+
+ inline KisKernelSP matrix() { return m_matrix; }
+ inline KisChannelInfo::enumChannelFlags channels() { return m_channelFlags; }
+
+private:
+
+ KisKernelSP m_matrix;
+ KisChannelInfo::enumChannelFlags m_channelFlags;
+
+};
+
+
+class KisConvolutionFilter : public KisFilter {
+
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ KisConvolutionFilter(const KisID& id, const TQString & category, const TQString & entry)
+ : KisFilter( id, category, entry )
+ {};
+
+public:
+
+ virtual void process(KisPaintDeviceSP,KisPaintDeviceSP, KisFilterConfiguration* , const TQRect&);
+ virtual bool supportsIncrementalPainting() { return false; }
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return FULLY_INDEPENDENT; };
+ virtual int overlapMarginNeeded(KisFilterConfiguration* c) const;
+};
+
+
+/**
+ * This class is used for a convolution filter with a constant matrix
+ */
+class KisConvolutionConstFilter : public KisConvolutionFilter {
+
+public:
+
+ KisConvolutionConstFilter(const KisID& id, const TQString & category, const TQString & entry)
+ : KisConvolutionFilter(id, category, entry)
+ {
+ m_channelFlags = KisChannelInfo::FLAG_COLOR_AND_ALPHA;
+ };
+
+ virtual ~KisConvolutionConstFilter() {};
+
+public:
+
+ virtual KisFilterConfiguration * configuration(TQWidget*);
+ virtual KisFilterConfiguration * configuration() { return configuration(0); };
+
+protected:
+
+ KisKernelSP m_matrix;
+ KisChannelInfo::enumChannelFlags m_channelFlags;
+};
+
+#endif
diff --git a/chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter.cc b/chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter.cc
new file mode 100644
index 00000000..8d48d25d
--- /dev/null
+++ b/chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter.cc
@@ -0,0 +1,93 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <kdebug.h>
+
+#include "kis_custom_convolution_filter.h"
+
+#include <tqspinbox.h>
+
+#include "kis_convolution_painter.h"
+#include "kis_custom_convolution_filter_configuration_widget.h"
+#include "kis_custom_convolution_filter_configuration_base_widget.h"
+#include "kis_matrix_widget.h"
+
+
+KisFilterConfigWidget * KisCustomConvolutionFilter::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP)
+{
+ KisCustomConvolutionFilterConfigurationWidget* ccfcw = new KisCustomConvolutionFilterConfigurationWidget(this,tqparent, "custom convolution config widget");
+ Q_CHECK_PTR(ccfcw);
+ return ccfcw;
+}
+
+KisFilterConfiguration * KisCustomConvolutionFilter::configuration(TQWidget* nwidget)
+{
+ KisCustomConvolutionFilterConfigurationWidget* widget = (KisCustomConvolutionFilterConfigurationWidget*) nwidget;
+
+ if ( widget == 0 )
+ {
+ // Create the identity matrix:
+ KisKernelSP kernel = new KisKernel();
+ kernel->width = 3;
+ kernel->height = 3;
+
+ kernel->factor = 1;
+ kernel->offset = 127;
+
+ kernel->data = new TQ_INT32[9];
+ kernel->data[0] = 0;
+ kernel->data[1] = 0;
+ kernel->data[2] = 0;
+ kernel->data[3] = 0;
+ kernel->data[4] = 1;
+ kernel->data[5] = 0;
+ kernel->data[6] = 0;
+ kernel->data[7] = 0;
+ kernel->data[8] = 0;
+
+ return new KisConvolutionConfiguration( "custom convolution", kernel );
+
+ } else {
+
+ // Create the identity matrices:
+ KisKernelSP kernel = new KisKernel();
+ kernel->width = 3;
+ kernel->height = 3;
+
+ kernel->data = new TQ_INT32[9];
+
+ KisCustomConvolutionFilterConfigurationBaseWidget* mw = widget->matrixWidget();
+
+ kernel->data[0] = mw->matrixWidget->m11->value();
+ kernel->data[1] = mw->matrixWidget->m21->value();
+ kernel->data[2] = mw->matrixWidget->m31->value();
+ kernel->data[3] = mw->matrixWidget->m12->value();
+ kernel->data[4] = mw->matrixWidget->m22->value();
+ kernel->data[5] = mw->matrixWidget->m32->value();
+ kernel->data[6] = mw->matrixWidget->m13->value();
+ kernel->data[7] = mw->matrixWidget->m23->value();
+ kernel->data[8] = mw->matrixWidget->m33->value();
+
+ kernel->factor = mw->spinBoxFactor->value();
+ kernel->offset = mw->spinBoxOffset->value();
+
+ return new KisConvolutionConfiguration( "custom convolution", kernel );
+ }
+}
diff --git a/chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter.h b/chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter.h
new file mode 100644
index 00000000..cbfd375e
--- /dev/null
+++ b/chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_CUSTOM_CONVOLUTION_FILTER_H_
+#define _KIS_CUSTOM_CONVOLUTION_FILTER_H_
+
+#include "kis_convolution_filter.h"
+#include "kis_filter_config_widget.h"
+#include "kis_id.h"
+#include "kis_types.h"
+
+class TQWidget;
+
+class KisCustomConvolutionFilter : public KisConvolutionFilter {
+
+public:
+ KisCustomConvolutionFilter() : KisConvolutionFilter(id(), "enhance", i18n("&Custom Convolution...")) {};
+
+public:
+ static inline KisID id() { return KisID("custom convolution", i18n("Custom Convolution")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsIncrementalPainting() { return true; }
+
+public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration * configuration(TQWidget*);
+ virtual KisFilterConfiguration * configuration() { return configuration(0); };
+protected:
+ virtual KisKernelSP matrix() { return m_matrix; };
+private:
+ KisKernelSP m_matrix;
+};
+
+
+
+
+#endif
diff --git a/chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter_configuration_base_widget.ui b/chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter_configuration_base_widget.ui
new file mode 100644
index 00000000..495fd3bc
--- /dev/null
+++ b/chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter_configuration_base_widget.ui
@@ -0,0 +1,189 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>KisCustomConvolutionFilterConfigurationBaseWidget</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>KisCustomConvolutionFilterConfigurationBaseWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>138</width>
+ <height>230</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Custom Convolution Filter Configuration Widget</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout5</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KisMatrixWidget">
+ <property name="name">
+ <cstring>matrixWidget</cstring>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabelFactor</cstring>
+ </property>
+ <property name="text">
+ <string>Factor:</string>
+ </property>
+ </widget>
+ <widget class="TQSpinBox">
+ <property name="name">
+ <cstring>spinBoxFactor</cstring>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>1</number>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>21</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabelOffset</cstring>
+ </property>
+ <property name="text">
+ <string>Offset:</string>
+ </property>
+ </widget>
+ <widget class="TQSpinBox">
+ <property name="name">
+ <cstring>spinBoxOffset</cstring>
+ </property>
+ <property name="maxValue">
+ <number>255</number>
+ </property>
+ <property name="minValue">
+ <number>-255</number>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>24</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer24</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KisMatrixWidget</class>
+ <header location="local">kis_matrix_widget.h</header>
+ <sizehint>
+ <width>150</width>
+ <height>100</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1125">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000042c49444154789cb5954f6c14551cc73fefcd7476b65bdaae4bb78bb5502a14d404e4801c88182d1c4c2c693da847400f9c24c68b878684238660e2b1e01f12c19493012ef2478c814412d354a46017a8a564bb6da5bbedccee767776e63d0ffb073751d483bfe49799974c3eeffb7ebf37df9fd05a530b2184040cc0042420aaf9a4d0d554800f045a6b256ae0e1e1e1d6bebebe838ee31c48a7d39b5cd7fd075e251cc7617272f2ded8d8d819cff33e0316819259537aead4a9839d5dd6d1784f91f55b0a94830242088404d304292bef68a89f520802a598fecddaa04f1a876f5c250c7c0a64cdeac686e33807e23d45e6b297c8b877f1831542614550b6599835c83c2a81b6786a75134faf2f1169f12997350881d9021d0903e06de0745d3160a6d3e94dbd5b0a64dcbb94b5831d0e3375ab892b1772dcf9790528543f8dd0d367b36768153b5e31503a0f1aecb004580b44ffac58baae8b1714f0833c7638cc8dab303a320f4822ab4c7a37c69196203de3319d5ce1c4d13c733331dedc67a129a154fd128401ab0616d55a130ac3d42d93d1913940d13fd0c9ee0183685c60da01c5421bd72f7a8c8efccef9afd374267ad93d642365be0636a0d28ec7600941d9e6f23917f0e97f23ce5bef35d19ec863da0ed9059b2be70bec196c66dfa10ec0e49b338f7017258651bf95021035c595429bb0903248fe52a2b5b595dd7b4d945cc2340cdca536be389ee3f67886c5798f773fe8e0dac508c989659277a2180da4ca4ff07821058b8b251445d63d6b13ed1098a6417e39cac85197dbe31962ab9bd9f1f22a226d45366f6d0620fdb08c900d281af6110284b20085b414861d905d88f2e52739ee8cbb8022143259d3dd84691730aa2d52da441a8de0c6958068870022a41e9629ad3473fd3b8fdbe319dadb9b4924da994d2d716c7896fbe35152f78b48245d6b2da4507faf582be8eaf159b721cc837b05ae7debb1f79d08cb8b515edad942a22bc4b1c33eb3d34b1c797f06af90a72d16e2f96d9a74aa11dca8586b222d01af0fb60070f6c402d72f15d97f28c6f6d7027a5f5ce6c3233dc4e2ede496b278be4fff608cee8d3e1add806aeca51094cbb06397c1ecc328e746537c7e3ccdb5cb1136bf60635882d4d41c6ec6836ab37efa214f72208ed9f4d7cdd38ee310280542e38b1c43fb6de26b3672e1ec3cc99bcb246f66a938a3241ab3e91f7c861fbf77710b1e5e49915bae974203ba0e9e9c9cbc373d6d6d305a040a89c2a77f50b27d5782bbbf7acccf28349235dd16cf6dd374f7295e1de8a45c02d37499182b01cc0201a085d61a2144d8b2ac8fb6ed340e77240c4261890e04c250185262546d534a032154b59e0ad394e41c98182bf268ce6721ed9f064e0253356f6da2e24c1f030f783c15fe6da680af8021602bd051532ca9b8521488559f61aa86c29343578fbf0264a94c906c7d3409214c20043457a116ff6de6795578012889ff6b98fe016ea0ce1c203e47720000000049454e44ae426082</data>
+ </image>
+</images>
+<tqlayoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter_configuration_widget.cc b/chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter_configuration_widget.cc
new file mode 100644
index 00000000..b1905d30
--- /dev/null
+++ b/chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter_configuration_widget.cc
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_custom_convolution_filter_configuration_widget.h"
+
+#include <tqlayout.h>
+#include <tqspinbox.h>
+
+#include <klocale.h>
+
+#include "kis_filter.h"
+#include "kis_image.h"
+#include "kis_layer.h"
+#include "kis_view.h"
+#include "kis_types.h"
+#include "kis_filter_configuration.h"
+#include "kis_colorspace.h"
+#include "kis_convolution_filter.h"
+#include "kis_custom_convolution_filter_configuration_base_widget.h"
+#include "kis_matrix_widget.h"
+
+KisCustomConvolutionFilterConfigurationWidget::KisCustomConvolutionFilterConfigurationWidget( KisFilter* /*nfilter*/, TQWidget * tqparent, const char * name)
+ : KisFilterConfigWidget ( tqparent, name )
+{
+ TQGridLayout *widgetLayout = new TQGridLayout(this, 2, 1);
+ Q_CHECK_PTR(widgetLayout);
+
+// TQPushButton *bnRefresh = new TQPushButton(i18n("Refresh Preview"), this, "bnrefresh");
+// Q_CHECK_PTR(bnRefresh);
+
+// TQSpacerItem *spacer = new TQSpacerItem(100, 30, TQSizePolicy::Expanding, TQSizePolicy::Minimum);
+// Q_CHECK_PTR(spacer);
+
+// widgetLayout->addWidget(bnRefresh, 0, 0);
+// widgetLayout->addItem(spacer, 0, 1);
+
+ m_ccfcws = new KisCustomConvolutionFilterConfigurationBaseWidget((TQWidget*)this);
+ Q_CHECK_PTR(m_ccfcws);
+
+ widgetLayout->addMultiCellWidget(m_ccfcws, 1, 1, 0, 1);
+
+// connect( bnRefresh, TQT_SIGNAL(clicked()), nfilter, TQT_SLOT(refreshPreview()));
+ connect( m_ccfcws->matrixWidget, TQT_SIGNAL(valueChanged()), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_ccfcws->spinBoxFactor, TQT_SIGNAL(valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_ccfcws->spinBoxOffset, TQT_SIGNAL(valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+}
+
+void KisCustomConvolutionFilterConfigurationWidget::setConfiguration(KisFilterConfiguration * cfg)
+{
+ KisConvolutionConfiguration * config = dynamic_cast<KisConvolutionConfiguration*>(cfg);
+
+ if (config->matrix()->width != 3 || config->matrix()->height != 3) return;
+
+ m_ccfcws->spinBoxOffset->setValue(config->matrix()->offset);
+ m_ccfcws->spinBoxFactor->setValue(config->matrix()->factor);
+
+ m_ccfcws->matrixWidget->m11->setValue(config->matrix()->data[0]);
+ m_ccfcws->matrixWidget->m21->setValue(config->matrix()->data[1]);
+ m_ccfcws->matrixWidget->m31->setValue(config->matrix()->data[2]);
+ m_ccfcws->matrixWidget->m12->setValue(config->matrix()->data[3]);
+ m_ccfcws->matrixWidget->m22->setValue(config->matrix()->data[4]);
+ m_ccfcws->matrixWidget->m32->setValue(config->matrix()->data[5]);
+ m_ccfcws->matrixWidget->m31->setValue(config->matrix()->data[6]);
+ m_ccfcws->matrixWidget->m32->setValue(config->matrix()->data[7]);
+ m_ccfcws->matrixWidget->m33->setValue(config->matrix()->data[8]);
+}
+
+#include "kis_custom_convolution_filter_configuration_widget.moc"
diff --git a/chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter_configuration_widget.h b/chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter_configuration_widget.h
new file mode 100644
index 00000000..b5819e39
--- /dev/null
+++ b/chalk/plugins/filters/convolutionfilters/kis_custom_convolution_filter_configuration_widget.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_CUSTOM_CONVOLUTION_FILTER_CONFIGURATION_WIDGET_H_
+#define _KIS_CUSTOM_CONVOLUTION_FILTER_CONFIGURATION_WIDGET_H_
+
+#include "kis_filter_config_widget.h"
+
+class TQWidget;
+class KisCustomConvolutionFilterConfigurationBaseWidget;
+class KisMatrixWidget;
+class KisFilter;
+
+class KisCustomConvolutionFilterConfigurationWidget : public KisFilterConfigWidget
+{
+
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ KisCustomConvolutionFilterConfigurationWidget( KisFilter* nfilter, TQWidget * tqparent, const char * name);
+ inline KisCustomConvolutionFilterConfigurationBaseWidget* matrixWidget() { return m_ccfcws; };
+ void setConfiguration(KisFilterConfiguration * config);
+
+private:
+
+ KisCustomConvolutionFilterConfigurationBaseWidget* m_ccfcws;
+};
+
+#endif
diff --git a/chalk/plugins/filters/cubismfilter/Makefile.am b/chalk/plugins/filters/cubismfilter/Makefile.am
new file mode 100644
index 00000000..e281360e
--- /dev/null
+++ b/chalk/plugins/filters/cubismfilter/Makefile.am
@@ -0,0 +1,24 @@
+kde_services_DATA = chalkcubismfilter.desktop
+
+INCLUDES = \
+ -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalkcubismfilter.la
+
+chalkcubismfilter_la_SOURCES = kis_cubism_filter_plugin.cc \
+ kis_cubism_filter.cc \
+ kis_polygon.cc
+
+noinst_HEADERS = kis_cubism_filter_plugin.h \
+ kis_cubism_filter.h \
+ kis_polygon.h
+
+chalkcubismfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+chalkcubismfilter_la_LIBADD = ../../../libchalkcommon.la
+
+chalkcubismfilter_la_METASOURCES = AUTO
diff --git a/chalk/plugins/filters/cubismfilter/chalkcubismfilter.desktop b/chalk/plugins/filters/cubismfilter/chalkcubismfilter.desktop
new file mode 100644
index 00000000..fd8e7e2b
--- /dev/null
+++ b/chalk/plugins/filters/cubismfilter/chalkcubismfilter.desktop
@@ -0,0 +1,85 @@
+[Desktop Entry]
+Name=Cubism Filter
+Name[bg]=Кубичен филтър
+Name[ca]=Filtre de cubisme
+Name[cy]=Hidlen Giwbiaeth
+Name[da]=Kubismefilter
+Name[de]=Kubismus-Filter
+Name[el]=Φίλτρο κυβισμού
+Name[eo]=Kubisma filtrilo
+Name[es]=Filtro de cubismo
+Name[et]=Kubismifilter
+Name[fa]=پالایۀ Cubism
+Name[fr]=Filtre de cubisme
+Name[fy]=Kubismefilter
+Name[gl]=Filtro de Cubismo
+Name[he]=מסנן קוביסטי
+Name[hu]=Kubista szűrő
+Name[is]=Teningasía
+Name[it]=Filtro cubista
+Name[ja]=キュビズムフィルタ
+Name[km]=តម្រង​គូប
+Name[lt]=Kubizmo filtras
+Name[lv]=Kubisma filtrs
+Name[nb]=Kubisme-filter
+Name[nds]=Wörpel-Filter
+Name[ne]=क्यूबिजम फिल्टर
+Name[nl]=Kubismefilter
+Name[pl]=Filtr kubistyczny
+Name[pt]=Filtro de Cubismo
+Name[pt_BR]=Filtro de Cubismo
+Name[ru]=Кубизм
+Name[se]=Kubisma-silli
+Name[sk]=Filter kubizmus
+Name[sl]=Filter Kubizem
+Name[sr]=Кубистички филтер
+Name[sr@Latn]=Kubistički filter
+Name[sv]=Kubismfilter
+Name[uk]=Фільтр кубізму
+Name[uz]=Kubizm filteri
+Name[uz@cyrillic]=Кубизм филтери
+Name[zh_TW]=立體過濾器
+Comment=Cubism filter
+Comment[bg]=Кубичен филтър
+Comment[ca]=Filtre de cubisme
+Comment[cy]=Hidlen Giwbiaeth
+Comment[da]=Kubismefilter
+Comment[de]=Kubismus-Filter
+Comment[el]=Φίλτρο κυβισμού
+Comment[eo]=Kubisma filtrilo
+Comment[es]=Filtro de cubismo
+Comment[et]=Kubismifilter
+Comment[fa]=پالایۀ Cubism
+Comment[fr]=Filtre de cubisme
+Comment[fy]=Kubismefilter
+Comment[gl]=Filtro de cubismo
+Comment[he]=מסנן קוביסטי
+Comment[hu]=Kubista szűrő
+Comment[is]=Teningasía
+Comment[it]=Filtro cubista
+Comment[ja]=キュビズムフィルタ
+Comment[km]=តម្រង​គូប
+Comment[lt]=Kubizmo filtras
+Comment[lv]=Kubisma filtrs
+Comment[nb]=Kubisme-filter
+Comment[nds]=Wörpel-Filter
+Comment[ne]=क्यूबिजम फिल्टर
+Comment[nl]=Kubismefilter
+Comment[pl]=Filtr kubistyczny
+Comment[pt]=Filtro de cubismo
+Comment[pt_BR]=Filtro de cubismo
+Comment[ru]=Кубизм
+Comment[se]=Kubisma-silli
+Comment[sk]=Filter kubizmus
+Comment[sl]=Filter Kubizem
+Comment[sr]=Кубистички филтер
+Comment[sr@Latn]=Kubistički filter
+Comment[sv]=Kubismfilter
+Comment[uk]=Фільтр кубізму
+Comment[uz]=Kubizm filteri
+Comment[uz@cyrillic]=Кубизм филтери
+Comment[zh_TW]=立體過濾器
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkcubismfilter
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/cubismfilter/kis_cubism_filter.cc b/chalk/plugins/filters/cubismfilter/kis_cubism_filter.cc
new file mode 100644
index 00000000..1cd1aa8d
--- /dev/null
+++ b/chalk/plugins/filters/cubismfilter/kis_cubism_filter.cc
@@ -0,0 +1,453 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * ported from Gimp, Copyright (C) 1997 Eiichi Takamori <taka@ma1.seikyou.ne.jp>
+ * 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 <stdlib.h>
+#include <time.h>
+#include <vector>
+
+#include <tqpoint.h>
+#include <tqspinbox.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <knuminput.h>
+
+#include <kis_painter.h>
+#include <kis_meta_registry.h>
+#include <kis_colorspace_factory_registry.h>
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_filter_registry.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_progress_display_interface.h>
+#include <kis_vec.h>
+
+#include "kis_multi_integer_filter_widget.h"
+#include "kis_cubism_filter.h"
+#include "kis_polygon.h"
+#include "kis_point.h"
+
+#define RANDOMNESS 5
+#define SUPERSAMPLE 4
+#define CLAMP(x,l,u) ((x)<(l)?(l):((x)>(u)?(u):(x)))
+#define SQR(x) ((x) * (x))
+
+KisCubismFilter::KisCubismFilter() : KisFilter(id(), "artistic", i18n("&Cubism..."))
+{
+}
+
+bool KisCubismFilter::workWith(KisColorSpace* /*cs*/)
+{
+ return true;
+}
+
+
+void KisCubismFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst,
+ KisFilterConfiguration* configuration, const TQRect& rect)
+{
+ Q_ASSERT(src);
+ Q_ASSERT(dst);
+ Q_ASSERT(configuration);
+
+ //read the filter configuration values from the KisFilterConfiguration object
+ TQ_UINT32 tileSize = ((KisCubismFilterConfiguration*)configuration)->tileSize();
+ TQ_UINT32 tileSaturation = ((KisCubismFilterConfiguration*)configuration)->tileSaturation();
+
+ KisColorSpace * cs = src->colorSpace();
+ TQString id = cs->id().id();
+
+ if (id == "RGBA" || id == "GRAY" || id == "CMYK") {
+ cubism(src, dst, rect, tileSize, tileSaturation);
+ }
+ else {
+ if (src->image()) src->image()->lock();
+
+ KisPaintDeviceSP dev = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getRGB8(), "temporary");
+ KisPainter gc(dev);
+ gc.bitBlt(0, 0, COMPOSITE_COPY, src, rect.x(), rect.y(), rect.width(), rect.height());
+ gc.end();
+
+ kdDebug() << src->colorSpace()->id().id() << endl;
+ cubism(dev, dev, TQRect(0, 0, rect.width(), rect.height()), tileSize, tileSaturation);
+
+ gc.begin(dst);
+ gc.bitBlt(rect.x(), rect.y(), COMPOSITE_COPY, dev, 0, 0, rect.width(), rect.height());
+ gc.end();
+ if (src->image()) src->image()->unlock();
+
+ kdDebug() << src->colorSpace()->id().id() << endl;
+ }
+}
+
+void KisCubismFilter::randomizeIndices (TQ_INT32 count, TQ_INT32* indices)
+{
+ TQ_INT32 index1, index2;
+ TQ_INT32 tmp;
+
+ //initialize random number generator with time
+ srand(static_cast<unsigned int>(time(0)));
+
+ for (TQ_INT32 i = 0; i < count * RANDOMNESS; i++)
+ {
+ index1 = randomIntNumber(0, count);
+ index2 = randomIntNumber(0, count);
+ tmp = indices[index1];
+ indices[index1] = indices[index2];
+ indices[index2] = tmp;
+ }
+}
+
+TQ_INT32 KisCubismFilter::randomIntNumber(TQ_INT32 lowestNumber, TQ_INT32 highestNumber)
+{
+ if(lowestNumber > highestNumber)
+ {
+ TQ_INT32 temp = lowestNumber;
+ lowestNumber = highestNumber;
+ highestNumber = temp;
+ }
+
+ return lowestNumber + (( highestNumber - lowestNumber ) * rand() )/ RAND_MAX;
+}
+
+double KisCubismFilter::randomDoubleNumber(double lowestNumber, double highestNumber)
+{
+ if(lowestNumber > highestNumber)
+ {
+ double temp = lowestNumber;
+ lowestNumber = highestNumber;
+ highestNumber = temp;
+ }
+
+ double range = highestNumber - lowestNumber;
+ return lowestNumber + range * rand() / (double)RAND_MAX;
+}
+
+double KisCubismFilter::calcAlphaBlend (double* vec, double oneOverDist, double x, double y)
+{
+
+ if ( oneOverDist==0 )
+ return 1.0;
+ else
+ {
+ double r = (vec[0] * x + vec[1] * y) * oneOverDist;
+ if (r < 0.2)
+ r = 0.2;
+ else if (r > 1.0)
+ r = 1.0;
+ return r;
+ }
+}
+
+void KisCubismFilter::convertSegment (TQ_INT32 x1, TQ_INT32 y1, TQ_INT32 x2, TQ_INT32 y2, TQ_INT32 offset, TQ_INT32* min, TQ_INT32* max, TQ_INT32 xmin, TQ_INT32 xmax)
+{
+ if (y1 > y2)
+ {
+ TQ_INT32 tmp = y2; y2 = y1; y1 = tmp;
+ tmp = x2; x2 = x1; x1 = tmp;
+ }
+ TQ_INT32 ydiff = (y2 - y1);
+
+ if (ydiff)
+ {
+ double xinc = static_cast<double>(x2 - x1) / static_cast<double>(ydiff);
+ double xstart = x1 + 0.5 * xinc;
+ for (TQ_INT32 y = y1 ; y < y2; y++)
+ {
+ if(xstart >= xmin && xstart <= xmax)
+ {
+ if (xstart < min[y - offset])
+ {
+ min[y-offset] = (int)xstart;
+ }
+ if (xstart > max[y - offset])
+ {
+ max[y-offset] = (int)xstart;
+ }
+ xstart += xinc;
+ }
+ }
+ }
+}
+
+#define USE_READABLE_BUT_SLOW_CODE
+
+void KisCubismFilter::fillPolyColor (KisPaintDeviceSP src, KisPaintDeviceSP dst, KisPolygon* poly, const TQ_UINT8* col, TQ_UINT8* /*s*/, TQRect rect)
+{
+ TQ_INT32 val;
+ TQ_INT32 alpha;
+ TQ_UINT8 buf[4];
+ TQ_INT32 x, y;
+ double xx, yy;
+ double vec[2];
+ TQ_INT32 x1 = rect.left(), y1 = rect.top(), x2 = rect.right(), y2 = rect.bottom();
+// TQ_INT32 selWidth, selHeight;
+ TQ_INT32 *vals, *valsIter, *valsEnd;
+ TQ_INT32 b;
+ TQ_INT32 xs, ys, xe, ye;
+
+
+ TQ_INT32 sx = (TQ_INT32) (*poly)[0].x();
+ TQ_INT32 sy = (TQ_INT32) (*poly)[0].y();
+ TQ_INT32 ex = (TQ_INT32) (*poly)[1].x();
+ TQ_INT32 ey = (TQ_INT32) (*poly)[1].y();
+
+ double dist = sqrt (SQR (ex - sx) + SQR (ey - sy));
+ double oneOverDist = 0.0;
+ if (dist > 0.0)
+ {
+ double oneOverDist = 1/dist;
+ vec[0] = (ex - sx) * oneOverDist;
+ vec[1] = (ey - sy) * oneOverDist;
+ }
+
+ TQ_INT32 pixelSize = src->pixelSize();
+ //get the extents of the polygon
+ double dMinX, dMinY, dMaxX, dMaxY;
+ poly->extents (dMinX, dMinY, dMaxX, dMaxY);
+ TQ_INT32 minX = static_cast<TQ_INT32>(dMinX);
+ TQ_INT32 minY = static_cast<TQ_INT32>(dMinY);
+ TQ_INT32 maxX = static_cast<TQ_INT32>(dMaxX);
+ TQ_INT32 maxY = static_cast<TQ_INT32>(dMaxY);
+ TQ_INT32 sizeX = (maxX - minX) * SUPERSAMPLE;
+ TQ_INT32 sizeY = (maxY - minY) * SUPERSAMPLE;
+
+ TQ_INT32 *minScanlines = new TQ_INT32[sizeY];
+ TQ_INT32 *minScanlinesIter = minScanlines;
+ TQ_INT32 *maxScanlines = new TQ_INT32[sizeY];
+ TQ_INT32 *maxScanlinesIter = maxScanlines;
+
+ for (TQ_INT32 i = 0; i < sizeY; i++)
+ {
+ minScanlines[i] = maxX * SUPERSAMPLE;
+ maxScanlines[i] = minX * SUPERSAMPLE;
+ }
+
+ if ( poly->numberOfPoints() )
+ {
+ TQ_INT32 polyNpts = poly->numberOfPoints();
+
+ xs = static_cast<TQ_INT32>((*poly)[polyNpts-1].x());
+ ys = static_cast<TQ_INT32>((*poly)[polyNpts-1].y());
+ xe = static_cast<TQ_INT32>((*poly)[0].x());
+ ye = static_cast<TQ_INT32>((*poly)[0].y());
+
+ xs *= SUPERSAMPLE;
+ ys *= SUPERSAMPLE;
+ xe *= SUPERSAMPLE;
+ ye *= SUPERSAMPLE;
+
+ convertSegment (xs, ys, xe, ye, minY * SUPERSAMPLE, minScanlines, maxScanlines, minX* SUPERSAMPLE, maxX* SUPERSAMPLE);
+
+ KisPolygon::iterator it;
+
+ for ( it = poly->begin(); it != poly->end(); )
+ {
+ xs = static_cast<TQ_INT32>((*it).x());
+ ys = static_cast<TQ_INT32>((*it).y());
+ ++it;
+
+ if( it != poly->end() )
+ {
+ xe = static_cast<TQ_INT32>((*it).x());
+ ye = static_cast<TQ_INT32>((*it).y());
+
+ xs *= SUPERSAMPLE;
+ ys *= SUPERSAMPLE;
+ xe *= SUPERSAMPLE;
+ ye *= SUPERSAMPLE;
+
+ convertSegment (xs, ys, xe, ye, minY * SUPERSAMPLE, minScanlines, maxScanlines, minX* SUPERSAMPLE, maxX* SUPERSAMPLE);
+ }
+ }
+ }
+
+ vals = new TQ_INT32[sizeX];
+// x1 = minX; x2 = maxX; y1 = minY; y2 = maxY;
+ for (TQ_INT32 i = 0; i < sizeY; i++, minScanlinesIter++, maxScanlinesIter++)
+ {
+ if (! (i % SUPERSAMPLE))
+ {
+ memset (vals, 0, sizeof( TQ_INT32 ) * sizeX);
+ }
+
+ yy = static_cast<double>(i) / static_cast<double>(SUPERSAMPLE) + minY;
+
+ for (TQ_INT32 j = *minScanlinesIter; j < *maxScanlinesIter; j++)
+ {
+ x = j - minX * SUPERSAMPLE;
+ vals[x] += 255;
+ }
+
+ if (! ((i + 1) % SUPERSAMPLE))
+ {
+ y = (i / SUPERSAMPLE) + minY;
+ if (y >= y1 && y <= y2)
+ {
+ for (TQ_INT32 j = 0; j < sizeX; j += SUPERSAMPLE)
+ {
+ x = (j / SUPERSAMPLE) + minX;
+
+ if (x >= x1 && x <= x2)
+ {
+ for (val = 0, valsIter = &vals[j], valsEnd = &valsIter[SUPERSAMPLE]; valsIter < valsEnd; valsIter++)
+ {
+ val += *valsIter;
+ }
+ val /= SQR(SUPERSAMPLE);
+
+ if (val > 0)
+ {
+ xx = static_cast<double>(j) / static_cast<double>(SUPERSAMPLE) + minX;
+ alpha = static_cast<TQ_INT32>(val * calcAlphaBlend (vec, oneOverDist, xx - sx, yy - sy));
+
+// KisRectIteratorPixel srcIt = src->createRectIterator(x,y,1,1, false);
+// const TQ_UINT8* srcPixel = srcIt.oldRawData();
+// memcpy( buf, srcPixel, sizeof(TQ_UINT8) * pixelSize );
+ src->readBytes(buf, x, y, 1, 1);
+ #ifndef USE_READABLE_BUT_SLOW_CODE
+ TQ_UINT8 *bufIter = buf;
+ const TQ_UINT8 *colIter = col;
+ TQ_UINT8 *bufEnd = buf+pixelSize;
+
+ for(; bufIter < bufEnd; bufIter++, colIter++)
+ *bufIter = (static_cast<TQ_UINT8>(*colIter * alpha)
+ + (static_cast<TQ_UINT8>(*bufIter)
+ * (256 - alpha))) >> 8;
+ #else //original, pre-ECL code
+ for (b = 0; b < pixelSize; b++)
+ {
+ buf[b] = ((col[b] * alpha) + (buf[b] * (255 - alpha))) / 255;
+ }
+ #endif
+
+ dst->writeBytes(buf, x, y, 1, 1);
+ }
+ }
+ }
+ }
+ }
+ }
+ delete[] vals;
+ delete[] minScanlines;
+ delete[] maxScanlines;
+}
+
+void KisCubismFilter::cubism(KisPaintDeviceSP src, KisPaintDeviceSP dst, const TQRect& rect, TQ_UINT32 tileSize, TQ_UINT32 tileSaturation)
+{
+ Q_ASSERT(src);
+ Q_ASSERT(dst);
+
+ //fill the destination image with the background color (black for now)
+ KisRectIteratorPixel dstIt = dst->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true );
+ TQ_INT32 depth = src->colorSpace()->nColorChannels();
+ while( ! dstIt.isDone() )
+ {
+ for( TQ_INT32 i = 0; i < depth; i++)
+ {
+ dstIt.rawData()[i] = 0;
+ }
+ ++dstIt;
+ }
+
+ //compute number of rows and columns
+ TQ_INT32 cols = ( rect.width() + tileSize - 1) / tileSize;
+ TQ_INT32 rows = ( rect.height() + tileSize - 1) / tileSize;
+ TQ_INT32 numTiles = (rows + 1) * (cols + 1);
+
+ setProgressTotalSteps(numTiles);
+ setProgressStage(i18n("Applying cubism filter..."),0);
+
+ TQ_INT32* randomIndices = new TQ_INT32[numTiles];
+ for (TQ_INT32 i = 0; i < numTiles; i++)
+ {
+ randomIndices[i] = i;
+ }
+ randomizeIndices (numTiles, randomIndices);
+
+ TQ_INT32 count = 0;
+ TQ_INT32 i, j, ix, iy;
+ double x, y, width, height, theta;
+ KisPolygon *poly = new KisPolygon();
+ TQ_INT32 pixelSize = src->pixelSize();
+ const TQ_UINT8 *srcPixel /*= new TQ_UINT8[ pixelSize ]*/;
+ TQ_UINT8 *dstPixel = 0;
+ while (count < numTiles)
+ {
+ i = randomIndices[count] / (cols + 1);
+ j = randomIndices[count] % (cols + 1);
+ x = j * tileSize + (tileSize / 4.0) - randomDoubleNumber(0, tileSize/2.0) + rect.x();
+ y = i * tileSize + (tileSize / 4.0) - randomDoubleNumber(0, tileSize/2.0) + rect.y();
+ width = (tileSize + randomDoubleNumber(0, tileSize / 4.0) - tileSize / 8.0) * tileSaturation;
+ height = (tileSize + randomDoubleNumber (0, tileSize / 4.0) - tileSize / 8.0) * tileSaturation;
+ theta = randomDoubleNumber(0, 2*M_PI);
+ poly->clear();
+ poly->addPoint( -width / 2.0, -height / 2.0 );
+ poly->addPoint( width / 2.0, -height / 2.0 );
+ poly->addPoint( width / 2.0, height / 2.0 );
+ poly->addPoint( -width / 2.0, height / 2.0 );
+ poly->rotate( theta );
+ poly->translate ( x, y );
+ // bounds check on x, y
+ ix = (TQ_INT32) CLAMP (x, rect.x(), rect.x() + rect.width() - 1);
+ iy = (TQ_INT32) CLAMP (y, rect.y(), rect.y() + rect.height() - 1);
+
+ //read the pixel at ix, iy
+ KisRectIteratorPixel srcIt = src->createRectIterator(ix,iy,1,1, false);
+ srcPixel = srcIt.oldRawData();
+ if (srcPixel[pixelSize - 1])
+ {
+ fillPolyColor (src, dst, poly, srcPixel, dstPixel, rect);
+ }
+ count++;
+ if ((count % 5) == 0) setProgress(count);
+ }
+ setProgressDone();
+}
+
+KisFilterConfigWidget * KisCubismFilter::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP /*dev*/)
+{
+ vKisIntegerWidgetParam param;
+ param.push_back( KisIntegerWidgetParam( 2, 40, 10, i18n("Tile size"), "tileSize" ) );
+ param.push_back( KisIntegerWidgetParam( 2, 40, 10, i18n("Tile saturation"), "tileSaturation" ) );
+ return new KisMultiIntegerFilterWidget(tqparent, id().id().ascii(), id().id().ascii(), param );
+}
+
+KisFilterConfiguration* KisCubismFilter::configuration(TQWidget* nwidget)
+{
+ KisMultiIntegerFilterWidget* widget = (KisMultiIntegerFilterWidget*) nwidget;
+ if( widget == 0 )
+ {
+ return new KisCubismFilterConfiguration( 10, 10);
+ } else {
+ return new KisCubismFilterConfiguration( widget->valueAt( 0 ), widget->valueAt( 1 ) );
+ }
+}
diff --git a/chalk/plugins/filters/cubismfilter/kis_cubism_filter.h b/chalk/plugins/filters/cubismfilter/kis_cubism_filter.h
new file mode 100644
index 00000000..f2624030
--- /dev/null
+++ b/chalk/plugins/filters/cubismfilter/kis_cubism_filter.h
@@ -0,0 +1,78 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_CUBISM_FILTER_H_
+#define _KIS_CUBISM_FILTER_H_
+
+#include "kis_filter.h"
+#include "kis_filter_config_widget.h"
+#include <kdebug.h>
+
+class KisPolygon;
+
+class KisCubismFilterConfiguration : public KisFilterConfiguration
+{
+public:
+ KisCubismFilterConfiguration(TQ_UINT32 tileSize, TQ_UINT32 tileSaturation)
+ : KisFilterConfiguration( "cubism", 1 )
+ , m_tileSize(tileSize)
+ , m_tileSaturation(tileSaturation)
+ {
+ setProperty("tileSize", tileSize);
+ setProperty("tileSaturation", tileSaturation);
+ };
+public:
+ inline TQ_UINT32 tileSize() { return getInt("tileSize"); };
+ inline TQ_UINT32 tileSaturation() {return getInt("tileSaturation"); };
+private:
+ TQ_UINT32 m_tileSize;
+ TQ_UINT32 m_tileSaturation;
+};
+
+class KisCubismFilter : public KisFilter
+{
+public:
+ KisCubismFilter();
+public:
+ virtual void process(KisPaintDeviceSP,KisPaintDeviceSP, KisFilterConfiguration* , const TQRect&);
+ static inline KisID id() { return KisID("cubism", i18n("Cubism")); };
+ virtual bool supportsPainting() { return false; }
+ virtual bool supportsPreview() { return true; }
+ virtual std::list<KisFilterConfiguration*> listOfExamplesConfiguration(KisPaintDeviceSP )
+ { std::list<KisFilterConfiguration*> list; list.insert(list.begin(), new KisCubismFilterConfiguration(10,10)); return list; }
+ virtual bool workWith(KisColorSpace* cs);
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return TO_RGBA8; };
+public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration* configuration(TQWidget*);
+ virtual KisFilterConfiguration* configuration() { return new KisCubismFilterConfiguration( 10, 10); };
+private:
+ //this function takes an array of ordered indices i1,i2,i3,... and randomizes them i3,i1,i2,...
+ void randomizeIndices (TQ_INT32 count, TQ_INT32* indices);
+ TQ_INT32 randomIntNumber(TQ_INT32 lowestNumber, TQ_INT32 highestNumber);
+ double randomDoubleNumber(double lowestNumber, double highestNumber);
+ double calcAlphaBlend(double *vec, double oneOverDist, double x, double y);
+ void convertSegment(TQ_INT32 x1, TQ_INT32 y1, TQ_INT32 x2, TQ_INT32 y2, TQ_INT32 offset, TQ_INT32* min, TQ_INT32* max, TQ_INT32 xmin, TQ_INT32 xmax);
+ void fillPolyColor(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisPolygon* poly, const TQ_UINT8* col, TQ_UINT8* dest, TQRect rect);
+ void cubism(KisPaintDeviceSP src, KisPaintDeviceSP dst, const TQRect& rect, TQ_UINT32 tileSize, TQ_UINT32 tileSaturation);
+
+};
+
+#endif
diff --git a/chalk/plugins/filters/cubismfilter/kis_cubism_filter_plugin.cc b/chalk/plugins/filters/cubismfilter/kis_cubism_filter_plugin.cc
new file mode 100644
index 00000000..4e7dfa7d
--- /dev/null
+++ b/chalk/plugins/filters/cubismfilter/kis_cubism_filter_plugin.cc
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <kgenericfactory.h>
+#include "kis_cubism_filter_plugin.h"
+#include "kis_cubism_filter.h"
+
+typedef KGenericFactory<KisCubismFilterPlugin> KisCubismFilterPluginFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkcubismfilter, KisCubismFilterPluginFactory( "chalk" ) )
+
+KisCubismFilterPlugin::KisCubismFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &) : KParts::Plugin(tqparent, name)
+{
+ setInstance(KisCubismFilterPluginFactory::instance());
+
+ if ( tqparent->inherits("KisFilterRegistry") )
+ {
+ KisFilterRegistry * r = dynamic_cast<KisFilterRegistry*>(tqparent);
+ r->add(new KisCubismFilter());
+ }
+}
+
+KisCubismFilterPlugin::~KisCubismFilterPlugin()
+{
+}
+
diff --git a/chalk/plugins/filters/cubismfilter/kis_cubism_filter_plugin.h b/chalk/plugins/filters/cubismfilter/kis_cubism_filter_plugin.h
new file mode 100644
index 00000000..b37e40c1
--- /dev/null
+++ b/chalk/plugins/filters/cubismfilter/kis_cubism_filter_plugin.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_CUBISM_FILTER_PLUGIN_H_
+#define _KIS_CUBISM_FILTER_PLUGIN_H_
+
+#include <kparts/plugin.h>
+
+class KisCubismFilterPlugin : public KParts::Plugin
+{
+public:
+ KisCubismFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~KisCubismFilterPlugin();
+};
+
+#endif
diff --git a/chalk/plugins/filters/cubismfilter/kis_polygon.cc b/chalk/plugins/filters/cubismfilter/kis_polygon.cc
new file mode 100644
index 00000000..cd2d979f
--- /dev/null
+++ b/chalk/plugins/filters/cubismfilter/kis_polygon.cc
@@ -0,0 +1,102 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * ported from Gimp, Copyright (C) 1997 Eiichi Takamori <taka@ma1.seikyou.ne.jp>
+ * 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 <math.h>
+#include <tqvaluevector.h>
+
+#include <kis_point.h>
+
+#include "kis_polygon.h"
+
+void KisPolygon::addPoint(double x, double y)
+{
+ KisPoint point(x, y);
+ append(point);
+}
+
+void KisPolygon::rotate(double theta)
+{
+ double ct, st, ox, oy;
+
+ ct = cos( theta );
+ st = sin( theta );
+
+ KisPointVector::iterator it;
+ for( it = begin(); it != end(); ++it )
+ {
+ ox = (*it).x();
+ oy = (*it).y();
+ (*it).setX( ct * ox - st * oy );
+ (*it).setY( st * ox + ct * oy );
+ }
+}
+
+void KisPolygon::translate(double tx, double ty)
+{
+ KisPointVector::iterator it;
+
+ for( it = begin(); it != end(); ++it )
+ {
+ (*it).setX( (*it).x() + tx );
+ (*it).setY( (*it).y() + ty );
+ }
+}
+
+TQ_INT32 KisPolygon::extents (double& x1, double& y1, double& x2, double& y2)
+{
+ if ( empty() )
+ {
+ return 0;
+ }
+ x1 = x2 = front().x();
+ y1 = y2 = front().y();
+
+ KisPointVector::iterator it;
+
+ for( it = begin(); it != end(); ++it )
+ {
+ if ((*it).x() < x1)
+ {
+ x1 = (*it).x();
+ }
+ if ((*it).x() > x2)
+ {
+ x2 = (*it).x();
+ }
+ if ((*it).y() < y1)
+ {
+ y1 = (*it).y();
+ }
+ if ((*it).y() > y2)
+ {
+ y2 = (*it).y();
+ }
+ }
+ return 1;
+}
+
+TQ_INT32 KisPolygon::numberOfPoints()
+{
+ return count();
+}
+
diff --git a/chalk/plugins/filters/cubismfilter/kis_polygon.h b/chalk/plugins/filters/cubismfilter/kis_polygon.h
new file mode 100644
index 00000000..372ef18b
--- /dev/null
+++ b/chalk/plugins/filters/cubismfilter/kis_polygon.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_POLYGON_H_
+#define _KIS_POLYGON_H_
+
+#include <tqvaluevector.h>
+
+typedef TQValueVector<KisPoint> KisPointVector;
+class KisPolygon : public KisPointVector
+{
+ public:
+ void addPoint(double x, double y);
+ void translate(double tx, double ty);
+ void rotate(double theta);
+ TQ_INT32 extents(double &minX, double &minY, double &maxX, double &maxY);
+ TQ_INT32 numberOfPoints();
+};
+
+#endif
diff --git a/chalk/plugins/filters/embossfilter/Makefile.am b/chalk/plugins/filters/embossfilter/Makefile.am
new file mode 100644
index 00000000..eaf403f4
--- /dev/null
+++ b/chalk/plugins/filters/embossfilter/Makefile.am
@@ -0,0 +1,24 @@
+kde_services_DATA = chalkembossfilter.desktop
+
+INCLUDES = \
+ -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../ui \
+ -I$(srcdir)/../../../../lib/kofficecore \
+ -I$(srcdir)/../../../../lib/kofficeui \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalkembossfilter.la
+
+chalkembossfilter_la_SOURCES = kis_emboss_filter_plugin.cc \
+ kis_emboss_filter.cc
+
+noinst_HEADERS = kis_emboss_filter_plugin.h \
+ kis_emboss_filter.h
+
+chalkembossfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkembossfilter_la_LIBADD = ../../../libchalkcommon.la
+
+chalkembossfilter_la_METASOURCES = AUTO
diff --git a/chalk/plugins/filters/embossfilter/chalkembossfilter.desktop b/chalk/plugins/filters/embossfilter/chalkembossfilter.desktop
new file mode 100644
index 00000000..af04bb1f
--- /dev/null
+++ b/chalk/plugins/filters/embossfilter/chalkembossfilter.desktop
@@ -0,0 +1,71 @@
+[Desktop Entry]
+Name=Emboss Filter
+Name[bg]=Релефен филтър
+Name[ca]=Filtre d'Emboss
+Name[cy]=Hidlen Foglynnu
+Name[da]=Relieffilter
+Name[de]=Relief-Filter
+Name[el]=Φίλτρο εμβάθυνσης
+Name[eo]=Reliefiga filtrilo
+Name[es]=Filtro de realce
+Name[et]=Kohrutusfilter
+Name[fa]=برجسته کردن پالایه
+Name[fr]=Filtre gravure
+Name[fy]=Reliëffilter
+Name[gl]=Filtro de Gravado
+Name[hu]=Emboss szűrő
+Name[is]=Upphleypt sía
+Name[it]=Filtro in rilievo
+Name[ja]=エンボスフィルタ
+Name[km]=តម្រង​ក្រឡោប
+Name[nb]=Pregefilter
+Name[nds]=Ingraven-Filter
+Name[ne]=अलंकृत फिल्टर
+Name[nl]=Reliëffilter
+Name[pl]=Filtr wytłaczania
+Name[pt]=Filtro de Gravação
+Name[pt_BR]=Filtro de Relevo
+Name[ru]=Рельеф
+Name[sl]=Filter Izboči
+Name[sr]=Рељефни филтер
+Name[sr@Latn]=Reljefni filter
+Name[sv]=Relieffilter
+Name[uk]=Фільтр барельєфу
+Name[zh_TW]=浮雕過濾器
+Comment=Emboss filter
+Comment[bg]=Релефен филтър
+Comment[ca]=Filtre d'Emboss
+Comment[cy]=Hidlen foglynnu
+Comment[da]=Relieffilter
+Comment[de]=Relief-Filter
+Comment[el]=Φίλτρο εμβάθυνσης
+Comment[eo]=Reliefiga filtrilo
+Comment[es]=Filtro de realce
+Comment[et]=Kohrutusfilter
+Comment[fa]=برجسته کردن پالایه
+Comment[fr]=Filtre gravure
+Comment[fy]=Reliëffilter
+Comment[gl]=Filtro de gravado
+Comment[hu]=Emboss szűrő
+Comment[is]=Upphleypt sía
+Comment[it]=Filtro in rilievo
+Comment[ja]=エンボスフィルタ
+Comment[km]=តម្រង​ក្រឡោប
+Comment[nb]=Pregefilter
+Comment[nds]=Ingraven-Filter
+Comment[ne]=अलंकृत फिल्टर
+Comment[nl]=Reliëffilter
+Comment[pl]=Filtr wytłaczania
+Comment[pt]=Filtro de gravação
+Comment[pt_BR]=Filtro de relevo
+Comment[ru]=Рельеф
+Comment[sl]=Filter Izboči
+Comment[sr]=Рељефни филтер
+Comment[sr@Latn]=Reljefni filter
+Comment[sv]=Relieffilter
+Comment[uk]=Фільтр барельєфу
+Comment[zh_TW]=浮雕過濾器
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkembossfilter
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/embossfilter/kis_emboss_filter.cc b/chalk/plugins/filters/embossfilter/kis_emboss_filter.cc
new file mode 100644
index 00000000..f15b5952
--- /dev/null
+++ b/chalk/plugins/filters/embossfilter/kis_emboss_filter.cc
@@ -0,0 +1,179 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * ported from digikam, Copyright 2004 by Gilles Caulier,
+ * Original Emboss algorithm copyrighted 2004 by
+ * Pieter Z. Voloshyn <pieter_voloshyn at ame.com.br>.
+ *
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+#include <tqspinbox.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <knuminput.h>
+
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_filter_registry.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_view.h>
+
+#include "kis_multi_integer_filter_widget.h"
+#include "kis_emboss_filter.h"
+
+KisEmbossFilter::KisEmbossFilter() : KisFilter(id(), "emboss", i18n("&Emboss with Variable Depth..."))
+{
+}
+
+void KisEmbossFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* configuration, const TQRect& rect)
+{
+ Q_UNUSED(dst);
+
+
+ //read the filter configuration values from the KisFilterConfiguration object
+ TQ_UINT32 embossdepth = ((KisEmbossFilterConfiguration*)configuration)->depth();
+
+ //the actual filter function from digikam. It needs a pointer to a TQ_UINT8 array
+ //with the actual pixel data.
+
+ Emboss(src, dst, rect, embossdepth);
+}
+
+// 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::Emboss(KisPaintDeviceSP src, KisPaintDeviceSP dst, const TQRect& rect, int d)
+{
+ float Depth = d / 10.0;
+ int R = 0, G = 0, B = 0;
+ uchar Gray = 0;
+ int Width = rect.width();
+ int Height = rect.height();
+
+ setProgressTotalSteps(Height);
+ setProgressStage(i18n("Applying emboss filter..."),0);
+
+ KisHLineIteratorPixel it = src->createHLineIterator(rect.x(), rect.y(), rect.width(), false);
+ KisHLineIteratorPixel dstIt = dst->createHLineIterator(rect.x(), rect.y(), rect.width(), true);
+ TQColor color1;
+ TQColor color2;
+ TQ_UINT8 opacity;
+ TQ_UINT8 opacity2;
+
+ for (int y = 0 ; !cancelRequested() && (y < Height) ; ++y)
+ {
+
+ for (int x = 0 ; !cancelRequested() && (x < Width) ; ++x, ++it, ++dstIt)
+ {
+ if (it.isSelected()) {
+
+// XXX: COLORSPACE_INDEPENDENCE
+ opacity = 0;
+ opacity2 = 0;
+
+ src->colorSpace()->toTQColor(it.rawData(), &color1, &opacity);
+
+ src->pixel(rect.x() + x + Lim_Max(x, 1, Width), rect.y() + y + Lim_Max(y, 1, Height), &color2, &opacity2);
+
+ R = abs((int)((color1.red() - color2.red()) * Depth + (TQ_UINT8_MAX / 2)));
+ G = abs((int)((color1.green() - color2.green()) * Depth + (TQ_UINT8_MAX / 2)));
+ B = abs((int)((color1.blue() - color2.blue()) * Depth + (TQ_UINT8_MAX / 2)));
+
+ Gray = CLAMP((R + G + B) / 3, 0, TQ_UINT8_MAX);
+
+ dst->colorSpace()->fromTQColor(TQColor(Gray, Gray, Gray), opacity, dstIt.rawData());
+ }
+ }
+
+ it.nextRow();
+ dstIt.nextRow();
+ setProgress(y);
+ }
+
+ setProgressDone();
+}
+
+// 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 go alright until reachs the
+ * w = 305, because in the next step w will go to 310, but we want
+ * to analize all the pixels. So, this function will reduce the
+ * "for step", when necessary, until reach the last possible value
+ */
+
+int KisEmbossFilter::Lim_Max (int Now, int Up, int Max)
+{
+ --Max;
+ while (Now > Max - Up)
+ --Up;
+ return (Up);
+}
+
+KisFilterConfigWidget * KisEmbossFilter::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP)
+{
+ vKisIntegerWidgetParam param;
+ param.push_back( KisIntegerWidgetParam( 10, 300, 30, i18n("Depth"), "depth" ) );
+ KisFilterConfigWidget * w = new KisMultiIntegerFilterWidget(tqparent, id().id().ascii(), id().id().ascii(), param );
+ Q_CHECK_PTR(w);
+ return w;
+}
+
+KisFilterConfiguration* KisEmbossFilter::configuration(TQWidget* nwidget)
+{
+ KisMultiIntegerFilterWidget* widget = (KisMultiIntegerFilterWidget*) nwidget;
+ if( widget == 0 )
+ {
+ return new KisEmbossFilterConfiguration( 30 );
+ } else {
+ return new KisEmbossFilterConfiguration( widget->valueAt( 0 ) );
+ }
+}
diff --git a/chalk/plugins/filters/embossfilter/kis_emboss_filter.h b/chalk/plugins/filters/embossfilter/kis_emboss_filter.h
new file mode 100644
index 00000000..fe4410ed
--- /dev/null
+++ b/chalk/plugins/filters/embossfilter/kis_emboss_filter.h
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_EMBOSS_FILTER_H_
+#define _KIS_EMBOSS_FILTER_H_
+
+#include "kis_filter.h"
+#include "kis_filter_config_widget.h"
+
+class KisEmbossFilterConfiguration : public KisFilterConfiguration
+{
+public:
+ KisEmbossFilterConfiguration(TQ_UINT32 depth)
+ : KisFilterConfiguration( "emboss", 1 )
+ {
+ setProperty("depth", depth);
+ };
+public:
+ inline TQ_UINT32 depth() { return getInt("depth"); };
+};
+
+class KisEmbossFilter : public KisFilter
+{
+public:
+ KisEmbossFilter();
+public:
+ virtual void process(KisPaintDeviceSP,KisPaintDeviceSP, KisFilterConfiguration* , const TQRect&);
+ static inline KisID id() { return KisID("emboss", i18n("Emboss")); };
+ virtual bool supportsPainting() { return false; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsAdjustmentLayers() { return false; };
+
+ virtual std::list<KisFilterConfiguration*> listOfExamplesConfiguration(KisPaintDeviceSP )
+ { std::list<KisFilterConfiguration*> list; list.insert(list.begin(), new KisEmbossFilterConfiguration(100)); return list; }
+ public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration* configuration(TQWidget*);
+ virtual KisFilterConfiguration* configuration() {return new KisEmbossFilterConfiguration( 30 );};
+
+private:
+ void Emboss(KisPaintDeviceSP src, KisPaintDeviceSP dst, const TQRect& rect, int d);
+ inline int Lim_Max (int Now, int Up, int Max);
+};
+
+#endif
diff --git a/chalk/plugins/filters/embossfilter/kis_emboss_filter_plugin.cc b/chalk/plugins/filters/embossfilter/kis_emboss_filter_plugin.cc
new file mode 100644
index 00000000..4aec1db6
--- /dev/null
+++ b/chalk/plugins/filters/embossfilter/kis_emboss_filter_plugin.cc
@@ -0,0 +1,40 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ * 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 <kgenericfactory.h>
+#include "kis_emboss_filter_plugin.h"
+#include "kis_emboss_filter.h"
+#include "kis_global.h"
+
+typedef KGenericFactory<KisEmbossFilterPlugin> KisEmbossFilterPluginFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkembossfilter, KisEmbossFilterPluginFactory( "chalk" ) )
+
+KisEmbossFilterPlugin::KisEmbossFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &) : KParts::Plugin(tqparent, name)
+{
+ setInstance(KisEmbossFilterPluginFactory::instance());
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisEmbossFilter());
+ }
+}
+
+KisEmbossFilterPlugin::~KisEmbossFilterPlugin()
+{
+}
diff --git a/chalk/plugins/filters/embossfilter/kis_emboss_filter_plugin.h b/chalk/plugins/filters/embossfilter/kis_emboss_filter_plugin.h
new file mode 100644
index 00000000..39803418
--- /dev/null
+++ b/chalk/plugins/filters/embossfilter/kis_emboss_filter_plugin.h
@@ -0,0 +1,32 @@
+/* This file is part of the KDE project
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_EMBOSS_FILTER_PLUGIN_H_
+#define _KIS_EMBOSS_FILTER_PLUGIN_H_
+
+#include <kparts/plugin.h>
+
+class KisEmbossFilterPlugin : public KParts::Plugin
+{
+public:
+ KisEmbossFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~KisEmbossFilterPlugin();
+};
+
+#endif
+
diff --git a/chalk/plugins/filters/example/Makefile.am b/chalk/plugins/filters/example/Makefile.am
new file mode 100644
index 00000000..f2f39c3a
--- /dev/null
+++ b/chalk/plugins/filters/example/Makefile.am
@@ -0,0 +1,22 @@
+chalkrcdir = $(kde_datadir)/chalk/chalkplugins
+
+kde_services_DATA = chalkexample.desktop
+
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkexample_la_SOURCES = example.cc
+
+kde_module_LTLIBRARIES = chalkexample.la
+noinst_HEADERS = example.h
+
+chalkexample_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkexample_la_LIBADD = ../../../libchalkcommon.la
+
+chalkexample_la_METASOURCES = AUTO
diff --git a/chalk/plugins/filters/example/chalkexample.desktop b/chalk/plugins/filters/example/chalkexample.desktop
new file mode 100644
index 00000000..e9fc3447
--- /dev/null
+++ b/chalk/plugins/filters/example/chalkexample.desktop
@@ -0,0 +1,81 @@
+[Desktop Entry]
+Name=Invert Filter
+Name[bg]=Инвертиращ филтър
+Name[ca]=Inverteix filtre
+Name[cy]=Hidlen Wrthdroi
+Name[da]=Inverteringsfilter
+Name[de]=Invertierungsfilter
+Name[el]=Φίλτρο αντιστροφής
+Name[eo]=Inversiga filtrilo
+Name[es]=Filtro de inversión
+Name[et]=Inverteerimisfilter
+Name[fa]=پالایۀ وارونه
+Name[fr]=Filtre d'inversion
+Name[fy]=Omdraaifilter
+Name[ga]=Scagaire Inbhéartaithe
+Name[gl]=Filtro de Inversión
+Name[hu]=Invertáló szűrő
+Name[is]=Andhverf sía
+Name[it]=File di inversione
+Name[ja]=反転フィルタ
+Name[km]=តម្រង​បញ្ច្រាស
+Name[lt]=Invertavimo filtras
+Name[nb]=Inverteringsfilter
+Name[nds]=Ümdreih-Filter
+Name[ne]=फिल्टर उल्टाउनुहोस्
+Name[nl]=Inversefilter
+Name[pl]=Filtr inwersji
+Name[pt]=Filtro de Inversão
+Name[pt_BR]=Filtro de Inversão
+Name[ru]=Инвертирование
+Name[se]=Inverterensilli
+Name[sk]=Inverzný Filter
+Name[sl]=Filter za obračanje
+Name[sr]=Филтер за инверзију
+Name[sr@Latn]=Filter za inverziju
+Name[sv]=Inverteringsfilter
+Name[uk]=Фільтр інвертування
+Name[zh_TW]=倒轉過濾器
+Comment=Invert the colors of an image
+Comment[bg]=Инвертиращ филтър
+Comment[ca]=Inverteix els colors d'una imatge
+Comment[cy]=Gwrthdroi lliwiau delwedd
+Comment[da]=Invertér farverne i et billede
+Comment[de]=Die Farben eines Bildes invertieren
+Comment[el]=Αντιστροφή των χρωμάτων μίας εικόνας
+Comment[en_GB]=Invert the colours of an image
+Comment[eo]=Inversigi la kolorojn de bildo
+Comment[es]=Invierte los colores de una imagen
+Comment[et]=Inverteerib pildi värvid
+Comment[fa]=وارونه کردن رنگهای یک تصویر
+Comment[fr]=Inverse les couleurs de l'image
+Comment[fy]=Draaid de kleuren fan in ôfbylding om
+Comment[gl]=Inverte as cores dunha imaxe
+Comment[hu]=Egy kép színeinek invertálása
+Comment[is]=Snúðu litum myndarinnar
+Comment[it]=Inverte i colori di un'immagine
+Comment[ja]=画像の色を反転
+Comment[km]=បញ្ច្រាស​ពណ៌​រូបភាព
+Comment[lt]=Invertuoja paveikslėlio spalvas
+Comment[nb]=Snu om fargene i et bilde
+Comment[nds]=De Klören vun en Bild ümdreihen
+Comment[ne]=एउटा छविको रङहरू उल्टाउनुहोस्
+Comment[nl]=Keert de kleuren van een afbeelding om
+Comment[pl]=Odwraca kolory obrazka
+Comment[pt]=Inverter as cores de uma imagem
+Comment[pt_BR]=Inverter as cores de uma imagem
+Comment[ru]=Инвертировать цвета изображения
+Comment[se]=Invertere ivnniid govas
+Comment[sk]=Invertovať farby obrázku
+Comment[sl]=Preobrni barve v sliki
+Comment[sr]=Инвертује боје на слици
+Comment[sr@Latn]=Invertuje boje na slici
+Comment[sv]=Invertera färgerna i en bild
+Comment[uk]=Інвертація кольорів зображення
+Comment[uz]=Rasmning ranglarini teskarisiga almashtirish
+Comment[uz@cyrillic]=Расмнинг рангларини тескарисига алмаштириш
+Comment[zh_TW]=倒轉圖片的色彩
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkexample
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/example/example.cc b/chalk/plugins/filters/example/example.cc
new file mode 100644
index 00000000..2e2fbc7c
--- /dev/null
+++ b/chalk/plugins/filters/example/example.cc
@@ -0,0 +1,95 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_filter_registry.h>
+#include <kis_global.h>
+#include <kis_types.h>
+
+// #include <kmessagebox.h>
+
+#include "example.h"
+
+typedef KGenericFactory<ChalkExample> ChalkExampleFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkexample, ChalkExampleFactory( "chalk" ) )
+
+ChalkExample::ChalkExample(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ChalkExampleFactory::instance());
+
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisFilterInvert());
+ }
+}
+
+ChalkExample::~ChalkExample()
+{
+}
+
+KisFilterInvert::KisFilterInvert() : KisFilter(id(), "adjust", i18n("&Invert"))
+{
+}
+
+void KisFilterInvert::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* /*config*/, const TQRect& rect)
+{
+ Q_ASSERT(src != 0);
+ Q_ASSERT(dst != 0);
+
+ KisRectIteratorPixel dstIt = dst->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true );
+ KisRectIteratorPixel srcIt = src->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), false);
+
+ int pixelsProcessed = 0;
+ setProgressTotalSteps(rect.width() * rect.height());
+
+ KisColorSpace * cs = src->colorSpace();
+ TQ_INT32 psize = cs->pixelSize();
+
+ while( ! srcIt.isDone() )
+ {
+ if(srcIt.isSelected())
+ {
+ if (src!=dst)
+ memcpy(dstIt.rawData(), srcIt.oldRawData(), psize);
+
+ cs->invertColor( dstIt.rawData(), 1);
+ }
+ setProgress(++pixelsProcessed);
+ ++srcIt;
+ ++dstIt;
+ }
+ setProgressDone(); // Must be called even if you don't really support progression
+}
diff --git a/chalk/plugins/filters/example/example.h b/chalk/plugins/filters/example/example.h
new file mode 100644
index 00000000..df49d036
--- /dev/null
+++ b/chalk/plugins/filters/example/example.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 EXAMPLE_H
+#define EXAMPLE_H
+
+#include <kparts/plugin.h>
+#include "kis_filter.h"
+
+class ChalkExample : public KParts::Plugin
+{
+public:
+ ChalkExample(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ChalkExample();
+};
+
+class KisFilterInvert : public KisFilter
+{
+public:
+ KisFilterInvert();
+public:
+ virtual void process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration*, const TQRect&);
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return FULLY_INDEPENDENT; };
+ static inline KisID id() { return KisID("invert", i18n("Invert")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+};
+
+#endif
diff --git a/chalk/plugins/filters/fastcolortransfer/Makefile.am b/chalk/plugins/filters/fastcolortransfer/Makefile.am
new file mode 100644
index 00000000..f29b7a3b
--- /dev/null
+++ b/chalk/plugins/filters/fastcolortransfer/Makefile.am
@@ -0,0 +1,23 @@
+chalkrcdir = $(kde_datadir)/chalk/chalkplugins
+
+kde_services_DATA = chalkfastcolortransfer.desktop
+
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkfastcolortransfer_la_SOURCES = wdgfastcolortransfer.ui fastcolortransfer.cc \
+ kis_wdg_fastcolortransfer.cpp
+
+kde_module_LTLIBRARIES = chalkfastcolortransfer.la
+noinst_HEADERS = fastcolortransfer.h kis_wdg_fastcolortransfer.h
+
+chalkfastcolortransfer_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficecore/.libs -lkofficecore
+chalkfastcolortransfer_la_LIBADD = ../../../libchalkcommon.la
+
+METASOURCES = AUTO
diff --git a/chalk/plugins/filters/fastcolortransfer/chalkfastcolortransfer.desktop b/chalk/plugins/filters/fastcolortransfer/chalkfastcolortransfer.desktop
new file mode 100644
index 00000000..cc32f72b
--- /dev/null
+++ b/chalk/plugins/filters/fastcolortransfer/chalkfastcolortransfer.desktop
@@ -0,0 +1,69 @@
+[Desktop Entry]
+Comment=This plugins allow to transfer color from an image to an other image
+Comment[bg]=Тази приставка позволява прехвърлянето на цвят от едно в друго изображение
+Comment[ca]=Aquest endollats permeten de transferir el color d'una imatge a una altra
+Comment[da]=Dette plugin gør det muligt at overføre en farve fra et billede til et andet billede
+Comment[de]=Diese Module ermöglichen die Farbübertragung von einem Bild zu einem anderen
+Comment[el]=Αυτό το πρόσθετο επιτρέπει τη μεταφορά χρώματος από μια εικόνα σε κάποια άλλη
+Comment[es]=Este complemento le permite transferir colores de una imagen a otra
+Comment[et]=See plugin võimaldab värvi ühelt pildilt teisele üle kanda
+Comment[fa]=این وصله اجازۀ انتقال رنگ از یک تصویر به تصویر دیگر را می‌دهد
+Comment[fr]=Ce module permet de transférer une couleur d'une image à une autre
+Comment[fy]=Mei dizze plugin kinne jo kleur fan in ôfbylding nei in oare oersette
+Comment[gl]=Estas extensión permiten transferir cor dunha imaxe a outra
+Comment[hu]=Színek átvitele egyik képről a másikra
+Comment[it]=Questo plugin permette di trasferire il colore da un'immagine a un'altra
+Comment[ja]=このプラグインは他の画像から色を移植することを可能にします
+Comment[km]=កម្មវិធី​ជំនួយ​នេះ​អនុញ្ញាត​ឲ្យ​ផ្ទេរ​ពណ៌​ពី​រូបភាព​មួយ​ទៅ​រូបភាព​មួយ​ផ្សេងទៀត​
+Comment[nb]=Med dette programtillegget kan farger overføres fra ett bilde til et annet
+Comment[nds]=Mit dissen Moduul laat sik Klören vun een Bild na en anner överdregen
+Comment[ne]=यो प्लगइनले एउटा छविबाट अर्को छविमा रङ स्थान्तरण गर्न अनुमति दिन्छ
+Comment[nl]=Met deze plugin kunt u kleur van een afbeelding naar een andere overzetten
+Comment[pl]=Ta wtyczka pozwala na przeniesienie koloru z jednego obrazka do drugiego
+Comment[pt]=Este 'plugin' permite transferir a cor de uma imagem para outra
+Comment[pt_BR]=Este plugin permite transferir a cor de uma imagem para outra
+Comment[ru]=Перенос цвета из одного изображения в другое
+Comment[sk]=Tieto moduly umožňujú presúvať farby medzi obrázkami
+Comment[sl]=Ta vstavek omogoča prenos barve iz ene slike v drugo
+Comment[sr]=Овај прикључак омогућава пренос боје са једне на другу слику
+Comment[sr@Latn]=Ovaj priključak omogućava prenos boje sa jedne na drugu sliku
+Comment[sv]=Insticksprogrammet gör det möjligt att överföra en färg från en bild till en annan bild
+Comment[uk]=Перенесення кольору з одного зображення в інше
+Comment[zh_TW]=這個外掛程式允許將一張圖片的顏色轉換為另一張圖片
+Icon=
+Name=Color Transfer Filter
+Name[bg]=Филтри за прехвърляне на цвят
+Name[ca]=Filtre de transferència de color
+Name[da]=Farveoverførselsfilter
+Name[de]=Farbübertragungsfilter
+Name[el]=Φίλτρο μεταφοράς χρώματος
+Name[eo]=Kolortransiga filtrilo
+Name[es]=Filtro de transferencia de color
+Name[et]=Värviülekande filter
+Name[fa]=پالایۀ انتقال رنگ
+Name[fr]=Filtres de transfert de couleur
+Name[fy]=Kleuroersetfilter
+Name[gl]=Filtros de Transferencia de Cores
+Name[hu]=Színátviteli szűrő
+Name[it]=Filtro di trasferimento del colore
+Name[ja]=色移植フィルタ
+Name[km]=តម្រង​ផ្ទេរ​ពណ៌​
+Name[nb]=Fargeoverføringsfilter
+Name[nds]=Klööröverdregenfilter
+Name[ne]=रङ स्थान्तरण फिल्टर
+Name[nl]=Kleuroverzetfilter
+Name[pl]=Filtr przeniesienia koloru
+Name[pt]=Filtro de Transferência de Cores
+Name[pt_BR]=Filtros de Transferência de Cores
+Name[ru]=Перенос цвета
+Name[sk]=Filter na premenu farieb
+Name[sl]=Filter za prenos barve
+Name[sr]=Филтер за пренос боја
+Name[sr@Latn]=Filter za prenos boja
+Name[sv]=Färgöverföringsfilter
+Name[uk]=Перенесення кольору
+Name[zh_TW]=色彩轉換過濾器
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkfastcolortransfer
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/fastcolortransfer/fastcolortransfer.cc b/chalk/plugins/filters/fastcolortransfer/fastcolortransfer.cc
new file mode 100644
index 00000000..10ef044d
--- /dev/null
+++ b/chalk/plugins/filters/fastcolortransfer/fastcolortransfer.cc
@@ -0,0 +1,206 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <kgenericfactory.h>
+#include <kurlrequester.h>
+
+#include <kis_colorspace_factory_registry.h>
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_meta_registry.h>
+#include <kis_paint_device.h>
+
+#include "kis_wdg_fastcolortransfer.h"
+#include "wdgfastcolortransfer.h"
+
+typedef KGenericFactory<FastColorTransferPlugin> ChalkFastColorTransferFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkfastcolortransfer, ChalkFastColorTransferFactory( "chalk" ) )
+
+
+FastColorTransferPlugin::FastColorTransferPlugin(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ChalkFastColorTransferFactory::instance());
+
+ kdDebug(41006) << "Color Transfer Filter plugin. Class: "
+ << className()
+ << ", Parent: "
+ << tqparent -> className()
+ << "\n";
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisFilterFastColorTransfer());
+ }
+}
+
+FastColorTransferPlugin::~FastColorTransferPlugin()
+{
+}
+
+KisFilterFastColorTransfer::KisFilterFastColorTransfer() : KisFilter(id(), "colors", i18n("&Color Transfer..."))
+{
+}
+
+
+KisFilterConfigWidget * KisFilterFastColorTransfer::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP )
+{
+ return new KisWdgFastColorTransfer(this, tqparent, "configuration of color to alpha");
+}
+
+KisFilterConfiguration* KisFilterFastColorTransfer::configuration(TQWidget* w)
+{
+ KisWdgFastColorTransfer * wCTA = dynamic_cast<KisWdgFastColorTransfer*>(w);
+ KisFilterConfiguration* config = new KisFilterConfiguration(id().id(), 1);
+ if(wCTA)
+ {
+ config->setProperty("filename", wCTA->widget()->fileNameURLRequester->url() );
+ }
+ return config;
+}
+
+void KisFilterFastColorTransfer::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* config, const TQRect& rect)
+{
+ kdDebug() << "Start transfering color" << endl;
+ TQVariant value;
+ TQString fileName;
+ if (config && config->getProperty("filename", value))
+ {
+ fileName = value.toString();
+ } else {
+ kdDebug() << "No file name for the reference image was specified." << endl;
+ return;
+ }
+
+ KisPaintDeviceSP ref;
+
+ KisDoc d;
+ d.import(fileName);
+ KisImageSP importedImage = d.currentImage();
+
+ if(importedImage)
+ {
+ ref = importedImage->projection();
+ }
+ if(!ref)
+ {
+ kdDebug() << "No reference image was specified." << endl;
+ return;
+ }
+
+ // Convert ref and src to LAB
+ KisColorSpace* labCS = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("LABA"),"");
+ if(!labCS)
+ {
+ kdDebug() << "The LAB colorspace is not available." << endl;
+ return;
+ }
+
+ setProgressTotalSteps(5);
+
+ KisColorSpace* oldCS = src->colorSpace();
+ KisPaintDeviceSP srcLAB = new KisPaintDevice(*src.data());
+ srcLAB->convertTo(labCS);
+ ref->convertTo(labCS);
+
+ setProgress( 1 );
+
+ // 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.;
+ KisRectIteratorPixel srcLABIt = srcLAB->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), false );
+ while(!srcLABIt.isDone())
+ {
+ const TQ_UINT16* data = reinterpret_cast<const TQ_UINT16*>(srcLABIt.oldRawData());
+ TQ_UINT32 L = data[0];
+ TQ_UINT32 A = data[1];
+ TQ_UINT32 B = data[2];
+ meanL_src += L;
+ meanA_src += A;
+ meanB_src += B;
+ sigmaL_src += L*L;
+ sigmaA_src += A*A;
+ sigmaB_src += B*B;
+ ++srcLABIt;
+ }
+
+ setProgress( 3 );
+
+ double size = 1. / ( rect.width() * rect.height() );
+ meanL_src *= size;
+ meanA_src *= size;
+ meanB_src *= size;
+ sigmaL_src *= size;
+ sigmaA_src *= size;
+ sigmaB_src *= size;
+ kdDebug() << size << " " << meanL_src << " " << meanA_src << " " << meanB_src << " " << sigmaL_src << " " << sigmaA_src << " " << sigmaB_src << endl;
+ // Compute the means and sigmas of src
+ double meanL_ref = 0., meanA_ref = 0., meanB_ref = 0.;
+ double sigmaL_ref = 0., sigmaA_ref = 0., sigmaB_ref = 0.;
+ KisRectIteratorPixel refIt = ref->createRectIterator(0, 0, importedImage->width(), importedImage->height(), false );
+ while(!refIt.isDone())
+ {
+ const TQ_UINT16* data = reinterpret_cast<const TQ_UINT16*>(refIt.oldRawData());
+ TQ_UINT32 L = data[0];
+ TQ_UINT32 A = data[1];
+ TQ_UINT32 B = data[2];
+ meanL_ref += L;
+ meanA_ref += A;
+ meanB_ref += B;
+ sigmaL_ref += L*L;
+ sigmaA_ref += A*A;
+ sigmaB_ref += B*B;
+ ++refIt;
+ }
+
+ setProgress( 4 );
+
+ size = 1. / ( importedImage->width() * importedImage->height() );
+ meanL_ref *= size;
+ meanA_ref *= size;
+ meanB_ref *= size;
+ sigmaL_ref *= size;
+ sigmaA_ref *= size;
+ sigmaB_ref *= size;
+ kdDebug() << size << " " << meanL_ref << " " << meanA_ref << " " << meanB_ref << " " << sigmaL_ref << " " << sigmaA_ref << " " << sigmaB_ref << endl;
+
+ // Transfer colors
+ dst->convertTo(labCS);
+ {
+ 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));
+ kdDebug() << coefL << " " << coefA << " " << coefB << endl;
+ KisRectIteratorPixel dstIt = dst->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true );
+ while(!dstIt.isDone())
+ {
+ TQ_UINT16* data = reinterpret_cast<TQ_UINT16*>(dstIt.rawData());
+ data[0] = (TQ_UINT16)CLAMP( ( (double)data[0] - meanL_src) * coefL + meanL_ref, 0., 65535.);
+ data[1] = (TQ_UINT16)CLAMP( ( (double)data[1] - meanA_src) * coefA + meanA_ref, 0., 65535.);
+ data[2] = (TQ_UINT16)CLAMP( ( (double)data[2] - meanB_src) * coefB + meanB_ref, 0., 65535.);
+ ++dstIt;
+ }
+ }
+ dst->convertTo(oldCS);
+ setProgressDone(); // Must be called even if you don't really support progression
+}
diff --git a/chalk/plugins/filters/fastcolortransfer/fastcolortransfer.h b/chalk/plugins/filters/fastcolortransfer/fastcolortransfer.h
new file mode 100644
index 00000000..d8a3c898
--- /dev/null
+++ b/chalk/plugins/filters/fastcolortransfer/fastcolortransfer.h
@@ -0,0 +1,55 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 COLORTRANSFER_H
+#define COLORTRANSFER_H
+
+// TODO: remove that
+#define LCMS_HEADER <lcms.h>
+// TODO: remove it !
+
+#include <kparts/plugin.h>
+#include <kis_filter.h>
+
+class FastColorTransferPlugin : public KParts::Plugin
+{
+ public:
+ FastColorTransferPlugin(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~FastColorTransferPlugin();
+};
+
+class KisFilterFastColorTransfer : public KisFilter
+{
+ public:
+ KisFilterFastColorTransfer();
+ public:
+ virtual void process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration*, const TQRect&);
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return FULLY_INDEPENDENT; };
+ static inline KisID id() { return KisID("colortransfer", i18n("Color Transfer")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ virtual bool supportsAdjustmentLayers() { return false; }
+ public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration* configuration(TQWidget*);
+};
+
+#endif
diff --git a/chalk/plugins/filters/fastcolortransfer/kis_wdg_fastcolortransfer.cpp b/chalk/plugins/filters/fastcolortransfer/kis_wdg_fastcolortransfer.cpp
new file mode 100644
index 00000000..3c08cac3
--- /dev/null
+++ b/chalk/plugins/filters/fastcolortransfer/kis_wdg_fastcolortransfer.cpp
@@ -0,0 +1,50 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_wdg_fastcolortransfer.h"
+
+#include <tqlayout.h>
+
+#include <kurlrequester.h>
+
+#include "wdgfastcolortransfer.h"
+
+KisWdgFastColorTransfer::KisWdgFastColorTransfer(KisFilter* nfilter, TQWidget * tqparent, const char * name) : KisFilterConfigWidget ( tqparent, name )
+{
+ TQGridLayout *widgetLayout = new TQGridLayout(this, 1, 1);
+ m_widget = new WdgFastColorTransfer(this);
+ widgetLayout -> addWidget(m_widget,0,0);
+ connect(m_widget->fileNameURLRequester, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SIGNAL(sigPleaseUpdatePreview()));
+}
+
+
+KisWdgFastColorTransfer::~KisWdgFastColorTransfer()
+{
+}
+
+void KisWdgFastColorTransfer::setConfiguration(KisFilterConfiguration* config)
+{
+ TQVariant value;
+ if (config->getProperty("filename", value))
+ {
+ widget()->fileNameURLRequester->setURL( value.toString() );
+ }
+
+}
diff --git a/chalk/plugins/filters/fastcolortransfer/kis_wdg_fastcolortransfer.h b/chalk/plugins/filters/fastcolortransfer/kis_wdg_fastcolortransfer.h
new file mode 100644
index 00000000..0a29aef5
--- /dev/null
+++ b/chalk/plugins/filters/fastcolortransfer/kis_wdg_fastcolortransfer.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_WDG_COLORTRANSFER_H
+#define KIS_WDG_COLORTRANSFER_H
+
+// TODO: remove that
+#define LCMS_HEADER <lcms.h>
+// TODO: remove it !
+
+#include <kis_filter_config_widget.h>
+
+class KisFilter;
+class WdgFastColorTransfer;
+
+/**
+ @author Cyrille Berger <cberger@cberger.net>
+*/
+class KisWdgFastColorTransfer : public KisFilterConfigWidget
+{
+ public:
+ KisWdgFastColorTransfer(KisFilter* nfilter, TQWidget * tqparent, const char * name);
+ ~KisWdgFastColorTransfer();
+ virtual void setConfiguration(KisFilterConfiguration*);
+ inline WdgFastColorTransfer* widget() { return m_widget; }
+ private:
+ WdgFastColorTransfer* m_widget;
+};
+
+#endif
diff --git a/chalk/plugins/filters/fastcolortransfer/wdgfastcolortransfer.ui b/chalk/plugins/filters/fastcolortransfer/wdgfastcolortransfer.ui
new file mode 100644
index 00000000..a7184b4b
--- /dev/null
+++ b/chalk/plugins/filters/fastcolortransfer/wdgfastcolortransfer.ui
@@ -0,0 +1,75 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgFastColorTransfer</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgFastColorTransfer</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>236</width>
+ <height>112</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>label1</cstring>
+ </property>
+ <property name="text">
+ <string>Reference image:</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>fileNameURLRequester</cstring>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Filename of the image whose tones and color you want to transfer to the current layer.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>101</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/filters/halftone/kis_halftone.cpp b/chalk/plugins/filters/halftone/kis_halftone.cpp
new file mode 100644
index 00000000..35e838ed
--- /dev/null
+++ b/chalk/plugins/filters/halftone/kis_halftone.cpp
@@ -0,0 +1,190 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net>
+ * 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_halftone.h"
+
+#include <cmath>
+
+#include <kgenericfactory.h>
+
+#include <kis_autobrush_resource.h>
+#include <kis_convolution_painter.h>
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_math_toolbox.h>
+#include <kis_meta_registry.h>
+#include <kis_multi_integer_filter_widget.h>
+#include <kis_paint_device.h>
+#include <kis_transaction.h>
+
+ typedef KGenericFactory<ChalkHalftone> ChalkHalftoneFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkhalftone, ChalkHalftoneFactory( "chalk" ) )
+
+ ChalkHalftone::ChalkHalftone(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ChalkHalftoneFactory::instance());
+
+ kdDebug(41006) << "Halftone filter plugin. Class: "
+ << className()
+ << ", Parent: "
+ << tqparent->className()
+ << "\n";
+
+
+ if ( tqparent->inherits("KisFilterRegistry") )
+ {
+ KisFilterRegistry * r = dynamic_cast<KisFilterRegistry*>(tqparent);
+ r->add(new KisHalftoneReduction());
+ }
+}
+
+ChalkHalftone::~ChalkHalftone()
+{
+}
+
+
+
+KisHalftoneReduction::KisHalftoneReduction()
+ : KisFilter(id(), "enhance", i18n("Halftone Reduction..."))
+{
+}
+
+
+KisHalftoneReduction::~KisHalftoneReduction()
+{
+}
+
+KisFilterConfigWidget * KisHalftoneReduction::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP )
+{
+ vKisIntegerWidgetParam param;
+ param.push_back( KisIntegerWidgetParam( 0, 100, BEST_WAVELET_FREQUENCY_VALUE, i18n("Frequency"), "frequency" ) );
+ param.push_back( KisIntegerWidgetParam( 0, 100, 2, i18n("Half-size"), "halfsize" ) );
+ return new KisMultiIntegerFilterWidget(tqparent, id().id().ascii(), id().id().ascii(), param );
+}
+
+KisFilterConfiguration* KisHalftoneReduction::configuration(TQWidget* nwidget )
+{
+ KisMultiIntegerFilterWidget* widget = (KisMultiIntegerFilterWidget*) nwidget;
+ if( widget == 0 )
+ {
+ return new KisHalftoneReductionConfiguration( BEST_WAVELET_FREQUENCY_VALUE, 2 );
+ } else {
+ return new KisHalftoneReductionConfiguration( widget->valueAt( 0 ), widget->valueAt( 1 ) );
+ }
+}
+
+void KisHalftoneReduction::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* config, const TQRect& rect)
+{
+
+ float frequency = 1.0;
+ int halfSize = 2;
+
+ if(config !=0)
+ {
+ KisHalftoneReductionConfiguration* configWNRC = (KisHalftoneReductionConfiguration*)config;
+ frequency = configWNRC->getDouble("frequency");
+ halfSize = configWNRC->getInt("halfsize");
+ kdDebug(41005) << "frequency: " << frequency << endl;
+ }
+
+
+ TQ_INT32 depth = src->colorSpace()->nColorChannels();
+
+ int size;
+ int maxrectsize = (rect.height() < rect.width()) ? rect.width() : rect.height();
+ for(size = 2; size < maxrectsize; size *= 2) ;
+
+ KisMathToolbox* mathToolbox = KisMetaRegistry::instance()->mtRegistry()->get( src->colorSpace()->mathToolboxID() );
+ setProgressTotalSteps(mathToolbox->fastWaveletTotalSteps(rect) * 2 + size*size*depth );
+ connect(mathToolbox, TQT_SIGNAL(nextStep()), this, TQT_SLOT(incProgress()));
+
+
+ kdDebug(41005) << size << " " << maxrectsize << " " << rect.x() << " " << rect.y() << endl;
+
+ kdDebug(41005) << halfSize << endl;
+ KisAutobrushShape* kas = new KisAutobrushCircleShape(2*halfSize+1, 2*halfSize+1 , halfSize, halfSize);
+
+ TQImage tqmask;
+ kas->createBrush(&tqmask);
+
+ KisKernelSP kernel = KisKernel::fromTQImage(tqmask); // TODO: for 1.6 reuse the chalk's core function for creating kernel : KisKernel::fromTQImage
+ tqmask.save("testtqmask.png", "PNG");
+
+ KisPaintDeviceSP interm = new KisPaintDevice(*src);
+ KisColorSpace * cs = src->colorSpace();
+
+ KisConvolutionPainter painter( interm );
+ painter.beginTransaction("bouuh");
+ painter.applyMatrix(kernel, rect.x(), rect.y(), rect.width(), rect.height(), BORDER_REPEAT);
+
+// KisPaintDeviceSP interm2 = new KisPaintDevice(*interm);
+
+
+ kdDebug(41005) << "Transforming..." << endl;
+ setProgressStage( i18n("Fast wavelet transformation") ,progress());
+ KisMathToolbox::KisWavelet* buff = 0;
+ KisMathToolbox::KisWavelet* wav = 0;
+ KisMathToolbox::KisWavelet* blurwav = 0;
+ try {
+ buff = mathToolbox->initWavelet(src, rect);
+ } catch(std::bad_alloc)
+ {
+ if(buff) delete buff;
+ return;
+ }
+ try {
+ wav = mathToolbox->fastWaveletTransformation(src, rect, buff);
+ blurwav = mathToolbox->fastWaveletTransformation(interm, rect, buff);
+ } catch(std::bad_alloc)
+ {
+ if(wav) delete wav;
+ return;
+ }
+
+ kdDebug(41005) << "frequencying..." << endl;
+// float* fin = wav->coeffs + wav->depth*wav->size*wav->size;
+// setProgressStage( i18n("frequencying") ,progress());
+// float* it2 = wav->coeffs + wav->depth;
+ int sizecopy = (int)pow(2, frequency);
+ if(sizecopy > wav->size) sizecopy = wav->size;
+ for(int i = 0; i < sizecopy; i++)
+ {
+ float *itNotblured = wav->coeffs + wav->depth * wav->size * i;
+ float *itBlured = blurwav->coeffs + blurwav->depth * blurwav->size * i;
+ for(int j = 0; j< sizecopy; j++)
+ {
+ memcpy(itBlured, itNotblured, sizeof(float) * blurwav->depth);
+ itBlured += blurwav->depth;
+ itNotblured += wav->depth;
+ }
+ }
+
+ kdDebug(41005) << "Untransforming..." << endl;
+
+ setProgressStage( i18n("Fast wavelet untransformation") ,progress());
+ mathToolbox->fastWaveletUntransformation( dst, rect, blurwav, buff);
+
+ delete wav;
+ delete blurwav;
+ delete buff;
+ disconnect(mathToolbox, TQT_SIGNAL(nextStep()), this, TQT_SLOT(incProgress()));
+
+ setProgressDone(); // Must be called even if you don't really support progression
+}
diff --git a/chalk/plugins/filters/halftone/kis_halftone.h b/chalk/plugins/filters/halftone/kis_halftone.h
new file mode 100644
index 00000000..38842d31
--- /dev/null
+++ b/chalk/plugins/filters/halftone/kis_halftone.h
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net>
+ * 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_HALFTONE_REDUCTION_H_
+#define KIS_HALFTONE_REDUCTION_H_
+
+#include <vector>
+
+#include <kis_filter.h>
+
+#define BEST_WAVELET_FREQUENCY_VALUE 2
+
+
+#include <kparts/plugin.h>
+
+class ChalkHalftone : public KParts::Plugin
+{
+ public:
+ ChalkHalftone(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ChalkHalftone();
+};
+
+
+class KisHalftoneReductionConfiguration
+ : public KisFilterConfiguration
+{
+public:
+ KisHalftoneReductionConfiguration(double nt, int hs)
+ : KisFilterConfiguration( "halftone", 1 )
+ {
+ setProperty("frequency", nt);
+ setProperty("halfsize", hs);
+ }
+
+};
+
+
+/**
+@author Cyrille Berger
+*/
+class KisHalftoneReduction : public KisFilter
+{
+public:
+ KisHalftoneReduction();
+
+ ~KisHalftoneReduction();
+
+public:
+ virtual void process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration*, const TQRect&);
+ virtual KisFilterConfiguration * configuration(TQWidget* nwidget);
+ virtual KisFilterConfiguration * configuration() {return new KisHalftoneReductionConfiguration( BEST_WAVELET_FREQUENCY_VALUE, 2 );};
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+
+ static inline KisID id() { return KisID("halftone", i18n("Halftone Reducer")); };
+ virtual bool supportsPainting() { return false; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ virtual bool supportsThreading() { return false; };
+ virtual bool supportsAdjustmentLayers() { return false; }
+
+};
+
+#endif
diff --git a/chalk/plugins/filters/imageenhancement/Makefile.am b/chalk/plugins/filters/imageenhancement/Makefile.am
new file mode 100644
index 00000000..c6a884cd
--- /dev/null
+++ b/chalk/plugins/filters/imageenhancement/Makefile.am
@@ -0,0 +1,27 @@
+chalkrcdir = $(kde_datadir)/chalk/chalkplugins
+
+kde_services_DATA = chalkimageenhancement.desktop
+
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkimageenhancement_la_SOURCES = imageenhancement.cpp \
+ kis_simple_noise_reducer.cpp kis_wavelet_noise_reduction.cpp
+
+kde_module_LTLIBRARIES = chalkimageenhancement.la
+
+chalkimageenhancement_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+
+noinst_HEADERS = imageenhancement.h kis_wavelet_noise_reduction.h
+
+chalkimageenhancement_la_LIBADD = ../../../libchalkcommon.la
+
+chalkimageenhencement_la_METASOURCES = AUTO
+
+KDE_CXXFLAGS = $(USE_EXCEPTIONS)
diff --git a/chalk/plugins/filters/imageenhancement/chalkimageenhancement.desktop b/chalk/plugins/filters/imageenhancement/chalkimageenhancement.desktop
new file mode 100644
index 00000000..0067412c
--- /dev/null
+++ b/chalk/plugins/filters/imageenhancement/chalkimageenhancement.desktop
@@ -0,0 +1,80 @@
+[Desktop Entry]
+Name=Enhancement Filters
+Name[bg]=Филтри за подобрения
+Name[ca]=Filtres de millora
+Name[cy]=Hidlau Tecáu
+Name[da]=Forbedringsfilter
+Name[de]=Verbesserungsfilter
+Name[el]=Φίλτρα βελτίωσης
+Name[eo]=Emfaziga filtrilo
+Name[es]=Filtros de realce
+Name[et]=Parandusfiltrid
+Name[fa]=پالایه‌های تقویت
+Name[fr]=Filtres d'amélioration
+Name[fy]=Korreksjefilters
+Name[gl]=Filtros de Melloras
+Name[hu]=Képjavító szűrők
+Name[is]=Endurbótasíur
+Name[it]=Filtri di miglioramento
+Name[ja]=エンハンスメントフィルタ
+Name[km]=តម្រង​ធ្វើ​ឲ្យ​ប្រសើរ
+Name[nb]=Forbedringsfiltre
+Name[nds]=Verbeternfilter
+Name[ne]=अधिकतम फिल्टरहरू
+Name[nl]=Correctiefilters
+Name[pl]=Filtry poprawy jakości
+Name[pt]=Filtros de Melhoramento
+Name[pt_BR]=Filtros de Melhoramento
+Name[ru]=Улучшение изображения
+Name[se]=Buoridansillit
+Name[sk]=Filtre vylepšení
+Name[sl]=Filtri za izboljšanje
+Name[sr]=Филтери за побољшање
+Name[sr@Latn]=Filteri za poboljšanje
+Name[sv]=Förbättringsfilter
+Name[uk]=Фільтри покращання
+Name[uz]=Yaxshilash filteri
+Name[uz@cyrillic]=Яхшилаш филтери
+Name[zh_CN]=增强过滤器
+Name[zh_TW]=增強過濾器
+Comment=Enhance the quality of an image
+Comment[bg]=Подобряване на качеството на изображения
+Comment[ca]=Millora la qualitat de la imatge
+Comment[cy]=Tecâu ansawdd delwedd
+Comment[da]=Forbedr kvaliteten af et billede
+Comment[de]=Die Qualität eines Bildes verbessern
+Comment[el]=Βελτίωση της ποιότητας μίας εικόνας
+Comment[eo]=Plibonigi la kvaliton de bildo
+Comment[es]=Realza la calidad de una imagen
+Comment[et]=Parandavad pildi kvaliteeti
+Comment[fa]=افزایش کیفیت یک تصویر
+Comment[fr]=Améliore la qualité d'une image
+Comment[fy]=De kwaliteit fan in ôfbylding ferbetterje
+Comment[gl]=Mellora a calidade dunha imaxe
+Comment[hu]=A képminőség feljavítására használható eszközök
+Comment[is]=Til að auka gæði mynda
+Comment[it]=Migliora la qualità di un'immagine
+Comment[ja]=画質を高める
+Comment[km]=បង្កើន​គុណភាព​រូបភាព
+Comment[nb]=Forbedre kvaliteten på et bilde
+Comment[nds]=De Gööd vun en Bild verbetern
+Comment[ne]=एउटा छविको विशेषता बढाउनुहोस्
+Comment[nl]=De kwaliteit van een afbeelding verbeteren
+Comment[pl]=Filtry poprawiające jakość obrazka
+Comment[pt]=Melhora a qualidade de uma imagem
+Comment[pt_BR]=Melhora a qualidade de uma imagem
+Comment[ru]=Улучшение качества изображения
+Comment[se]=Buorit govvakvalitehta
+Comment[sk]=Vylepšiť kvalitu obrázka
+Comment[sl]=Izboljšaj kvaliteto slike
+Comment[sr]=Побољшава квалитет слике
+Comment[sr@Latn]=Poboljšava kvalitet slike
+Comment[sv]=Förbättra kvaliteten hos en bild
+Comment[uk]=Покращання якості зображення
+Comment[uz]=Rasmning sifatini oshirish
+Comment[uz@cyrillic]=Расмнинг сифатини ошириш
+Comment[zh_TW]=增強圖片的品質
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkimageenhancement
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/imageenhancement/imageenhancement.cpp b/chalk/plugins/filters/imageenhancement/imageenhancement.cpp
new file mode 100644
index 00000000..8108a3d6
--- /dev/null
+++ b/chalk/plugins/filters/imageenhancement/imageenhancement.cpp
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_filter_registry.h>
+#include <kis_global.h>
+#include <kis_types.h>
+
+#include "imageenhancement.h"
+
+#include "kis_simple_noise_reducer.h"
+#include "kis_wavelet_noise_reduction.h"
+
+typedef KGenericFactory<ChalkImageEnhancement> ChalkImageEnhancementFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkimageenhancement, ChalkImageEnhancementFactory( "chalk" ) )
+
+ ChalkImageEnhancement::ChalkImageEnhancement(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ChalkImageEnhancementFactory::instance());
+
+ kdDebug(41006) << "Image enhancement filter plugin. Class: "
+ << className()
+ << ", Parent: "
+ << tqparent->className()
+ << "\n";
+
+
+ if ( tqparent->inherits("KisFilterRegistry") )
+ {
+ KisFilterRegistry * r = dynamic_cast<KisFilterRegistry*>(tqparent);
+ r->add(new KisSimpleNoiseReducer());
+ r->add(new KisWaveletNoiseReduction());
+ }
+}
+
+ChalkImageEnhancement::~ChalkImageEnhancement()
+{
+}
+
diff --git a/chalk/plugins/filters/imageenhancement/imageenhancement.h b/chalk/plugins/filters/imageenhancement/imageenhancement.h
new file mode 100644
index 00000000..b333e25f
--- /dev/null
+++ b/chalk/plugins/filters/imageenhancement/imageenhancement.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 EXAMPLE_H
+#define EXAMPLE_H
+
+#include <kparts/plugin.h>
+
+class ChalkImageEnhancement : public KParts::Plugin
+{
+ public:
+ ChalkImageEnhancement(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ChalkImageEnhancement();
+};
+
+#endif
diff --git a/chalk/plugins/filters/imageenhancement/kis_simple_noise_reducer.cpp b/chalk/plugins/filters/imageenhancement/kis_simple_noise_reducer.cpp
new file mode 100644
index 00000000..0ff7a958
--- /dev/null
+++ b/chalk/plugins/filters/imageenhancement/kis_simple_noise_reducer.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_simple_noise_reducer.h"
+
+#include <kis_iterators_pixel.h>
+
+#include <kis_autobrush_resource.h>
+#include <kis_convolution_painter.h>
+#include <kis_colorspace_factory_registry.h>
+#include <kis_multi_integer_filter_widget.h>
+#include <kis_meta_registry.h>
+#include <kis_progress_display_interface.h>
+#include <kis_progress_subject.h>
+
+KisSimpleNoiseReducer::KisSimpleNoiseReducer()
+ : KisFilter(id(), "enhance", i18n("&Gaussian Noise Reduction..."))
+{
+}
+
+
+KisSimpleNoiseReducer::~KisSimpleNoiseReducer()
+{
+}
+
+KisFilterConfigWidget * KisSimpleNoiseReducer::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP)
+{
+ vKisIntegerWidgetParam param;
+ param.push_back( KisIntegerWidgetParam( 0, 255, 50, i18n("Threshold"), "threshold" ) );
+ param.push_back( KisIntegerWidgetParam( 0, 10, 1, i18n("Window size"), "windowsize") );
+ return new KisMultiIntegerFilterWidget(tqparent, id().id().ascii(), id().id().ascii(), param );
+}
+
+KisFilterConfiguration* KisSimpleNoiseReducer::configuration(TQWidget* nwidget)
+{
+ KisMultiIntegerFilterWidget* widget = (KisMultiIntegerFilterWidget*) nwidget;
+ if( widget == 0 )
+ {
+ return new KisSimpleNoiseReducerConfiguration( 50, 1);
+ } else {
+ return new KisSimpleNoiseReducerConfiguration( widget->valueAt( 0 ), widget->valueAt( 1 ) );
+ }
+}
+
+inline int ABS(int v)
+{
+ if(v < 0) return -v;
+ return v;
+}
+
+void KisSimpleNoiseReducer::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* config, const TQRect& rect)
+{
+ int threshold, windowsize;
+ if(config !=0)
+ {
+ KisSimpleNoiseReducerConfiguration* configSNRC = (KisSimpleNoiseReducerConfiguration*)config;
+ threshold = configSNRC->threshold();
+ windowsize = configSNRC->windowsize();
+ } else {
+ threshold = 50;
+ windowsize = 1;
+ }
+
+ KisColorSpace* cs = src->colorSpace();
+
+ // Compute the blur tqmask
+ KisAutobrushShape* kas = new KisAutobrushCircleShape(2*windowsize+1, 2*windowsize+1, windowsize, windowsize);
+
+ TQImage tqmask;
+ kas->createBrush(&tqmask);
+
+ KisKernelSP kernel = KisKernel::fromTQImage(tqmask);
+
+ KisPaintDeviceSP interm = new KisPaintDevice(*src);
+ KisConvolutionPainter painter( interm );
+
+ if (m_progressDisplay)
+ m_progressDisplay->setSubject( &painter, true, true );
+
+ painter.beginTransaction("bouuh");
+ painter.applyMatrix(kernel, rect.x(), rect.y(), rect.width(), rect.height(), BORDER_REPEAT);
+
+ if (painter.cancelRequested()) {
+ cancel();
+ }
+
+ KisHLineIteratorPixel dstIt = dst->createHLineIterator(rect.x(), rect.y(), rect.width(), true );
+ KisHLineIteratorPixel srcIt = src->createHLineIterator(rect.x(), rect.y(), rect.width(), false);
+ KisHLineIteratorPixel intermIt = interm->createHLineIterator(rect.x(), rect.y(), rect.width(), false);
+
+ for( int j = 0; j < rect.height(); j++)
+ {
+ while( ! srcIt.isDone() )
+ {
+ if(srcIt.isSelected())
+ {
+ TQ_UINT8 diff = cs->difference(srcIt.oldRawData(), intermIt.rawData());
+ if( diff > threshold)
+ {
+ cs->bitBlt( dstIt.rawData(), 0, cs, intermIt.rawData(), 0, 0, 0, 255, 1, 1, KisCompositeOp(COMPOSITE_COPY) );
+ }
+ }
+ //incProgress();
+ ++srcIt;
+ ++dstIt;
+ ++intermIt;
+ }
+ srcIt.nextRow();
+ dstIt.nextRow();
+ intermIt.nextRow();
+ }
+
+ setProgressDone(); // Must be called even if you don't really support progression
+}
+
diff --git a/chalk/plugins/filters/imageenhancement/kis_simple_noise_reducer.h b/chalk/plugins/filters/imageenhancement/kis_simple_noise_reducer.h
new file mode 100644
index 00000000..a233bb85
--- /dev/null
+++ b/chalk/plugins/filters/imageenhancement/kis_simple_noise_reducer.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 KISSIMPLENOISEREDUCER_H
+#define KISSIMPLENOISEREDUCER_H
+
+#include <kis_filter.h>
+#include "kis_filter_config_widget.h"
+/**
+@author Cyrille Berger
+*/
+
+class KisSimpleNoiseReducerConfiguration
+ : public KisFilterConfiguration
+{
+ public:
+ KisSimpleNoiseReducerConfiguration(int nt, int ws)
+ : KisFilterConfiguration( "gaussiannoisereducer", 1 )
+ {
+ setProperty("threshold", nt);
+ setProperty("windowsize", ws);
+ }
+ int threshold() { return getInt("threshold"); };
+ int windowsize() { return getInt("windowsize"); };
+};
+
+class KisSimpleNoiseReducer : public KisFilter
+{
+ public:
+ KisSimpleNoiseReducer();
+ ~KisSimpleNoiseReducer();
+ public:
+ virtual void process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration*, const TQRect&);
+ virtual KisFilterConfiguration * configuration(TQWidget* nwidget);
+ virtual KisFilterConfiguration * configuration() { return new KisSimpleNoiseReducerConfiguration( 50, 1); };
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+
+ static inline KisID id() { return KisID("gaussiannoisereducer", i18n("Gaussian Noise Reducer")); };
+ virtual bool supportsPainting() { return false; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ virtual bool supportsAdjustmentLayers() { return false; }
+};
+
+#endif
diff --git a/chalk/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.cpp b/chalk/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.cpp
new file mode 100644
index 00000000..021bf5c6
--- /dev/null
+++ b/chalk/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.cpp
@@ -0,0 +1,130 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ * 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 <cmath>
+
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_math_toolbox.h>
+#include <kis_meta_registry.h>
+#include <kis_multi_double_filter_widget.h>
+#include <kis_paint_device.h>
+
+KisWaveletNoiseReduction::KisWaveletNoiseReduction()
+ : KisFilter(id(), "enhance", i18n("&Wavelet Noise Reduction..."))
+{
+}
+
+
+KisWaveletNoiseReduction::~KisWaveletNoiseReduction()
+{
+}
+
+KisFilterConfigWidget * KisWaveletNoiseReduction::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP )
+{
+ vKisDoubleWidgetParam param;
+ param.push_back( KisDoubleWidgetParam( 0.0, 256.0, BEST_WAVELET_THRESHOLD_VALUE, i18n("Threshold"), "threshold" ) );
+ return new KisMultiDoubleFilterWidget(tqparent, id().id().ascii(), id().id().ascii(), param );
+}
+
+KisFilterConfiguration* KisWaveletNoiseReduction::configuration(TQWidget* nwidget )
+{
+ KisMultiDoubleFilterWidget* widget = (KisMultiDoubleFilterWidget*) nwidget;
+ if( widget == 0 )
+ {
+ return new KisWaveletNoiseReductionConfiguration( BEST_WAVELET_THRESHOLD_VALUE );
+ } else {
+ return new KisWaveletNoiseReductionConfiguration( widget->valueAt( 0 ) );
+ }
+}
+
+void KisWaveletNoiseReduction::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* config, const TQRect& rect)
+{
+
+ float threshold = 1.0;
+
+ if(config !=0)
+ {
+ KisWaveletNoiseReductionConfiguration* configWNRC = (KisWaveletNoiseReductionConfiguration*)config;
+ kdDebug() << "threshold: " << configWNRC->threshold() << endl;
+ threshold = configWNRC->threshold();
+ }
+
+
+ TQ_INT32 depth = src->colorSpace()->nColorChannels();
+
+ int size;
+ int maxrectsize = (rect.height() < rect.width()) ? rect.width() : rect.height();
+ for(size = 2; size < maxrectsize; size *= 2) ;
+
+ KisMathToolbox* mathToolbox = KisMetaRegistry::instance()->mtRegistry()->get( src->colorSpace()->mathToolboxID() );
+ setProgressTotalSteps(mathToolbox->fastWaveletTotalSteps(rect) * 2 + size*size*depth );
+ connect(mathToolbox, TQT_SIGNAL(nextStep()), this, TQT_SLOT(incProgress()));
+
+
+ kdDebug(41005) << size << " " << maxrectsize << " " << rect.x() << " " << rect.y() << endl;
+
+ kdDebug(41005) << "Transforming..." << endl;
+ setProgressStage( i18n("Fast wavelet transformation") ,progress());
+ KisMathToolbox::KisWavelet* buff = 0;
+ KisMathToolbox::KisWavelet* wav = 0;
+ try {
+ buff = mathToolbox->initWavelet(src, rect);
+ } catch(std::bad_alloc)
+ {
+ if(buff) delete buff;
+ return;
+ }
+ try {
+ wav = mathToolbox->fastWaveletTransformation(src, rect, buff);
+ } catch(std::bad_alloc)
+ {
+ if(wav) delete wav;
+ return;
+ }
+
+ kdDebug(41005) << "Thresholding..." << endl;
+ float* fin = wav->coeffs + wav->depth*wav->size*wav->size;
+ setProgressStage( i18n("Thresholding") ,progress());
+ for(float* it = wav->coeffs + wav->depth; it < fin; it++)
+ {
+ if( *it > threshold)
+ {
+ *it -= threshold;
+ } else if( *it < -threshold ) {
+ *it += threshold;
+ } else {
+ *it = 0.;
+ }
+ incProgress();
+ }
+
+ kdDebug(41005) << "Untransforming..." << endl;
+
+ setProgressStage( i18n("Fast wavelet untransformation") ,progress());
+ mathToolbox->fastWaveletUntransformation( dst, rect, wav, buff);
+
+ delete wav;
+ delete buff;
+ disconnect(mathToolbox, TQT_SIGNAL(nextStep()), this, TQT_SLOT(incProgress()));
+
+ setProgressDone(); // Must be called even if you don't really support progression
+}
diff --git a/chalk/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.h b/chalk/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.h
new file mode 100644
index 00000000..85a96ec8
--- /dev/null
+++ b/chalk/plugins/filters/imageenhancement/kis_wavelet_noise_reduction.h
@@ -0,0 +1,68 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ * 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_WAVELET_NOISE_REDUCTION_H
+#define KIS_WAVELET_NOISE_REDUCTION_H
+
+#include <vector>
+
+#include <kis_filter.h>
+
+#define BEST_WAVELET_THRESHOLD_VALUE 7.0
+
+class KisWaveletNoiseReductionConfiguration
+ : public KisFilterConfiguration
+{
+public:
+ KisWaveletNoiseReductionConfiguration(double nt)
+ : KisFilterConfiguration( "waveletnoisereducer", 1 )
+ {
+ setProperty("threshold", nt);
+ }
+
+ double threshold() { return getDouble("threshold"); };
+};
+
+
+/**
+@author Cyrille Berger
+*/
+class KisWaveletNoiseReduction : public KisFilter
+{
+public:
+ KisWaveletNoiseReduction();
+
+ ~KisWaveletNoiseReduction();
+
+public:
+ virtual void process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration*, const TQRect&);
+ virtual KisFilterConfiguration * configuration(TQWidget* nwidget);
+ virtual KisFilterConfiguration * configuration() {return new KisWaveletNoiseReductionConfiguration( BEST_WAVELET_THRESHOLD_VALUE );};
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+
+ static inline KisID id() { return KisID("waveletnoisereducer", i18n("Wavelet Noise Reducer")); };
+ virtual bool supportsPainting() { return false; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ virtual bool supportsThreading() { return false; };
+ virtual bool supportsAdjustmentLayers() { return false; }
+
+};
+
+#endif
diff --git a/chalk/plugins/filters/lenscorrectionfilter/Makefile.am b/chalk/plugins/filters/lenscorrectionfilter/Makefile.am
new file mode 100644
index 00000000..c074bd65
--- /dev/null
+++ b/chalk/plugins/filters/lenscorrectionfilter/Makefile.am
@@ -0,0 +1,23 @@
+chalkrcdir = $(kde_datadir)/chalk/chalkplugins
+
+kde_services_DATA = chalklenscorrectionfilter.desktop
+
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalklenscorrectionfilter_la_SOURCES = lenscorrectionfilter.cc \
+ wdglenscorrectionoptions.ui kis_wdg_lens_correction.cpp
+
+kde_module_LTLIBRARIES = chalklenscorrectionfilter.la
+noinst_HEADERS = lenscorrectionfilter.h
+
+chalklenscorrectionfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalklenscorrectionfilter_la_LIBADD = ../../../libchalkcommon.la
+
+METASOURCES = AUTO
diff --git a/chalk/plugins/filters/lenscorrectionfilter/chalklenscorrectionfilter.desktop b/chalk/plugins/filters/lenscorrectionfilter/chalklenscorrectionfilter.desktop
new file mode 100644
index 00000000..52bb0057
--- /dev/null
+++ b/chalk/plugins/filters/lenscorrectionfilter/chalklenscorrectionfilter.desktop
@@ -0,0 +1,69 @@
+[Desktop Entry]
+Comment=Transform an image in a lenscorrection
+Comment[bg]=Преобразуване на изображение в коригиране на лещи
+Comment[ca]=Transforma una imatge en una lent correctora
+Comment[da]=Transformér et billede med linsekorrektion
+Comment[de]=Ein Bild mit einer Linsenkorrektur transformieren
+Comment[el]=Μετασχηματισμός μιας εικόνας με διόρθωση οπτικών φακών
+Comment[es]=Transforma una imagen en un corrección de lente
+Comment[et]=Pildi teisendamine läätsekorrektsiooniga
+Comment[fa]=تبدیل یک تصویر به صورت اصلاح عدسی
+Comment[fy]=Transformearje in ôfbylding yn in lenskorreksje
+Comment[gl]=Transforma unha imaxe nunha corrección de lente
+Comment[hu]=Lencsekorrekció végrehajtása képen
+Comment[it]=Trasforma un'immagine in una correzione lenticolare
+Comment[ja]=レンズ補正によって画像を変形
+Comment[km]=ប្លែង​រូបភាព​ក្នុង​ការកែ​កែវ​ម៉ាស៊ីន​ថតរូប
+Comment[nb]=Transformer et bilde med linsekorreksjon
+Comment[nds]=En Bild mit Glööskorrektuur ümwanneln
+Comment[ne]=लेन्ससुधारमा छवि रूपान्तरण गर्नुहोस्
+Comment[nl]=Transformeer een afbeelding in een lenscorrectie
+Comment[pl]=Usuwa efekt soczewki ze zdjęcia
+Comment[pt]=Transformar uma imagem numa correcção de lentes
+Comment[pt_BR]=Transforma uma imagem numa correção de lentes
+Comment[ru]=Убрать искажение от линзы фотоаппарата
+Comment[sk]=Transformovať obrázok pomocou korekcie šošovky
+Comment[sl]=Preoblikuj sliko s popravljanjem lečenja
+Comment[sr]=Трансформација слике за поправку сочива
+Comment[sr@Latn]=Transformacija slike za popravku sočiva
+Comment[sv]=Omvandla en bild med linskorrektion
+Comment[uk]=Коректувати спотворення від лінзи фотоапарата
+Comment[zh_TW]=在 lenscorrection 下轉換圖片
+Icon=
+Name=LensCorrection Filter
+Name[bg]=Филтри за коригиране на лещи
+Name[ca]=Filtre de Lent correctora
+Name[da]=Linekorrektionsfilter
+Name[de]=Linsenkorrekturfilter
+Name[el]=Φίλτρο οπτικών φακών
+Name[eo]=LensKorekta filtrilo
+Name[es]=Filtro de corrección de lente
+Name[et]=Läätsekorrektsiooni filter
+Name[fa]=پالایۀ اصلاح عدسی
+Name[fy]=Lenskorreksjefilter
+Name[gl]=Filtros de Corrección de Lente
+Name[hu]=Lencsekorrekciós szűrő
+Name[it]=Filtro di correzione lenticolare
+Name[ja]=レンズ補正フィルタ
+Name[km]=តម្រង​ការកែ​កែវ​ម៉ាស៊ីន​ថតរូប
+Name[nb]=Linsekorreksjonsfilter
+Name[nds]=Glööskorrektuurfilter
+Name[ne]=लेन्ससुधार फिल्टर
+Name[nl]=Lenscorrectiefilter
+Name[pl]=Filtr korekcji efektu soczewki
+Name[pt]=Filtro de Correcção de Lentes
+Name[pt_BR]=Filtro de Correção de Lentes
+Name[ru]=Убрать искажение линзы
+Name[sk]=Filter korekcie šošovky
+Name[sl]=Filter Popravljanje lečenja
+Name[sr]=Филтер за поправку сочива
+Name[sr@Latn]=Filter za popravku sočiva
+Name[sv]=Linskorrektionsfilter
+Name[uk]=Корекція спотворення лінзи
+Name[uz]=Linzani toʻgʻrilash filteri
+Name[uz@cyrillic]=Линзани тўғрилаш филтери
+Name[zh_TW]=LensCorrection 過濾器
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalklenscorrectionfilter
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/lenscorrectionfilter/kis_wdg_lens_correction.cpp b/chalk/plugins/filters/lenscorrectionfilter/kis_wdg_lens_correction.cpp
new file mode 100644
index 00000000..f33681a5
--- /dev/null
+++ b/chalk/plugins/filters/lenscorrectionfilter/kis_wdg_lens_correction.cpp
@@ -0,0 +1,74 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_wdg_lens_correction.h"
+
+#include <tqlayout.h>
+
+#include <knuminput.h>
+
+#include "wdglenscorrectionoptions.h"
+
+KisWdgLensCorrection::KisWdgLensCorrection(KisFilter* /*nfilter*/, TQWidget* tqparent, const char* name)
+ : KisFilterConfigWidget(tqparent,name)
+{
+ TQGridLayout *widgetLayout = new TQGridLayout(this, 1, 1);
+ m_widget = new WdgLensCorrectionOptions(this);
+ widgetLayout -> addWidget(m_widget, 0, 0);
+
+ connect( widget()->intXCenter, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->intYCenter, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->dblCorrectionNearCenter, TQT_SIGNAL( valueChanged(double)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->dblCorrectionNearEdges, TQT_SIGNAL( valueChanged(double)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->dblBrightness, TQT_SIGNAL( valueChanged(double)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+}
+
+KisWdgLensCorrection::~KisWdgLensCorrection()
+{
+}
+
+void KisWdgLensCorrection::setConfiguration(KisFilterConfiguration* config)
+{
+ TQVariant value;
+ if (config->getProperty("xcenter", value))
+ {
+ widget()->intXCenter->setValue( value.toUInt() );
+ }
+ if (config->getProperty("ycenter", value))
+ {
+ widget()->intYCenter->setValue( value.toUInt() );
+ }
+ if (config->getProperty("correctionnearcenter", value))
+ {
+ widget()->dblCorrectionNearCenter->setValue( value.toDouble() );
+ }
+ if (config->getProperty("correctionnearedges", value))
+ {
+ widget()->dblCorrectionNearEdges->setValue( value.toDouble() );
+ }
+ if (config->getProperty("brightness", value))
+ {
+ widget()->dblBrightness->setValue( value.toDouble() );
+ }
+}
+
+
+#include "kis_wdg_lens_correction.moc"
+
diff --git a/chalk/plugins/filters/lenscorrectionfilter/kis_wdg_lens_correction.h b/chalk/plugins/filters/lenscorrectionfilter/kis_wdg_lens_correction.h
new file mode 100644
index 00000000..193aa5aa
--- /dev/null
+++ b/chalk/plugins/filters/lenscorrectionfilter/kis_wdg_lens_correction.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_WDG_LENS_CORRECTION_H
+#define KIS_WDG_LENS_CORRECTION_H
+
+#include <kis_filter_config_widget.h>
+
+class WdgLensCorrectionOptions;
+class KisFilter;
+
+class KisWdgLensCorrection : public KisFilterConfigWidget
+{
+ Q_OBJECT
+ TQ_OBJECT
+ public:
+ KisWdgLensCorrection(KisFilter* nfilter, TQWidget* tqparent = 0, const char* name = 0);
+ ~KisWdgLensCorrection();
+ public:
+ inline WdgLensCorrectionOptions* widget() { return m_widget; };
+ virtual void setConfiguration(KisFilterConfiguration*);
+ private:
+ WdgLensCorrectionOptions* m_widget;
+};
+
+#endif
+
diff --git a/chalk/plugins/filters/lenscorrectionfilter/lenscorrectionfilter.cc b/chalk/plugins/filters/lenscorrectionfilter/lenscorrectionfilter.cc
new file mode 100644
index 00000000..cd3627c5
--- /dev/null
+++ b/chalk/plugins/filters/lenscorrectionfilter/lenscorrectionfilter.cc
@@ -0,0 +1,152 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * Inspired by a similar plugin for the digikam project from:
+ * Copyright (c) 2005 Gilles Caulier <caulier dot gilles at kdemail dot net>
+ *
+ * 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 "lenscorrectionfilter.h"
+
+#include <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_filter_registry.h>
+#include <kis_global.h>
+#include <kis_layer.h>
+#include <kis_random_sub_accessor.h>
+#include <kis_types.h>
+
+#include "kis_wdg_lens_correction.h"
+#include "wdglenscorrectionoptions.h"
+
+typedef KGenericFactory<ChalkLensCorrectionFilter> ChalkLensCorrectionFilterFactory;
+K_EXPORT_COMPONENT_FACTORY( chalklenscorrectionfilter, ChalkLensCorrectionFilterFactory( "chalk" ) )
+
+ChalkLensCorrectionFilter::ChalkLensCorrectionFilter(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ChalkLensCorrectionFilterFactory::instance());
+
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisFilterLensCorrection());
+ }
+}
+
+ChalkLensCorrectionFilter::~ChalkLensCorrectionFilter()
+{
+}
+
+KisFilterLensCorrection::KisFilterLensCorrection() : KisFilter(id(), "other", i18n("&Lens Correction..."))
+{
+}
+
+KisFilterConfiguration* KisFilterLensCorrection::configuration(TQWidget* w)
+{
+ TQVariant value;
+ KisWdgLensCorrection* wN = dynamic_cast<KisWdgLensCorrection*>(w);
+ KisFilterConfiguration* config = new KisFilterConfiguration(id().id(), 1);
+ if(wN)
+ {
+ config->setProperty("xcenter", wN->widget()->intXCenter->value() );
+ config->setProperty("ycenter", wN->widget()->intYCenter->value() );
+ config->setProperty("correctionnearcenter", wN->widget()->dblCorrectionNearCenter->value() );
+ config->setProperty("correctionnearedges", wN->widget()->dblCorrectionNearEdges->value() );
+ config->setProperty("brightness", wN->widget()->dblBrightness->value() );
+ }
+ return config;
+}
+
+KisFilterConfigWidget * KisFilterLensCorrection::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP /*dev*/)
+{
+ return new KisWdgLensCorrection((KisFilter*)this, (TQWidget*)tqparent, i18n("Configuration of lens correction filter").ascii());
+}
+
+void KisFilterLensCorrection::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* config, const TQRect& rawrect)
+{
+ Q_ASSERT(src != 0);
+ Q_ASSERT(dst != 0);
+
+ TQRect layerrect = src->exactBounds();
+
+ TQRect workingrect = layerrect.intersect( rawrect );
+
+ setProgressTotalSteps(workingrect.width() * workingrect.height());
+
+ KisColorSpace* cs = dst->colorSpace();
+
+ TQVariant value;
+ double xcenter = (config && config->getProperty("xcenter", value)) ? value.toInt() : 50;
+ double ycenter = (config && config->getProperty("ycenter", value)) ? value.toInt() : 50;
+ double correctionnearcenter = (config && config->getProperty("correctionnearcenter", value)) ? value.toDouble() : 0.;
+ double correctionnearedges = (config && config->getProperty("correctionnearedges", value)) ? value.toDouble() : 0.;
+ double brightness = ( (config && config->getProperty("brightness", value)) ? value.toDouble() : 0. );
+
+ KisRectIteratorPixel dstIt = dst->createRectIterator(workingrect.x(), workingrect.y(), workingrect.width(), workingrect.height(), true );
+ KisRandomSubAccessorPixel srcRSA = src->createRandomSubAccessor();
+
+ double normallise_radius_sq = 4.0 / (layerrect.width() * layerrect.width() + layerrect.height() * layerrect.height());
+ xcenter = layerrect.x() + layerrect.width() * xcenter / 100.0;
+ ycenter = layerrect.y() + layerrect.height() * ycenter / 100.0;
+ double mult_sq = correctionnearcenter / 200.0;
+ double mult_qd = correctionnearedges / 200.0;
+
+ TQ_UINT16 lab[4];
+
+ while(!dstIt.isDone())
+ {
+ double off_x = dstIt.x() - xcenter;
+ double off_y = dstIt.y() - ycenter;
+ double radius_sq = ( (off_x * off_x) + (off_y * off_y) ) * normallise_radius_sq;
+
+ double radius_mult = radius_sq * mult_sq + radius_sq * radius_sq * mult_qd;
+ double mag = radius_mult;
+ radius_mult += 1.0;
+
+ double srcX = xcenter + radius_mult * off_x;
+ double srcY = ycenter + radius_mult * off_y;
+
+ double brighten = 1.0 + mag * brightness;
+
+ srcRSA.moveTo( KisPoint( srcX, srcY ) );
+ srcRSA.sampledOldRawData( dstIt.rawData() );
+ cs->toLabA16( dstIt.rawData(), (TQ_UINT8*)lab, 1);
+ lab[0] = CLAMP( lab[0] * static_cast<TQ_UINT16>( brighten ), 0, 65535);
+ cs->fromLabA16( (TQ_UINT8*)lab, dstIt.rawData(), 1);
+
+ ++dstIt;
+ incProgress();
+ }
+ setProgressDone(); // Must be called even if you don't really support progression
+}
diff --git a/chalk/plugins/filters/lenscorrectionfilter/lenscorrectionfilter.h b/chalk/plugins/filters/lenscorrectionfilter/lenscorrectionfilter.h
new file mode 100644
index 00000000..f04012b6
--- /dev/null
+++ b/chalk/plugins/filters/lenscorrectionfilter/lenscorrectionfilter.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 LENS_CORRECTIONFILTER_H
+#define LENS_CORRECTIONFILTER_H
+
+#include <kparts/plugin.h>
+#include "kis_filter.h"
+
+class KisFilterConfigWidget;
+
+class ChalkLensCorrectionFilter : public KParts::Plugin
+{
+public:
+ ChalkLensCorrectionFilter(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ChalkLensCorrectionFilter();
+};
+
+class KisFilterLensCorrection : public KisFilter
+{
+ public:
+ KisFilterLensCorrection();
+ public:
+ virtual void process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration*, const TQRect&);
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return FULLY_INDEPENDENT; };
+ static inline KisID id() { return KisID("lenscorrection", i18n("Lens Correction")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ virtual bool supportsAdjustmentLayers() { return false; }
+ public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration* configuration(TQWidget*);
+};
+
+#endif
diff --git a/chalk/plugins/filters/lenscorrectionfilter/wdglenscorrectionoptions.ui b/chalk/plugins/filters/lenscorrectionfilter/wdglenscorrectionoptions.ui
new file mode 100644
index 00000000..d5ef416d
--- /dev/null
+++ b/chalk/plugins/filters/lenscorrectionfilter/wdglenscorrectionoptions.ui
@@ -0,0 +1,229 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgLensCorrectionOptions</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgLensCorrectionOptions</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>235</width>
+ <height>207</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>90</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="0" column="2">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQGroupBox" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Distortion Correction</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="5" column="1">
+ <property name="name">
+ <cstring>Center_3</cstring>
+ </property>
+ <property name="text">
+ <string>Y:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="1" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>Center_2</cstring>
+ </property>
+ <property name="text">
+ <string>X:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="3" column="2" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>intXCenter</cstring>
+ </property>
+ <property name="value">
+ <number>50</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="4" column="2" rowspan="2" colspan="2">
+ <property name="name">
+ <cstring>intYCenter</cstring>
+ </property>
+ <property name="value">
+ <number>50</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ </widget>
+ <spacer row="3" column="0">
+ <property name="name">
+ <cstring>spacer11</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="3" column="4">
+ <property name="name">
+ <cstring>spacer12</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>51</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLabel" row="0" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Near center:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Near edges:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0" rowspan="1" colspan="4">
+ <property name="name">
+ <cstring>Center</cstring>
+ </property>
+ <property name="text">
+ <string>Center:</string>
+ </property>
+ </widget>
+ <widget class="KDoubleNumInput" row="0" column="3" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>dblCorrectionNearCenter</cstring>
+ </property>
+ <property name="minValue">
+ <number>-100</number>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ </widget>
+ <widget class="KDoubleNumInput" row="1" column="3" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>dblCorrectionNearEdges</cstring>
+ </property>
+ <property name="minValue">
+ <number>-100</number>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Brightness correction:</string>
+ </property>
+ </widget>
+ <widget class="KDoubleNumInput" row="1" column="1">
+ <property name="name">
+ <cstring>dblBrightness</cstring>
+ </property>
+ <property name="minValue">
+ <number>-100</number>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/filters/levelfilter/Makefile.am b/chalk/plugins/filters/levelfilter/Makefile.am
new file mode 100644
index 00000000..2f6fb459
--- /dev/null
+++ b/chalk/plugins/filters/levelfilter/Makefile.am
@@ -0,0 +1,25 @@
+kde_services_DATA = chalklevelfilter.desktop
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalklevelfilter_la_SOURCES = levelfilter.cc \
+ wdg_level.ui \
+ kis_level_filter.cc \
+ kgradientslider.cc
+
+noinst_HEADERS = levelfilter.h \
+ kis_level_filter.h \
+ kgradientslider.h
+
+chalklevelfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalklevelfilter_la_LIBADD = ../../../libchalkcommon.la
+
+kde_module_LTLIBRARIES = chalklevelfilter.la
+
+chalklevelfilter_la_METASOURCES = AUTO
diff --git a/chalk/plugins/filters/levelfilter/chalklevelfilter.desktop b/chalk/plugins/filters/levelfilter/chalklevelfilter.desktop
new file mode 100644
index 00000000..8426b08d
--- /dev/null
+++ b/chalk/plugins/filters/levelfilter/chalklevelfilter.desktop
@@ -0,0 +1,73 @@
+[Desktop Entry]
+Name=Levels
+Name[bg]=Нива
+Name[br]=Liveoù
+Name[ca]=Nivells
+Name[da]=Niveauer
+Name[de]=Stufen
+Name[el]=Επίπεδα
+Name[eo]=Niveloj
+Name[es]=Niveles
+Name[et]=Tasemed
+Name[fa]=سطوح
+Name[fy]=Nivo's
+Name[hr]=Razine
+Name[hu]=Szintek
+Name[it]=Livelli
+Name[ja]=レベル
+Name[km]=កម្រិត
+Name[lt]=Lygiai
+Name[nb]=Nivåer
+Name[nds]=Stopen
+Name[ne]=स्तर
+Name[nl]=Niveaus
+Name[pl]=Poziomy
+Name[pt]=Níveis
+Name[pt_BR]=Níveis
+Name[ru]=Уровни
+Name[se]=Dásit
+Name[sk]=Úrovne
+Name[sl]=Ravni
+Name[sr]=Нивои
+Name[sr@Latn]=Nivoi
+Name[sv]=Nivåer
+Name[uk]=Рівні
+Name[zh_TW]=等級
+Comment=Levels
+Comment[bg]=Нива
+Comment[br]=Liveoù
+Comment[ca]=Nivells
+Comment[da]=Niveauer
+Comment[de]=Stufen
+Comment[el]=Επίπεδα
+Comment[eo]=Niveloj
+Comment[es]=Niveles
+Comment[et]=Tasemed
+Comment[fa]=سطوح
+Comment[fy]=Nivo's
+Comment[hr]=Razine
+Comment[hu]=Szintek
+Comment[it]=Livelli
+Comment[ja]=レベル
+Comment[km]=កម្រិត
+Comment[lt]=Lygiai
+Comment[nb]=Nivåer
+Comment[nds]=Stopen
+Comment[ne]=स्तर
+Comment[nl]=Niveaus
+Comment[pl]=Poziomy
+Comment[pt]=Níveis
+Comment[pt_BR]=Níveis
+Comment[ru]=Уровни
+Comment[se]=Dásit
+Comment[sk]=Úrovne
+Comment[sl]=Ravni
+Comment[sr]=Нивои
+Comment[sr@Latn]=Nivoi
+Comment[sv]=Nivåer
+Comment[uk]=Рівні
+Comment[zh_TW]=等級
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalklevelfilter
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/levelfilter/kgradientslider.cc b/chalk/plugins/filters/levelfilter/kgradientslider.cc
new file mode 100644
index 00000000..104ef375
--- /dev/null
+++ b/chalk/plugins/filters/levelfilter/kgradientslider.cc
@@ -0,0 +1,338 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Frederic Coiffier <fcoiffie@gmail.com>
+ *
+ * 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.
+ */
+
+// C++ includes.
+
+#include <cmath>
+#include <cstdlib>
+
+// TQt includes.
+
+#include <tqpixmap.h>
+#include <tqpainter.h>
+#include <tqpoint.h>
+#include <tqpen.h>
+
+// Local includes.
+
+#include "kgradientslider.h"
+
+KGradientSlider::KGradientSlider(TQWidget *tqparent, const char *name, WFlags f)
+ : TQWidget(tqparent, name, f)
+{
+ m_dragging = false;
+
+ setMouseTracking(true);
+ setPaletteBackgroundColor(TQt::NoBackground);
+ setMaximumSize(255, 28);
+
+ m_blackcursor = 0;
+ m_whitecursor = 255;
+ m_gamma = 1.0;
+ m_gammaEnabled = false;
+ setFocusPolicy(TQ_StrongFocus);
+}
+
+KGradientSlider::~KGradientSlider()
+{
+}
+
+void KGradientSlider::paintEvent(TQPaintEvent *)
+{
+ int x, y;
+ int wWidth = width();
+ int wHeight = height();
+
+ int gradientHeight = (wHeight / 3);
+
+ // A TQPixmap is used for enable the double buffering.
+ /*if (!m_dragging) {*/
+ TQPixmap pm(size());
+ TQPainter p1;
+ p1.tqbegin(TQT_TQPAINTDEVICE(&pm), this);
+
+ pm.fill();
+
+ // Draw first gradient
+ y = 0;
+ p1.setPen(TQPen::TQPen(TQColor(0,0,0),1, TQt::SolidLine));
+ for( x=0; x<255; ++x )
+ {
+ int gray = (255 * x) / wWidth;
+ p1.setPen(TQColor(gray, gray, gray));
+ p1.drawLine(x, y, x, y + gradientHeight - 1);
+ }
+
+ // Draw second gradient
+ y = (wHeight / 3);
+ if (m_blackcursor > 0) {
+ p1.fillRect(0, y, (int)m_blackcursor, gradientHeight, TQBrush(TQt::black));
+ }
+ if (m_whitecursor < 255) {
+ p1.fillRect((int)m_whitecursor, y, 255, gradientHeight, TQBrush(TQt::white));
+ }
+ for(x = (int)m_blackcursor; x < (int)m_whitecursor; ++x )
+ {
+ double inten = (double)(x - m_blackcursor) / (double)(m_whitecursor - m_blackcursor);
+ inten = pow (inten, (1.0 / m_gamma));
+ int gray = (int)(255 * inten);
+ p1.setPen(TQColor(gray, gray, gray));
+ p1.drawLine(x, y, x, y + gradientHeight - 1);
+ }
+
+ // Draw cursors
+ y = (2 * wHeight / 3);
+ TQPointArray *a = new TQPointArray(3);
+ p1.setPen(TQt::black);
+
+ a->setPoint(0, m_blackcursor, y);
+ a->setPoint(1, m_blackcursor + 3, wHeight - 1);
+ a->setPoint(2, m_blackcursor - 3, wHeight - 1);
+ p1.setBrush(TQt::black);
+ p1.drawPolygon(*a);
+
+ if (m_gammaEnabled) {
+ a->setPoint(0, m_gammacursor, y);
+ a->setPoint(1, m_gammacursor + 3, wHeight - 1);
+ a->setPoint(2, m_gammacursor - 3, wHeight - 1);
+ p1.setBrush(TQt::gray);
+ p1.drawPolygon(*a);
+ }
+
+ a->setPoint(0, m_whitecursor, y);
+ a->setPoint(1, m_whitecursor + 3, wHeight - 1);
+ a->setPoint(2, m_whitecursor - 3, wHeight - 1);
+ p1.setBrush(TQt::white);
+ p1.drawPolygon(*a);
+
+ p1.end();
+ bitBlt(this, 0, 0, &pm);
+}
+
+void KGradientSlider::mousePressEvent ( TQMouseEvent * e )
+{
+ eCursor closest_cursor;
+ int distance;
+
+ if (e->button() != Qt::LeftButton)
+ return;
+
+ unsigned int x = e->pos().x();
+
+ distance = 1000; // just a big number
+
+ if (abs((int)(x - m_blackcursor)) < distance)
+ {
+ distance = abs((int)(x - m_blackcursor));
+ closest_cursor = BlackCursor;
+ }
+
+ if (abs((int)(x - m_whitecursor)) < distance)
+ {
+ distance = abs((int)(x - m_whitecursor));
+ closest_cursor = WhiteCursor;
+ }
+
+ if (m_gammaEnabled && (abs((int)(x - m_gammacursor)) < distance))
+ {
+ distance = abs((int)(x - m_gammacursor));
+ closest_cursor = GammaCursor;
+ }
+
+ if (distance > 20)
+ {
+ return;
+ }
+
+
+ m_dragging = true;
+
+ // Determine cursor values and the leftmost and rightmost points.
+
+ switch (closest_cursor) {
+ case BlackCursor:
+ m_blackcursor = x;
+ m_grab_cursor = closest_cursor;
+ m_leftmost = 0;
+ m_rightmost = m_whitecursor;
+ if (m_gammaEnabled) {
+ double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
+ double mid = (double)m_blackcursor + delta;
+ double tmp = log10 (1.0 / m_gamma);
+ m_gammacursor = (unsigned int)tqRound(mid + delta * tmp);
+ }
+ break;
+ case WhiteCursor:
+ m_whitecursor = x;
+ m_grab_cursor = closest_cursor;
+ m_leftmost = m_blackcursor;
+ m_rightmost = 255;
+ if (m_gammaEnabled) {
+ double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
+ double mid = (double)m_blackcursor + delta;
+ double tmp = log10 (1.0 / m_gamma);
+ m_gammacursor = (unsigned int)tqRound(mid + delta * tmp);
+ }
+ break;
+ case GammaCursor:
+ m_gammacursor = x;
+ m_grab_cursor = closest_cursor;
+ m_leftmost = m_blackcursor;
+ m_rightmost = m_whitecursor;
+
+ double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
+ double mid = (double)m_blackcursor + delta;
+ double tmp = (x - mid) / delta;
+ m_gamma = 1.0 / pow (10, tmp);
+ break;
+ }
+ tqrepaint(false);
+}
+
+void KGradientSlider::mouseReleaseEvent ( TQMouseEvent * e )
+{
+ if (e->button() != Qt::LeftButton)
+ return;
+
+ m_dragging = false;
+ tqrepaint(false);
+
+ switch (m_grab_cursor) {
+ case BlackCursor:
+ emit modifiedBlack(m_blackcursor);
+ break;
+ case WhiteCursor:
+ emit modifiedWhite(m_whitecursor);
+ break;
+ case GammaCursor:
+ emit modifiedGamma(m_gamma);
+ break;
+ }
+}
+
+void KGradientSlider::mouseMoveEvent ( TQMouseEvent * e )
+{
+ unsigned int x = abs(e->pos().x());
+
+ if (m_dragging == true) // Else, drag the selected point
+ {
+ if (x <= m_leftmost)
+ x = m_leftmost;
+
+ if(x >= m_rightmost)
+ x = m_rightmost;
+
+ /*if(x > 255)
+ x = 255;
+
+ if(x < 0)
+ x = 0;*/
+
+ switch (m_grab_cursor) {
+ case BlackCursor:
+ if (m_blackcursor != x)
+ {
+ m_blackcursor = x;
+ if (m_gammaEnabled) {
+ double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
+ double mid = (double)m_blackcursor + delta;
+ double tmp = log10 (1.0 / m_gamma);
+ m_gammacursor = (unsigned int)tqRound(mid + delta * tmp);
+ }
+ }
+ break;
+ case WhiteCursor:
+ if (m_whitecursor != x)
+ {
+ m_whitecursor = x;
+ if (m_gammaEnabled) {
+ double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
+ double mid = (double)m_blackcursor + delta;
+ double tmp = log10 (1.0 / m_gamma);
+ m_gammacursor = (unsigned int)tqRound(mid + delta * tmp);
+ }
+ }
+ break;
+ case GammaCursor:
+ if (m_gammacursor != x)
+ {
+ m_gammacursor = x;
+ double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
+ double mid = (double)m_blackcursor + delta;
+ double tmp = (x - mid) / delta;
+ m_gamma = 1.0 / pow (10, tmp);
+ }
+ break;
+ }
+ }
+
+ tqrepaint(false);
+}
+
+void KGradientSlider::leaveEvent( TQEvent * )
+{
+}
+
+
+void KGradientSlider::enableGamma(bool b)
+{
+ m_gammaEnabled = b;
+ tqrepaint(false);
+}
+
+double KGradientSlider::getGamma(void)
+{
+ return m_gamma;
+}
+
+void KGradientSlider::modifyBlack(int v) {
+ if (v >= 0 && v <= (int)m_whitecursor) {
+ m_blackcursor = (unsigned int)v;
+ if (m_gammaEnabled) {
+ double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
+ double mid = (double)m_blackcursor + delta;
+ double tmp = log10 (1.0 / m_gamma);
+ m_gammacursor = (unsigned int)tqRound(mid + delta * tmp);
+ }
+ tqrepaint(false);
+ }
+}
+void KGradientSlider::modifyWhite(int v) {
+ if (v >= (int)m_blackcursor && v <= 255) {
+ m_whitecursor = (unsigned int)v;
+ if (m_gammaEnabled) {
+ double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
+ double mid = (double)m_blackcursor + delta;
+ double tmp = log10 (1.0 / m_gamma);
+ m_gammacursor = (unsigned int)tqRound(mid + delta * tmp);
+ }
+ tqrepaint(false);
+ }
+}
+void KGradientSlider::modifyGamma(double v) {
+ m_gamma = v;
+ double delta = (double) (m_whitecursor - m_blackcursor) / 2.0;
+ double mid = (double)m_blackcursor + delta;
+ double tmp = log10 (1.0 / m_gamma);
+ m_gammacursor = (unsigned int)tqRound(mid + delta * tmp);
+ tqrepaint(false);
+}
+
+#include "kgradientslider.moc"
diff --git a/chalk/plugins/filters/levelfilter/kgradientslider.h b/chalk/plugins/filters/levelfilter/kgradientslider.h
new file mode 100644
index 00000000..c8990c80
--- /dev/null
+++ b/chalk/plugins/filters/levelfilter/kgradientslider.h
@@ -0,0 +1,85 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Frederic Coiffier <fcoiffie@gmail.com>
+ *
+ * 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 KGRADIENTSLIDER_H
+#define KGRADIENTSLIDER_H
+
+// TQt includes.
+
+#include <tqwidget.h>
+#include <tqcolor.h>
+#include <tqptrlist.h>
+#include <tqpair.h>
+
+class KGradientSlider : public TQWidget
+{
+Q_OBJECT
+ TQ_OBJECT
+
+ typedef enum {
+ BlackCursor,
+ GammaCursor,
+ WhiteCursor
+ } eCursor;
+
+public:
+ KGradientSlider(TQWidget *tqparent = 0, const char *name = 0, WFlags f = 0);
+
+ virtual ~KGradientSlider();
+
+public slots:
+ void modifyBlack(int);
+ void modifyWhite(int);
+ void modifyGamma(double);
+
+signals:
+
+ void modifiedBlack(int);
+ void modifiedWhite(int);
+ void modifiedGamma(double);
+
+protected:
+ void paintEvent(TQPaintEvent *);
+ void mousePressEvent (TQMouseEvent * e);
+ void mouseReleaseEvent ( TQMouseEvent * e );
+ void mouseMoveEvent ( TQMouseEvent * e );
+ void leaveEvent ( TQEvent * );
+
+public:
+ void enableGamma(bool b);
+ double getGamma(void);
+
+private:
+ unsigned int m_leftmost;
+ unsigned int m_rightmost;
+ eCursor m_grab_cursor;
+ unsigned int m_grab_index;
+ bool m_dragging;
+
+ unsigned int m_blackcursor;
+ unsigned int m_whitecursor;
+ unsigned int m_gammacursor;
+
+ bool m_gammaEnabled;
+ double m_gamma;
+};
+
+
+#endif /* KGRADIENTSLIDER_H */
diff --git a/chalk/plugins/filters/levelfilter/kis_level_filter.cc b/chalk/plugins/filters/levelfilter/kis_level_filter.cc
new file mode 100644
index 00000000..6b8dd6a0
--- /dev/null
+++ b/chalk/plugins/filters/levelfilter/kis_level_filter.cc
@@ -0,0 +1,324 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Frederic Coiffier <fcoiffie@gmail.com>
+ *
+ * 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 <math.h>
+
+#include <klocale.h>
+
+#include <tqlayout.h>
+#include <tqpixmap.h>
+#include <tqpainter.h>
+#include <tqlabel.h>
+#include <tqspinbox.h>
+
+#include "kis_filter_config_widget.h"
+#include "kis_level_filter.h"
+#include "wdg_level.h"
+#include "kis_colorspace.h"
+#include "kis_paint_device.h"
+#include "kis_iterators_pixel.h"
+#include "kis_iterator.h"
+#include "kis_histogram.h"
+#include "kis_basic_histogram_producers.h"
+#include "kis_painter.h"
+#include "kgradientslider.h"
+
+KisLevelFilterConfiguration::KisLevelFilterConfiguration()
+ : KisFilterConfiguration( "levels", 1 )
+{
+ whitevalue = 255;
+ blackvalue = 0;
+ gammavalue = 1.0;
+
+ outwhitevalue = 0xFFFF;
+ outblackvalue = 0;
+
+ m_adjustment = 0;
+}
+
+KisLevelFilterConfiguration::~KisLevelFilterConfiguration()
+{
+ delete m_adjustment;
+}
+
+void KisLevelFilterConfiguration::fromXML( const TQString& s )
+{
+ KisFilterConfiguration::fromXML(s);
+ blackvalue = getInt( "blackvalue" );
+ whitevalue = getInt( "whitevalue" );
+ gammavalue = getDouble( "gammavalue" );
+ outblackvalue = getInt( "outblackvalue" );
+ outwhitevalue = getInt( "outwhitevalue" );
+}
+
+TQString KisLevelFilterConfiguration::toString()
+{
+ m_properties.clear();
+ setProperty("blackvalue", blackvalue);
+ setProperty("whitevalue", whitevalue);
+ setProperty("gammavalue", gammavalue);
+ setProperty("outblackvalue", outblackvalue);
+ setProperty("outwhitevalue", outwhitevalue);
+
+ return KisFilterConfiguration::toString();
+}
+
+KisLevelFilter::KisLevelFilter()
+ : KisFilter( id(), "adjust", i18n("&Levels"))
+{
+
+}
+
+KisFilterConfigWidget * KisLevelFilter::createConfigurationWidget(TQWidget *tqparent, KisPaintDeviceSP dev)
+{
+ return new KisLevelConfigWidget(tqparent, dev);
+}
+
+KisFilterConfiguration* KisLevelFilter::configuration(TQWidget *nwidget)
+{
+ KisLevelConfigWidget* widget = (KisLevelConfigWidget*)nwidget;
+
+ if ( widget == 0 )
+ {
+ return new KisLevelFilterConfiguration();
+ } else {
+ return widget->config();
+ }
+}
+
+std::list<KisFilterConfiguration*> KisLevelFilter::listOfExamplesConfiguration(KisPaintDeviceSP /*dev*/)
+{
+ //XXX should really come up with a list of configurations
+ std::list<KisFilterConfiguration*> list;
+ list.insert(list.begin(), new KisLevelFilterConfiguration( ));
+ return list;
+}
+
+bool KisLevelFilter::workWith(KisColorSpace* cs)
+{
+ return (cs->getProfile() != 0);
+}
+
+
+void KisLevelFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* config, const TQRect& rect)
+{
+
+ if (!config) {
+ kdWarning() << "No configuration object for level filter\n";
+ return;
+ }
+
+ KisLevelFilterConfiguration* configBC = (KisLevelFilterConfiguration*) config;
+ Q_ASSERT(config);
+
+ if (src!=dst) {
+ KisPainter gc(dst);
+ gc.bitBlt(rect.x(), rect.y(), COMPOSITE_COPY, src, rect.x(), rect.y(), rect.width(), rect.height());
+ gc.end();
+ }
+
+ if (configBC->m_adjustment == 0) {
+ TQ_UINT16 transfer[256];
+ for (int i = 0; i < 256; i++) {
+ if (i <= configBC->blackvalue)
+ transfer[i] = configBC->outblackvalue;
+ else if (i < configBC->whitevalue)
+ {
+ double a = (double)(i - configBC->blackvalue) / (double)(configBC->whitevalue - configBC->blackvalue);
+ a = (double)(configBC->outwhitevalue - configBC->outblackvalue) * pow (a, (1.0 / configBC->gammavalue));
+ transfer[i] = int(configBC->outblackvalue + a);
+ }
+ else
+ transfer[i] = configBC->outwhitevalue;
+ }
+ configBC->m_adjustment = src->colorSpace()->createBrightnessContrastAdjustment(transfer);
+ }
+
+ KisRectIteratorPixel iter = dst->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true );
+
+ setProgressTotalSteps(rect.width() * rect.height());
+ TQ_INT32 pixelsProcessed = 0;
+
+ while( ! iter.isDone() && !cancelRequested())
+ {
+ TQ_UINT32 npix=0, maxpix = iter.nConseqPixels();
+ TQ_UINT8 selectedness = iter.selectedness();
+ // The idea here is to handle stretches of completely selected and completely unselected pixels.
+ // Partially selected pixels are handled one pixel at a time.
+ switch(selectedness)
+ {
+ case MIN_SELECTED:
+ while(iter.selectedness()==MIN_SELECTED && maxpix)
+ {
+ --maxpix;
+ ++iter;
+ ++npix;
+ }
+ pixelsProcessed += npix;
+ break;
+
+ case MAX_SELECTED:
+ {
+ TQ_UINT8 *firstPixel = iter.rawData();
+ while(iter.selectedness()==MAX_SELECTED && maxpix)
+ {
+ --maxpix;
+ if (maxpix != 0)
+ ++iter;
+ ++npix;
+ }
+ // adjust
+ src->colorSpace()->applyAdjustment(firstPixel, firstPixel, configBC->m_adjustment, npix);
+ pixelsProcessed += npix;
+ ++iter;
+ break;
+ }
+
+ default:
+ // adjust, but since it's partially selected we also only partially adjust
+ src->colorSpace()->applyAdjustment(iter.oldRawData(), iter.rawData(), configBC->m_adjustment, 1);
+ const TQ_UINT8 *pixels[2] = {iter.oldRawData(), iter.rawData()};
+ TQ_UINT8 weights[2] = {MAX_SELECTED - selectedness, selectedness};
+ src->colorSpace()->mixColors(pixels, weights, 2, iter.rawData());
+ ++iter;
+ pixelsProcessed++;
+ break;
+ }
+ setProgress(pixelsProcessed);
+ }
+
+ setProgressDone();
+}
+
+KisLevelConfigWidget::KisLevelConfigWidget(TQWidget * tqparent, KisPaintDeviceSP dev, const char * name, WFlags f)
+ : KisFilterConfigWidget(tqparent, name, f)
+{
+ m_page = new WdgLevel(this);
+ histogram = NULL;
+
+ m_page->ingradient->enableGamma(true);
+ m_page->blackspin->setValue(0);
+ m_page->whitespin->setValue(255);
+ m_page->gammaspin->setNum(1.0);
+ m_page->ingradient->modifyGamma(1.0);
+ m_page->outblackspin->setValue(0);
+ m_page->outwhitespin->setValue(255);
+
+ TQHBoxLayout * l = new TQHBoxLayout(this);
+ Q_CHECK_PTR(l);
+ l->addWidget(m_page, 0, TQt::AlignTop);
+
+ connect( m_page->blackspin, TQT_SIGNAL(valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->whitespin, TQT_SIGNAL(valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->ingradient, TQT_SIGNAL(modifiedGamma(double)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+
+ connect( m_page->blackspin, TQT_SIGNAL(valueChanged(int)), m_page->ingradient, TQT_SLOT(modifyBlack(int)));
+ connect( m_page->whitespin, TQT_SIGNAL(valueChanged(int)), m_page->ingradient, TQT_SLOT(modifyWhite(int)));
+ //connect( m_page->whitespin, TQT_SIGNAL(valueChanged(int)), m_page->ingradient, TQT_SLOT(modifyGamma()));
+
+ connect( m_page->ingradient, TQT_SIGNAL(modifiedBlack(int)), m_page->blackspin, TQT_SLOT(setValue(int)));
+ connect( m_page->ingradient, TQT_SIGNAL(modifiedWhite(int)), m_page->whitespin, TQT_SLOT(setValue(int)));
+ connect( m_page->ingradient, TQT_SIGNAL(modifiedGamma(double)), m_page->gammaspin, TQT_SLOT(setNum(double)));
+
+
+ connect( m_page->outblackspin, TQT_SIGNAL(valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( m_page->outwhitespin, TQT_SIGNAL(valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+
+ connect( m_page->outblackspin, TQT_SIGNAL(valueChanged(int)), m_page->outgradient, TQT_SLOT(modifyBlack(int)));
+ connect( m_page->outwhitespin, TQT_SIGNAL(valueChanged(int)), m_page->outgradient, TQT_SLOT(modifyWhite(int)));
+
+ connect( m_page->outgradient, TQT_SIGNAL(modifiedBlack(int)), m_page->outblackspin, TQT_SLOT(setValue(int)));
+ connect( m_page->outgradient, TQT_SIGNAL(modifiedWhite(int)), m_page->outwhitespin, TQT_SLOT(setValue(int)));
+
+ connect( (TQObject*)(m_page->chkLogarithmic), TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(drawHistogram(bool)));
+
+ KisHistogramProducerSP producer = new KisGenericLabHistogramProducer();
+ histogram = new KisHistogram(dev, producer, LINEAR);
+ m_histlog = false;
+ drawHistogram();
+
+}
+
+KisLevelConfigWidget::~KisLevelConfigWidget()
+{
+ delete histogram;
+}
+
+void KisLevelConfigWidget::drawHistogram(bool logarithmic)
+{
+ int height = 256;
+
+ if (m_histlog != logarithmic) {
+ // Update the histogram
+ if (logarithmic)
+ histogram->setHistogramType(LOGARITHMIC);
+ else
+ histogram->setHistogramType(LINEAR);
+ m_histlog = logarithmic;
+ }
+
+ TQPixmap pix(256, height);
+ pix.fill();
+ TQPainter p(&pix);
+ p.setPen(TQPen::TQPen(TQt::gray,1, TQt::SolidLine));
+
+ double highest = (double)histogram->calculations().getHighest();
+ TQ_INT32 bins = histogram->producer()->numberOfBins();
+
+ if (histogram->getHistogramType() == LINEAR) {
+ double factor = (double)height / highest;
+ for( int i=0; i<bins; ++i ) {
+ p.drawLine(i, height, i, height - int(histogram->getValue(i) * factor));
+ }
+ } else {
+ double factor = (double)height / (double)log(highest);
+ for( int i = 0; i < bins; ++i ) {
+ p.drawLine(i, height, i, height - int(log((double)histogram->getValue(i)) * factor));
+ }
+ }
+
+ m_page->histview->setPixmap(pix);
+}
+
+KisLevelFilterConfiguration * KisLevelConfigWidget::config()
+{
+ KisLevelFilterConfiguration * cfg = new KisLevelFilterConfiguration();
+
+ cfg->blackvalue = m_page->blackspin->value();
+ cfg->whitevalue = m_page->whitespin->value();
+ cfg->gammavalue = m_page->ingradient->getGamma();
+
+ cfg->outblackvalue = m_page->outblackspin->value() * 255;
+ cfg->outwhitevalue = m_page->outwhitespin->value() * 255;
+
+ return cfg;
+}
+
+void KisLevelConfigWidget::setConfiguration( KisFilterConfiguration * config )
+{
+ KisLevelFilterConfiguration * cfg = dynamic_cast<KisLevelFilterConfiguration *>(config);
+ m_page->blackspin->setValue(cfg->blackvalue);
+ m_page->whitespin->setValue(cfg->whitevalue);
+ m_page->ingradient->modifyGamma(cfg->gammavalue);
+
+ m_page->outblackspin->setValue(cfg->outblackvalue / 255);
+ m_page->outwhitespin->setValue(cfg->outwhitevalue / 255);
+}
+
diff --git a/chalk/plugins/filters/levelfilter/kis_level_filter.h b/chalk/plugins/filters/levelfilter/kis_level_filter.h
new file mode 100644
index 00000000..8f3d3591
--- /dev/null
+++ b/chalk/plugins/filters/levelfilter/kis_level_filter.h
@@ -0,0 +1,94 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Frederic Coiffier <fcoiffie@gmail.com>
+ *
+ * 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_LEVEL_FILTER_H_
+#define _KIS_LEVEL_FILTER_H_
+
+#include "kis_filter.h"
+#include "kis_filter_config_widget.h"
+
+class WdgLevel;
+class TQWidget;
+class KisColorAdjustment;
+class KisHistogram;
+
+class KisLevelFilterConfiguration : public KisFilterConfiguration {
+
+public:
+
+ KisLevelFilterConfiguration();
+ virtual ~KisLevelFilterConfiguration();
+ virtual void fromXML( const TQString& );
+ virtual TQString toString();
+
+public:
+ TQ_UINT8 blackvalue, whitevalue;
+ double gammavalue;
+ TQ_UINT16 outblackvalue, outwhitevalue;
+ KisColorAdjustment * m_adjustment;
+};
+
+/**
+ * This class affect Intensity Y of the image
+ */
+class KisLevelFilter : public KisFilter
+{
+
+public:
+
+ KisLevelFilter();
+
+public:
+
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration * configuration(TQWidget *);
+ virtual KisFilterConfiguration * configuration() { return new KisLevelFilterConfiguration(); };
+ virtual void process(KisPaintDeviceSP, KisPaintDeviceSP, KisFilterConfiguration* , const TQRect&);
+ static inline KisID id() { return KisID("levels", i18n("Levels")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ virtual std::list<KisFilterConfiguration*> listOfExamplesConfiguration(KisPaintDeviceSP dev);
+
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return TO_LAB16; };
+ virtual bool workWith(KisColorSpace* cs);
+};
+
+
+class KisLevelConfigWidget : public KisFilterConfigWidget {
+Q_OBJECT
+ TQ_OBJECT
+public:
+ KisLevelConfigWidget(TQWidget * tqparent, KisPaintDeviceSP dev, const char * name = 0, WFlags f = 0 );
+ virtual ~KisLevelConfigWidget();
+
+ KisLevelFilterConfiguration * config();
+ void setConfiguration( KisFilterConfiguration * config );
+ WdgLevel * m_page;
+
+protected slots:
+ void drawHistogram(bool logarithmic = false);
+
+protected:
+ KisHistogram *histogram;
+ bool m_histlog;
+};
+
+#endif
diff --git a/chalk/plugins/filters/levelfilter/levelfilter.cc b/chalk/plugins/filters/levelfilter/levelfilter.cc
new file mode 100644
index 00000000..669775fb
--- /dev/null
+++ b/chalk/plugins/filters/levelfilter/levelfilter.cc
@@ -0,0 +1,67 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Frederic Coiffier <fcoiffie@gmail.com>
+ *
+ * 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 <math.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <tqslider.h>
+#include <tqpoint.h>
+#include <tqcolor.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_layer.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_iterators_pixel.h>
+#include <kis_colorspace.h>
+#include <kis_painter.h>
+#include <kis_selection.h>
+#include "levelfilter.h"
+#include "kis_level_filter.h"
+
+typedef KGenericFactory<LevelFilter> LevelFilterFactory;
+K_EXPORT_COMPONENT_FACTORY( chalklevelfilter, LevelFilterFactory( "chalk" ) )
+
+LevelFilter::LevelFilter(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(LevelFilterFactory::instance());
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisLevelFilter());
+ }
+}
+
+LevelFilter::~LevelFilter()
+{
+}
diff --git a/chalk/plugins/filters/levelfilter/levelfilter.h b/chalk/plugins/filters/levelfilter/levelfilter.h
new file mode 100644
index 00000000..69627ff7
--- /dev/null
+++ b/chalk/plugins/filters/levelfilter/levelfilter.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Frederic Coiffier <fcoiffie@gmail.com>
+ *
+ * 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 LEVEL_H
+#define LEVEL_H
+
+#include <kparts/plugin.h>
+
+class KisColorSpace;
+class KisColorAdjustment;
+
+class LevelFilter : public KParts::Plugin
+{
+ public:
+ LevelFilter(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~LevelFilter();
+};
+
+#endif
diff --git a/chalk/plugins/filters/levelfilter/wdg_level.ui b/chalk/plugins/filters/levelfilter/wdg_level.ui
new file mode 100644
index 00000000..0db94640
--- /dev/null
+++ b/chalk/plugins/filters/levelfilter/wdg_level.ui
@@ -0,0 +1,331 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgLevel</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgLevel</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>269</width>
+ <height>479</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>32767</width>
+ <height>32767</height>
+ </size>
+ </property>
+ <property name="caption">
+ <string>Levels</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="TQCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>chkLogarithmic</cstring>
+ </property>
+ <property name="text">
+ <string>Logarithmic</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Input levels&lt;/b&gt;</string>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget" row="2" column="0">
+ <property name="name">
+ <cstring>tqlayout7</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>histview</cstring>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>256</width>
+ <height>256</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>256</width>
+ <height>256</height>
+ </size>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout5</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KGradientSlider">
+ <property name="name">
+ <cstring>ingradient</cstring>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>256</width>
+ <height>20</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQSpinBox">
+ <property name="name">
+ <cstring>blackspin</cstring>
+ </property>
+ <property name="buttonSymbols">
+ <enum>PlusMinus</enum>
+ </property>
+ <property name="maxValue">
+ <number>255</number>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>MinimumExpanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>25</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>gammaspin</cstring>
+ </property>
+ <property name="text">
+ <string>1.0</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>MinimumExpanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>25</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQSpinBox">
+ <property name="name">
+ <cstring>whitespin</cstring>
+ </property>
+ <property name="buttonSymbols">
+ <enum>PlusMinus</enum>
+ </property>
+ <property name="maxValue">
+ <number>255</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;b&gt;Output levels&lt;/b&gt;</string>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout6</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KGradientSlider">
+ <property name="name">
+ <cstring>outgradient</cstring>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>256</width>
+ <height>20</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQSpinBox">
+ <property name="name">
+ <cstring>outblackspin</cstring>
+ </property>
+ <property name="buttonSymbols">
+ <enum>PlusMinus</enum>
+ </property>
+ <property name="maxValue">
+ <number>255</number>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>MinimumExpanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>50</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQSpinBox">
+ <property name="name">
+ <cstring>outwhitespin</cstring>
+ </property>
+ <property name="buttonSymbols">
+ <enum>PlusMinus</enum>
+ </property>
+ <property name="maxValue">
+ <number>255</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer row="2" column="1">
+ <property name="name">
+ <cstring>spacer5_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>21</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="3" column="0">
+ <property name="name">
+ <cstring>spacer6_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KGradientSlider</class>
+ <header location="local">kgradientslider.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>0</hordata>
+ <verdata>0</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data>
+ </image>
+</images>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kgradientslider.h</includehint>
+ <includehint>kgradientslider.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/filters/noisefilter/Makefile.am b/chalk/plugins/filters/noisefilter/Makefile.am
new file mode 100644
index 00000000..c3db54d0
--- /dev/null
+++ b/chalk/plugins/filters/noisefilter/Makefile.am
@@ -0,0 +1,23 @@
+chalkrcdir = $(kde_datadir)/chalk/chalkplugins
+
+kde_services_DATA = chalknoisefilter.desktop
+
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalknoisefilter_la_SOURCES = noisefilter.cc wdgnoiseoptions.ui \
+ kis_wdg_noise.cpp
+
+kde_module_LTLIBRARIES = chalknoisefilter.la
+noinst_HEADERS = noisefilter.h kis_wdg_noise.h
+
+chalknoisefilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalknoisefilter_la_LIBADD = ../../../libchalkcommon.la
+
+chalknoisefilter_la_METASOURCES = AUTO
diff --git a/chalk/plugins/filters/noisefilter/chalknoisefilter.desktop b/chalk/plugins/filters/noisefilter/chalknoisefilter.desktop
new file mode 100644
index 00000000..6ff1e2f1
--- /dev/null
+++ b/chalk/plugins/filters/noisefilter/chalknoisefilter.desktop
@@ -0,0 +1,77 @@
+[Desktop Entry]
+Name=Noise Filter
+Name[bg]=Шумов филтър
+Name[ca]=Filtre de soroll
+Name[da]=Støjfilter
+Name[de]=Rauschfilter
+Name[el]=Φίλτρο θορύβου
+Name[eo]=Brufiltrilo
+Name[es]=Filtro de ruido
+Name[et]=Mürafilter
+Name[fa]=پالایۀ نوفه
+Name[fr]=Filtre de bruit
+Name[fy]=Rûsfilter
+Name[ga]=Scagaire Torainn
+Name[gl]=Filtro de Ruído
+Name[hu]=Zajszűrő
+Name[it]=Filtro dei disturbi
+Name[ja]=ノイズフィルタ
+Name[km]=តម្រង​ភាព​មិន​ច្បាស់
+Name[lt]=Triukšmo filtras
+Name[lv]=Trokšņu filtrs
+Name[nb]=Støyfilter
+Name[nds]=Ruusfilter
+Name[ne]=ध्वनि फिल्टर
+Name[nl]=Ruisfilter
+Name[pl]=Filtr dodania szumu
+Name[pt]=Filtro de Ruído
+Name[pt_BR]=Filtro de Ruído
+Name[ru]=Шум
+Name[se]=Gádjasilli
+Name[sk]=Filter zrnenie
+Name[sl]=Filter za šum
+Name[sr]=Филтер за шум
+Name[sr@Latn]=Filter za šum
+Name[sv]=Brusfilter
+Name[uk]=Фільтр шуму
+Name[uz]=Shovqin filteri
+Name[uz@cyrillic]=Шовқин филтери
+Name[zh_TW]=雜訊過濾器
+Comment=Add noise to an image
+Comment[bg]=Добавяне на шум към изображение
+Comment[ca]=Afegeix soroll a una imatge
+Comment[da]=Tilføj støj til et billede
+Comment[de]=Einem Bild Rauschen hinzufügen
+Comment[el]=Προσθήκη θορύβου σε μια εικόνα
+Comment[eo]=Aldoni bruon (entropion) al bildo
+Comment[es]=Añadir ruido a una imagen
+Comment[et]=Müra lisamine pildile
+Comment[fa]=افزودن نوفه به یک تصویر
+Comment[fr]=Ajouter du bruit à une image
+Comment[fy]=Rûs oan in ôfbylding taheakje
+Comment[gl]=Engade ruído a unha imaxe
+Comment[hu]=Zaj hozzáadása képhez
+Comment[it]=Aggiungi un disturbo all'immagine
+Comment[ja]=画像にノイズを加える
+Comment[km]=បន្ថែម​ភាព​មិន​ច្បាស់​ទៅ​រូបភាព
+Comment[lv]=Pievieno attēlam troksni
+Comment[nb]=Legg til støy i et bilde
+Comment[nds]=En Bild Rusen tofögen
+Comment[ne]=एउटा छविमा ध्वनि थप्नुहोस्
+Comment[nl]=Voeg ruis toe aan een afbeelding
+Comment[pl]=Dodaje szum do obrazka
+Comment[pt]=Adiciona ruído a uma imagem
+Comment[pt_BR]=Adiciona ruído a uma imagem
+Comment[ru]=Добавление шума в изображение
+Comment[se]=Lasit gája govvii
+Comment[sk]=Pridať do obrázku zrnenie
+Comment[sl]=Dodaj šum k sliki
+Comment[sr]=Додај шум на слику
+Comment[sr@Latn]=Dodaj šum na sliku
+Comment[sv]=Lägg till brus i en bild
+Comment[uk]=Додавання шуму в зображення
+Comment[zh_TW]=在圖片中增加雜訊
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalknoisefilter
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/noisefilter/kis_wdg_noise.cpp b/chalk/plugins/filters/noisefilter/kis_wdg_noise.cpp
new file mode 100644
index 00000000..060418f3
--- /dev/null
+++ b/chalk/plugins/filters/noisefilter/kis_wdg_noise.cpp
@@ -0,0 +1,59 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_wdg_noise.h"
+
+#include <tqlayout.h>
+
+#include <knuminput.h>
+
+#include "wdgnoiseoptions.h"
+
+KisWdgNoise::KisWdgNoise(KisFilter* /*nfilter*/, TQWidget* tqparent, const char* name)
+ : KisFilterConfigWidget(tqparent,name)
+{
+ TQGridLayout *widgetLayout = new TQGridLayout(this, 1, 1);
+ m_widget = new WdgNoiseOptions(this);
+ widgetLayout -> addWidget(m_widget,0,0);
+
+ connect( widget()->intLevel, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->intOpacity, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+}
+
+KisWdgNoise::~KisWdgNoise()
+{
+}
+
+void KisWdgNoise::setConfiguration(KisFilterConfiguration* config)
+{
+ TQVariant value;
+ if (config->getProperty("level", value))
+ {
+ widget()->intLevel->setValue( value.toUInt() );
+ }
+ if (config->getProperty("opacity", value))
+ {
+ widget()->intOpacity->setValue( value.toUInt() );
+ }
+}
+
+
+#include "kis_wdg_noise.moc"
+
diff --git a/chalk/plugins/filters/noisefilter/kis_wdg_noise.h b/chalk/plugins/filters/noisefilter/kis_wdg_noise.h
new file mode 100644
index 00000000..ca42ebd2
--- /dev/null
+++ b/chalk/plugins/filters/noisefilter/kis_wdg_noise.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_WDG_NOISE_H
+#define KIS_WDG_NOISE_H
+
+#include <kis_filter_config_widget.h>
+
+class WdgNoiseOptions;
+class KisFilter;
+
+class KisWdgNoise : public KisFilterConfigWidget
+{
+ Q_OBJECT
+ TQ_OBJECT
+ public:
+ KisWdgNoise(KisFilter* nfilter, TQWidget* tqparent = 0, const char* name = 0);
+ ~KisWdgNoise();
+ public:
+ inline WdgNoiseOptions* widget() { return m_widget; };
+ virtual void setConfiguration(KisFilterConfiguration*);
+ private:
+ WdgNoiseOptions* m_widget;
+};
+
+#endif
+
diff --git a/chalk/plugins/filters/noisefilter/noisefilter.cc b/chalk/plugins/filters/noisefilter/noisefilter.cc
new file mode 100644
index 00000000..af593703
--- /dev/null
+++ b/chalk/plugins/filters/noisefilter/noisefilter.cc
@@ -0,0 +1,128 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kgenericfactory.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_filter_registry.h>
+#include <kis_global.h>
+#include <kis_types.h>
+
+#include "kis_wdg_noise.h"
+#include "wdgnoiseoptions.h"
+
+typedef KGenericFactory<ChalkNoiseFilter> ChalkNoiseFilterFactory;
+K_EXPORT_COMPONENT_FACTORY( chalknoisefilter, ChalkNoiseFilterFactory( "chalk" ) )
+
+ChalkNoiseFilter::ChalkNoiseFilter(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ChalkNoiseFilterFactory::instance());
+
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisFilterNoise());
+ }
+}
+
+ChalkNoiseFilter::~ChalkNoiseFilter()
+{
+}
+
+KisFilterNoise::KisFilterNoise() : KisFilter(id(), "other", i18n("&Random Noise..."))
+{
+}
+
+KisFilterConfiguration* KisFilterNoise::configuration(TQWidget* w)
+{
+ KisWdgNoise* wN = dynamic_cast<KisWdgNoise*>(w);
+ KisFilterConfiguration* config = new KisFilterConfiguration(id().id(), 1);
+ if(wN)
+ {
+ config->setProperty("level", wN->widget()->intLevel->value() );
+ config->setProperty("opacity", wN->widget()->intOpacity->value() );
+ }
+ return config;
+}
+
+KisFilterConfigWidget * KisFilterNoise::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev)
+{
+ return new KisWdgNoise((KisFilter*)this, (TQWidget*)tqparent, i18n("Configuration of noise filter").ascii());
+}
+
+void KisFilterNoise::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* config, const TQRect& rect)
+{
+ Q_ASSERT(src != 0);
+ Q_ASSERT(dst != 0);
+
+ setProgressTotalSteps(rect.width() * rect.height());
+
+ KisColorSpace * cs = src->colorSpace();
+ TQ_INT32 psize = cs->pixelSize();
+
+ TQVariant value;
+ int level = (config && config->getProperty("level", value)) ? value.toInt() : 50;
+ int opacity = (config && config->getProperty("opacity", value)) ? value.toInt() : 100;
+
+ KisRectIteratorPixel dstIt = dst->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true );
+ KisRectIteratorPixel srcIt = src->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), false);
+
+ TQ_UINT8* interm = new TQ_UINT8[ cs->pixelSize() ];
+ TQ_UINT32 threshold = (RAND_MAX / 100) * (100 - level);
+
+ TQ_UINT8 weights[2];
+ weights[0] = (255 * opacity) / 100; weights[1] = 255 - weights[0];
+ const TQ_UINT8* pixels[2];
+ pixels[0] = interm;
+ while(!srcIt.isDone())
+ {
+ if(rand() > threshold)
+ {
+ TQColor c = tqRgb((double)rand()/RAND_MAX * 255,(double)rand()/RAND_MAX * 255,(double)rand()/RAND_MAX * 255);
+ cs->fromTQColor( c, interm, 0 );
+ pixels[1] = srcIt.oldRawData();
+ cs->mixColors( pixels, weights, 2, dstIt.rawData() );
+ }
+ ++srcIt;
+ ++dstIt;
+ incProgress();
+ }
+
+ delete interm;
+ setProgressDone(); // Must be called even if you don't really support progression
+}
diff --git a/chalk/plugins/filters/noisefilter/noisefilter.h b/chalk/plugins/filters/noisefilter/noisefilter.h
new file mode 100644
index 00000000..b73c761f
--- /dev/null
+++ b/chalk/plugins/filters/noisefilter/noisefilter.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 NOISEFILTER_H
+#define NOISEFILTER_H
+
+#include <kparts/plugin.h>
+#include "kis_filter.h"
+
+class KisFilterConfigWidget;
+
+class ChalkNoiseFilter : public KParts::Plugin
+{
+public:
+ ChalkNoiseFilter(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ChalkNoiseFilter();
+};
+
+class KisFilterNoise : public KisFilter
+{
+ public:
+ KisFilterNoise();
+ public:
+ virtual void process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration*, const TQRect&);
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return FULLY_INDEPENDENT; };
+ static inline KisID id() { return KisID("noise", i18n("Noise")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration* configuration(TQWidget*);
+};
+
+#endif
diff --git a/chalk/plugins/filters/noisefilter/wdgnoiseoptions.ui b/chalk/plugins/filters/noisefilter/wdgnoiseoptions.ui
new file mode 100644
index 00000000..969d4153
--- /dev/null
+++ b/chalk/plugins/filters/noisefilter/wdgnoiseoptions.ui
@@ -0,0 +1,111 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgNoiseOptions</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgNoiseOptions</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>174</width>
+ <height>63</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Opacity:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Level:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="1" column="1">
+ <property name="name">
+ <cstring>intOpacity</cstring>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="0" column="1">
+ <property name="name">
+ <cstring>intLevel</cstring>
+ </property>
+ <property name="value">
+ <number>50</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ </widget>
+ <spacer row="1" column="2">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>21</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="2" column="1">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/filters/oilpaintfilter/Makefile.am b/chalk/plugins/filters/oilpaintfilter/Makefile.am
new file mode 100644
index 00000000..d67aab54
--- /dev/null
+++ b/chalk/plugins/filters/oilpaintfilter/Makefile.am
@@ -0,0 +1,24 @@
+kde_services_DATA = chalkoilpaintfilter.desktop
+
+INCLUDES = \
+ -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../ui \
+ -I../../../ui/ \
+ -I$(srcdir)/../../../../lib/kofficecore \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalkoilpaintfilter.la
+
+chalkoilpaintfilter_la_SOURCES = kis_oilpaint_filter_plugin.cc \
+ kis_oilpaint_filter.cc
+
+noinst_HEADERS = kis_oilpaint_filter_plugin.h \
+ kis_oilpaint_filter.h
+
+chalkoilpaintfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkoilpaintfilter_la_LIBADD = ../../../libchalkcommon.la
+
+chalkoilpaintfilter_la_METASOURCES = AUTO
diff --git a/chalk/plugins/filters/oilpaintfilter/chalkoilpaintfilter.desktop b/chalk/plugins/filters/oilpaintfilter/chalkoilpaintfilter.desktop
new file mode 100644
index 00000000..ae6682f6
--- /dev/null
+++ b/chalk/plugins/filters/oilpaintfilter/chalkoilpaintfilter.desktop
@@ -0,0 +1,77 @@
+[Desktop Entry]
+Name=Oilpaint Filter
+Name[bg]=Филтър маслена боя
+Name[ca]=Filtre de pintura a l'oli
+Name[cy]=Hidlen Baent Olew
+Name[da]=Oliemalerifilter
+Name[de]=Ölgemälde-Filter
+Name[el]=Φίλτρο ελαιογραφίας
+Name[eo]=Olefarba filtrilo
+Name[es]=Filtro de pintura al óleo
+Name[et]=Õlimaalifilter
+Name[fa]=پالایۀ رنگ روغن
+Name[fi]=Öljymaalaussuodin
+Name[fr]=Filtre de peinture à l'huile
+Name[fy]=Oaljefervefilter
+Name[gl]=Filtro de Pintura ao Óleo
+Name[he]=מסנן צבעי שמן
+Name[hu]=Olajfestmény szűrő
+Name[is]=Olíumálunarsía
+Name[it]=Filtro di pittura a olio
+Name[ja]=油絵フィルタ
+Name[km]=តម្រង​គំនូរ​ពណ៌​ប្រេង
+Name[nb]=Oljemalingsfilter
+Name[nds]=Öölbild-Filter
+Name[ne]=ओइलपेन्ट फिल्टर
+Name[nl]=Olieverffilter
+Name[pl]=Filtr farb olejnych
+Name[pt]=Filtro de Pintura a Óleo
+Name[pt_BR]=Filtro de Pintura a Óleo
+Name[ru]=Масляная краска
+Name[sk]=Filter olejomaľba
+Name[sl]=Filter Oljne barve
+Name[sr]=Филтер за уље на платну
+Name[sr@Latn]=Filter za ulje na platnu
+Name[sv]=Oljemålningsfilter
+Name[uk]=Фільтр олійних фарб
+Name[zh_TW]=油畫過濾器
+Comment=Oilpaint filter
+Comment[bg]=Филтър маслена боя
+Comment[ca]=Filtre de pintura a l'oli
+Comment[cy]=Hidlen baent olew
+Comment[da]=Oliemalerifilter
+Comment[de]=Ölgemälde-Filter
+Comment[el]=Φίλτρο ελαιογραφίας
+Comment[eo]=Olefarba filtrilo
+Comment[es]=Filtro de pintura al óleo
+Comment[et]=Õlimaalifilter
+Comment[fa]=پالایۀ رنگ روغن
+Comment[fi]=Öljymaalaussuodin
+Comment[fr]=Filtre peinture à l'huile
+Comment[fy]=Oaljefervefilter
+Comment[gl]=Filtro de pintura ao óleo
+Comment[he]=מסנן צבעי שמן
+Comment[hu]=Olajfestmény szűrő
+Comment[is]=Olíumálunarsía
+Comment[it]=Filtro di pittura a olio
+Comment[ja]=油絵フィルタ
+Comment[km]=តម្រង​គំនូរ​ពណ៌​ប្រេង
+Comment[nb]=Oljemalingsfilter
+Comment[nds]=Öölbild-Filter
+Comment[ne]=ओइलपेन्ट फिल्टर
+Comment[nl]=Olieverffilter
+Comment[pl]=Filtr farb olejnych
+Comment[pt]=Filtro de pintura a óleo
+Comment[pt_BR]=Filtro de pintura a óleo
+Comment[ru]=Масляная краска
+Comment[sk]=Filter olejomaľba
+Comment[sl]=Filter Oljna barva
+Comment[sr]=Филтер за уље на платну
+Comment[sr@Latn]=Filter za ulje na platnu
+Comment[sv]=Oljemålningsfilter
+Comment[uk]=Фільтр олійних фарб
+Comment[zh_TW]=油畫過濾器
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkoilpaintfilter
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/oilpaintfilter/kis_oilpaint_filter.cc b/chalk/plugins/filters/oilpaintfilter/kis_oilpaint_filter.cc
new file mode 100644
index 00000000..fc96b991
--- /dev/null
+++ b/chalk/plugins/filters/oilpaintfilter/kis_oilpaint_filter.cc
@@ -0,0 +1,256 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * ported from digikam, Copyright 2004 by Gilles Caulier,
+ * Original Oilpaint algorithm copyrighted 2004 by
+ * Pieter Z. Voloshyn <pieter_voloshyn at ame.com.br>.
+ *
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+#include <tqspinbox.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <knuminput.h>
+
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_filter_registry.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_progress_display_interface.h>
+
+#include "kis_multi_integer_filter_widget.h"
+#include "kis_oilpaint_filter.h"
+
+KisOilPaintFilter::KisOilPaintFilter() : KisFilter(id(), "artistic", i18n("&Oilpaint..."))
+{
+}
+
+void KisOilPaintFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* configuration, const TQRect& rect)
+{
+
+ if (!configuration) {
+ kdWarning() << "No configuration object for oilpaint filter\n";
+ return;
+ }
+
+ Q_UNUSED(dst);
+
+ TQ_INT32 x = rect.x(), y = rect.y();
+ TQ_INT32 width = rect.width();
+ TQ_INT32 height = rect.height();
+
+ //read the filter configuration values from the KisFilterConfiguration object
+ TQ_UINT32 brushSize = ((KisOilPaintFilterConfiguration*)configuration)->brushSize();
+ TQ_UINT32 smooth = ((KisOilPaintFilterConfiguration*)configuration)->smooth();
+
+
+ OilPaint(src, dst, x, y, width, height, brushSize, smooth);
+}
+
+// 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(KisPaintDeviceSP src, KisPaintDeviceSP dst, int x, int y, int w, int h, int BrushSize, int Smoothness)
+{
+ setProgressTotalSteps(h);
+ setProgressStage(i18n("Applying oilpaint filter..."),0);
+
+ TQRect bounds(x, y, w, h);
+
+ for (TQ_INT32 yOffset = 0; yOffset < h; yOffset++) {
+
+ KisHLineIteratorPixel it = src->createHLineIterator(x, y + yOffset, w, false);
+ KisHLineIteratorPixel dstIt = dst->createHLineIterator(x, y + yOffset, w, true);
+
+ while (!it.isDone() && !cancelRequested()) {
+
+ if (it.isSelected()) {
+
+ uint color = MostFrequentColor(src, bounds, it.x(), it.y(), BrushSize, Smoothness);
+ dst->colorSpace()->fromTQColor(TQColor(tqRed(color), tqGreen(color), tqBlue(color)), tqAlpha(color), dstIt.rawData());
+ }
+
+ ++it;
+ ++dstIt;
+ }
+
+ setProgress(yOffset);
+ }
+
+ setProgressDone();
+}
+
+// This method have been ported from Pieter Z. Voloshyn algorithm code.
+
+/* 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 analized
+ * Intensity => Intensity to calcule
+ *
+ * Theory => This function creates a matrix with the analized pixel in
+ * the center of this matrix and find the most frequenty color
+ */
+
+uint KisOilPaintFilter::MostFrequentColor (KisPaintDeviceSP src, const TQRect& bounds, int X, int Y, int Radius, int Intensity)
+{
+ uint color;
+ uint I;
+
+ double Scale = Intensity / 255.0;
+
+ // Alloc some arrays to be used
+ uchar *IntensityCount = new uchar[(Intensity + 1) * sizeof (uchar)];
+ uint *AverageColorR = new uint[(Intensity + 1) * sizeof (uint)];
+ uint *AverageColorG = new uint[(Intensity + 1) * sizeof (uint)];
+ uint *AverageColorB = new uint[(Intensity + 1) * sizeof (uint)];
+
+ // Erase the array
+ memset(IntensityCount, 0, (Intensity + 1) * sizeof (uchar));
+
+ /*for (i = 0; i <= Intensity; ++i)
+ IntensityCount[i] = 0;*/
+
+ KisRectIteratorPixel it = src->createRectIterator(X - Radius, Y - Radius, (2 * Radius) + 1, (2 * Radius) + 1, false);
+
+ while (!it.isDone()) {
+
+ if (bounds.tqcontains(it.x(), it.y())) {
+
+// XXX: COLORSPACE_INDEPENDENCE
+
+ TQColor c;
+ src->colorSpace()->toTQColor(it.rawData(), &c);
+
+ // Swapping red and blue here is done because that gives the same
+ // output as digikam, even though it might be interpreted as a bug
+ // in both applications.
+ int b = c.red();
+ int g = c.green();
+ int r = c.blue();
+
+ I = (uint)(GetIntensity (r, g, b) * Scale);
+ IntensityCount[I]++;
+
+ if (IntensityCount[I] == 1)
+ {
+ AverageColorR[I] = r;
+ AverageColorG[I] = g;
+ AverageColorB[I] = b;
+ }
+ else
+ {
+ AverageColorR[I] += r;
+ AverageColorG[I] += g;
+ AverageColorB[I] += b;
+ }
+ }
+
+ ++it;
+ }
+
+ I = 0;
+ int MaxInstance = 0;
+
+ for (int i = 0 ; i <= Intensity ; ++i)
+ {
+ if (IntensityCount[i] > MaxInstance)
+ {
+ I = i;
+ MaxInstance = IntensityCount[i];
+ }
+ }
+
+ int R, G, B;
+ if (MaxInstance != 0) {
+ R = AverageColorR[I] / MaxInstance;
+ G = AverageColorG[I] / MaxInstance;
+ B = AverageColorB[I] / MaxInstance;
+ } else {
+ R = 0;
+ G = 0;
+ B = 0;
+ }
+
+ // Swap red and blue back to get the correct colour.
+ color = tqRgb (B, G, R);
+
+ delete [] IntensityCount; // free all the arrays
+ delete [] AverageColorR;
+ delete [] AverageColorG;
+ delete [] AverageColorB;
+
+ return (color); // return the most frequenty color
+}
+
+
+KisFilterConfigWidget * KisOilPaintFilter::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP /*dev*/)
+{
+ vKisIntegerWidgetParam param;
+ param.push_back( KisIntegerWidgetParam( 1, 5, 1, i18n("Brush size"), "brushSize" ) );
+ param.push_back( KisIntegerWidgetParam( 10, 255, 30, i18n("Smooth"), "smooth" ) );
+ return new KisMultiIntegerFilterWidget(tqparent, id().id().ascii(), id().id().ascii(), param );
+}
+
+KisFilterConfiguration* KisOilPaintFilter::configuration(TQWidget* nwidget)
+{
+ KisMultiIntegerFilterWidget* widget = (KisMultiIntegerFilterWidget*) nwidget;
+ if( widget == 0 )
+ {
+ return new KisOilPaintFilterConfiguration( 1, 30);
+ } else {
+ return new KisOilPaintFilterConfiguration( widget->valueAt( 0 ), widget->valueAt( 1 ) );
+ }
+}
+
+std::list<KisFilterConfiguration*> KisOilPaintFilter::listOfExamplesConfiguration(KisPaintDeviceSP )
+{
+ std::list<KisFilterConfiguration*> list;
+ list.insert(list.begin(), new KisOilPaintFilterConfiguration( 1, 30));
+ return list;
+}
+
diff --git a/chalk/plugins/filters/oilpaintfilter/kis_oilpaint_filter.h b/chalk/plugins/filters/oilpaintfilter/kis_oilpaint_filter.h
new file mode 100644
index 00000000..fbc07a63
--- /dev/null
+++ b/chalk/plugins/filters/oilpaintfilter/kis_oilpaint_filter.h
@@ -0,0 +1,69 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_OILPAINT_FILTER_H_
+#define _KIS_OILPAINT_FILTER_H_
+
+#include "kis_filter.h"
+#include "kis_filter_config_widget.h"
+
+class KisOilPaintFilterConfiguration : public KisFilterConfiguration
+{
+
+public:
+
+ KisOilPaintFilterConfiguration(TQ_UINT32 brushSize, TQ_UINT32 smooth)
+ : KisFilterConfiguration( "oilpaint", 1 )
+ {
+ setProperty("brushSize", brushSize);
+ setProperty("smooth", smooth);
+ };
+public:
+
+ inline TQ_UINT32 brushSize() { return getInt("brushSize"); };
+ inline TQ_UINT32 smooth() {return getInt("smooth"); };
+
+};
+
+
+class KisOilPaintFilter : public KisFilter
+{
+public:
+ KisOilPaintFilter();
+public:
+ virtual void process(KisPaintDeviceSP,KisPaintDeviceSP, KisFilterConfiguration* , const TQRect&);
+ static inline KisID id() { return KisID("oilpaint", i18n("Oilpaint")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsAdjustmentLayers() { return false; }
+ virtual std::list<KisFilterConfiguration*> listOfExamplesConfiguration(KisPaintDeviceSP dev);
+ public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration * configuration(TQWidget*);
+ virtual KisFilterConfiguration * configuration() { return new KisOilPaintFilterConfiguration( 1, 30); };
+private:
+ void OilPaint(KisPaintDeviceSP src, KisPaintDeviceSP dst, int x, int y, int w, int h, int BrushSize, int Smoothness);
+ uint MostFrequentColor(KisPaintDeviceSP, const TQRect& bounds, int X, int Y, int Radius, int Intensity);
+ // Function to calcule the color intensity and return the luminance (Y)
+ // component of YIQ color model.
+ inline uint GetIntensity(uint Red, uint Green, uint Blue) { return ((uint)(Red * 0.3 + Green * 0.59 + Blue * 0.11)); }
+};
+
+#endif
diff --git a/chalk/plugins/filters/oilpaintfilter/kis_oilpaint_filter_plugin.cc b/chalk/plugins/filters/oilpaintfilter/kis_oilpaint_filter_plugin.cc
new file mode 100644
index 00000000..7167b04d
--- /dev/null
+++ b/chalk/plugins/filters/oilpaintfilter/kis_oilpaint_filter_plugin.cc
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <kgenericfactory.h>
+#include "kis_oilpaint_filter_plugin.h"
+#include "kis_oilpaint_filter.h"
+#include "kis_global.h"
+
+typedef KGenericFactory<KisOilPaintFilterPlugin> KisOilPaintFilterPluginFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkoilpaintfilter, KisOilPaintFilterPluginFactory( "chalk" ) )
+
+KisOilPaintFilterPlugin::KisOilPaintFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &) : KParts::Plugin(tqparent, name)
+{
+ setInstance(KisOilPaintFilterPluginFactory::instance());
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisOilPaintFilter());
+ }
+
+}
+
+KisOilPaintFilterPlugin::~KisOilPaintFilterPlugin()
+{
+}
+
diff --git a/chalk/plugins/filters/oilpaintfilter/kis_oilpaint_filter_plugin.h b/chalk/plugins/filters/oilpaintfilter/kis_oilpaint_filter_plugin.h
new file mode 100644
index 00000000..1f780918
--- /dev/null
+++ b/chalk/plugins/filters/oilpaintfilter/kis_oilpaint_filter_plugin.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_OILPAINT_FILTER_PLUGIN_H_
+#define _KIS_OILPAINT_FILTER_PLUGIN_H_
+
+#include <kparts/plugin.h>
+
+class KisOilPaintFilterPlugin : public KParts::Plugin
+{
+public:
+ KisOilPaintFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~KisOilPaintFilterPlugin();
+};
+
+#endif
diff --git a/chalk/plugins/filters/pixelizefilter/Makefile.am b/chalk/plugins/filters/pixelizefilter/Makefile.am
new file mode 100644
index 00000000..9a8771a6
--- /dev/null
+++ b/chalk/plugins/filters/pixelizefilter/Makefile.am
@@ -0,0 +1,24 @@
+kde_services_DATA = chalkpixelizefilter.desktop
+
+INCLUDES = \
+ -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../ui \
+ -I$(srcdir)/../../../../lib/kofficecore \
+ -I$(srcdir)/../../../../lib/kofficeui \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalkpixelizefilter.la
+
+chalkpixelizefilter_la_SOURCES = kis_pixelize_filter_plugin.cc \
+ kis_pixelize_filter.cc
+
+noinst_HEADERS = kis_pixelize_filter_plugin.h \
+ kis_pixelize_filter.h
+
+chalkpixelizefilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkpixelizefilter_la_LIBADD = ../../../libchalkcommon.la
+
+chalkpixelizefilter_la_METASOURCES = AUTO
diff --git a/chalk/plugins/filters/pixelizefilter/chalkpixelizefilter.desktop b/chalk/plugins/filters/pixelizefilter/chalkpixelizefilter.desktop
new file mode 100644
index 00000000..a7a2e88f
--- /dev/null
+++ b/chalk/plugins/filters/pixelizefilter/chalkpixelizefilter.desktop
@@ -0,0 +1,83 @@
+[Desktop Entry]
+Name=Pixelize Filter
+Name[bg]=Филтър Pixelize
+Name[ca]=Filtre de pixelació
+Name[cy]=Hidlen bicseleiddio
+Name[da]=Billedpunktfilter
+Name[de]=Pixelize-Filter
+Name[el]=Φίλτρο δημιουργίας εικονοστοιχείων
+Name[en_GB]=Pixelise Filter
+Name[eo]=Rastrumiga filtrilo
+Name[es]=Filtro de pixelación
+Name[et]=Mosaiigi filter
+Name[fa]=پالایۀ Pixelize
+Name[fr]=Filtre pixélisation
+Name[fy]=Byldpuntfilter
+Name[ga]=Scagaire Picteilínithe
+Name[gl]=Filtro de Pixelización
+Name[he]=מסנן מפוקסל
+Name[hu]=Pixelesítő szűrő
+Name[is]=Punktasía
+Name[it]=Filtro di pixellizzazione
+Name[ja]=ピクセル化フィルタ
+Name[km]=តម្រង​ធ្វើ​ភីកសែល
+Name[nb]=Pikseleringsfilter
+Name[nds]=Pixelfilter
+Name[ne]=फिल्टर पिक्सेलाइज गर्नुहोस्
+Name[nl]=Pixelfilter
+Name[pl]=Filtr pikselizacji
+Name[pt]=Filtro de Pixelização
+Name[pt_BR]=Filtro de Pixelização
+Name[ru]=Пикселизация
+Name[sk]=Filter pixelizovať
+Name[sl]=Filter Spremeni v pike
+Name[sr]=Филтер за пикселизацију
+Name[sr@Latn]=Filter za pikselizaciju
+Name[sv]=Bildpunktsfilter
+Name[uk]=Фільтр пікселювання
+Name[uz]=Piksellashtirish filteri
+Name[uz@cyrillic]=Пикселлаштириш филтери
+Name[zh_TW]=像素化過濾器
+Comment=Pixelize filter
+Comment[bg]=Филтър Pixelize
+Comment[ca]=Filtre de pixelació
+Comment[cy]=Hidlen bicseleiddio
+Comment[da]=Billedpunktfilter
+Comment[de]=Pixelize-Filter
+Comment[el]=Φίλτρο δημιουργίας εικονοστοιχείων
+Comment[en_GB]=Pixelise filter
+Comment[eo]=Rastrumiga filtrilo
+Comment[es]=Filtro de pixelación
+Comment[et]=Mosaiigi filter
+Comment[fa]=پالایۀ Pixelize
+Comment[fr]=Filtre pixélisation
+Comment[fy]=Byldpuntfilter
+Comment[ga]=Scagaire picteilínithe
+Comment[gl]=Filtro de pixelización
+Comment[he]=מסנן מפוקסל
+Comment[hu]=Pixelesítő szűrő
+Comment[is]=Punktasía
+Comment[it]=Filtro di pixellizzazione
+Comment[ja]=ピクセル化フィルタ
+Comment[km]=តម្រង​ធ្វើ​ភីកសែល
+Comment[nb]=Pikseleringsfilter
+Comment[nds]=Pixelfilter
+Comment[ne]=फिल्टर पिक्सेलाइज गर्नुहोस्
+Comment[nl]=Pixelfilter
+Comment[pl]=Filtr pikselizacji
+Comment[pt]=Filtro de pixelização
+Comment[pt_BR]=Filtro de pixelização
+Comment[ru]=Пикселизация
+Comment[sk]=Filter pixelizovať
+Comment[sl]=Filter Spremeni v pike
+Comment[sr]=Филтер за пикселизацију
+Comment[sr@Latn]=Filter za pikselizaciju
+Comment[sv]=Bildpunktsfilter
+Comment[uk]=Фільтр пікселювання
+Comment[uz]=Piksellashtirish filteri
+Comment[uz@cyrillic]=Пикселлаштириш филтери
+Comment[zh_TW]=像素化過濾器
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkpixelizefilter
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/pixelizefilter/kis_pixelize_filter.cc b/chalk/plugins/filters/pixelizefilter/kis_pixelize_filter.cc
new file mode 100644
index 00000000..267b159b
--- /dev/null
+++ b/chalk/plugins/filters/pixelizefilter/kis_pixelize_filter.cc
@@ -0,0 +1,188 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * ported from Gimp, Copyright (C) 1997 Eiichi Takamori <taka@ma1.seikyou.ne.jp>
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+#include <tqspinbox.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <knuminput.h>
+
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_filter_registry.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_progress_display_interface.h>
+
+#include "kis_multi_integer_filter_widget.h"
+#include "kis_pixelize_filter.h"
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+KisPixelizeFilter::KisPixelizeFilter() : KisFilter(id(), "artistic", i18n("&Pixelize..."))
+{
+}
+
+void KisPixelizeFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* configuration, const TQRect& rect)
+{
+ Q_ASSERT( src );
+ Q_ASSERT( dst );
+ Q_ASSERT( configuration );
+ Q_ASSERT( rect.isValid() );
+
+ TQ_INT32 x = rect.x(), y = rect.y();
+ TQ_INT32 width = rect.width();
+ TQ_INT32 height = rect.height();
+
+ //read the filter configuration values from the KisFilterConfiguration object
+ TQ_UINT32 pixelWidth = ((KisPixelizeFilterConfiguration*)configuration)->pixelWidth();
+ TQ_UINT32 pixelHeight = ((KisPixelizeFilterConfiguration*)configuration)->pixelHeight();
+
+ pixelize(src, dst, x, y, width, height, pixelWidth, pixelHeight);
+}
+
+void KisPixelizeFilter::pixelize(KisPaintDeviceSP src, KisPaintDeviceSP dst, int startx, int starty, int width, int height, int pixelWidth, int pixelHeight)
+{
+ Q_ASSERT(src);
+ Q_ASSERT(dst);
+
+ if (!src) return;
+ if (!dst) return;
+
+ TQ_INT32 pixelSize = src->pixelSize();
+ TQMemArray<TQ_INT32> average( pixelSize );
+
+ TQ_INT32 count;
+
+ //calculate the total number of pixels
+ TQ_INT32 numX=0;
+ TQ_INT32 numY=0;
+
+ for (TQ_INT32 x = startx; x < startx + width; x += pixelWidth - (x % pixelWidth))
+ {
+ numX++;
+ }
+ for (TQ_INT32 y = starty; y < starty + height; y += pixelHeight - (y % pixelHeight))
+ {
+ numY++;
+ }
+
+ setProgressTotalSteps( numX * numY );
+ setProgressStage(i18n("Applying pixelize filter..."),0);
+
+ TQ_INT32 numberOfPixelsProcessed = 0;
+
+ for (TQ_INT32 y = starty; y < starty + height; y += pixelHeight - (y % pixelHeight))
+ {
+ TQ_INT32 h = pixelHeight - (y % pixelHeight);
+ h = MIN(h, starty + height - y);
+
+ for (TQ_INT32 x = startx; x < startx + width; x += pixelWidth - (x % pixelWidth))
+ {
+ TQ_INT32 w = pixelWidth - (x % pixelWidth);
+ w = MIN(w, startx + width - x);
+
+ for (TQ_INT32 i = 0; i < pixelSize; i++)
+ {
+ average[i] = 0;
+ }
+ count = 0;
+
+ //read
+ KisRectIteratorPixel srcIt = src->createRectIterator(x, y, w, h, false);
+ while( ! srcIt.isDone() ) {
+ if(srcIt.isSelected())
+ {
+ for (TQ_INT32 i = 0; i < pixelSize; i++)
+ {
+ average[i] += srcIt.oldRawData()[i];
+ }
+ count++;
+ }
+ ++srcIt;
+ }
+
+ //average
+ if (count > 0)
+ {
+ for (TQ_INT32 i = 0; i < pixelSize; i++)
+ average[i] /= count;
+ }
+ //write
+ srcIt = src->createRectIterator(x, y, w, h, false);
+ KisRectIteratorPixel dstIt = dst->createRectIterator(x, y, w, h, true );
+ while( ! srcIt.isDone() )
+ {
+ if(srcIt.isSelected())
+ {
+ for( int i = 0; i < pixelSize; i++)
+ {
+ dstIt.rawData()[i] = average[i];
+ }
+ }
+ ++srcIt;
+ ++dstIt;
+ }
+ numberOfPixelsProcessed++;
+ setProgress(numberOfPixelsProcessed);
+ }
+ }
+
+ setProgressDone();
+}
+
+KisFilterConfigWidget * KisPixelizeFilter::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP /*dev*/)
+{
+ vKisIntegerWidgetParam param;
+ param.push_back( KisIntegerWidgetParam( 2, 40, 10, i18n("Pixel width"), "pixelWidth" ) );
+ param.push_back( KisIntegerWidgetParam( 2, 40, 10, i18n("Pixel height"), "pixelHeight" ) );
+ return new KisMultiIntegerFilterWidget(tqparent, id().id().ascii(), id().id().ascii(), param );
+}
+
+KisFilterConfiguration* KisPixelizeFilter::configuration(TQWidget* nwidget)
+{
+ KisMultiIntegerFilterWidget* widget = (KisMultiIntegerFilterWidget*) nwidget;
+ if( widget == 0 )
+ {
+ return new KisPixelizeFilterConfiguration( 10, 10);
+ } else {
+ return new KisPixelizeFilterConfiguration( widget->valueAt( 0 ), widget->valueAt( 1 ) );
+ }
+}
+
+KisFilterConfiguration * KisPixelizeFilter::configuration()
+{
+ return new KisPixelizeFilterConfiguration(10, 10);
+}
diff --git a/chalk/plugins/filters/pixelizefilter/kis_pixelize_filter.h b/chalk/plugins/filters/pixelizefilter/kis_pixelize_filter.h
new file mode 100644
index 00000000..c7d8bb31
--- /dev/null
+++ b/chalk/plugins/filters/pixelizefilter/kis_pixelize_filter.h
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_PIXELIZE_FILTER_H_
+#define _KIS_PIXELIZE_FILTER_H_
+
+#include "kis_filter.h"
+#include "kis_filter_config_widget.h"
+
+class KisPixelizeFilterConfiguration : public KisFilterConfiguration
+{
+public:
+ KisPixelizeFilterConfiguration(TQ_UINT32 pixelWidth, TQ_UINT32 pixelHeight)
+ : KisFilterConfiguration( "pixelize", 1 )
+ {
+ setProperty("pixelWidth", pixelWidth);
+ setProperty("pixelHeight", pixelHeight);
+ };
+public:
+ inline TQ_UINT32 pixelWidth() { return getInt("pixelWidth"); };
+ inline TQ_UINT32 pixelHeight() {return getInt("pixelHeight"); };
+};
+
+class KisPixelizeFilter : public KisFilter
+{
+public:
+ KisPixelizeFilter();
+public:
+ virtual void process(KisPaintDeviceSP,KisPaintDeviceSP, KisFilterConfiguration* , const TQRect&);
+ static inline KisID id() { return KisID("pixelize", i18n("Pixelize")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsAdjustmentLayers() { return false; }
+ virtual std::list<KisFilterConfiguration*> listOfExamplesConfiguration(KisPaintDeviceSP )
+ { std::list<KisFilterConfiguration*> list; list.insert(list.begin(), new KisPixelizeFilterConfiguration(10,10)); return list; }
+public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration* configuration(TQWidget*);
+ virtual KisFilterConfiguration * configuration();
+private:
+ void pixelize(KisPaintDeviceSP src, KisPaintDeviceSP dst, int x, int y, int w, int h, int pixelWidth, int pixelHeight);
+};
+
+#endif
diff --git a/chalk/plugins/filters/pixelizefilter/kis_pixelize_filter_plugin.cc b/chalk/plugins/filters/pixelizefilter/kis_pixelize_filter_plugin.cc
new file mode 100644
index 00000000..93309146
--- /dev/null
+++ b/chalk/plugins/filters/pixelizefilter/kis_pixelize_filter_plugin.cc
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <kgenericfactory.h>
+#include "kis_pixelize_filter_plugin.h"
+#include "kis_pixelize_filter.h"
+#include "kis_global.h"
+
+typedef KGenericFactory<KisPixelizeFilterPlugin> KisPixelizeFilterPluginFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkpixelizefilter, KisPixelizeFilterPluginFactory( "chalk" ) )
+
+KisPixelizeFilterPlugin::KisPixelizeFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(KisPixelizeFilterPluginFactory::instance());
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisPixelizeFilter());
+ }
+}
+
+KisPixelizeFilterPlugin::~KisPixelizeFilterPlugin()
+{
+}
+
diff --git a/chalk/plugins/filters/pixelizefilter/kis_pixelize_filter_plugin.h b/chalk/plugins/filters/pixelizefilter/kis_pixelize_filter_plugin.h
new file mode 100644
index 00000000..25d8a62f
--- /dev/null
+++ b/chalk/plugins/filters/pixelizefilter/kis_pixelize_filter_plugin.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_PIXELIZE_FILTER_PLUGIN_H_
+#define _KIS_PIXELIZE_FILTER_PLUGIN_H_
+
+#include <kparts/plugin.h>
+
+class KisPixelizeFilterPlugin : public KParts::Plugin
+{
+public:
+ KisPixelizeFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~KisPixelizeFilterPlugin();
+};
+
+#endif
diff --git a/chalk/plugins/filters/raindropsfilter/Makefile.am b/chalk/plugins/filters/raindropsfilter/Makefile.am
new file mode 100644
index 00000000..d4e5632d
--- /dev/null
+++ b/chalk/plugins/filters/raindropsfilter/Makefile.am
@@ -0,0 +1,24 @@
+kde_services_DATA = chalkraindropsfilter.desktop
+
+INCLUDES = \
+ -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../chalkcolor/color_strategy \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalkraindropsfilter.la
+
+chalkraindropsfilter_la_SOURCES = kis_raindrops_filter_plugin.cc \
+ kis_raindrops_filter.cc
+
+noinst_HEADERS = kis_raindrops_filter_plugin.h \
+ kis_raindrops_filter.h
+
+chalkraindropsfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkraindropsfilter_la_LIBADD = ../../../libchalkcommon.la
+
+chalkraindropsfilter_la_METASOURCES = AUTO
diff --git a/chalk/plugins/filters/raindropsfilter/chalkraindropsfilter.desktop b/chalk/plugins/filters/raindropsfilter/chalkraindropsfilter.desktop
new file mode 100644
index 00000000..13b90349
--- /dev/null
+++ b/chalk/plugins/filters/raindropsfilter/chalkraindropsfilter.desktop
@@ -0,0 +1,81 @@
+[Desktop Entry]
+Name=Raindrops Filter
+Name[bg]=Филтър за дъждовни капки
+Name[ca]=Filtre de gotes de pluja
+Name[cy]=Hidlen Ddiferion Glaw
+Name[da]=Regndråbefilter
+Name[de]=Regentropfen-Filter
+Name[el]=Φίλτρο σταγόνων βροχής
+Name[eo]=Pluvguta filtrilo
+Name[es]=Filtro de gotas de lluvia
+Name[et]=Vihmapiiskade filter
+Name[fa]=پالایۀ قطرات باران
+Name[fi]=Vesipisarasuodin
+Name[fr]=Filtre gouttes de pluie
+Name[fy]=Reindruppenfilter
+Name[gl]=Filtro de Pingas de Chuvia
+Name[hu]=Esőcsepp szűrő
+Name[is]=Regndropasía
+Name[it]=Filtro a gocce di pioggia
+Name[ja]=雨滴フィルタ
+Name[km]=តម្រង​តំណក់ទឹកភ្លៀង
+Name[nb]=Regndråpefilter
+Name[nds]=Regendrüppen-Filter
+Name[ne]=वर्षाथोपा फिल्टर
+Name[nl]=Regendruppelfilter
+Name[pl]=Filtr symulujący krople deszczu
+Name[pt]=Filtro de Pingos de Chuva
+Name[pt_BR]=Filtro de Pingos de Chuva
+Name[ru]=Дождевые капли
+Name[se]=Arvečalbmesilli
+Name[sk]=Filter dažďové kvapky
+Name[sl]=Filter Dežne kapljice
+Name[sr]=Филтер за кишне капи
+Name[sr@Latn]=Filter za kišne kapi
+Name[sv]=Regndroppsfilter
+Name[uk]=Фільтр дощових крапель
+Name[uz]=Yomgʻir tomchilari filteri
+Name[uz@cyrillic]=Ёмғир томчилари филтери
+Name[zh_TW]=雨滴過濾器
+Comment=Raindrops filter
+Comment[bg]=Филтър за дъждовни капки
+Comment[ca]=Filtre de gotes de pluja
+Comment[cy]=Hidlen ddiferion glaw
+Comment[da]=Regndråbefilter
+Comment[de]=Regentropfen-Filter
+Comment[el]=Φίλτρο σταγόνων βροχής
+Comment[eo]=Pluvguta filtrilo
+Comment[es]=Filtro de gotas de lluvia
+Comment[et]=Vihmapiiskade filter
+Comment[fa]=پالایۀ قطرات باران
+Comment[fi]=Vesipisarasuodin
+Comment[fr]=Filtre gouttes de pluie
+Comment[fy]=Reindruppenfilter
+Comment[gl]=Filtro de pingas de chuvia
+Comment[hu]=Esőcsepp szűrő
+Comment[is]=Regndropasía
+Comment[it]=Filtro a gocce di pioggia
+Comment[ja]=雨滴フィルタ
+Comment[km]=តម្រង​តំណក់​ទឹកភ្លៀង
+Comment[nb]=Regndråpefilter
+Comment[nds]=Regendrüppen-Filter
+Comment[ne]=वर्षाथोपा फिल्टर
+Comment[nl]=Regendruppelfilter
+Comment[pl]=Filtr symulujący krople deszczu
+Comment[pt]=Filtro de pingos de chuva
+Comment[pt_BR]=Filtro de pingos de chuva
+Comment[ru]=Дождевые капли
+Comment[se]=Arvečalbmesilli
+Comment[sk]=Filter dažďové kvapky
+Comment[sl]=Filter Dežne kapljice
+Comment[sr]=Филтер за кишне капи
+Comment[sr@Latn]=Filter za kišne kapi
+Comment[sv]=Regndroppsfilter
+Comment[uk]=Фільтр дощових крапель
+Comment[uz]=Yomgʻir tomchilari filteri
+Comment[uz@cyrillic]=Ёмғир томчилари филтери
+Comment[zh_TW]=雨滴過濾器
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkraindropsfilter
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/raindropsfilter/kis_raindrops_filter.cc b/chalk/plugins/filters/raindropsfilter/kis_raindrops_filter.cc
new file mode 100644
index 00000000..c208bb52
--- /dev/null
+++ b/chalk/plugins/filters/raindropsfilter/kis_raindrops_filter.cc
@@ -0,0 +1,439 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * ported from digikam, Copyright 2004 by Gilles Caulier,
+ * Original RainDrops algorithm copyrighted 2004 by
+ * Pieter Z. Voloshyn <pieter_voloshyn at ame.com.br>.
+ *
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+#include <tqspinbox.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <knuminput.h>
+
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_random_accessor.h>
+#include <kis_layer.h>
+#include <kis_filter_registry.h>
+#include <kis_filter.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_view.h>
+#include <kis_progress_display_interface.h>
+
+#include "kis_multi_integer_filter_widget.h"
+#include "kis_raindrops_filter.h"
+
+KisRainDropsFilter::KisRainDropsFilter() : KisFilter(id(), "artistic", i18n("&Raindrops..."))
+{
+}
+
+void KisRainDropsFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* configuration, const TQRect& rect)
+{
+
+ Q_UNUSED(dst);
+
+ //read the filter configuration values from the KisFilterConfiguration object
+ TQ_UINT32 dropSize = ((KisRainDropsFilterConfiguration*)configuration)->dropSize();
+ TQ_UINT32 number = ((KisRainDropsFilterConfiguration*)configuration)->number();
+ TQ_UINT32 fishEyes = ((KisRainDropsFilterConfiguration*)configuration)->fishEyes();
+
+
+ rainDrops(src, dst, rect, dropSize, number, fishEyes);
+}
+
+// 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
+ * Amount => Maximum number of raindrops
+ * Coeff => FishEye coefficient
+ *
+ * Theory => This functions does several math's functions and the engine
+ * is simple to undestand, 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::rainDrops(KisPaintDeviceSP src, KisPaintDeviceSP dst, const TQRect& rect, int DropSize, int Amount, int Coeff)
+{
+ setProgressTotalSteps(Amount);
+ setProgressStage(i18n("Applying oilpaint filter..."),0);
+
+ if (Coeff <= 0) Coeff = 1;
+
+ if (Coeff > 100) Coeff = 100;
+
+ int Width = rect.width();
+ int Height = rect.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 NewCoeff = (double)Coeff * 0.01; // FishEye Coefficients
+ double s;
+ double R, G, B;
+
+ bool FindAnother = false; // To search for good coordinates
+
+ KisColorSpace * cs = src->colorSpace();
+
+ TQDateTime dt = TQDateTime::tqcurrentDateTime();
+ TQDateTime Y2000( TQDate(2000, 1, 1), TQTime(0, 0, 0) );
+
+ srand ((uint) dt.secsTo(Y2000));
+
+ // Init booleen Matrix.
+
+ for (i = 0 ; !cancelRequested() && (i < Width) ; ++i)
+ {
+ for (j = 0 ; !cancelRequested() && (j < Height) ; ++j)
+ {
+ BoolMatrix[i][j] = false;
+ }
+ }
+ KisRandomAccessorPixel oldIt = src->createRandomAccessor(0,0,false);
+ KisRandomAccessorPixel dstIt = dst->createRandomAccessor(0,0,true);
+
+ for (int NumBlurs = 0 ; !cancelRequested() && (NumBlurs <= Amount) ; ++NumBlurs)
+ {
+ NewSize = (int)(rand() * ((double)(DropSize - 5) / RAND_MAX) + 5);
+ halfSize = NewSize / 2;
+ Radius = halfSize;
+ s = Radius / log (NewCoeff * Radius + 1);
+
+ Counter = 0;
+
+ do
+ {
+ FindAnother = false;
+ y = (int)(rand() * ((double)( Width - 1) / RAND_MAX));
+ x = (int)(rand() * ((double)(Height - 1) / RAND_MAX));
+
+ if (BoolMatrix[y][x])
+ FindAnother = true;
+ else
+ for (i = x - halfSize ; !cancelRequested() && (i <= x + halfSize) ; i++)
+ for (j = y - halfSize ; !cancelRequested() && (j <= y + halfSize) ; j++)
+ if ((i >= 0) && (i < Height) && (j >= 0) && (j < Width))
+ if (BoolMatrix[j][i])
+ FindAnother = true;
+
+ Counter++;
+ }
+ while (!cancelRequested() && (FindAnother && (Counter < 10000)) );
+
+ if (Counter >= 10000)
+ {
+ NumBlurs = Amount;
+ break;
+ }
+
+ for (i = -1 * halfSize ; !cancelRequested() && (i < NewSize - halfSize) ; i++)
+ {
+ for (j = -1 * halfSize ; !cancelRequested() && (j < NewSize - halfSize) ; j++)
+ {
+ r = sqrt (i * i + j * j);
+ a = atan2 (i, j);
+
+ if (r <= Radius)
+ {
+ OldRadius = r;
+ r = (exp (r / s) - 1) / NewCoeff;
+
+ 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;
+
+ TQColor originalColor;
+ oldIt.moveTo(rect.x() + l, rect.y() + k);
+ cs->toTQColor(oldIt.oldRawData(), &originalColor);
+
+ int newRed = CLAMP(originalColor.red() + Bright, 0, TQ_UINT8_MAX);
+ int newGreen = CLAMP(originalColor.green() + Bright, 0, TQ_UINT8_MAX);
+ int newBlue = CLAMP(originalColor.blue() + Bright, 0, TQ_UINT8_MAX);
+
+ TQColor newColor;
+ newColor.setRgb(newRed, newGreen, newBlue);
+
+ dstIt.moveTo(rect.x() + n, rect.y() + m);
+ cs->fromTQColor(newColor, dstIt.rawData());
+ }
+ }
+ }
+ }
+ }
+
+ BlurRadius = NewSize / 25 + 1;
+
+ for (i = -1 * halfSize - BlurRadius ; !cancelRequested() && (i < NewSize - halfSize + BlurRadius) ; i++)
+ {
+ for (j = -1 * halfSize - BlurRadius ; !cancelRequested() && (j < NewSize - halfSize + BlurRadius) ; j++)
+ {
+ r = sqrt (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))
+ {
+ TQColor color;
+ dstIt.moveTo(rect.x() + n, rect.y() + m);
+
+ cs->toTQColor(dstIt.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))
+ {
+ TQColor color;
+
+ color.setRgb((int)(R / BlurPixels), (int)(G / BlurPixels), (int)(B / BlurPixels));
+ dstIt.moveTo(rect.x() + n, rect.y() + m);
+
+ cs->fromTQColor(color, dstIt.rawData());
+ }
+ }
+ }
+ }
+
+ setProgress(NumBlurs);
+ }
+
+/* KisRectIteratorPixel srcIt2 = src->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), false);
+ KisRectIteratorPixel dstIt2 = src->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true);
+
+ while (!srcIt2.isDone()) {
+
+ if (!srcIt2.isSelected()) {
+ memcpy(dstIt2.rawData(), srcIt2.oldRawData(), src->pixelSize());
+ }
+ ++srcIt2;
+ }
+*/
+ FreeBoolArray (BoolMatrix, Width);
+
+ setProgressDone();
+}
+
+// This method have been ported from Pieter Z. Voloshyn algorithm code.
+
+/* Function to free a dinamic boolean array
+ *
+ * lpbArray => Dynamic boolean array
+ * Columns => The array bidimension value
+ *
+ * Theory => An easy to undestand 'for' statement
+ */
+void KisRainDropsFilter::FreeBoolArray (bool** lpbArray, uint Columns)
+{
+ for (uint i = 0; i < Columns; ++i)
+ free (lpbArray[i]);
+
+ free (lpbArray);
+}
+
+/* Function to create a bidimentional dinamic boolean array
+ *
+ * Columns => Number of columns
+ * Rows => Number of rows
+ *
+ * Theory => Using 'for' statement, we can alloc multiple dinamic arrays
+ * To create more dimentions, just add some 'for's, ok?
+ */
+bool** KisRainDropsFilter::CreateBoolArray (uint Columns, uint Rows)
+{
+ bool** lpbArray = NULL;
+ lpbArray = (bool**) malloc (Columns * sizeof (bool*));
+
+ if (lpbArray == NULL)
+ return (NULL);
+
+ for (uint i = 0; i < Columns; ++i)
+ {
+ lpbArray[i] = (bool*) malloc (Rows * sizeof (bool));
+ if (lpbArray[i] == NULL)
+ {
+ FreeBoolArray (lpbArray, Columns);
+ return (NULL);
+ }
+ }
+
+ 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 analized
+ *
+ * Theory => A color is represented in RGB value (e.g. 0xFFFFFF is
+ * white color). But R, G and B values has 256 values to be used
+ * so, this function analize the value and limits to this range
+ */
+
+uchar KisRainDropsFilter::LimitValues (int ColorValue)
+{
+ if (ColorValue > 255) // MAX = 255
+ ColorValue = 255;
+ if (ColorValue < 0) // MIN = 0
+ ColorValue = 0;
+ return ((uchar) ColorValue);
+}
+
+KisFilterConfigWidget * KisRainDropsFilter::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP)
+{
+ 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" ) );
+ return new KisMultiIntegerFilterWidget(tqparent, id().id().ascii(), id().id().ascii(), param );
+}
+
+KisFilterConfiguration* KisRainDropsFilter::configuration(TQWidget* nwidget)
+{
+ KisMultiIntegerFilterWidget* widget = (KisMultiIntegerFilterWidget*) nwidget;
+ if( widget == 0 )
+ {
+ return new KisRainDropsFilterConfiguration( 30, 80, 20);
+ } else {
+ return new KisRainDropsFilterConfiguration( widget->valueAt( 0 ), widget->valueAt( 1 ), widget->valueAt( 2 ) );
+ }
+}
diff --git a/chalk/plugins/filters/raindropsfilter/kis_raindrops_filter.h b/chalk/plugins/filters/raindropsfilter/kis_raindrops_filter.h
new file mode 100644
index 00000000..0d797d7d
--- /dev/null
+++ b/chalk/plugins/filters/raindropsfilter/kis_raindrops_filter.h
@@ -0,0 +1,67 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_RAINDROPS_FILTER_H_
+#define _KIS_RAINDROPS_FILTER_H_
+
+#include "kis_filter.h"
+#include "kis_filter_config_widget.h"
+
+class KisRainDropsFilterConfiguration : public KisFilterConfiguration
+{
+public:
+ KisRainDropsFilterConfiguration(TQ_UINT32 dropSize, TQ_UINT32 number, TQ_UINT32 fishEyes)
+ : KisFilterConfiguration( "raindrops", 1 )
+ {
+ setProperty("dropsize", dropSize);
+ setProperty("number", number);
+ setProperty("fishEyes", fishEyes);
+ };
+public:
+ inline TQ_UINT32 dropSize() { return getInt("dropsize"); };
+ inline TQ_UINT32 number() {return getInt("number"); };
+ inline TQ_UINT32 fishEyes() {return getInt("fishEyes"); };
+
+};
+
+class KisRainDropsFilter : public KisFilter
+{
+public:
+ KisRainDropsFilter();
+public:
+ virtual void process(KisPaintDeviceSP,KisPaintDeviceSP, KisFilterConfiguration* , const TQRect&);
+ static inline KisID id() { return KisID("raindrops", i18n("Raindrops")); };
+ virtual bool supportsPainting() { return false; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsAdjustmentLayers() { return false; }
+ virtual std::list<KisFilterConfiguration*> listOfExamplesConfiguration(KisPaintDeviceSP )
+ { std::list<KisFilterConfiguration*> list; list.insert(list.begin(), new KisRainDropsFilterConfiguration( 30, 80, 20)); return list; }
+
+public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration* configuration(TQWidget*);
+private:
+ void rainDrops(KisPaintDeviceSP src, KisPaintDeviceSP dst, const TQRect& rect, int DropSize, int Amount, int Coeff);
+ bool** CreateBoolArray (uint Columns, uint Rows);
+ void FreeBoolArray (bool** lpbArray, uint Columns);
+ uchar LimitValues (int ColorValue);
+};
+
+#endif
diff --git a/chalk/plugins/filters/raindropsfilter/kis_raindrops_filter_plugin.cc b/chalk/plugins/filters/raindropsfilter/kis_raindrops_filter_plugin.cc
new file mode 100644
index 00000000..593311d5
--- /dev/null
+++ b/chalk/plugins/filters/raindropsfilter/kis_raindrops_filter_plugin.cc
@@ -0,0 +1,44 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <kgenericfactory.h>
+
+#include <kis_filter_registry.h>
+
+#include "kis_raindrops_filter_plugin.h"
+#include "kis_raindrops_filter.h"
+
+
+typedef KGenericFactory<KisRainDropsFilterPlugin> KisRainDropsFilterPluginFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkraindropsfilter, KisRainDropsFilterPluginFactory( "chalk" ) )
+
+KisRainDropsFilterPlugin::KisRainDropsFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &) : KParts::Plugin(tqparent, name)
+{
+ setInstance(KisRainDropsFilterPluginFactory::instance());
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisRainDropsFilter());
+ }
+}
+
+KisRainDropsFilterPlugin::~KisRainDropsFilterPlugin()
+{
+}
diff --git a/chalk/plugins/filters/raindropsfilter/kis_raindrops_filter_plugin.h b/chalk/plugins/filters/raindropsfilter/kis_raindrops_filter_plugin.h
new file mode 100644
index 00000000..ca4e05d3
--- /dev/null
+++ b/chalk/plugins/filters/raindropsfilter/kis_raindrops_filter_plugin.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_RAINDROPS_FILTER_PLUGIN_H_
+#define _KIS_RAINDROPS_FILTER_PLUGIN_H_
+
+#include <kparts/plugin.h>
+
+class KisRainDropsFilterPlugin : public KParts::Plugin
+{
+public:
+ KisRainDropsFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~KisRainDropsFilterPlugin();
+};
+
+#endif
diff --git a/chalk/plugins/filters/randompickfilter/Makefile.am b/chalk/plugins/filters/randompickfilter/Makefile.am
new file mode 100644
index 00000000..0757704c
--- /dev/null
+++ b/chalk/plugins/filters/randompickfilter/Makefile.am
@@ -0,0 +1,23 @@
+chalkrcdir = $(kde_datadir)/chalk/chalkplugins
+
+kde_services_DATA = chalkrandompickfilter.desktop
+
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkrandompickfilter_la_SOURCES = randompickfilter.cc wdgrandompickoptions.ui \
+ kis_wdg_random_pick.cpp
+
+kde_module_LTLIBRARIES = chalkrandompickfilter.la
+noinst_HEADERS = randompickfilter.h
+
+chalkrandompickfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkrandompickfilter_la_LIBADD = ../../../libchalkcommon.la
+
+chalkrandompickfilter_la_METASOURCES = AUTO
diff --git a/chalk/plugins/filters/randompickfilter/chalkrandompickfilter.desktop b/chalk/plugins/filters/randompickfilter/chalkrandompickfilter.desktop
new file mode 100644
index 00000000..b7bb807a
--- /dev/null
+++ b/chalk/plugins/filters/randompickfilter/chalkrandompickfilter.desktop
@@ -0,0 +1,65 @@
+[Desktop Entry]
+Comment=Random pick to an image
+Comment[bg]=Случайно избиране на изображение
+Comment[ca]=Agafa aleatòriament una imatge
+Comment[da]=Udfør tilfældigt valg i et billede
+Comment[de]=Zufallsauswahl zu einem Bild
+Comment[el]=Τυχαία ανύψωση σε μια εικόνα
+Comment[es]=Elección aleatoria de una imagen
+Comment[et]=Juhuslik valik pildil
+Comment[fa]=برداشتن تصادفی برای یک تصویر
+Comment[fy]=Samar in kar foar in ôfbylding
+Comment[gl]=Toma aleatoria para unha imaxe
+Comment[hu]=Véletlenszerű képszűrő
+Comment[it]=Scegli casualmente un'immagine
+Comment[km]=រើស​ដោយ​ចៃដន្យ​ទៅ​រូបភាព
+Comment[nb]=Tilfeldig plukk til et bilde
+Comment[nds]=Tofällig Bildutwahl
+Comment[ne]=एउटा छविमा अनियन्त्रित तरिकाले टिप्नुहोस्
+Comment[nl]=Willekeurige keuze voor een afbeelding
+Comment[pl]=Losowy wybór fragmentu obrazka
+Comment[pt]=Extrai aleatoriamente para uma imagem
+Comment[pt_BR]=Extrai aleatoriamente para uma imagem
+Comment[ru]=Меняет местами некоторые точки в случайном порядке
+Comment[sk]=Random pick do obrázku
+Comment[sl]=Uzberi sliko naključno
+Comment[sr]=Насумичан избор са слике
+Comment[sr@Latn]=Nasumičan izbor sa slike
+Comment[sv]=Utför slumpmässigt urval i en bild
+Comment[uk]=Міняє місцями деякі точки зображення
+Comment[zh_TW]=隨機挑選圖片
+Icon=
+Name=Random pick Filter
+Name[bg]=Филтър за случайно избиране
+Name[ca]=Aplica un filtre aleatòriament
+Name[da]=Tilfældigt udvalgsfilter
+Name[de]=Zufallsauswahlfilter
+Name[el]=Φίλτρο τυχαίας ανύψωσης
+Name[es]=Filtro de elección aleatoria
+Name[et]=Juhusliku valiku filter
+Name[fa]=پالایۀ برداشتن تصادفی
+Name[fy]=Samar-kar-filter
+Name[gl]=Filtro de toma aleatoria
+Name[hu]=Véletlenszerű szűrő
+Name[it]=Filtro di scelta casuale
+Name[ja]=ランダムピックフィルタ
+Name[km]=តម្រង​រើស​ដោយ​ចៃដន្យ
+Name[nb]=Tilfeldig plukk-filter
+Name[nds]=Filter för tofällig Bildutwahl
+Name[ne]=फिल्टर अनियन्त्रित तरिकाले टिप्नुहोस्
+Name[nl]=Willekeurige-keuze-filter
+Name[pl]=Filtr losowego wyboru
+Name[pt]=Filtro de Extracção Aleatória
+Name[pt_BR]=Filtro de Extração Aleatória
+Name[ru]=Случайный выбор
+Name[sk]=Random pick filter
+Name[sl]=Filter za naključno izbiro
+Name[sr]=Филтер за насумичан избор
+Name[sr@Latn]=Filter za nasumičan izbor
+Name[sv]=Slumpmässigt urvalsfilter
+Name[uk]=Випадковий вибір
+Name[zh_TW]=隨機挑選過濾器
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkrandompickfilter
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/randompickfilter/kis_wdg_random_pick.cpp b/chalk/plugins/filters/randompickfilter/kis_wdg_random_pick.cpp
new file mode 100644
index 00000000..044f9613
--- /dev/null
+++ b/chalk/plugins/filters/randompickfilter/kis_wdg_random_pick.cpp
@@ -0,0 +1,64 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_wdg_random_pick.h"
+
+#include <tqlayout.h>
+
+#include <knuminput.h>
+
+#include "wdgrandompickoptions.h"
+
+KisWdgRandomPick::KisWdgRandomPick(KisFilter* /*nfilter*/, TQWidget* tqparent, const char* name)
+ : KisFilterConfigWidget(tqparent,name)
+{
+ TQGridLayout *widgetLayout = new TQGridLayout(this, 1, 1);
+ m_widget = new WdgRandomPickOptions(this);
+ widgetLayout -> addWidget(m_widget,0,0);
+
+ connect( widget()->intLevel, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->intWindowSize, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->intOpacity, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+}
+
+KisWdgRandomPick::~KisWdgRandomPick()
+{
+}
+
+void KisWdgRandomPick::setConfiguration(KisFilterConfiguration* config)
+{
+ TQVariant value;
+ if (config->getProperty("level", value))
+ {
+ widget()->intLevel->setValue( value.toUInt() );
+ }
+ if (config->getProperty("windowsize", value))
+ {
+ widget()->intWindowSize->setValue( value.toUInt() );
+ }
+ if (config->getProperty("opacity", value))
+ {
+ widget()->intOpacity->setValue( value.toUInt() );
+ }
+}
+
+
+#include "kis_wdg_random_pick.moc"
+
diff --git a/chalk/plugins/filters/randompickfilter/kis_wdg_random_pick.h b/chalk/plugins/filters/randompickfilter/kis_wdg_random_pick.h
new file mode 100644
index 00000000..54b46e20
--- /dev/null
+++ b/chalk/plugins/filters/randompickfilter/kis_wdg_random_pick.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_WDG_RANDOMPICK_H
+#define KIS_WDG_RANDOMPICK_H
+
+#include <kis_filter_config_widget.h>
+
+class WdgRandomPickOptions;
+class KisFilter;
+
+class KisWdgRandomPick : public KisFilterConfigWidget
+{
+ Q_OBJECT
+ TQ_OBJECT
+ public:
+ KisWdgRandomPick(KisFilter* nfilter, TQWidget* tqparent = 0, const char* name = 0);
+ ~KisWdgRandomPick();
+ public:
+ inline WdgRandomPickOptions* widget() { return m_widget; };
+ virtual void setConfiguration(KisFilterConfiguration*);
+ private:
+ WdgRandomPickOptions* m_widget;
+};
+
+#endif
+
diff --git a/chalk/plugins/filters/randompickfilter/randompickfilter.cc b/chalk/plugins/filters/randompickfilter/randompickfilter.cc
new file mode 100644
index 00000000..3a645590
--- /dev/null
+++ b/chalk/plugins/filters/randompickfilter/randompickfilter.cc
@@ -0,0 +1,131 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kgenericfactory.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_random_accessor.h>
+#include <kis_layer.h>
+#include <kis_filter_registry.h>
+#include <kis_global.h>
+#include <kis_types.h>
+
+#include "kis_wdg_random_pick.h"
+#include "wdgrandompickoptions.h"
+
+typedef KGenericFactory<ChalkRandomPickFilter> ChalkRandomPickFilterFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkrandompickfilter, ChalkRandomPickFilterFactory( "chalk" ) )
+
+ChalkRandomPickFilter::ChalkRandomPickFilter(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ChalkRandomPickFilterFactory::instance());
+
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisFilterRandomPick());
+ }
+}
+
+ChalkRandomPickFilter::~ChalkRandomPickFilter()
+{
+}
+
+KisFilterRandomPick::KisFilterRandomPick() : KisFilter(id(), "other", i18n("&Random Pick..."))
+{
+}
+
+KisFilterConfiguration* KisFilterRandomPick::configuration(TQWidget* w)
+{
+ KisWdgRandomPick* wN = dynamic_cast<KisWdgRandomPick*>(w);
+ KisFilterConfiguration* config = new KisFilterConfiguration(id().id(), 1);
+ if(wN)
+ {
+ config->setProperty("level", wN->widget()->intLevel->value() );
+ config->setProperty("windowsize", wN->widget()->intWindowSize->value() );
+ config->setProperty("opacity", wN->widget()->intOpacity->value() );
+ }
+ return config;
+}
+
+KisFilterConfigWidget * KisFilterRandomPick::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev)
+{
+ return new KisWdgRandomPick((KisFilter*)this, (TQWidget*)tqparent, i18n("Configuration of random pick filter").ascii());
+}
+
+void KisFilterRandomPick::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* config, const TQRect& rect)
+{
+ Q_ASSERT(src != 0);
+ Q_ASSERT(dst != 0);
+
+ setProgressTotalSteps(rect.height() * rect.width());
+
+ KisColorSpace * cs = src->colorSpace();
+ TQ_INT32 psize = cs->pixelSize();
+
+ TQVariant value;
+ int level = (config && config->getProperty("level", value)) ? value.toInt() : 50;
+ double windowsize = (config && config->getProperty("windowsize", value)) ? value.toInt() / 2. : 2.5;
+ int opacity = (config && config->getProperty("opacity", value)) ? value.toInt() : 100;
+
+ KisRectIteratorPixel dstIt = dst->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true );
+ KisRectIteratorPixel srcIt = src->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), false);
+ KisRandomAccessorPixel srcRA = src->createRandomAccessor(0, 0, false);
+
+ TQ_UINT32 threshold = (RAND_MAX / 100) * (100 - level);
+
+ TQ_UINT8 weights[2];
+ weights[0] = (255 * opacity) / 100; weights[1] = 255 - weights[0];
+ const TQ_UINT8* pixels[2];
+ while(!srcIt.isDone())
+ {
+ if(rand() > threshold)
+ {
+ int x = srcIt.x() + 2.5 * rand() / RAND_MAX;
+ int y = srcIt.y() + 2.5 * rand() / RAND_MAX;
+ srcRA.moveTo( x, y);
+ pixels[0] = srcRA.oldRawData();
+ pixels[1] = srcIt.oldRawData();
+ cs->mixColors( pixels, weights, 2, dstIt.rawData() );
+ }
+ ++srcIt;
+ ++dstIt;
+ incProgress();
+ }
+
+ setProgressDone(); // Must be called even if you don't really support progression
+}
diff --git a/chalk/plugins/filters/randompickfilter/randompickfilter.h b/chalk/plugins/filters/randompickfilter/randompickfilter.h
new file mode 100644
index 00000000..4b50c215
--- /dev/null
+++ b/chalk/plugins/filters/randompickfilter/randompickfilter.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 RANDOMPICKFILTER_H
+#define RANDOMPICKFILTER_H
+
+#include <kparts/plugin.h>
+#include "kis_filter.h"
+
+class KisFilterConfigWidget;
+
+class ChalkRandomPickFilter : public KParts::Plugin
+{
+public:
+ ChalkRandomPickFilter(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ChalkRandomPickFilter();
+};
+
+class KisFilterRandomPick : public KisFilter
+{
+ public:
+ KisFilterRandomPick();
+ public:
+ virtual void process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration*, const TQRect&);
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return FULLY_INDEPENDENT; };
+ static inline KisID id() { return KisID("randompick", i18n("Random Pick")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration* configuration(TQWidget*);
+};
+
+#endif
diff --git a/chalk/plugins/filters/randompickfilter/wdgrandompickoptions.ui b/chalk/plugins/filters/randompickfilter/wdgrandompickoptions.ui
new file mode 100644
index 00000000..5bdae980
--- /dev/null
+++ b/chalk/plugins/filters/randompickfilter/wdgrandompickoptions.ui
@@ -0,0 +1,135 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgRandomPickOptions</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgRandomPickOptions</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>242</width>
+ <height>93</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Level:</string>
+ </property>
+ </widget>
+ <spacer row="3" column="1">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>50</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Opacity:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="2" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>intOpacity</cstring>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="0" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>intLevel</cstring>
+ </property>
+ <property name="value">
+ <number>50</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Size of the window:</string>
+ </property>
+ </widget>
+ <spacer row="1" column="3">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KIntNumInput" row="1" column="2">
+ <property name="name">
+ <cstring>intWindowSize</cstring>
+ </property>
+ <property name="value">
+ <number>5</number>
+ </property>
+ <property name="minValue">
+ <number>3</number>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/filters/roundcorners/Makefile.am b/chalk/plugins/filters/roundcorners/Makefile.am
new file mode 100644
index 00000000..1e884560
--- /dev/null
+++ b/chalk/plugins/filters/roundcorners/Makefile.am
@@ -0,0 +1,23 @@
+kde_services_DATA = chalkroundcornersfilter.desktop
+
+INCLUDES = \
+ -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalkroundcornersfilter.la
+
+chalkroundcornersfilter_la_SOURCES = kis_round_corners_filter_plugin.cc \
+ kis_round_corners_filter.cc
+
+noinst_HEADERS = kis_round_corners_filter_plugin.h \
+ kis_round_corners_filter.h
+
+chalkroundcornersfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkroundcornersfilter_la_LIBADD = ../../../libchalkcommon.la
+
+chalkroundcornersfilter_la_METASOURCES = AUTO
diff --git a/chalk/plugins/filters/roundcorners/chalkroundcornersfilter.desktop b/chalk/plugins/filters/roundcorners/chalkroundcornersfilter.desktop
new file mode 100644
index 00000000..c3b6e182
--- /dev/null
+++ b/chalk/plugins/filters/roundcorners/chalkroundcornersfilter.desktop
@@ -0,0 +1,39 @@
+[Desktop Entry]
+Name=Sobel Filter
+Name[bg]=Филтър Sobel
+Name[ca]=Filtre Sobel
+Name[cy]=Hidlen Sobel
+Name[da]=Sobelfilter
+Name[de]=Sobel-Filter
+Name[el]=Φίλτρο άκρων Sobel
+Name[es]=Filtro Sobel
+Name[et]=Sobeli filter
+Name[fa]=پالایۀ Sobel
+Name[fr]=Filtre de Sobel
+Name[fy]=Sobelfilter
+Name[ga]=Scagaire Sobel
+Name[gl]=Filtro Sobel
+Name[hu]=Sobel-eszköz
+Name[is]=Sobel sía
+Name[it]=Filtro Sobel
+Name[ja]=ソーベルフィルタ
+Name[km]=តម្រង​ស៊ូបែល​
+Name[nds]=Sobelfilter
+Name[ne]=सोबेल फिल्टर
+Name[nl]=Sobelfilter
+Name[pl]=Filtr Sobela
+Name[pt]=Filtro Sobel
+Name[pt_BR]=Filtro Sobel
+Name[ru]=Собел
+Name[se]=Sobelsilli
+Name[sk]=Sobel filter
+Name[sl]=Filter Sobel
+Name[sr]=Собелов филтер
+Name[sr@Latn]=Sobelov filter
+Name[sv]=Sobelfilter
+Name[uk]=Фільтр Собеля
+Name[zh_TW]=Sobel 過濾器
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkroundcornersfilter
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/roundcorners/kis_round_corners_filter.cc b/chalk/plugins/filters/roundcorners/kis_round_corners_filter.cc
new file mode 100644
index 00000000..3b8177d4
--- /dev/null
+++ b/chalk/plugins/filters/roundcorners/kis_round_corners_filter.cc
@@ -0,0 +1,158 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * ported from Gimp, Copyright (C) 1997 Eiichi Takamori <taka@ma1.seikyou.ne.jp>
+ * 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 <stdlib.h>
+#include <vector>
+#include <math.h>
+
+#include <tqpoint.h>
+#include <tqspinbox.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <knuminput.h>
+
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_filter_registry.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_progress_display_interface.h>
+
+#include "kis_multi_integer_filter_widget.h"
+#include "kis_round_corners_filter.h"
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+KisRoundCornersFilter::KisRoundCornersFilter() : KisFilter(id(), "map", i18n("&Round Corners..."))
+{
+}
+
+void KisRoundCornersFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* configuration, const TQRect& rect)
+{
+ //read the filter configuration values from the KisFilterConfiguration object
+ TQ_INT32 radius = (TQ_INT32)((KisRoundCornersFilterConfiguration*)configuration)->radius();
+ TQ_UINT32 pixelSize = src->pixelSize();
+
+ setProgressTotalSteps( rect.height() );
+ setProgressStage(i18n("Applying pixelize filter..."),0);
+
+ for (TQ_INT32 y = rect.y(); y < rect.height(); y++)
+ {
+ TQ_INT32 x = rect.x();
+ TQ_INT32 x0 = rect.x();
+ TQ_INT32 y0 = rect.x();
+ TQ_INT32 width = rect.width();
+ TQ_INT32 height = rect.height();
+ KisHLineIteratorPixel dstIt = dst->createHLineIterator(x, y, width, true );
+ KisHLineIteratorPixel srcIt = src->createHLineIterator(x, y, width, false);
+ while( ! srcIt.isDone() )
+ {
+ if(srcIt.isSelected())
+ {
+ for( unsigned int i = 0; i < pixelSize; i++)
+ {
+ if ( i < pixelSize - 1 )
+ {
+ dstIt.rawData()[i] = srcIt.oldRawData()[i];
+ }
+ else
+ {
+ if( x <= radius && y <= radius)
+ {
+ double dx = radius - x;
+ double dy = radius - y;
+ double dradius = static_cast<double>(radius);
+ if ( dx >= sqrt( dradius*dradius - dy*dy ) )
+ {
+ dstIt.rawData()[i] = 0;
+ }
+ }
+ else if( x >= x0 + width - radius && y <= radius)
+ {
+ double dx = x + radius - x0 - width;
+ double dy = radius - y;
+ double dradius = static_cast<double>(radius);
+ if ( dx >= sqrt( dradius*dradius - dy*dy ) )
+ {
+ dstIt.rawData()[i] = 0;
+ }
+ }
+ else if( x <= radius && y >= y0 + height - radius)
+ {
+ double dx = radius - x;
+ double dy = y + radius - y0 - height;
+ double dradius = static_cast<double>(radius);
+ if ( dx >= sqrt( dradius*dradius - dy*dy ) )
+ {
+ dstIt.rawData()[i] = 0;
+ }
+ }
+ else if( x >= x0 + width - radius && y >= y0 + height - radius)
+ {
+
+ double dx = x + radius - x0 - width;
+ double dy = y + radius - y0 - height;
+ double dradius = static_cast<double>(radius);
+ if ( dx >= sqrt( dradius*dradius - dy*dy ) )
+ {
+ dstIt.rawData()[i] = 0;
+ }
+ }
+ }
+ }
+ }
+ ++srcIt;
+ ++dstIt;
+ ++x;
+ }
+ setProgress(y);
+ }
+ setProgressDone();
+}
+
+KisFilterConfigWidget * KisRoundCornersFilter::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP /*dev*/)
+{
+ vKisIntegerWidgetParam param;
+ param.push_back( KisIntegerWidgetParam( 2, 100, 30, i18n("Radius"), "radius" ) );
+ return new KisMultiIntegerFilterWidget(tqparent, id().id().ascii(), id().id().ascii(), param );
+}
+
+KisFilterConfiguration* KisRoundCornersFilter::configuration(TQWidget* nwidget)
+{
+ KisMultiIntegerFilterWidget* widget = (KisMultiIntegerFilterWidget*) nwidget;
+ if( widget == 0 )
+ {
+ return new KisRoundCornersFilterConfiguration( 30 );
+ } else {
+ return new KisRoundCornersFilterConfiguration( widget->valueAt( 0 ) );
+ }
+}
diff --git a/chalk/plugins/filters/roundcorners/kis_round_corners_filter.h b/chalk/plugins/filters/roundcorners/kis_round_corners_filter.h
new file mode 100644
index 00000000..ec5fb9fb
--- /dev/null
+++ b/chalk/plugins/filters/roundcorners/kis_round_corners_filter.h
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_ROUND_CORNERS_FILTER_H_
+#define _KIS_ROUND_CORNERS_FILTER_H_
+
+#include "kis_filter.h"
+#include "kis_filter_config_widget.h"
+
+class KisRoundCornersFilterConfiguration : public KisFilterConfiguration
+{
+public:
+ KisRoundCornersFilterConfiguration(TQ_INT32 radius)
+ : KisFilterConfiguration( "roundcorners", 1 )
+ {
+ setProperty("radius", radius);
+ };
+public:
+ inline TQ_INT32 radius() { return getInt("radius"); };
+};
+
+class KisRoundCornersFilter : public KisFilter
+{
+public:
+ KisRoundCornersFilter();
+public:
+ virtual void process(KisPaintDeviceSP,KisPaintDeviceSP, KisFilterConfiguration* , const TQRect&);
+ static inline KisID id() { return KisID("roundcorners", i18n("Round Corners")); };
+ virtual bool supportsPainting() { return false; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsAdjustmentLayers () { return false; }
+ virtual std::list<KisFilterConfiguration*> listOfExamplesConfiguration(KisPaintDeviceSP )
+ { std::list<KisFilterConfiguration*> list; list.insert(list.begin(), new KisRoundCornersFilterConfiguration(30)); return list; }
+public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration* configuration(TQWidget*);
+ virtual KisFilterConfiguration * configuration() { return new KisRoundCornersFilterConfiguration( 30 ); };
+private:
+};
+
+#endif
diff --git a/chalk/plugins/filters/roundcorners/kis_round_corners_filter_plugin.cc b/chalk/plugins/filters/roundcorners/kis_round_corners_filter_plugin.cc
new file mode 100644
index 00000000..f53acf46
--- /dev/null
+++ b/chalk/plugins/filters/roundcorners/kis_round_corners_filter_plugin.cc
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <kgenericfactory.h>
+#include "kis_round_corners_filter_plugin.h"
+#include "kis_round_corners_filter.h"
+#include "kis_global.h"
+
+typedef KGenericFactory<KisRoundCornersFilterPlugin> KisRoundCornersFilterPluginFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkroundcornersfilter, KisRoundCornersFilterPluginFactory( "chalk" ) )
+
+KisRoundCornersFilterPlugin::KisRoundCornersFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(KisRoundCornersFilterPluginFactory::instance());
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisRoundCornersFilter());
+ }
+}
+
+KisRoundCornersFilterPlugin::~KisRoundCornersFilterPlugin()
+{
+}
+
diff --git a/chalk/plugins/filters/roundcorners/kis_round_corners_filter_plugin.h b/chalk/plugins/filters/roundcorners/kis_round_corners_filter_plugin.h
new file mode 100644
index 00000000..e55239e4
--- /dev/null
+++ b/chalk/plugins/filters/roundcorners/kis_round_corners_filter_plugin.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_ROUND_CORNERS_FILTER_PLUGIN_H_
+#define _KIS_ROUND_CORNERS_FILTER_PLUGIN_H_
+
+#include <kparts/plugin.h>
+
+class KisRoundCornersFilterPlugin : public KParts::Plugin
+{
+public:
+ KisRoundCornersFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~KisRoundCornersFilterPlugin();
+};
+
+#endif
diff --git a/chalk/plugins/filters/smalltilesfilter/Makefile.am b/chalk/plugins/filters/smalltilesfilter/Makefile.am
new file mode 100644
index 00000000..87a17332
--- /dev/null
+++ b/chalk/plugins/filters/smalltilesfilter/Makefile.am
@@ -0,0 +1,23 @@
+kde_services_DATA = chalksmalltilesfilter.desktop
+
+INCLUDES = \
+ -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../ui \
+ -I$(srcdir)/../../../../lib/kofficecore \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalksmalltilesfilter.la
+
+chalksmalltilesfilter_la_SOURCES = kis_small_tiles_filter_plugin.cc \
+ kis_small_tiles_filter.cc
+
+noinst_HEADERS = kis_small_tiles_filter_plugin.h \
+ kis_small_tiles_filter.h
+
+chalksmalltilesfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalksmalltilesfilter_la_LIBADD = ../../../libchalkcommon.la
+
+chalksmalltilesfilter_la_METASOURCES = AUTO
diff --git a/chalk/plugins/filters/smalltilesfilter/chalksmalltilesfilter.desktop b/chalk/plugins/filters/smalltilesfilter/chalksmalltilesfilter.desktop
new file mode 100644
index 00000000..ae9bcc2f
--- /dev/null
+++ b/chalk/plugins/filters/smalltilesfilter/chalksmalltilesfilter.desktop
@@ -0,0 +1,39 @@
+[Desktop Entry]
+Name=Small Tiles Filter
+Name[bg]=Филтър "малки плочки"
+Name[br]=Sil teoloù bihan
+Name[ca]=Filtre de petites rajoles
+Name[cy]=Hidlen Deiliau Bychain
+Name[da]=Småflisefilter
+Name[de]=Kleine-Quadrate-Filter
+Name[el]=Φίλτρο μικρών παραθέσεων
+Name[es]=Filtro de azulejos pequeños
+Name[et]=Väikeste klotside filter
+Name[fa]=پالایۀ کاشیهای کوچک
+Name[fr]=Filtre mosaïque
+Name[fy]=Lytse-tegelfilter
+Name[gl]=Filtro de Pequenos Mosaicos
+Name[hu]=Aprómozaik szűrő
+Name[is]=Smá flísasía
+Name[it]=Filtro per piccoli riquadri
+Name[ja]=小タイルフィルタ
+Name[km]=តម្រង​ក្រឡា​ក្បឿង​តូច
+Name[nb]=Små fliser-filter
+Name[nds]=Lüttkachel-Filter
+Name[ne]=सानो टाइल फिल्टर
+Name[nl]=Kleine tegeltjes
+Name[pl]=Filtr małych kafelków
+Name[pt]=Filtro de Pequenos Padrões
+Name[pt_BR]=Filtro de Pequenos Padrões
+Name[ru]=Маленькая черепица
+Name[sk]=Filter malé dlaždice
+Name[sl]=Filter Majhni kvadrati
+Name[sr]=Филтер малих плоча
+Name[sr@Latn]=Filter malih ploča
+Name[sv]=Smårutorsfilter
+Name[uk]=Фільтр маленьких плиток
+Name[zh_TW]=小塊拼貼過濾器
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalksmalltilesfilter
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/smalltilesfilter/kis_small_tiles_filter.cc b/chalk/plugins/filters/smalltilesfilter/kis_small_tiles_filter.cc
new file mode 100644
index 00000000..6c621e47
--- /dev/null
+++ b/chalk/plugins/filters/smalltilesfilter/kis_small_tiles_filter.cc
@@ -0,0 +1,187 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * ported from Gimp, Copyright (C) 1997 Eiichi Takamori <taka@ma1.seikyou.ne.jp>
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+#include <tqspinbox.h>
+#include <tqvaluevector.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <knuminput.h>
+
+#include <kis_painter.h>
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_filter_registry.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_progress_display_interface.h>
+#include <kis_paint_device.h>
+#include <kis_filter_strategy.h>
+#include <kis_painter.h>
+#include <kis_selection.h>
+
+#include "kis_multi_integer_filter_widget.h"
+#include "kis_small_tiles_filter.h"
+
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+void KisSmallTilesFilterConfiguration::fromXML(const TQString & s)
+{
+ KisFilterConfiguration::fromXML(s);
+ m_numberOfTiles = getInt("numberOfTiles");
+}
+
+TQString KisSmallTilesFilterConfiguration::toString()
+{
+ m_properties.clear();
+ setProperty("numberOfTiles()", m_numberOfTiles);
+
+ return KisFilterConfiguration::toString();
+}
+
+KisSmallTilesFilter::KisSmallTilesFilter() : KisFilter(id(), "map", i18n("&Small Tiles..."))
+{
+}
+
+void KisSmallTilesFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* configuration, const TQRect& rect)
+{
+ //read the filter configuration values from the KisFilterConfiguration object
+ TQ_UINT32 numberOfTiles = ((KisSmallTilesFilterConfiguration*)configuration)->numberOfTiles();
+
+ createSmallTiles(src, dst, rect, numberOfTiles);
+}
+
+void KisSmallTilesFilter::createSmallTiles(KisPaintDeviceSP src, KisPaintDeviceSP dst, const TQRect& rect, TQ_UINT32 numberOfTiles)
+{
+ if (!src) return;
+ if (!dst) return;
+
+ TQRect srcRect = src->exactBounds();
+
+ int w = static_cast<int>(srcRect.width() / numberOfTiles);
+ int h = static_cast<int>(srcRect.height() / numberOfTiles);
+
+ KisPaintDeviceSP tile = 0;
+ if (src->hasSelection()) {
+ KisPaintDeviceSP tmp = new KisPaintDevice(src->colorSpace(), "selected bit");
+ KisPainter gc(tmp);
+ gc.bltSelection(0, 0, COMPOSITE_COPY, src, OPACITY_OPAQUE, rect.x(), rect.y(), rect.width(), rect.height());
+ tile = src->createThumbnailDevice(srcRect.width() / numberOfTiles, srcRect.height() / numberOfTiles);
+ }
+ else {
+ tile = src->createThumbnailDevice(srcRect.width() / numberOfTiles, srcRect.height() / numberOfTiles);
+ }
+ if (tile == 0) return;
+
+ KisPaintDeviceSP scratch = new KisPaintDevice(src->colorSpace());
+
+ KisPainter gc(scratch);
+
+ setProgressTotalSteps(numberOfTiles);
+
+ for (uint y = 0; y < numberOfTiles; ++y) {
+ for (uint x = 0; x < numberOfTiles; ++x) {
+ // XXX make composite op and opacity configurable
+ gc.bitBlt( w * x, h * y, COMPOSITE_COPY, tile, 0, 0, w, h);
+ setProgress(y);
+ }
+ }
+ gc.end();
+
+ gc.begin(dst);
+ if (src->hasSelection()) {
+ gc.bltSelection(rect.x(), rect.y(), COMPOSITE_OVER, scratch, src->selection(), OPACITY_OPAQUE, 0, 0, rect.width(), rect.height() );
+ }
+ else {
+ gc.bitBlt(rect.x(), rect.y(), COMPOSITE_OVER, scratch, OPACITY_OPAQUE, 0, 0, rect.width(), rect.height() );
+ }
+ setProgressDone();
+ gc.end();
+
+ //KisPainter gc(tmp);
+ //gc.bitBlt(rect.x(), rect.y(), COMPOSITE_COPY, src, rect.x(), rect.y(), rect.width(), rect.height());
+ //gc.end();
+
+ //KisScaleWorker worker(tmp, 1.0 / static_cast<double>(numberOfTiles), 1.0 / static_cast<double>(numberOfTiles), new KisMitchellFilterStrategy() );
+ //worker.run();
+
+// TQRect tmpRect = tmp->exactBounds();
+//
+// for( TQ_UINT32 i=0; i < numberOfTiles; i++ )
+// {
+// for( TQ_UINT32 j=0; j < numberOfTiles; j++ )
+// {
+// for( TQ_INT32 row = tmpRect.y(); row < tmpRect.height(); row++ )
+// {
+// KisHLineIteratorPixel tmpIt = tmp->createHLineIterator(tmpRect.x(), row, tmpRect.width() , false);
+// KisHLineIteratorPixel dstIt = dst->createHLineIterator( tmpRect.x() + i * tmpRect.width(), row + j * tmpRect.height(), tmpRect.width() , true);
+//
+// while( ! tmpIt.isDone() )
+// {
+// if(tmpIt.isSelected())
+// {
+// for( int i = 0; i < depth; i++)
+// {
+// dstIt.rawData()[i] = tmpIt.oldRawData()[i];
+// }
+// }
+// ++tmpIt;
+// ++dstIt;
+// }
+// }
+// }
+// }
+
+ setProgressDone();
+}
+
+KisFilterConfigWidget * KisSmallTilesFilter::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP /*dev*/)
+{
+ vKisIntegerWidgetParam param;
+ param.push_back( KisIntegerWidgetParam( 2, 5, 1, i18n("Number of tiles"), "smalltiles" ) );
+ return new KisMultiIntegerFilterWidget(tqparent, id().id().ascii(), id().id().ascii(), param );
+}
+
+KisFilterConfiguration* KisSmallTilesFilter::configuration(TQWidget* nwidget)
+{
+ KisMultiIntegerFilterWidget* widget = (KisMultiIntegerFilterWidget*) nwidget;
+ if( widget == 0 )
+ {
+ return new KisSmallTilesFilterConfiguration( 2 );
+ } else {
+ return new KisSmallTilesFilterConfiguration( widget->valueAt( 0 ) );
+ }
+}
diff --git a/chalk/plugins/filters/smalltilesfilter/kis_small_tiles_filter.h b/chalk/plugins/filters/smalltilesfilter/kis_small_tiles_filter.h
new file mode 100644
index 00000000..8d82eda2
--- /dev/null
+++ b/chalk/plugins/filters/smalltilesfilter/kis_small_tiles_filter.h
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_SMALL_TILES_FILTER_H_
+#define _KIS_SMALL_TILES_FILTER_H_
+
+#include "kis_filter.h"
+#include "kis_filter_config_widget.h"
+
+class KisSmallTilesFilterConfiguration : public KisFilterConfiguration
+{
+public:
+ KisSmallTilesFilterConfiguration(TQ_UINT32 numberOfTiles)
+ : KisFilterConfiguration( "smalltiles", 1 )
+ , m_numberOfTiles(numberOfTiles) {};
+
+
+ virtual void fromXML( const TQString& );
+ virtual TQString toString();
+
+public:
+ inline TQ_UINT32 numberOfTiles() { return m_numberOfTiles; };
+
+private:
+ TQ_UINT32 m_numberOfTiles;
+};
+
+class KisSmallTilesFilter : public KisFilter
+{
+
+public:
+ KisSmallTilesFilter();
+
+public:
+ virtual void process(KisPaintDeviceSP,KisPaintDeviceSP, KisFilterConfiguration* , const TQRect&);
+ static inline KisID id() { return KisID("smalltiles", i18n("Small Tiles")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ virtual bool supportsAdjustmentLayers() { return false; }
+ virtual std::list<KisFilterConfiguration*> listOfExamplesConfiguration(KisPaintDeviceSP )
+ { std::list<KisFilterConfiguration*> list; list.insert(list.begin(), new KisSmallTilesFilterConfiguration(2)); return list; }
+
+public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration * configuration(TQWidget*);
+ virtual KisFilterConfiguration * configuration() { return new KisSmallTilesFilterConfiguration( 2 ); };
+
+private:
+ void createSmallTiles(KisPaintDeviceSP src, KisPaintDeviceSP dst, const TQRect& rect, TQ_UINT32 numberOfTiles);
+};
+
+#endif
diff --git a/chalk/plugins/filters/smalltilesfilter/kis_small_tiles_filter_plugin.cc b/chalk/plugins/filters/smalltilesfilter/kis_small_tiles_filter_plugin.cc
new file mode 100644
index 00000000..5283980c
--- /dev/null
+++ b/chalk/plugins/filters/smalltilesfilter/kis_small_tiles_filter_plugin.cc
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <kgenericfactory.h>
+#include "kis_small_tiles_filter_plugin.h"
+#include "kis_small_tiles_filter.h"
+#include "kis_global.h"
+
+typedef KGenericFactory<KisSmallTilesFilterPlugin> KisSmallTilesFilterPluginFactory;
+K_EXPORT_COMPONENT_FACTORY( chalksmalltilesfilter, KisSmallTilesFilterPluginFactory( "chalk" ) )
+
+KisSmallTilesFilterPlugin::KisSmallTilesFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(KisSmallTilesFilterPluginFactory::instance());
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisSmallTilesFilter());
+ }
+}
+
+KisSmallTilesFilterPlugin::~KisSmallTilesFilterPlugin()
+{
+}
+
diff --git a/chalk/plugins/filters/smalltilesfilter/kis_small_tiles_filter_plugin.h b/chalk/plugins/filters/smalltilesfilter/kis_small_tiles_filter_plugin.h
new file mode 100644
index 00000000..601568f2
--- /dev/null
+++ b/chalk/plugins/filters/smalltilesfilter/kis_small_tiles_filter_plugin.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_SMALL_TILES_FILTER_PLUGIN_H_
+#define _KIS_SMALL_TILES_FILTER_PLUGIN_H_
+
+#include <kparts/plugin.h>
+
+class KisSmallTilesFilterPlugin : public KParts::Plugin
+{
+public:
+ KisSmallTilesFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~KisSmallTilesFilterPlugin();
+};
+
+#endif
diff --git a/chalk/plugins/filters/sobelfilter/Makefile.am b/chalk/plugins/filters/sobelfilter/Makefile.am
new file mode 100644
index 00000000..c7853223
--- /dev/null
+++ b/chalk/plugins/filters/sobelfilter/Makefile.am
@@ -0,0 +1,23 @@
+kde_services_DATA = chalksobelfilter.desktop
+
+INCLUDES = \
+ -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalksobelfilter.la
+
+chalksobelfilter_la_SOURCES = kis_sobel_filter_plugin.cc \
+ kis_sobel_filter.cc
+
+noinst_HEADERS = kis_sobel_filter_plugin.h \
+ kis_sobel_filter.h
+
+chalksobelfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalksobelfilter_la_LIBADD = ../../../libchalkcommon.la
+
+chalksobelfilter_la_METASOURCES = AUTO
diff --git a/chalk/plugins/filters/sobelfilter/chalksobelfilter.desktop b/chalk/plugins/filters/sobelfilter/chalksobelfilter.desktop
new file mode 100644
index 00000000..46ecd68f
--- /dev/null
+++ b/chalk/plugins/filters/sobelfilter/chalksobelfilter.desktop
@@ -0,0 +1,39 @@
+[Desktop Entry]
+Name=Sobel Filter
+Name[bg]=Филтър Sobel
+Name[ca]=Filtre Sobel
+Name[cy]=Hidlen Sobel
+Name[da]=Sobelfilter
+Name[de]=Sobel-Filter
+Name[el]=Φίλτρο άκρων Sobel
+Name[es]=Filtro Sobel
+Name[et]=Sobeli filter
+Name[fa]=پالایۀ Sobel
+Name[fr]=Filtre de Sobel
+Name[fy]=Sobelfilter
+Name[ga]=Scagaire Sobel
+Name[gl]=Filtro Sobel
+Name[hu]=Sobel-eszköz
+Name[is]=Sobel sía
+Name[it]=Filtro Sobel
+Name[ja]=ソーベルフィルタ
+Name[km]=តម្រង​ស៊ូបែល​
+Name[nds]=Sobelfilter
+Name[ne]=सोबेल फिल्टर
+Name[nl]=Sobelfilter
+Name[pl]=Filtr Sobela
+Name[pt]=Filtro Sobel
+Name[pt_BR]=Filtro Sobel
+Name[ru]=Собел
+Name[se]=Sobelsilli
+Name[sk]=Sobel filter
+Name[sl]=Filter Sobel
+Name[sr]=Собелов филтер
+Name[sr@Latn]=Sobelov filter
+Name[sv]=Sobelfilter
+Name[uk]=Фільтр Собеля
+Name[zh_TW]=Sobel 過濾器
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalksobelfilter
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/sobelfilter/kis_sobel_filter.cc b/chalk/plugins/filters/sobelfilter/kis_sobel_filter.cc
new file mode 100644
index 00000000..9a2f5604
--- /dev/null
+++ b/chalk/plugins/filters/sobelfilter/kis_sobel_filter.cc
@@ -0,0 +1,217 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * ported from Gimp, Copyright (C) 1997 Eiichi Takamori <taka@ma1.seikyou.ne.jp>
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+#include <tqspinbox.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <knuminput.h>
+
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_filter_registry.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_progress_display_interface.h>
+
+#include "kis_multi_bool_filter_widget.h"
+#include "kis_sobel_filter.h"
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+void KisSobelFilterConfiguration::fromXML(const TQString & s)
+{
+ KisFilterConfiguration::fromXML(s);
+ m_doHorizontally = getBool( "doHorizontally" );
+ m_doVertically = getBool( "doVertically" );
+ m_keepSign = getBool( "makeOpaque" );
+}
+
+TQString KisSobelFilterConfiguration::toString()
+{
+ m_properties.clear();
+ setProperty("doHorizontally", m_doHorizontally);
+ setProperty("doVertically", m_doVertically);
+ setProperty("keepSign", m_keepSign);
+ setProperty("makeOpaque", m_makeOpaque);
+
+ return KisFilterConfiguration::toString();
+}
+
+KisSobelFilter::KisSobelFilter() : KisFilter(id(), "edge", i18n("&Sobel..."))
+{
+}
+
+void KisSobelFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* configuration, const TQRect& rect)
+{
+ //read the filter configuration values from the KisFilterConfiguration object
+ bool doHorizontally = ((KisSobelFilterConfiguration*)configuration)->doHorizontally();
+ bool doVertically = ((KisSobelFilterConfiguration*)configuration)->doVertically();
+ bool keepSign = ((KisSobelFilterConfiguration*)configuration)->keepSign();
+ bool makeOpaque = ((KisSobelFilterConfiguration*)configuration)->makeOpaque();
+
+ //pixelize(src, dst, x, y, width, height, pixelWidth, pixelHeight);
+ sobel(rect, src, dst, doHorizontally, doVertically, keepSign, makeOpaque);
+}
+
+void KisSobelFilter::prepareRow (KisPaintDeviceSP src, TQ_UINT8* data, TQ_UINT32 x, TQ_UINT32 y, TQ_UINT32 w, TQ_UINT32 h)
+{
+ if (y > h -1) y = h -1;
+ TQ_UINT32 pixelSize = src->pixelSize();
+
+ src->readBytes( data, x, y, w, 1 );
+
+ for (TQ_UINT32 b = 0; b < pixelSize; b++) {
+ int offset = pixelSize - b;
+ data[-offset] = data[b];
+ data[w * pixelSize + b] = data[(w - 1) * pixelSize + b];
+ }
+}
+
+#define RMS(a, b) (sqrt ((a) * (a) + (b) * (b)))
+#define ROUND(x) ((int) ((x) + 0.5))
+
+void KisSobelFilter::sobel(const TQRect & rc, KisPaintDeviceSP src, KisPaintDeviceSP dst, bool doHorizontal, bool doVertical, bool keepSign, bool makeOpaque)
+{
+ TQRect rect = rc; //src->exactBounds();
+ TQ_UINT32 x = rect.x();
+ TQ_UINT32 y = rect.y();
+ TQ_UINT32 width = rect.width();
+ TQ_UINT32 height = rect.height();
+ TQ_UINT32 pixelSize = src->pixelSize();
+
+ setProgressTotalSteps( height );
+ setProgressStage(i18n("Applying sobel filter..."),0);
+
+ /* allocate row buffers */
+ TQ_UINT8* prevRow = new TQ_UINT8[ (width + 2) * pixelSize];
+ Q_CHECK_PTR(prevRow);
+ TQ_UINT8* curRow = new TQ_UINT8[ (width + 2) * pixelSize];
+ Q_CHECK_PTR(curRow);
+ TQ_UINT8* nextRow = new TQ_UINT8[ (width + 2) * pixelSize];
+ Q_CHECK_PTR(nextRow);
+ TQ_UINT8* dest = new TQ_UINT8[ width * pixelSize];
+ Q_CHECK_PTR(dest);
+
+ TQ_UINT8* pr = prevRow + pixelSize;
+ TQ_UINT8* cr = curRow + pixelSize;
+ TQ_UINT8* nr = nextRow + pixelSize;
+
+ prepareRow (src, pr, x, y - 1, width, height);
+ prepareRow (src, cr, x, y, width, height);
+
+ TQ_UINT32 counter =0;
+ TQ_UINT8* d;
+ TQ_UINT8* tmp;
+ TQ_INT32 gradient, horGradient, verGradient;
+ // loop through the rows, applying the sobel convolution
+ for (TQ_UINT32 row = 0; row < height; row++)
+ {
+
+ // prepare the next row
+ prepareRow (src, nr, x, row + 1, width, height);
+ d = dest;
+
+ for (TQ_UINT32 col = 0; col < width * pixelSize; col++)
+ {
+ int positive = col + pixelSize;
+ int negative = col - pixelSize;
+ horGradient = (doHorizontal ?
+ ((pr[negative] + 2 * pr[col] + pr[positive]) -
+ (nr[negative] + 2 * nr[col] + nr[positive]))
+ : 0);
+
+ verGradient = (doVertical ?
+ ((pr[negative] + 2 * cr[negative] + nr[negative]) -
+ (pr[positive] + 2 * cr[positive] + nr[positive]))
+ : 0);
+ gradient = (TQ_INT32)((doVertical && doHorizontal) ?
+ (ROUND (RMS (horGradient, verGradient)) / 5.66) // always >0
+ : (keepSign ? (127 + (ROUND ((horGradient + verGradient) / 8.0)))
+ : (ROUND (TQABS (horGradient + verGradient) / 4.0))));
+
+ *d++ = gradient;
+ if (gradient > 10) counter ++;
+ }
+
+ // shuffle the row pointers
+ tmp = pr;
+ pr = cr;
+ cr = nr;
+ nr = tmp;
+
+ //store the dest
+ dst->writeBytes(dest, x, row, width, 1);
+
+ if ( makeOpaque )
+ {
+ KisHLineIteratorPixel dstIt = dst->createHLineIterator(x, row, width, true);
+ while( ! dstIt.isDone() )
+ {
+ dstIt.rawData()[pixelSize-1]=255; //XXXX: is the alpha channel always 8 bit? Otherwise this is wrong!
+ ++dstIt;
+ }
+ }
+ setProgress(row);
+ }
+ setProgressDone();
+
+ delete[] prevRow;
+ delete[] curRow;
+ delete[] nextRow;
+ delete[] dest;
+}
+
+
+KisFilterConfigWidget * KisSobelFilter::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP)
+{
+ vKisBoolWidgetParam param;
+ param.push_back( KisBoolWidgetParam( true, i18n("Sobel horizontally"), "doHorizontally" ) );
+ param.push_back( KisBoolWidgetParam( true, i18n("Sobel vertically"), "doVertically" ) );
+ param.push_back( KisBoolWidgetParam( true, i18n("Keep sign of result"), "keepSign" ) );
+ param.push_back( KisBoolWidgetParam( true, i18n("Make image opaque"), "makeOpaque" ) );
+ return new KisMultiBoolFilterWidget(tqparent, id().id().ascii(), id().id().ascii(), param );
+}
+
+KisFilterConfiguration* KisSobelFilter::configuration(TQWidget* nwidget)
+{
+ KisMultiBoolFilterWidget* widget = (KisMultiBoolFilterWidget*) nwidget;
+ if( widget == 0 )
+ {
+ return new KisSobelFilterConfiguration( true, true, true, true);
+ } else {
+ return new KisSobelFilterConfiguration( widget->valueAt( 0 ), widget->valueAt( 1 ), widget->valueAt( 2 ), widget->valueAt( 3 ) );
+ }
+}
diff --git a/chalk/plugins/filters/sobelfilter/kis_sobel_filter.h b/chalk/plugins/filters/sobelfilter/kis_sobel_filter.h
new file mode 100644
index 00000000..757757bc
--- /dev/null
+++ b/chalk/plugins/filters/sobelfilter/kis_sobel_filter.h
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_SOBEL_FILTER_H_
+#define _KIS_SOBEL_FILTER_H_
+
+#include "kis_filter.h"
+#include "kis_filter_config_widget.h"
+
+class KisSobelFilterConfiguration : public KisFilterConfiguration
+{
+public:
+ KisSobelFilterConfiguration(bool doHorizontally, bool doVertically, bool keepSign, bool makeOpaque)
+ : KisFilterConfiguration( "sobel", 1 )
+ , m_doHorizontally(doHorizontally)
+ , m_doVertically(doVertically)
+ , m_keepSign(keepSign)
+ , m_makeOpaque(makeOpaque)
+ {};
+
+ virtual void fromXML( const TQString& );
+ virtual TQString toString();
+
+public:
+ inline bool doHorizontally() { return m_doHorizontally; };
+ inline bool doVertically() {return m_doVertically; };
+ inline bool keepSign() {return m_keepSign; };
+ inline bool makeOpaque() {return m_makeOpaque; };
+
+private:
+ bool m_doHorizontally;
+ bool m_doVertically;
+ bool m_keepSign;
+ bool m_makeOpaque;
+};
+
+class KisSobelFilter : public KisFilter
+{
+public:
+ KisSobelFilter();
+public:
+ virtual void process(KisPaintDeviceSP,KisPaintDeviceSP, KisFilterConfiguration* , const TQRect&);
+ static inline KisID id() { return KisID("sobel", i18n("Sobel")); };
+ virtual bool supportsPainting() { return false; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsAdjustmentLayers() { return false; }
+ virtual std::list<KisFilterConfiguration*> listOfExamplesConfiguration(KisPaintDeviceSP )
+ { std::list<KisFilterConfiguration*> list; list.insert(list.begin(), new KisSobelFilterConfiguration(true,true,true,true)); return list; }
+public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration* configuration(TQWidget*);
+ virtual KisFilterConfiguration * configuration() { return new KisSobelFilterConfiguration( true, true, true, true); };
+private:
+ void prepareRow (KisPaintDeviceSP src, TQ_UINT8* data, TQ_UINT32 x, TQ_UINT32 y, TQ_UINT32 w, TQ_UINT32 h);
+ void sobel(const TQRect & rc, KisPaintDeviceSP src, KisPaintDeviceSP dst, bool doHorizontal, bool doVertical, bool keepSign, bool makeOpaque);
+};
+
+#endif
diff --git a/chalk/plugins/filters/sobelfilter/kis_sobel_filter_plugin.cc b/chalk/plugins/filters/sobelfilter/kis_sobel_filter_plugin.cc
new file mode 100644
index 00000000..e0ef8c80
--- /dev/null
+++ b/chalk/plugins/filters/sobelfilter/kis_sobel_filter_plugin.cc
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <kgenericfactory.h>
+#include "kis_sobel_filter_plugin.h"
+#include "kis_sobel_filter.h"
+#include "kis_global.h"
+
+typedef KGenericFactory<KisSobelFilterPlugin> KisSobelFilterPluginFactory;
+K_EXPORT_COMPONENT_FACTORY( chalksobelfilter, KisSobelFilterPluginFactory( "chalk" ) )
+
+KisSobelFilterPlugin::KisSobelFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(KisSobelFilterPluginFactory::instance());
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisSobelFilter());
+ }
+}
+
+KisSobelFilterPlugin::~KisSobelFilterPlugin()
+{
+}
+
diff --git a/chalk/plugins/filters/sobelfilter/kis_sobel_filter_plugin.h b/chalk/plugins/filters/sobelfilter/kis_sobel_filter_plugin.h
new file mode 100644
index 00000000..87564cfe
--- /dev/null
+++ b/chalk/plugins/filters/sobelfilter/kis_sobel_filter_plugin.h
@@ -0,0 +1,32 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_SOBEL_FILTER_PLUGIN_H_
+#define _KIS_SOBEL_FILTER_PLUGIN_H_
+
+#include <kparts/plugin.h>
+
+class KisSobelFilterPlugin : public KParts::Plugin
+{
+public:
+ KisSobelFilterPlugin(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~KisSobelFilterPlugin();
+};
+
+#endif
diff --git a/chalk/plugins/filters/threadtest/Makefile.am b/chalk/plugins/filters/threadtest/Makefile.am
new file mode 100644
index 00000000..7846c3c0
--- /dev/null
+++ b/chalk/plugins/filters/threadtest/Makefile.am
@@ -0,0 +1,18 @@
+kde_services_DATA = chalkthreadtest.desktop
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$(srcdir)/../../../../lib/kofficecore \
+ $(all_includes)
+
+chalkthreadtest_la_SOURCES = threadtest.cc
+
+kde_module_LTLIBRARIES = chalkthreadtest.la
+noinst_HEADERS = threadtest.h
+
+chalkthreadtest_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+chalkthreadtest_la_LIBADD = ../../../libchalkcommon.la
+
+chalkthreadtest_la_METASOURCES = AUTO
diff --git a/chalk/plugins/filters/threadtest/chalkthreadtest.desktop b/chalk/plugins/filters/threadtest/chalkthreadtest.desktop
new file mode 100644
index 00000000..658964a1
--- /dev/null
+++ b/chalk/plugins/filters/threadtest/chalkthreadtest.desktop
@@ -0,0 +1,38 @@
+[Desktop Entry]
+Name=Invert Filter with Threads
+Name[bg]=Инвертиращ филтър с нишки
+Name[ca]=Inverteix filtre amb fils
+Name[cy]=Gwrthdroi Hidlen efo Edeifion
+Name[da]=Inverteringsfilter med tråde
+Name[de]=Invertierungsfilter mit Threads
+Name[el]=Φίλτρο αντιστροφής με νήματα
+Name[es]=Invertir filtro con hilos
+Name[et]=Lõimedega inverteerimise filter
+Name[fa]=وارونه کردن پالایه با رشته‌ها
+Name[fr]=Filtre d'inversion avec fils
+Name[fy]=Filter mei trieden omdraaie
+Name[ga]=Inbhéartaigh Scagaire le Snáitheanna
+Name[gl]=Filtro de Inversión Multifío
+Name[hu]=Invertáló szűrő szálakkal
+Name[is]=Snúa síu með þráðum
+Name[it]=File di inversione con trama
+Name[km]=បញ្ច្រាស​តម្រង​ជាមួយ​សរសៃ
+Name[nb]=Inverteringsfilter med tråder
+Name[nds]=Ümdreihfilter mit Sträng
+Name[ne]=धागोसँग फिल्टर उल्टाउनुहोस्
+Name[nl]=Filter met threads omkeren
+Name[pl]=Filtr inwersji z wątkami
+Name[pt]=Filtro de Inversão Multitarefa
+Name[pt_BR]=Filtro de Inversão Multitarefa
+Name[ru]=Инвертирование
+Name[sk]=Filter inverzie s vláknami
+Name[sl]=Filter za obračanje z nitmi
+Name[sr]=Филтер за инверзију са нитима
+Name[sr@Latn]=Filter za inverziju sa nitima
+Name[sv]=Inverteringsfilter med trådar
+Name[uk]=Інвертування
+Name[zh_TW]=有 Thread 的反轉過濾器
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkthreadtest
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/threadtest/threadtest.cc b/chalk/plugins/filters/threadtest/threadtest.cc
new file mode 100644
index 00000000..f96a1616
--- /dev/null
+++ b/chalk/plugins/filters/threadtest/threadtest.cc
@@ -0,0 +1,140 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+#include <tqrect.h>
+#include <tqthread.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_filter_registry.h>
+#include <kis_global.h>
+#include <kis_types.h>
+
+// #include <kmessagebox.h>
+
+#include "threadtest.h"
+
+typedef KGenericFactory<ChalkThreadTest> ChalkThreadTestFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkthreadtest, ChalkThreadTestFactory( "chalk" ) )
+
+ChalkThreadTest::ChalkThreadTest(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ChalkThreadTestFactory::instance());
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * r = dynamic_cast<KisFilterRegistry *>(tqparent);
+ r->add(new KisFilterInvert());
+ }
+}
+
+ChalkThreadTest::~ChalkThreadTest()
+{
+}
+
+class InversionThread : public TQThread
+{
+
+public:
+
+ InversionThread(const TQString & name, KisPaintDeviceSP src, KisPaintDeviceSP dst, const TQRect& rect)
+ : TQThread()
+ , m_name(name)
+ , m_src(src)
+ , m_dst(dst)
+ , m_rect(rect)
+ {
+ kdDebug() << "Thread created " << m_name << ", " << TQThread::currentThread() << ", " << m_rect << "\n";
+ };
+
+ void run()
+ {
+ kdDebug() << "Thread started:" << m_name << ", " << TQThread::currentThread() << "\n";
+
+ KisRectIteratorPixel dstIt = m_dst->createRectIterator(m_rect.x(), m_rect.y(), m_rect.width(), m_rect.height(), true );
+ KisRectIteratorPixel srcIt = m_src->createRectIterator(m_rect.x(), m_rect.y(), m_rect.width(), m_rect.height(), false);
+ TQ_INT32 depth = m_src -> colorSpace() -> nColorChannels();
+
+ kdDebug() << "Thread " << m_name << " starts loop \n";
+
+ while( ! srcIt.isDone() ) {
+ if ( srcIt.isSelected() ) {
+ for( int i = 0; i < depth; i++) {
+ dstIt.rawData()[i] = TQ_UINT8_MAX - srcIt.oldRawData()[i];
+ }
+ }
+ ++srcIt;
+ ++dstIt;
+ }
+ kdDebug() << "Thread " << m_name << " finished \n";
+ };
+
+private:
+ TQString m_name;
+ KisPaintDeviceSP m_src;
+ KisPaintDeviceSP m_dst;
+ TQRect m_rect;
+
+};
+
+KisFilterInvert::KisFilterInvert() : KisFilter(id(), "colors", i18n("Invert with &Threads"))
+{
+}
+
+void KisFilterInvert::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* /*config*/, const TQRect& rect)
+{
+ kdDebug() << "Going to invert " << rect << "\n";
+ int h2 = rect.height() / 2;
+ int w2 = rect.width() / 2;
+
+ setProgressTotalSteps(4);
+ InversionThread t1("t1", src, dst, TQRect(0, 0, w2, h2));
+ InversionThread t2("t2", src, dst, TQRect(w2, 0, w2, h2));
+ InversionThread t3("t3", src, dst, TQRect(0, h2, w2, h2));
+ InversionThread t4("t4", src, dst, TQRect(w2, h2, w2, h2));
+
+ t1.start();
+ t2.start();
+ t3.start();
+ t4.start();
+ t1.wait();
+ setProgress(1);
+ t2.wait();
+ setProgress(2);
+ t3.wait();
+ setProgress(3);
+ t4.wait();
+ setProgress(4);
+
+ setProgressDone();
+}
diff --git a/chalk/plugins/filters/threadtest/threadtest.h b/chalk/plugins/filters/threadtest/threadtest.h
new file mode 100644
index 00000000..26c61a58
--- /dev/null
+++ b/chalk/plugins/filters/threadtest/threadtest.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 THREADTEST_H
+#define THREADTESt_H
+
+#include <kparts/plugin.h>
+#include "kis_filter.h"
+
+class ChalkThreadTest : public KParts::Plugin
+{
+public:
+ ChalkThreadTest(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ChalkThreadTest();
+};
+
+class KisFilterInvert : public KisFilter
+{
+public:
+ KisFilterInvert();
+public:
+ virtual void process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration*, const TQRect&);
+ static inline KisID id() { return KisID("invertthread", i18n("Invert with Threads")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+};
+
+#endif
diff --git a/chalk/plugins/filters/unsharp/Makefile.am b/chalk/plugins/filters/unsharp/Makefile.am
new file mode 100644
index 00000000..fb34c63e
--- /dev/null
+++ b/chalk/plugins/filters/unsharp/Makefile.am
@@ -0,0 +1,20 @@
+chalkrcdir = $(kde_datadir)/chalk/chalkplugins
+
+kde_services_DATA = chalkunsharpfilter.desktop
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkunsharpfilter_la_SOURCES = wdgunsharp.ui kis_wdg_unsharp.cc unsharp.cc kis_unsharp_filter.cc
+
+kde_module_LTLIBRARIES = chalkunsharpfilter.la
+
+chalkunsharpfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkunsharpfilter_la_LIBADD = ../../../libchalkcommon.la
+
+METASOURCES = AUTO
diff --git a/chalk/plugins/filters/unsharp/chalkunsharpfilter.desktop b/chalk/plugins/filters/unsharp/chalkunsharpfilter.desktop
new file mode 100644
index 00000000..cbf7edcf
--- /dev/null
+++ b/chalk/plugins/filters/unsharp/chalkunsharpfilter.desktop
@@ -0,0 +1,40 @@
+[Desktop Entry]
+Icon=
+Name=Image enhancement Filters (Extension)
+Name[bg]=Филтри за подобрения (разширения)
+Name[ca]=Filtres de millora d'imatge (Extensió)
+Name[da]=Billedforbedringsfiltre (Udvidelse)
+Name[de]=Verbesserungsfilter (Erweiterung)
+Name[el]=Φίλτρα βελτίωσης εικόνας (Επέκταση)
+Name[es]=Filtros de realce de imagen (Extensión)
+Name[et]=Parandusfiltrid (laiendus)
+Name[fa]=پالایه‌های تقویت تصویر )پسوند(
+Name[fr]=Filtres d'amélioration d'images (extension)
+Name[fy]=Ofbyldingsfilters (útwreiding)
+Name[gl]=Filtros de Mellora da Imaxe (Extensións)
+Name[hu]=Képjavító szűrők (kiterjesztés)
+Name[it]=Filtri di miglioramento delle immagini (estensione)
+Name[ja]=画像エンハンスメントフィルタ (拡張)
+Name[km]=តម្រង​ធ្វើ​ឲ្យ​រូបភាព​ប្រសើរ (ផ្នែក​បន្ថែម)
+Name[nb]=Bildeforbedringsfiltre (Utvidelse)
+Name[nds]=Verbeternfilter (Verwiedern)
+Name[ne]=छवि अधिकता फिल्टरहरू (अपवाद)
+Name[nl]=Afbeeldingsfilters (extensie)
+Name[pl]=Filtry poprawy jakości (rozszerzenie)
+Name[pt]=Filtros de Melhoramento de Imagem (Extensão)
+Name[pt_BR]=Filtros de Melhoramento de Imagem (Extensão)
+Name[ru]=Улучшение изображения (расширение)
+Name[se]=Govvabuoridansillit (viiddádus)
+Name[sk]=Filtre vylepšenia obrázkov (rozšírenie)
+Name[sl]=Filtri za izboljšanje slike (razširitev)
+Name[sr]=Филтери за побољшање слика (проширење)
+Name[sr@Latn]=Filteri za poboljšanje slika (proširenje)
+Name[sv]=Bildförbättringsfilter (utökning)
+Name[uk]=Фільтри покращання зображення (розширення)
+Name[uz]=Rasmning sifatini oshirish filterlari (kengaytma)
+Name[uz@cyrillic]=Расмнинг сифатини ошириш филтерлари (кенгайтма)
+Name[zh_TW]=增強過濾器(延伸)
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkunsharpfilter
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/unsharp/kis_unsharp_filter.cc b/chalk/plugins/filters/unsharp/kis_unsharp_filter.cc
new file mode 100644
index 00000000..d9539920
--- /dev/null
+++ b/chalk/plugins/filters/unsharp/kis_unsharp_filter.cc
@@ -0,0 +1,152 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_unsharp_filter.h"
+
+#include <kcombobox.h>
+#include <knuminput.h>
+
+#include <kis_autobrush_resource.h>
+#include <kis_convolution_painter.h>
+#include <kis_iterators_pixel.h>
+
+
+#include "kis_wdg_unsharp.h"
+#include "wdgunsharp.h"
+
+KisKernelSP kernelFromTQImage(const TQImage& img)
+{
+ KisKernelSP k = new KisKernel;
+ k->width = img.width();
+ k->height = img.height();
+ k->offset = 0;
+ uint count = k->width * k->height;
+ k->data = new TQ_INT32[count];
+ TQ_INT32* itData = k->data;
+ TQ_UINT8* itImg = (TQ_UINT8*)img.bits();
+ k->factor = 0;
+ for(uint i = 0; i < count; ++i , ++itData, itImg+=4)
+ {
+ *itData = 255 - ( *itImg + *(itImg+1) + *(itImg+2) ) / 3;
+ k->factor += *itData;
+ }
+ return k;
+}
+
+
+KisUnsharpFilter::KisUnsharpFilter() : KisFilter(id(), "enhance", i18n("&Unsharp Mask..."))
+{
+}
+
+KisFilterConfigWidget * KisUnsharpFilter::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP )
+{
+ return new KisWdgUnsharp(this, tqparent, "configuration of color to alpha");
+}
+
+KisFilterConfiguration* KisUnsharpFilter::configuration(TQWidget* w)
+{
+ KisWdgUnsharp * wCTA = dynamic_cast<KisWdgUnsharp*>(w);
+ KisFilterConfiguration* config = new KisFilterConfiguration(id().id(), 1);
+ if(wCTA)
+ {
+ config->setProperty("halfSize", wCTA->widget()->intHalfSize->value() );
+ config->setProperty("amount", wCTA->widget()->doubleAmount->value() );
+ config->setProperty("threshold", wCTA->widget()->intThreshold->value() );
+ }
+ return config;
+ return 0;
+}
+
+void KisUnsharpFilter::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* config, const TQRect& rect)
+{
+ Q_ASSERT(src != 0);
+ Q_ASSERT(dst != 0);
+
+ setProgressTotalSteps(rect.width() * rect.height());
+
+ if(!config) config = new KisFilterConfiguration(id().id(), 1);
+
+ TQVariant value;
+ uint halfSize = (config->getProperty("halfSize", value)) ? value.toUInt() : 4;
+ uint size = 2 * halfSize + 1;
+ double amount = (config->getProperty("amount", value)) ? value.toDouble() : 0.5;
+ uint threshold = (config->getProperty("threshold", value)) ? value.toUInt() : 10;
+
+ kdDebug() << " brush size = " << size << " " << halfSize << endl;
+ KisAutobrushShape* kas = new KisAutobrushCircleShape(size, size , halfSize, halfSize);
+
+ TQImage tqmask;
+ kas->createBrush(&tqmask);
+
+ KisKernelSP kernel = kernelFromTQImage(tqmask); // TODO: for 1.6 reuse the chalk's core function for creating kernel : KisKernel::fromTQImage
+
+ KisPaintDeviceSP interm = new KisPaintDevice(*src);
+ KisColorSpace * cs = src->colorSpace();
+
+ KisConvolutionPainter painter( interm );
+ painter.beginTransaction("bouuh");
+ painter.applyMatrix(kernel, rect.x(), rect.y(), rect.width(), rect.height(), BORDER_REPEAT);
+
+ if (painter.cancelRequested()) {
+ cancel();
+ }
+
+ KisHLineIteratorPixel dstIt = dst->createHLineIterator(rect.x(), rect.y(), rect.width(), true );
+ KisHLineIteratorPixel srcIt = src->createHLineIterator(rect.x(), rect.y(), rect.width(), false);
+ KisHLineIteratorPixel intermIt = interm->createHLineIterator(rect.x(), rect.y(), rect.width(), false);
+
+ TQ_UINT8 *colors[2];
+
+ int pixelsProcessed = 0;
+ TQ_INT32 weights[2];
+/* weights[0] = 128;
+ TQ_INT32 factor = (TQ_UINT32) 128 / amount;
+ weights[1] = (factor - 128);*/
+ TQ_INT32 factor = 128;
+ weights[0] = factor * ( 1. + amount);
+ weights[1] = -factor * amount;
+ kdDebug() << (int) weights[0] << " " << (int)weights[1] << " " << factor << endl;
+ for( int j = 0; j < rect.height(); j++)
+ {
+ while( ! srcIt.isDone() )
+ {
+ if(srcIt.isSelected())
+ {
+ TQ_UINT8 diff = cs->difference(srcIt.oldRawData(), intermIt.rawData());
+ if( diff > threshold)
+ {
+ colors[0] = srcIt.rawData();
+ colors[1] = intermIt.rawData();
+ cs->convolveColors(colors, weights, KisChannelInfo::FLAG_COLOR, dstIt.rawData(), factor, 0, 2 );
+ }
+ }
+ setProgress(++pixelsProcessed);
+ ++srcIt;
+ ++dstIt;
+ ++intermIt;
+ }
+ srcIt.nextRow();
+ dstIt.nextRow();
+ intermIt.nextRow();
+ }
+
+
+ setProgressDone(); // Must be called even if you don't really support progression
+}
diff --git a/chalk/plugins/filters/unsharp/kis_unsharp_filter.h b/chalk/plugins/filters/unsharp/kis_unsharp_filter.h
new file mode 100644
index 00000000..0f25f318
--- /dev/null
+++ b/chalk/plugins/filters/unsharp/kis_unsharp_filter.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_BLUR_FILTER_H
+#define KIS_BLUR_FILTER_H
+
+// TODO: remove that
+#define LCMS_HEADER <lcms.h>
+// TODO: remove it !
+
+#include "kis_filter.h"
+
+class KisUnsharpFilter : public KisFilter
+{
+ public:
+ KisUnsharpFilter();
+ public:
+ virtual void process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration*, const TQRect&);
+ static inline KisID id() { return KisID("unsharptqmask", i18n("Unsharp Mask")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ virtual bool supportsAdjustmentLayers() { return false; }
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return FULLY_INDEPENDENT; };
+ public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration* configuration(TQWidget*);
+};
+
+#endif
diff --git a/chalk/plugins/filters/unsharp/kis_wdg_unsharp.cc b/chalk/plugins/filters/unsharp/kis_wdg_unsharp.cc
new file mode 100644
index 00000000..4a59a224
--- /dev/null
+++ b/chalk/plugins/filters/unsharp/kis_wdg_unsharp.cc
@@ -0,0 +1,52 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_wdg_unsharp.h"
+
+#include <tqlayout.h>
+#include <tqtoolbutton.h>
+
+#include <kcombobox.h>
+#include <knuminput.h>
+
+#include <kis_filter.h>
+
+#include "wdgunsharp.h"
+
+KisWdgUnsharp::KisWdgUnsharp( KisFilter* , TQWidget * tqparent, const char * name) : KisFilterConfigWidget ( tqparent, name )
+{
+ TQGridLayout *widgetLayout = new TQGridLayout(this, 1, 1);
+ m_widget = new WdgUnsharp(this);
+ widgetLayout -> addWidget(m_widget,0,0);
+
+ connect( widget()->intHalfSize, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->doubleAmount, TQT_SIGNAL( valueChanged(double)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->intThreshold, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+}
+
+void KisWdgUnsharp::setConfiguration(KisFilterConfiguration* config)
+{
+ TQVariant value;
+ widget()->intHalfSize->setValue( (config->getProperty("halfSize", value)) ? value.toUInt() : 4 );
+ widget()->doubleAmount->setValue( (config->getProperty("amount", value)) ? value.toDouble() : 0.1 );
+ widget()->intThreshold->setValue( (config->getProperty("threshold", value)) ? value.toUInt() : 20 );
+}
+
+#include "kis_wdg_unsharp.moc"
diff --git a/chalk/plugins/filters/unsharp/kis_wdg_unsharp.h b/chalk/plugins/filters/unsharp/kis_wdg_unsharp.h
new file mode 100644
index 00000000..52ffb584
--- /dev/null
+++ b/chalk/plugins/filters/unsharp/kis_wdg_unsharp.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_WDG_UNSHARP_H_
+#define _KIS_WDG_UNSHARP_H_
+
+// TODO: remove that
+#define LCMS_HEADER <lcms.h>
+// TODO: remove it !
+
+#include <kis_filter_config_widget.h>
+
+class KisFilter;
+class WdgUnsharp;
+
+class KisWdgUnsharp : public KisFilterConfigWidget
+{
+ Q_OBJECT
+ TQ_OBJECT
+ public:
+ KisWdgUnsharp( KisFilter* nfilter, TQWidget * tqparent, const char * name);
+ inline WdgUnsharp* widget() { return m_widget; };
+ virtual void setConfiguration(KisFilterConfiguration*);
+ private:
+ WdgUnsharp* m_widget;
+};
+
+#endif
diff --git a/chalk/plugins/filters/unsharp/unsharp.cc b/chalk/plugins/filters/unsharp/unsharp.cc
new file mode 100644
index 00000000..60516f42
--- /dev/null
+++ b/chalk/plugins/filters/unsharp/unsharp.cc
@@ -0,0 +1,50 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 "unsharp.h"
+
+#include <kgenericfactory.h>
+
+#include "kis_unsharp_filter.h"
+
+typedef KGenericFactory<UnsharpPlugin> UnsharpPluginFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkunsharpfilter, UnsharpPluginFactory( "chalk" ) )
+
+UnsharpPlugin::UnsharpPlugin(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(UnsharpPluginFactory::instance());
+
+
+ kdDebug(41006) << "Extensions Image enhancement Filters plugin. Class: "
+ << className()
+ << ", Parent: "
+ << tqparent -> className()
+ << "\n";
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisUnsharpFilter());
+ }
+}
+
+UnsharpPlugin::~UnsharpPlugin()
+{
+}
diff --git a/chalk/plugins/filters/unsharp/unsharp.h b/chalk/plugins/filters/unsharp/unsharp.h
new file mode 100644
index 00000000..59a92694
--- /dev/null
+++ b/chalk/plugins/filters/unsharp/unsharp.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 _UNSHARP_PLUGIN_H_
+#define _UNSHARP_PLUGIN_H_
+
+// TODO: remove that
+#define LCMS_HEADER <lcms.h>
+// TODO: remove it !
+
+#include <kparts/plugin.h>
+
+class UnsharpPlugin : public KParts::Plugin
+{
+public:
+ UnsharpPlugin(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~UnsharpPlugin();
+};
+
+#endif
diff --git a/chalk/plugins/filters/unsharp/wdgunsharp.ui b/chalk/plugins/filters/unsharp/wdgunsharp.ui
new file mode 100644
index 00000000..376ed16e
--- /dev/null
+++ b/chalk/plugins/filters/unsharp/wdgunsharp.ui
@@ -0,0 +1,138 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgUnsharp</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgUnsharp</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>181</width>
+ <height>81</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="KIntNumInput" row="0" column="1">
+ <property name="name">
+ <cstring>intHalfSize</cstring>
+ </property>
+ <property name="value">
+ <number>4</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="maxValue">
+ <number>1000</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Half-size:</string>
+ </property>
+ </widget>
+ <widget class="KDoubleNumInput" row="1" column="1">
+ <property name="name">
+ <cstring>doubleAmount</cstring>
+ </property>
+ <property name="value">
+ <number>0.5</number>
+ </property>
+ <property name="maxValue">
+ <number>5</number>
+ </property>
+ <property name="precision">
+ <number>2</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Threshold:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Amount:</string>
+ </property>
+ </widget>
+ <spacer row="1" column="2">
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>21</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KIntNumInput" row="2" column="1">
+ <property name="name">
+ <cstring>intThreshold</cstring>
+ </property>
+ <property name="value">
+ <number>10</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>255</number>
+ </property>
+ </widget>
+ <spacer row="3" column="1">
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/filters/wavefilter/Makefile.am b/chalk/plugins/filters/wavefilter/Makefile.am
new file mode 100644
index 00000000..0e4aacf9
--- /dev/null
+++ b/chalk/plugins/filters/wavefilter/Makefile.am
@@ -0,0 +1,23 @@
+chalkrcdir = $(kde_datadir)/chalk/chalkplugins
+
+kde_services_DATA = chalkwavefilter.desktop
+
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkwavefilter_la_SOURCES = wavefilter.cc wdgwaveoptions.ui \
+ kis_wdg_wave.cpp
+
+kde_module_LTLIBRARIES = chalkwavefilter.la
+noinst_HEADERS = wavefilter.h kis_wdg_wave.h
+
+chalkwavefilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkwavefilter_la_LIBADD = ../../../libchalkcommon.la
+
+METASOURCES = AUTO
diff --git a/chalk/plugins/filters/wavefilter/chalkwavefilter.desktop b/chalk/plugins/filters/wavefilter/chalkwavefilter.desktop
new file mode 100644
index 00000000..4a08b628
--- /dev/null
+++ b/chalk/plugins/filters/wavefilter/chalkwavefilter.desktop
@@ -0,0 +1,72 @@
+[Desktop Entry]
+Comment=Transform an image in a wave
+Comment[bg]=Превръщане на изображение във вълна
+Comment[ca]=Transforma una imatge en una ona
+Comment[da]=Tranbsformér et billede med en bølge
+Comment[de]=Ein Bild in eine Welle transformieren
+Comment[el]=Μετασχηματισμός μιας εικόνας με κυματομορφή
+Comment[es]=Transformar una imagen en una onda
+Comment[et]=Pildi teisendamine lainefiltris
+Comment[fa]=تبدیل یک تصویر به صورت یک موج
+Comment[fr]=Transformer une image en une vague
+Comment[fy]=Transformearje in ôfbylding yn in golf
+Comment[gl]=Transforma unha imaxe nunha onda
+Comment[hu]=Kép hullámosítása
+Comment[it]=Trasforma un'immagine in un'onda
+Comment[ja]=画像を波で変形
+Comment[km]=ប្លែង​រូបភាព​ក្នុង​រលក
+Comment[nb]=Transformer et bilde i en bølge
+Comment[nds]=En Bild na en Bülg ümwanneln
+Comment[ne]=तरङमा छवि रूपान्तरण गर्नुहोस्
+Comment[nl]=Transformeer een afbeelding in een golf
+Comment[pl]=Przekształca obrazek w falę
+Comment[pt]=Transforma uma imagem numa onda
+Comment[pt_BR]=Transforma uma imagem numa onda
+Comment[ru]=Искажает изображение волнами
+Comment[sk]=Transformovať obrázok pomocou vlny
+Comment[sl]=Pretvorba slike v val
+Comment[sr]=Трансформише слику у таласу
+Comment[sr@Latn]=Transformiše sliku u talasu
+Comment[sv]=Omvandla en bild med en våg
+Comment[uk]=Спотворення зображення хвилями
+Comment[zh_TW]=在 wave 中轉換圖片
+Icon=
+Name=Wave Filter
+Name[bg]=Вълнови филтър
+Name[ca]=Filtre d'ona
+Name[da]=Bølgefilter
+Name[de]=Wellenfilter
+Name[el]=Φίλτρο κυμματομορφής
+Name[eo]=Ondofiltrilo
+Name[es]=Filtro de onda
+Name[et]=Lainefilter
+Name[fa]=پالایۀ موج
+Name[fr]=Filtre vague
+Name[fy]=Golf-filter
+Name[gl]=Filtro de Onda
+Name[hu]=Hullámszűrő
+Name[it]=Filtro onda
+Name[ja]=波フィルタ
+Name[km]=តម្រង​រលក
+Name[nb]=Bølgefilter
+Name[nds]=Bülgenfilter
+Name[ne]=तरङ फिल्टर
+Name[nl]=Golffilter
+Name[pl]=Filtr fali
+Name[pt]=Filtro de Onda
+Name[pt_BR]=Filtro de Onda
+Name[ru]=Волны
+Name[se]=Bárrosilli
+Name[sk]=Filter vlna
+Name[sl]=Filter za valove
+Name[sr]=Филтер за таласе
+Name[sr@Latn]=Filter za talase
+Name[sv]=Vågfilter
+Name[uk]=Хвилі
+Name[uz]=Toʻlqin filteri
+Name[uz@cyrillic]=Тўлқин филтери
+Name[zh_TW]=Wave 過濾器
+ServiceTypes=Chalk/Filter
+Type=Service
+X-KDE-Library=chalkwavefilter
+X-Chalk-Version=2
diff --git a/chalk/plugins/filters/wavefilter/kis_wdg_wave.cpp b/chalk/plugins/filters/wavefilter/kis_wdg_wave.cpp
new file mode 100644
index 00000000..374fc6c8
--- /dev/null
+++ b/chalk/plugins/filters/wavefilter/kis_wdg_wave.cpp
@@ -0,0 +1,90 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_wdg_wave.h"
+
+#include <tqlayout.h>
+
+#include <kcombobox.h>
+#include <knuminput.h>
+
+#include "wdgwaveoptions.h"
+
+KisWdgWave::KisWdgWave(KisFilter* /*nfilter*/, TQWidget* tqparent, const char* name)
+ : KisFilterConfigWidget(tqparent,name)
+{
+ TQGridLayout *widgetLayout = new TQGridLayout(this, 1, 1);
+ m_widget = new WdgWaveOptions(this);
+ widgetLayout -> addWidget(m_widget, 0, 0);
+
+ connect( widget()->intHWavelength, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->intHShift, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->intHAmplitude, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->cbHShape, TQT_SIGNAL( activated(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->intVWavelength, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->intVShift, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->intVAmplitude, TQT_SIGNAL( valueChanged(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+ connect( widget()->cbVShape, TQT_SIGNAL( activated(int)), TQT_SIGNAL(sigPleaseUpdatePreview()));
+}
+
+KisWdgWave::~KisWdgWave()
+{
+}
+
+void KisWdgWave::setConfiguration(KisFilterConfiguration* config)
+{
+ TQVariant value;
+ if (config->getProperty("horizontalwavelength", value))
+ {
+ widget()->intHWavelength->setValue( value.toUInt() );
+ }
+ if (config->getProperty("horizontalshift", value))
+ {
+ widget()->intHShift->setValue( value.toUInt() );
+ }
+ if (config->getProperty("horizontalamplitude", value))
+ {
+ widget()->intHAmplitude->setValue( value.toUInt() );
+ }
+ if (config->getProperty("horizontaltqshape", value))
+ {
+ widget()->cbHShape->setCurrentItem( value.toUInt() );
+ }
+ if (config->getProperty("verticalwavelength", value))
+ {
+ widget()->intVWavelength->setValue( value.toUInt() );
+ }
+ if (config->getProperty("verticalshift", value))
+ {
+ widget()->intVShift->setValue( value.toUInt() );
+ }
+ if (config->getProperty("verticalamplitude", value))
+ {
+ widget()->intVAmplitude->setValue( value.toUInt() );
+ }
+ if (config->getProperty("verticaltqshape", value))
+ {
+ widget()->cbVShape->setCurrentItem( value.toUInt() );
+ }
+}
+
+
+#include "kis_wdg_wave.moc"
+
diff --git a/chalk/plugins/filters/wavefilter/kis_wdg_wave.h b/chalk/plugins/filters/wavefilter/kis_wdg_wave.h
new file mode 100644
index 00000000..6f9b0744
--- /dev/null
+++ b/chalk/plugins/filters/wavefilter/kis_wdg_wave.h
@@ -0,0 +1,44 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_WDG_WAVE_H
+#define KIS_WDG_WAVE_H
+
+#include <kis_filter_config_widget.h>
+
+class WdgWaveOptions;
+class KisFilter;
+
+class KisWdgWave : public KisFilterConfigWidget
+{
+ Q_OBJECT
+ TQ_OBJECT
+ public:
+ KisWdgWave(KisFilter* nfilter, TQWidget* tqparent = 0, const char* name = 0);
+ ~KisWdgWave();
+ public:
+ inline WdgWaveOptions* widget() { return m_widget; };
+ virtual void setConfiguration(KisFilterConfiguration*);
+ private:
+ WdgWaveOptions* m_widget;
+};
+
+#endif
+
diff --git a/chalk/plugins/filters/wavefilter/wavefilter.cc b/chalk/plugins/filters/wavefilter/wavefilter.cc
new file mode 100644
index 00000000..1d78bafc
--- /dev/null
+++ b/chalk/plugins/filters/wavefilter/wavefilter.cc
@@ -0,0 +1,169 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+
+#include <kcombobox.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <knuminput.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_filter_registry.h>
+#include <kis_global.h>
+#include <kis_layer.h>
+#include <kis_random_sub_accessor.h>
+#include <kis_types.h>
+
+#include "kis_wdg_wave.h"
+#include "wdgwaveoptions.h"
+
+typedef KGenericFactory<ChalkWaveFilter> ChalkWaveFilterFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkwavefilter, ChalkWaveFilterFactory( "chalk" ) )
+
+class KisWaveCurve {
+ public:
+ virtual double valueAt(int x, int y) =0;
+};
+
+class KisSinusoidalWaveCurve : public KisWaveCurve {
+ public:
+ KisSinusoidalWaveCurve(int amplitude, int wavelenght, int shift) : m_amplitude(amplitude), m_wavelength(wavelenght), m_shift(shift)
+ {
+ }
+ virtual double valueAt(int x, int y)
+ {
+ 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 wavelenght, int shift) : m_amplitude(amplitude), m_wavelength(wavelenght), m_shift(shift)
+ {
+ }
+ virtual double valueAt(int x, int y)
+ {
+ return y + m_amplitude * pow( -1, (m_shift + x) / m_wavelength ) * (0.5 - (double)( (m_shift + x) % m_wavelength ) / m_wavelength );
+ }
+ private:
+ int m_amplitude, m_wavelength, m_shift;
+};
+
+
+
+ChalkWaveFilter::ChalkWaveFilter(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ChalkWaveFilterFactory::instance());
+
+
+ if (tqparent->inherits("KisFilterRegistry")) {
+ KisFilterRegistry * manager = dynamic_cast<KisFilterRegistry *>(tqparent);
+ manager->add(new KisFilterWave());
+ }
+}
+
+ChalkWaveFilter::~ChalkWaveFilter()
+{
+}
+
+KisFilterWave::KisFilterWave() : KisFilter(id(), "other", i18n("&Wave..."))
+{
+}
+
+KisFilterConfiguration* KisFilterWave::configuration(TQWidget* w)
+{
+ KisWdgWave* wN = dynamic_cast<KisWdgWave*>(w);
+ KisFilterConfiguration* config = new KisFilterConfiguration(id().id(), 1);
+ if(wN)
+ {
+ config->setProperty("horizontalwavelength", wN->widget()->intHWavelength->value() );
+ config->setProperty("horizontalshift", wN->widget()->intHShift->value() );
+ config->setProperty("horizontalamplitude", wN->widget()->intHAmplitude->value() );
+ config->setProperty("horizontaltqshape", wN->widget()->cbHShape->currentItem() );
+ config->setProperty("verticalwavelength", wN->widget()->intVWavelength->value() );
+ config->setProperty("verticalshift", wN->widget()->intVShift->value() );
+ config->setProperty("verticalamplitude", wN->widget()->intVAmplitude->value() );
+ config->setProperty("verticaltqshape", wN->widget()->cbVShape->currentItem() );
+ }
+ return config;
+}
+
+KisFilterConfigWidget * KisFilterWave::createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP /*dev*/)
+{
+ return new KisWdgWave((KisFilter*)this, (TQWidget*)tqparent, i18n("Configuration of wave filter").ascii());
+}
+
+void KisFilterWave::process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration* config, const TQRect& rect)
+{
+ Q_ASSERT(src != 0);
+ Q_ASSERT(dst != 0);
+
+ setProgressTotalSteps(rect.width() * rect.height());
+
+ TQVariant 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 horizontaltqshape = (config && config->getProperty("horizontaltqshape", 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 verticaltqshape = (config && config->getProperty("verticaltqshape", value)) ? value.toInt() : 0;
+ KisRectIteratorPixel dstIt = dst->createRectIterator(rect.x(), rect.y(), rect.width(), rect.height(), true );
+ KisWaveCurve* verticalcurve;
+ if(verticaltqshape == 1)
+ verticalcurve = new KisTriangleWaveCurve(verticalamplitude, verticalwavelength, verticalshift);
+ else
+ verticalcurve = new KisSinusoidalWaveCurve(verticalamplitude, verticalwavelength, verticalshift);
+ KisWaveCurve* horizontalcurve;
+ if(horizontaltqshape == 1)
+ horizontalcurve = new KisTriangleWaveCurve(horizontalamplitude, horizontalwavelength, horizontalshift);
+ else
+ horizontalcurve = new KisSinusoidalWaveCurve(horizontalamplitude, horizontalwavelength, horizontalshift);
+ KisRandomSubAccessorPixel srcRSA = src->createRandomSubAccessor();
+ while(!dstIt.isDone())
+ {
+ double xv = horizontalcurve->valueAt( dstIt.y(), dstIt.x() );
+ double yv = verticalcurve->valueAt( dstIt.x(), dstIt.y() );
+ srcRSA.moveTo( KisPoint( xv, yv ) );
+ srcRSA.sampledOldRawData(dstIt.rawData());
+ ++dstIt;
+ incProgress();
+ }
+ delete horizontalcurve;
+ delete verticalcurve;
+ setProgressDone(); // Must be called even if you don't really support progression
+}
diff --git a/chalk/plugins/filters/wavefilter/wavefilter.h b/chalk/plugins/filters/wavefilter/wavefilter.h
new file mode 100644
index 00000000..3397ab0b
--- /dev/null
+++ b/chalk/plugins/filters/wavefilter/wavefilter.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 WAVEFILTER_H
+#define WAVEFILTER_H
+
+#include <kparts/plugin.h>
+#include "kis_filter.h"
+
+class KisFilterConfigWidget;
+
+class ChalkWaveFilter : public KParts::Plugin
+{
+public:
+ ChalkWaveFilter(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ChalkWaveFilter();
+};
+
+class KisFilterWave : public KisFilter
+{
+ public:
+ KisFilterWave();
+ public:
+ virtual void process(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisFilterConfiguration*, const TQRect&);
+ virtual ColorSpaceIndependence colorSpaceIndependence() { return FULLY_INDEPENDENT; };
+ static inline KisID id() { return KisID("wave", i18n("Wave")); };
+ virtual bool supportsPainting() { return true; }
+ virtual bool supportsPreview() { return true; }
+ virtual bool supportsIncrementalPainting() { return false; }
+ virtual bool supportsAdjustmentLayers() { return false; }
+ public:
+ virtual KisFilterConfigWidget * createConfigurationWidget(TQWidget* tqparent, KisPaintDeviceSP dev);
+ virtual KisFilterConfiguration* configuration(TQWidget*);
+};
+
+#endif
diff --git a/chalk/plugins/filters/wavefilter/wdgwaveoptions.ui b/chalk/plugins/filters/wavefilter/wdgwaveoptions.ui
new file mode 100644
index 00000000..10fff389
--- /dev/null
+++ b/chalk/plugins/filters/wavefilter/wdgwaveoptions.ui
@@ -0,0 +1,281 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgWaveOptions</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgWaveOptions</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>223</width>
+ <height>303</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <spacer row="0" column="1">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>60</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>60</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>Horizontal Wave</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Wavelength:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="0" column="2">
+ <property name="name">
+ <cstring>intHWavelength</cstring>
+ </property>
+ <property name="value">
+ <number>50</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="maxValue">
+ <number>1000000</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Shift:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="1" column="2">
+ <property name="name">
+ <cstring>intHShift</cstring>
+ </property>
+ <property name="value">
+ <number>0</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>1000000</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Amplitude:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="2" column="2">
+ <property name="name">
+ <cstring>intHAmplitude</cstring>
+ </property>
+ <property name="value">
+ <number>20</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>1000000</number>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="3" column="1" rowspan="1" colspan="2">
+ <item>
+ <property name="text">
+ <string>Sinusoidale</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Triangle</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>cbHShape</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Shape:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>Vertical_wave</cstring>
+ </property>
+ <property name="title">
+ <string>Vertical Wave</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string>Wavelength:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="0" column="2">
+ <property name="name">
+ <cstring>intVWavelength</cstring>
+ </property>
+ <property name="value">
+ <number>50</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="maxValue">
+ <number>1000000</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel2_3</cstring>
+ </property>
+ <property name="text">
+ <string>Shift:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="1" column="2">
+ <property name="name">
+ <cstring>intVShift</cstring>
+ </property>
+ <property name="value">
+ <number>0</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>1000000</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel2_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Amplitude:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="2" column="2">
+ <property name="name">
+ <cstring>intVAmplitude</cstring>
+ </property>
+ <property name="value">
+ <number>20</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>1000000</number>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="3" column="1" rowspan="1" colspan="2">
+ <item>
+ <property name="text">
+ <string>Sinusoidale</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Triangle</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>cbVShape</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel1_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Shape:</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>kcombobox.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/paintops/Makefile.am b/chalk/plugins/paintops/Makefile.am
new file mode 100644
index 00000000..328f0162
--- /dev/null
+++ b/chalk/plugins/paintops/Makefile.am
@@ -0,0 +1,2 @@
+SUBDIRS = \
+ defaultpaintops
diff --git a/chalk/plugins/paintops/defaultpaintops/Makefile.am b/chalk/plugins/paintops/defaultpaintops/Makefile.am
new file mode 100644
index 00000000..120368c6
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/Makefile.am
@@ -0,0 +1,39 @@
+chalkimagesdir = $(prefix)/share/apps/chalk/images
+
+chalkimages_DATA = \
+ airbrush.png \
+ paintbrush.png \
+ eraser.png \
+ pencil.png
+
+
+kde_services_DATA = chalkdefaultpaintops.desktop
+
+# all_includes must remain last!
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) $(KOPAINTER_INCLUDES) $(all_includes)
+
+
+chalkdefaultpaintops_la_SOURCES = \
+ defaultpaintops_plugin.cc \
+ kis_airbrushop.cc \
+ kis_brushop.cc \
+ kis_duplicateop.cc \
+ kis_eraseop.cc \
+ kis_penop.cc \
+ kis_dlgbrushcurvecontrol.ui \
+ kis_smudgeop.cc
+
+noinst_HEADERS = defaultpaintops_plugin.h kis_airbrushop.h kis_brushop.h \
+ kis_duplicateop.h kis_eraseop.h kis_penop.h kis_smudgeop.h
+
+kde_module_LTLIBRARIES = chalkdefaultpaintops.la
+
+chalkdefaultpaintops_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkdefaultpaintops_la_LIBADD = ../../../libchalkcommon.la $(LIB_KOPAINTER) $(LIB_KOFFICECORE)
+
+chalkdefaultpaintops_la_METASOURCES = AUTO
diff --git a/chalk/plugins/paintops/defaultpaintops/README b/chalk/plugins/paintops/defaultpaintops/README
new file mode 100644
index 00000000..47b07ce7
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/README
@@ -0,0 +1,3 @@
+Default implementations of the paintop interface. These may
+some day become plugins. New paintops should be created as
+plugins.
diff --git a/chalk/plugins/paintops/defaultpaintops/airbrush.png b/chalk/plugins/paintops/defaultpaintops/airbrush.png
new file mode 100644
index 00000000..36c1d707
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/airbrush.png
Binary files differ
diff --git a/chalk/plugins/paintops/defaultpaintops/chalkdefaultpaintops.desktop b/chalk/plugins/paintops/defaultpaintops/chalkdefaultpaintops.desktop
new file mode 100644
index 00000000..e1c940b2
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/chalkdefaultpaintops.desktop
@@ -0,0 +1,93 @@
+[Desktop Entry]
+Name=Default Paint Operations
+Name[bg]=Операции за рисуване по подразбиране
+Name[ca]=Operacions de pintura per defecte
+Name[cy]=Gweithrediadau Paent Rhagosodol
+Name[da]=Standard maleoperationer
+Name[de]=Standard Maloperation
+Name[el]=Προκαθορισμένες λειτουργίες ζωγραφικής
+Name[eo]=Aprioraj pentrooperacioj
+Name[es]=Operaciones de pintura predefinidas
+Name[et]=Vaikimisi joonistamistoimingud
+Name[eu]=Margotze-eragiketa lehenetsiak
+Name[fa]=عملیات رنگ‌آمیزی پیش‌فرض
+Name[fi]=Oletusväritystoimenpiteet
+Name[fr]=Opérations de dessin par défaut
+Name[fy]=Standertskilderaksjes
+Name[ga]=Oibríochtaí Réamhshocraithe Péinteála
+Name[gl]=Operacións de Pintura Predefinidas
+Name[he]=פעולות הצביעה המוגדרות כברירת מחדל
+Name[hu]=Alapértelmezett festési műveletek
+Name[is]=Sjálfgefnar málunaraðgerðir
+Name[it]=Operazioni predefinite di disegno
+Name[ja]=標準の描画操作
+Name[km]=ប្រតិបត្តិការ​គូរ​លំនាំដើម
+Name[ms]=Operasi Cat Piawai
+Name[nb]=Standard maleteknikker
+Name[nds]=Standard-Maalakschonen
+Name[ne]=पूर्वनिर्धारित पेन्ट सञ्चालन
+Name[nl]=Standaardschilderoperaties
+Name[nn]=Standard måleoperasjonar
+Name[pl]=Domyślne operacje na obrazkach
+Name[pt]=Operações de Pintura Predefinidas
+Name[pt_BR]=Operações de pintura padrão
+Name[ru]=Стандартные инструменты рисования
+Name[se]=Standárda málendoaimmat
+Name[sk]=Štandardné operácie kreslenia
+Name[sl]=Privzete operacije za slikanje
+Name[sr]=Подразумеване сликарске операције
+Name[sr@Latn]=Podrazumevane slikarske operacije
+Name[sv]=Förvalda målningsåtgärder
+Name[uk]=Типові дії малювання
+Name[uz]=Andoza chizish amallari
+Name[uz@cyrillic]=Андоза чизиш амаллари
+Name[zh_CN]=默认绘图操作
+Name[zh_TW]=預設繪圖操作
+Comment=Default paint operations
+Comment[bg]=Операции за рисуване по подразбиране
+Comment[ca]=Operacions de pintura per defecte
+Comment[cy]=Gweithrediadau paent rhagosodol
+Comment[da]=Standard maleoperationer
+Comment[de]=Standard Maloperation
+Comment[el]=Προκαθορισμένες λειτουργίες ζωγραφικής
+Comment[eo]=Aprioraj pentrooperacioj
+Comment[es]=Operaciones de pintado predefinidas
+Comment[et]=Vaikimisi joonistamistoimingud
+Comment[eu]=Margotze-eragiketa lehenetsiak
+Comment[fa]=عملیات رنگ‌آمیزی پیش‌فرض
+Comment[fi]=Oletusväritystoimenpiteet
+Comment[fr]=Opérations de dessin par défaut
+Comment[fy]=Standertskilderaksjes
+Comment[ga]=Oibríochtaí réamhshocraithe péinteála
+Comment[gl]=Operacións de pintura predefinidas
+Comment[he]=פעולות הצביעה המוגדרות כברירת מחדל
+Comment[hu]=Alapértelmezett festési műveletek
+Comment[is]=Sjálfgefnar málunaraðgerðir
+Comment[it]=Operazioni predefinite di disegno
+Comment[ja]=標準の描画操作
+Comment[km]=ប្រតិបត្តិកា​គូរ​លំនាំ​ដើម​
+Comment[ms]=Operasi cat piawai
+Comment[nb]=Standard maleteknikker
+Comment[nds]=Standard-Maalakschonen
+Comment[ne]=पूर्वनिर्धारित पेन्ट सञ्चालन
+Comment[nl]=Standaardschilderoperaties
+Comment[nn]=Standard måleoperasjonar
+Comment[pl]=Domyślne operacje na obrazkach
+Comment[pt]=Operações de pintura predefinidas
+Comment[pt_BR]=Operações de pintura padrão
+Comment[ru]=Инструменты рисования по умолчанию
+Comment[se]=Standárda málendoaimmat
+Comment[sk]=Štandardné operácie kreslenia
+Comment[sl]=Privzete operacije za slikanje
+Comment[sr]=Подразумеване сликарске операције
+Comment[sr@Latn]=Podrazumevane slikarske operacije
+Comment[sv]=Förvalda målningsåtgärder
+Comment[uk]=Типові дії малювання
+Comment[uz]=Andoza chizish amallari
+Comment[uz@cyrillic]=Андоза чизиш амаллари
+Comment[zh_CN]=默认绘图操作
+Comment[zh_TW]=預設繪圖操作
+ServiceTypes=Chalk/Paintop
+Type=Service
+X-KDE-Library=chalkdefaultpaintops
+X-Chalk-Version=2
diff --git a/chalk/plugins/paintops/defaultpaintops/defaultpaintops_plugin.cc b/chalk/plugins/paintops/defaultpaintops/defaultpaintops_plugin.cc
new file mode 100644
index 00000000..5a267f57
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/defaultpaintops_plugin.cc
@@ -0,0 +1,70 @@
+/*
+ * defaultpaintops_plugin.cc -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_paintop_registry.h>
+
+#include "kis_airbrushop.h"
+#include "kis_brushop.h"
+#include "kis_duplicateop.h"
+#include "kis_eraseop.h"
+#include "kis_smudgeop.h"
+#include "kis_penop.h"
+#include "kis_global.h"
+#include "kis_paintop_registry.h"
+
+#include "defaultpaintops_plugin.h"
+
+typedef KGenericFactory<DefaultPaintOpsPlugin> DefaultPaintOpsPluginFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkdefaultpaintops, DefaultPaintOpsPluginFactory( "chalkcore" ) )
+
+
+DefaultPaintOpsPlugin::DefaultPaintOpsPlugin(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(DefaultPaintOpsPluginFactory::instance());
+
+ // This is not a gui plugin; only load it when the doc is created.
+ if ( tqparent->inherits("KisPaintOpRegistry") )
+ {
+ KisPaintOpRegistry * r = dynamic_cast<KisPaintOpRegistry*>(tqparent);
+ // Add hard-coded paint ops. Plugin paintops will add
+ // themselves in the plugin initialization code.
+ r->add ( new KisAirbrushOpFactory );
+ r->add ( new KisBrushOpFactory );
+ r->add ( new KisDuplicateOpFactory );
+ r->add ( new KisEraseOpFactory );
+ r->add ( new KisPenOpFactory );
+ r->add ( new KisSmudgeOpFactory );
+ }
+
+}
+
+DefaultPaintOpsPlugin::~DefaultPaintOpsPlugin()
+{
+}
+
+#include "defaultpaintops_plugin.moc"
diff --git a/chalk/plugins/paintops/defaultpaintops/defaultpaintops_plugin.h b/chalk/plugins/paintops/defaultpaintops/defaultpaintops_plugin.h
new file mode 100644
index 00000000..d7afb9d0
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/defaultpaintops_plugin.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2005 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 DEFAULT_PAINTOPS_PLUGIN_H_
+#define DEFAULT_PAINTOPS_PLUGIN_H_
+
+#include <kparts/plugin.h>
+
+/**
+ * A plugin wrapper that adds the paintop factories to the paintop registry.
+ */
+class DefaultPaintOpsPlugin : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ DefaultPaintOpsPlugin(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~DefaultPaintOpsPlugin();
+};
+
+#endif // DEFAULT_PAINTOPSGRAY_PLUGIN_H_
diff --git a/chalk/plugins/paintops/defaultpaintops/eraser.png b/chalk/plugins/paintops/defaultpaintops/eraser.png
new file mode 100644
index 00000000..c5461aba
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/eraser.png
Binary files differ
diff --git a/chalk/plugins/paintops/defaultpaintops/kis_airbrushop.cc b/chalk/plugins/paintops/defaultpaintops/kis_airbrushop.cc
new file mode 100644
index 00000000..85bef3f6
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/kis_airbrushop.cc
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Clarence Dang <dang@kde.org>
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <tqrect.h>
+
+#include <kdebug.h>
+
+#include "kis_vec.h"
+#include "kis_brush.h"
+#include "kis_global.h"
+#include "kis_paint_device.h"
+#include "kis_painter.h"
+#include "kis_types.h"
+#include "kis_paintop.h"
+#include "kis_layer.h"
+#include "kis_selection.h"
+#include "kis_airbrushop.h"
+
+KisPaintOp * KisAirbrushOpFactory::createOp(const KisPaintOpSettings */*settings*/, KisPainter * painter)
+{
+ KisPaintOp * op = new KisAirbrushOp(painter);
+ Q_CHECK_PTR(op);
+ return op;
+}
+
+
+KisAirbrushOp::KisAirbrushOp(KisPainter * painter)
+ : super(painter)
+{
+}
+
+KisAirbrushOp::~KisAirbrushOp()
+{
+}
+
+void KisAirbrushOp::paintAt(const KisPoint &pos, const KisPaintInformation& info)
+{
+// See: http://www.sysf.physto.se/~klere/airbrush/ for information
+// about _real_ airbrushes.
+//
+// Most graphics apps -- especially the simple ones like Kolourpaint
+// and the previous version of this routine in Chalk took a brush
+// tqshape -- often a simple ellipse -- and filled that tqshape with a
+// random 'spray' of single pixels.
+//
+// Other, more advanced graphics apps, like the Gimp or Photoshop,
+// take the brush tqshape and paint just as with the brush paint op,
+// only making the initial dab more transparent, and perhaps adding
+// extra transparence near the edges. Then, using a timer, when the
+// cursor stays in place, dab upon dab is positioned in the same
+// place, which makes the result less and less transparent.
+//
+// What I want to do here is create an airbrush that approaches a real
+// one. It won't use brush tqshapes, instead going for the old-fashioned
+// circle. Depending upon pressure, both the size of the dab and the
+// rate of paint deposition is determined. The edges of the dab are
+// more transparent than the center, with perhaps even some fully
+// transparent pixels between the near-transparent pixels.
+//
+// By pressing some to-be-determined key at the same time as pressing
+// mouse-down, one edge of the dab is made straight, to simulate
+// working with a shield.
+//
+// Tilt may be used to make the gradients more realistic, but I don't
+// have a tablet that supports tilt.
+//
+// Anyway, it's exactly twenty years ago that I have held a real
+// airbrush, for the first and up to now the last time...
+//
+
+ if (!m_painter) return;
+
+ KisPaintDeviceSP device = m_painter->device();
+
+ // For now: use the current brush tqshape -- it beats calculating
+ // ellipes and cones, and it shows the working of the timer.
+ if (!device) return;
+
+ KisBrush * brush = m_painter->brush();
+ if (! brush->canPaintFor(info) )
+ return;
+ KisPaintDeviceSP dab = m_painter->dab();
+
+ KisPoint hotSpot = brush->hotSpot(info);
+ KisPoint pt = pos - hotSpot;
+
+ TQ_INT32 x;
+ double xFraction;
+ TQ_INT32 y;
+ double yFraction;
+
+ splitCoordinate(pt.x(), &x, &xFraction);
+ splitCoordinate(pt.y(), &y, &yFraction);
+
+ if (brush->brushType() == IMAGE || brush->brushType() == PIPE_IMAGE) {
+ dab = brush->image(device->colorSpace(), info, xFraction, yFraction);
+ }
+ else {
+ KisAlphaMaskSP tqmask = brush->tqmask(info, xFraction, yFraction);
+ dab = computeDab(tqmask);
+ }
+
+ m_painter->setDab(dab); // Cache dab for future paints in the painter.
+ m_painter->setPressure(info.pressure); // Cache pressure in the current painter.
+
+ TQRect dabRect = TQRect(0, 0, brush->tqmaskWidth(info), brush->tqmaskHeight(info));
+ TQRect dstRect = TQRect(x, y, dabRect.width(), dabRect.height());
+
+ KisImage * image = device->image();
+
+ if (image != 0) {
+ dstRect &= image->bounds();
+ }
+
+ if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return;
+
+ TQ_INT32 sx = dstRect.x() - x;
+ TQ_INT32 sy = dstRect.y() - y;
+ TQ_INT32 sw = dstRect.width();
+ TQ_INT32 sh = dstRect.height();
+
+ if (m_source->hasSelection()) {
+ m_painter->bltSelection(dstRect.x(), dstRect.y(), m_painter->compositeOp(), dab.data(),
+ m_source->selection(), m_painter->opacity(), sx, sy, sw, sh);
+ }
+ else {
+ m_painter->bitBlt(dstRect.x(), dstRect.y(), m_painter->compositeOp(), dab.data(), m_painter->opacity(), sx, sy, sw, sh);
+ }
+
+ m_painter->addDirtyRect(dstRect);
+}
diff --git a/chalk/plugins/paintops/defaultpaintops/kis_airbrushop.h b/chalk/plugins/paintops/defaultpaintops/kis_airbrushop.h
new file mode 100644
index 00000000..805664d7
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/kis_airbrushop.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Clarence Dang <dang@kde.org>
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_AIRBRUSHOP_H_
+#define KIS_AIRBRUSHOP_H_
+
+#include "kis_paintop.h"
+
+class KisPoint;
+class KisPainter;
+
+class KisAirbrushOpFactory : public KisPaintOpFactory {
+
+public:
+ KisAirbrushOpFactory() {}
+ virtual ~KisAirbrushOpFactory() {}
+
+ virtual KisPaintOp * createOp(const KisPaintOpSettings *settings, KisPainter * painter);
+ virtual KisID id() { return KisID("airbrush", i18n("Pixel Airbrush")); }
+ virtual TQString pixmap() { return "airbrush.png"; }
+};
+
+
+
+class KisAirbrushOp : public KisPaintOp {
+
+ typedef KisPaintOp super;
+
+public:
+
+ KisAirbrushOp(KisPainter * painter);
+ virtual ~KisAirbrushOp();
+
+ // We want to spray even when the pointer doesn't move.
+ virtual bool incremental() { return true; }
+
+ void paintAt(const KisPoint &pos, const KisPaintInformation& info);
+
+};
+
+#endif // KIS_AIRBRUSHOP_H_
diff --git a/chalk/plugins/paintops/defaultpaintops/kis_brushop.cc b/chalk/plugins/paintops/defaultpaintops/kis_brushop.cc
new file mode 100644
index 00000000..360fa66e
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/kis_brushop.cc
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Clarence Dang <dang@kde.org>
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <string.h>
+
+#include <tqrect.h>
+#include <tqwidget.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqcheckbox.h>
+#include <tqtoolbutton.h>
+
+#include <kdebug.h>
+
+#include "kcurve.h"
+#include "kis_brush.h"
+#include "kis_global.h"
+#include "kis_paint_device.h"
+#include "kis_layer.h"
+#include "kis_painter.h"
+#include "kis_types.h"
+#include "kis_paintop.h"
+#include "kis_input_device.h"
+#include "kis_selection.h"
+#include "kis_brushop.h"
+
+#include "kis_dlgbrushcurvecontrol.h"
+
+KisPaintOp * KisBrushOpFactory::createOp(const KisPaintOpSettings *settings, KisPainter * painter)
+{
+ const KisBrushOpSettings *brushopSettings = dynamic_cast<const KisBrushOpSettings *>(settings);
+ Q_ASSERT(settings == 0 || brushopSettings != 0);
+
+ KisPaintOp * op = new KisBrushOp(brushopSettings, painter);
+ Q_CHECK_PTR(op);
+ return op;
+}
+
+KisBrushOpSettings::KisBrushOpSettings(TQWidget *tqparent)
+ : super(tqparent)
+{
+ m_optionsWidget = new TQWidget(tqparent, "brush option widget");
+ TQHBoxLayout * l = new TQHBoxLayout(m_optionsWidget);
+ l->setAutoAdd(true);
+ m_pressureVariation = new TQLabel(i18n("Pressure variation: "), m_optionsWidget);
+ m_size = new TQCheckBox(i18n("Size"), m_optionsWidget);
+ m_size->setChecked(true);
+ m_opacity = new TQCheckBox(i18n("Opacity"), m_optionsWidget);
+ m_darken = new TQCheckBox(i18n("Darken"), m_optionsWidget);
+ m_curveControl = new WdgBrushCurveControl(m_optionsWidget);
+ TQToolButton* moreButton = new TQToolButton(TQt::UpArrow, m_optionsWidget);
+ moreButton->tqsetSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding);
+ moreButton->setMinimumSize(TQSize(24,24)); // Bah, I had hoped the above line would make this unneeded
+ connect(moreButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotCustomCurves()));
+
+ m_customSize = false;
+ m_customOpacity = false;
+ m_customDarken = false;
+ // the curves will get filled in when the slot gets accepted
+}
+
+void KisBrushOpSettings::slotCustomCurves() {
+ if (m_curveControl->exec() == TQDialog::Accepted) {
+ m_customSize = m_curveControl->sizeCheckbox->isChecked();
+ m_customOpacity = m_curveControl->opacityCheckbox->isChecked();
+ m_customDarken = m_curveControl->darkenCheckbox->isChecked();
+
+ if (m_customSize) {
+ transferCurve(m_curveControl->sizeCurve, m_sizeCurve);
+ }
+ if (m_customOpacity) {
+ transferCurve(m_curveControl->opacityCurve, m_opacityCurve);
+ }
+ if (m_customDarken) {
+ transferCurve(m_curveControl->darkenCurve, m_darkenCurve);
+ }
+ }
+}
+
+void KisBrushOpSettings::transferCurve(KCurve* curve, double* target) {
+ double value;
+ for (int i = 0; i < 256; i++) {
+ value = curve->getCurveValue( i / 255.0);
+ if (value < PRESSURE_MIN)
+ target[i] = PRESSURE_MIN;
+ else if (value > PRESSURE_MAX)
+ target[i] = PRESSURE_MAX;
+ else
+ target[i] = value;
+ }
+}
+
+
+bool KisBrushOpSettings::varySize() const
+{
+ return m_size->isChecked();
+}
+
+bool KisBrushOpSettings::varyOpacity() const
+{
+ return m_opacity->isChecked();
+}
+
+bool KisBrushOpSettings::varyDarken() const
+{
+ return m_darken->isChecked();
+}
+
+KisPaintOpSettings* KisBrushOpFactory::settings(TQWidget * tqparent, const KisInputDevice& inputDevice)
+{
+ if (inputDevice == KisInputDevice::mouse()) {
+ // No options for mouse, only tablet devices
+ return 0;
+ } else {
+ return new KisBrushOpSettings(tqparent);
+ }
+}
+
+KisBrushOp::KisBrushOp(const KisBrushOpSettings *settings, KisPainter *painter)
+ : super(painter)
+ , m_pressureSize(true)
+ , m_pressureOpacity(false)
+ , m_pressureDarken(false)
+ , m_customSize(false)
+ , m_customOpacity(false)
+ , m_customDarken(false)
+{
+ if (settings != 0) {
+ m_pressureSize = settings->varySize();
+ painter->setVaryBrushSpacingWithPressureWhenDrawingALine( m_pressureSize );
+
+ m_pressureOpacity = settings->varyOpacity();
+ m_pressureDarken = settings->varyDarken();
+ m_customSize = settings->customSize();
+ m_customOpacity = settings->customOpacity();
+ m_customDarken = settings->customDarken();
+ if (m_customSize) {
+ memcpy(m_sizeCurve, settings->sizeCurve(), 256 * sizeof(double));
+ }
+ if (m_customOpacity) {
+ memcpy(m_opacityCurve, settings->opacityCurve(), 256 * sizeof(double));
+ }
+ if (m_customDarken) {
+ memcpy(m_darkenCurve, settings->darkenCurve(), 256 * sizeof(double));
+ }
+ }
+}
+
+KisBrushOp::~KisBrushOp()
+{
+ m_painter->setVaryBrushSpacingWithPressureWhenDrawingALine( true );
+}
+
+void KisBrushOp::paintAt(const KisPoint &pos, const KisPaintInformation& info)
+{
+ KisPaintInformation adjustedInfo(info);
+ if (!m_pressureSize)
+ adjustedInfo.pressure = PRESSURE_DEFAULT;
+ else if (m_customSize)
+ adjustedInfo.pressure = scaleToCurve(adjustedInfo.pressure, m_sizeCurve);
+
+ // Painting should be implemented according to the following algorithm:
+ // retrieve brush
+ // if brush == tqmask
+ // retrieve tqmask
+ // else if brush == image
+ // retrieve image
+ // subsample (tqmask | image) for position -- pos should be double!
+ // apply filters to tqmask (colour | gradient | pattern | etc.
+ // composite filtered tqmask into temporary layer
+ // composite temporary layer into target layer
+ // @see: doc/brush.txt
+
+ if (!m_painter->device()) return;
+
+ KisBrush *brush = m_painter->brush();
+
+ Q_ASSERT(brush);
+ if (!brush) return;
+ if (! brush->canPaintFor(adjustedInfo) )
+ return;
+
+ KisPaintDeviceSP device = m_painter->device();
+
+ KisPoint hotSpot = brush->hotSpot(adjustedInfo);
+ KisPoint pt = pos - hotSpot;
+
+ // Split the coordinates into integer plus fractional parts. The integer
+ // is where the dab will be positioned and the fractional part determines
+ // the sub-pixel positioning.
+ TQ_INT32 x;
+ double xFraction;
+ TQ_INT32 y;
+ double yFraction;
+
+ splitCoordinate(pt.x(), &x, &xFraction);
+ splitCoordinate(pt.y(), &y, &yFraction);
+
+ KisPaintDeviceSP dab = 0;
+
+ TQ_UINT8 origOpacity = m_painter->opacity();
+ KisColor origColor = m_painter->paintColor();
+
+ if (m_pressureOpacity) {
+ if (!m_customOpacity)
+ m_painter->setOpacity((TQ_INT8)(origOpacity * info.pressure));
+ else
+ m_painter->setOpacity((TQ_INT8)(origOpacity * scaleToCurve(info.pressure, m_opacityCurve)));
+ }
+
+ if (m_pressureDarken) {
+ KisColor darkened = origColor;
+ // Darken docs aren't really clear about what exactly the amount param can have as value...
+ TQ_UINT32 darkenAmount;
+ if (!m_customDarken)
+ darkenAmount = (TQ_INT32)(255 - 75 * info.pressure);
+ else
+ darkenAmount = (TQ_INT32)(255 - 75 * scaleToCurve(info.pressure, m_darkenCurve));
+
+ darkened.colorSpace()->darken(origColor.data(), darkened.data(),
+ darkenAmount, false, 0.0, 1);
+ m_painter->setPaintColor(darkened);
+ }
+
+ if (brush->brushType() == IMAGE || brush->brushType() == PIPE_IMAGE) {
+ dab = brush->image(device->colorSpace(), adjustedInfo, xFraction, yFraction);
+ }
+ else {
+ KisAlphaMaskSP tqmask = brush->tqmask(adjustedInfo, xFraction, yFraction);
+ dab = computeDab(tqmask);
+ }
+
+ m_painter->setPressure(adjustedInfo.pressure);
+
+ TQRect dabRect = TQRect(0, 0, brush->tqmaskWidth(adjustedInfo),
+ brush->tqmaskHeight(adjustedInfo));
+ TQRect dstRect = TQRect(x, y, dabRect.width(), dabRect.height());
+
+ KisImage * image = device->image();
+
+ if (image != 0) {
+ dstRect &= image->bounds();
+ }
+
+ if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return;
+
+ TQ_INT32 sx = dstRect.x() - x;
+ TQ_INT32 sy = dstRect.y() - y;
+ TQ_INT32 sw = dstRect.width();
+ TQ_INT32 sh = dstRect.height();
+
+ if (m_source->hasSelection()) {
+ m_painter->bltSelection(dstRect.x(), dstRect.y(), m_painter->compositeOp(), dab.data(),
+ m_source->selection(), m_painter->opacity(), sx, sy, sw, sh);
+ }
+ else {
+ m_painter->bitBlt(dstRect.x(), dstRect.y(), m_painter->compositeOp(), dab.data(), m_painter->opacity(), sx, sy, sw, sh);
+ }
+ m_painter->addDirtyRect(dstRect);
+
+ m_painter->setOpacity(origOpacity);
+ m_painter->setPaintColor(origColor);
+}
+
+#include "kis_brushop.moc"
diff --git a/chalk/plugins/paintops/defaultpaintops/kis_brushop.h b/chalk/plugins/paintops/defaultpaintops/kis_brushop.h
new file mode 100644
index 00000000..6475b3d7
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/kis_brushop.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Clarence Dang <dang@kde.org>
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_BRUSHOP_H_
+#define KIS_BRUSHOP_H_
+
+#include "kis_paintop.h"
+
+class TQWidget;
+class TQCheckBox;
+class TQLabel;
+class KisPoint;
+class KisPainter;
+class KCurve;
+class WdgBrushCurveControl;
+
+class KisBrushOpFactory : public KisPaintOpFactory {
+
+public:
+ KisBrushOpFactory() {}
+ virtual ~KisBrushOpFactory() {}
+
+ virtual KisPaintOp * createOp(const KisPaintOpSettings *settings, KisPainter * painter);
+ virtual KisID id() { return KisID("paintbrush", i18n("Pixel Brush")); }
+ virtual TQString pixmap() { return "paintbrush.png"; }
+ virtual KisPaintOpSettings *settings(TQWidget * tqparent, const KisInputDevice& inputDevice);
+};
+
+class KisBrushOpSettings : public TQObject, public KisPaintOpSettings {
+ Q_OBJECT
+ TQ_OBJECT
+ typedef KisPaintOpSettings super;
+public:
+ KisBrushOpSettings(TQWidget *tqparent);
+
+ bool varySize() const;
+ bool varyOpacity() const;
+ bool varyDarken() const;
+
+ bool customSize() const { return m_customSize; }
+ bool customOpacity() const { return m_customOpacity; }
+ bool customDarken() const { return m_customDarken; }
+ const double* sizeCurve() const { return m_sizeCurve; }
+ const double* opacityCurve() const { return m_opacityCurve; }
+ const double* darkenCurve() const { return m_darkenCurve; }
+
+ virtual TQWidget *widget() const { return m_optionsWidget; }
+private slots:
+ void slotCustomCurves();
+private:
+ void transferCurve(KCurve* curve, double* target);
+ TQWidget *m_optionsWidget;
+ TQLabel * m_pressureVariation;
+ TQCheckBox * m_size;
+ TQCheckBox * m_opacity;
+ TQCheckBox * m_darken;
+ WdgBrushCurveControl* m_curveControl;
+
+ bool m_customSize;
+ bool m_customOpacity;
+ bool m_customDarken;
+ double m_sizeCurve[256];
+ double m_opacityCurve[256];
+ double m_darkenCurve[256];
+};
+
+class KisBrushOp : public KisPaintOp {
+
+ typedef KisPaintOp super;
+
+public:
+
+ KisBrushOp(const KisBrushOpSettings *settings, KisPainter * painter);
+ virtual ~KisBrushOp();
+
+ void paintAt(const KisPoint &pos, const KisPaintInformation& info);
+
+private:
+ inline double scaleToCurve(double pressure, double* curve) const {
+ int offset = CLAMP(int(255.0 * pressure), 0, 255);
+ return curve[offset];
+ }
+ bool m_pressureSize;
+ bool m_pressureOpacity;
+ bool m_pressureDarken;
+ bool m_customSize;
+ bool m_customOpacity;
+ bool m_customDarken;
+ double m_sizeCurve[256];
+ double m_opacityCurve[256];
+ double m_darkenCurve[256];
+};
+
+#endif // KIS_BRUSHOP_H_
diff --git a/chalk/plugins/paintops/defaultpaintops/kis_convolveop.cc b/chalk/plugins/paintops/defaultpaintops/kis_convolveop.cc
new file mode 100644
index 00000000..72bf9e66
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/kis_convolveop.cc
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Clarence Dang <dang@kde.org>
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <tqrect.h>
+
+#include <kdebug.h>
+
+#include "kis_brush.h"
+#include "kis_global.h"
+#include "kis_paint_device.h"
+#include "kis_painter.h"
+#include "kis_layer.h"
+#include "kis_types.h"
+#include "kis_paintop.h"
+#include "kis_selection.h"
+#include "kis_convolveop.h"
+
+
+KisPaintOp * KisConvolveOpFactory::createOp(const KisPaintOpSettings */*settings*/, KisPainter * painter)
+{
+ KisPaintOp * op = new KisConvolveOp(painter);
+ Q_CHECK_PTR(op);
+ return op;
+}
+
+
+KisConvolveOp::KisConvolveOp(KisPainter * painter)
+ : super(painter)
+{
+}
+
+KisConvolveOp::~KisConvolveOp()
+{
+}
+
+void KisConvolveOp::paintAt(const KisPoint &/*pos*/, const KisPaintInformation& /*info*/)
+{
+ // XXX: use convolve painter here.
+
+}
diff --git a/chalk/plugins/paintops/defaultpaintops/kis_convolveop.h b/chalk/plugins/paintops/defaultpaintops/kis_convolveop.h
new file mode 100644
index 00000000..d5dc3764
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/kis_convolveop.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Clarence Dang <dang@kde.org>
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_CONVOLVEOP_H_
+#define KIS_CONVOLVEOP_H_
+
+#include "kis_paintop.h"
+
+class KisPoint;
+class KisPainter;
+
+
+class KisConvolveOpFactory : public KisPaintOpFactory {
+
+public:
+ KisConvolveOpFactory() {}
+ virtual ~KisConvolveOpFactory() {}
+
+ virtual KisPaintOp * createOp(const KisPaintOpSettings *settings, KisPainter * painter);
+ virtual KisID id() { return KisID("convolve", i18n("Convolve")); }
+};
+
+
+class KisConvolveOp : public KisPaintOp {
+
+ typedef KisPaintOp super;
+
+public:
+
+ KisConvolveOp(KisPainter * painter);
+ virtual ~KisConvolveOp();
+
+ void paintAt(const KisPoint &pos, const KisPaintInformation& info);
+
+};
+
+#endif // KIS_CONVOLVEOP_H_
diff --git a/chalk/plugins/paintops/defaultpaintops/kis_dlgbrushcurvecontrol.ui b/chalk/plugins/paintops/defaultpaintops/kis_dlgbrushcurvecontrol.ui
new file mode 100644
index 00000000..f6021ecc
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/kis_dlgbrushcurvecontrol.ui
@@ -0,0 +1,271 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgBrushCurveControl</class>
+<widget class="TQDialog">
+ <property name="name">
+ <cstring>WdgBrushCurveControl</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>477</width>
+ <height>430</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Custom Curves</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQTabWidget">
+ <property name="name">
+ <cstring>tabWidget</cstring>
+ </property>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>Widget8</cstring>
+ </property>
+ <attribute name="title">
+ <string>Size Curve</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tqlayout4</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQCheckBox">
+ <property name="name">
+ <cstring>sizeCheckbox</cstring>
+ </property>
+ <property name="text">
+ <string>Use custom curve</string>
+ </property>
+ </widget>
+ <widget class="KCurve">
+ <property name="name">
+ <cstring>sizeCurve</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>Widget9</cstring>
+ </property>
+ <attribute name="title">
+ <string>Opacity Curve</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tqlayout3</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQCheckBox">
+ <property name="name">
+ <cstring>opacityCheckbox</cstring>
+ </property>
+ <property name="text">
+ <string>Use custom curve</string>
+ </property>
+ </widget>
+ <widget class="KCurve">
+ <property name="name">
+ <cstring>opacityCurve</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>Darken Curve</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tqlayout5</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQCheckBox">
+ <property name="name">
+ <cstring>darkenCheckbox</cstring>
+ </property>
+ <property name="text">
+ <string>Use custom curve</string>
+ </property>
+ </widget>
+ <widget class="KCurve">
+ <property name="name">
+ <cstring>darkenCurve</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KCurve</class>
+ <header location="local">kcurve.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>WdgBrushCurveControl</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>WdgBrushCurveControl</receiver>
+ <slot>reject()</slot>
+ </connection>
+</connections>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcurve.h</includehint>
+ <includehint>kcurve.h</includehint>
+ <includehint>kcurve.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/paintops/defaultpaintops/kis_duplicateop.cc b/chalk/plugins/paintops/defaultpaintops/kis_duplicateop.cc
new file mode 100644
index 00000000..139ed51d
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/kis_duplicateop.cc
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Clarence Dang <dang@kde.org>
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ * Copyright (c) 2004-2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_duplicateop.h"
+
+#include <tqrect.h>
+
+#include <kdebug.h>
+
+#include "kis_brush.h"
+#include "kis_global.h"
+#include "kis_paint_device.h"
+#include "kis_layer.h"
+#include "kis_painter.h"
+#include "kis_types.h"
+#include "kis_meta_registry.h"
+#include "kis_colorspace_factory_registry.h"
+#include "kis_paintop.h"
+#include "kis_iterators_pixel.h"
+#include "kis_selection.h"
+#include "kis_perspective_grid.h"
+#include "kis_random_sub_accessor.h"
+
+KisPaintOp * KisDuplicateOpFactory::createOp(const KisPaintOpSettings */*settings*/, KisPainter * painter)
+{
+ KisPaintOp * op = new KisDuplicateOp(painter);
+ Q_CHECK_PTR(op);
+ return op;
+}
+
+
+KisDuplicateOp::KisDuplicateOp(KisPainter * painter)
+ : super(painter)
+ , m_target(0)
+ , m_srcdev(0)
+{
+}
+
+KisDuplicateOp::~KisDuplicateOp()
+{
+}
+
+double KisDuplicateOp::minimizeEnergy(const double* m, double* sol, int w, int h)
+{
+ int rowstride = 3*w;
+ double err = 0;
+ memcpy(sol, m, 3* sizeof(double) * w);
+ m+=rowstride;
+ sol+=rowstride;
+ for ( int i = 1; i < h - 1; i++)
+ {
+ memcpy(sol, m, 3* sizeof(double));
+ m+=3; sol+=3;
+ for ( int j = 3; j < rowstride-3; j++)
+ {
+ double tmp = *sol;
+ *sol = ( ( *(m - 3 ) + *(m + 3) + *(m - rowstride ) + *(m + rowstride )) + 2 * *m ) /6;
+ double diff = *sol - tmp;
+ err += diff*diff;
+ m ++; sol ++;
+ }
+ memcpy(sol, m, 3* sizeof(double));
+ m+=3; sol+=3;
+}
+ memcpy(sol, m, 3* sizeof(double) * w);
+ return err;
+}
+
+
+void KisDuplicateOp::paintAt(const KisPoint &pos, const KisPaintInformation& info)
+{
+ if (!m_painter) return;
+
+ bool heal = m_painter->duplicateHealing();
+// int healradius = m_painter->duplicateHealingRadius();
+
+ KisPaintDeviceSP device = m_painter->device();
+ if (m_source) device = m_source;
+ if (!device) return;
+
+ KisBrush * brush = m_painter->brush();
+ if (!brush) return;
+ if (! brush->canPaintFor(info) )
+ return;
+
+ KisPoint hotSpot = brush->hotSpot(info);
+ KisPoint pt = pos - hotSpot;
+
+ // Split the coordinates into integer plus fractional parts. The integer
+ // is where the dab will be positioned and the fractional part determines
+ // the sub-pixel positioning.
+ TQ_INT32 x;
+ double xFraction;
+ TQ_INT32 y;
+ double yFraction;
+
+ splitCoordinate(pt.x(), &x, &xFraction);
+ splitCoordinate(pt.y(), &y, &yFraction);
+ xFraction = yFraction = 0.0;
+
+ KisPaintDeviceSP dab = 0;
+
+ if (brush->brushType() == IMAGE ||
+ brush->brushType() == PIPE_IMAGE) {
+ dab = brush->image(device->colorSpace(), info, xFraction, yFraction);
+ dab->convertTo(KisMetaRegistry::instance()->csRegistry()->getAlpha8());
+ }
+ else {
+ KisAlphaMaskSP tqmask = brush->tqmask(info, xFraction, yFraction);
+ dab = computeDab(tqmask, KisMetaRegistry::instance()->csRegistry()->getAlpha8());
+ }
+
+ m_painter->setPressure(info.pressure);
+
+ KisPoint srcPointF = pt - m_painter->duplicateOffset();
+ TQPoint srcPoint = TQPoint(x - static_cast<TQ_INT32>(m_painter->duplicateOffset().x()),
+ y - static_cast<TQ_INT32>(m_painter->duplicateOffset().y()));
+
+
+ TQ_INT32 sw = dab->extent().width();
+ TQ_INT32 sh = dab->extent().height();
+
+ if (srcPoint.x() < 0 )
+ srcPoint.setX(0);
+
+ if( srcPoint.y() < 0)
+ srcPoint.setY(0);
+ if( !(m_srcdev && m_srcdev->colorSpace() != device->colorSpace()) )
+ {
+ m_srcdev = new KisPaintDevice(device->colorSpace(), "duplicate source dev");
+ m_target = new KisPaintDevice(device->colorSpace(), "duplicate target dev");
+ }
+ Q_CHECK_PTR(m_srcdev);
+
+ // Perspective correction ?
+ KisPainter copyPainter(m_srcdev);
+ if(m_painter->duplicatePerspectiveCorrection())
+ {
+ double startM[3][3];
+ double endM[3][3];
+ for(int i = 0; i < 3; i++)
+ {
+ for(int j = 0; j < 3; j++)
+ {
+ startM[i][j] = 0.;
+ endM[i][j] = 0.;
+ }
+ startM[i][i] = 1.;
+ endM[i][i] = 1.;
+ }
+ // First look for the grid corresponding to the start point
+ KisSubPerspectiveGrid* subGridStart = *device->image()->perspectiveGrid()->begin();//device->image()->perspectiveGrid()->gridAt(KisPoint(srcPoint.x() +hotSpot.x(),srcPoint.y() +hotSpot.y()));
+ TQRect r = TQRect(0,0, device->image()->width(), device->image()->height());
+
+#if 1
+ if(subGridStart)
+ {
+// kdDebug() << "fgrid" << endl;
+// kdDebug() << *subGridStart->topLeft() << " " << *subGridStart->topRight() << " " << *subGridStart->bottomLeft() << " " << *subGridStart->bottomRight() << endl;
+ double* b = KisPerspectiveMath::computeMatrixTransfoFromPerspective( r, *subGridStart->topLeft(), *subGridStart->topRight(), *subGridStart->bottomLeft(), *subGridStart->bottomRight());
+ for(int i = 0; i < 3; i++)
+ {
+ for(int j = 0; j < 3; j++)
+ {
+// kdDebug() << "sol[" << 3*i+j << "]=" << b[3*i+j] << endl;
+ startM[i][j] = b[3*i+j];
+ }
+ }
+
+ }
+#endif
+#if 1
+ // Second look for the grid corresponding to the end point
+ KisSubPerspectiveGrid* subGridEnd = *device->image()->perspectiveGrid()->begin();// device->image()->perspectiveGrid()->gridAt(pos);
+ if(subGridEnd)
+ {
+// kdDebug() << "second grid" << endl;
+ double* b = KisPerspectiveMath::computeMatrixTransfoToPerspective(*subGridEnd->topLeft(), *subGridEnd->topRight(), *subGridEnd->bottomLeft(), *subGridEnd->bottomRight(), r);
+ for(int i = 0; i < 3; i++)
+ {
+ for(int j = 0; j < 3; j++)
+ {
+// kdDebug() << "sol[" << 3*i+j << "]=" << b[3*i+j] << endl;
+ endM[i][j] = b[3*i+j];
+ }
+ }
+ }
+#endif
+// kdDebug()<< " oouuuuh" << srcPointF << KisPerspectiveMath::matProd(startM, KisPerspectiveMath::matProd(endM, srcPointF ) ) << KisPerspectiveMath::matProd(endM, KisPerspectiveMath::matProd(startM, srcPointF ) );
+
+ // Compute the translation in the perspective transformation space:
+ KisPoint positionStartPaintingT = KisPerspectiveMath::matProd(endM, m_painter->duplicateStart() );
+ KisPoint duplicateStartPoisitionT = KisPerspectiveMath::matProd(endM, m_painter->duplicateStart() - m_painter->duplicateOffset() );
+ KisPoint translat = duplicateStartPoisitionT - positionStartPaintingT;
+ KisRectIteratorPixel dstIt = m_srcdev->createRectIterator(0, 0, sw, sh, true);
+ KisRandomSubAccessorPixel srcAcc = device->createRandomSubAccessor();
+ //Action
+ while(!dstIt.isDone())
+ {
+ if(dstIt.isSelected())
+ {
+ KisPoint p = KisPerspectiveMath::matProd(startM, KisPerspectiveMath::matProd(endM, KisPoint(dstIt.x() + x, dstIt.y() + y) ) + translat );
+ srcAcc.moveTo( p );
+ srcAcc.sampledOldRawData( dstIt.rawData() );
+ }
+ ++dstIt;
+ }
+
+
+ } else {
+ // Or, copy the source data on the temporary device:
+ copyPainter.bitBlt(0, 0, COMPOSITE_COPY, device, srcPoint.x(), srcPoint.y(), sw, sh);
+ copyPainter.end();
+ }
+
+ // heal ?
+
+ if(heal)
+ {
+ TQ_UINT16 dataDevice[4];
+ TQ_UINT16 dataSrcDev[4];
+ TQMemArray<double> matrix ( 3 * sw * sh );
+ // First divide
+ KisColorSpace* deviceCs = device->colorSpace();
+ KisHLineIteratorPixel deviceIt = device->createHLineIterator(x, y, sw, false );
+ KisHLineIteratorPixel srcDevIt = m_srcdev->createHLineIterator(0, 0, sw, true );
+ double* matrixIt = &matrix[0];
+ for(int j = 0; j < sh; j++)
+ {
+ for(int i= 0; !srcDevIt.isDone(); i++)
+ {
+ deviceCs->toLabA16(deviceIt.rawData(), (TQ_UINT8*)dataDevice, 1);
+ deviceCs->toLabA16(srcDevIt.rawData(), (TQ_UINT8*)dataSrcDev, 1);
+ // Division
+ for( int k = 0; k < 3; k++)
+ {
+ matrixIt[k] = dataDevice[k] / (double)TQMAX(dataSrcDev [k], 1);
+ }
+ ++deviceIt;
+ ++srcDevIt;
+ matrixIt +=3;
+ }
+ deviceIt.nextRow();
+ srcDevIt.nextRow();
+ }
+ // Minimize energy
+ {
+ int iter = 0;
+ double err;
+ TQMemArray<double> solution ( 3 * sw * sh );
+ do {
+ err = minimizeEnergy(&matrix[0], &solution[0],sw,sh);
+ memcpy (&matrix[0], &solution[0], sw * sh * 3 * sizeof(double));
+ iter++;
+ } while( err < 0.00001 && iter < 100);
+ }
+
+ // Finaly multiply
+ deviceIt = device->createHLineIterator(x, y, sw, false );
+ srcDevIt = m_srcdev->createHLineIterator(0, 0, sw, true );
+ matrixIt = &matrix[0];
+ for(int j = 0; j < sh; j++)
+ {
+ for(int i= 0; !srcDevIt.isDone(); i++)
+ {
+ deviceCs->toLabA16(deviceIt.rawData(), (TQ_UINT8*)dataDevice, 1);
+ deviceCs->toLabA16(srcDevIt.rawData(), (TQ_UINT8*)dataSrcDev, 1);
+ // Multiplication
+ for( int k = 0; k < 3; k++)
+ {
+ dataSrcDev[k] = (int)CLAMP( matrixIt[k] * TQMAX( dataSrcDev[k], 1), 0, 65535 );
+ }
+ deviceCs->fromLabA16((TQ_UINT8*)dataSrcDev, srcDevIt.rawData(), 1);
+ ++deviceIt;
+ ++srcDevIt;
+ matrixIt +=3;
+ }
+ deviceIt.nextRow();
+ srcDevIt.nextRow();
+ }
+ }
+
+
+ // Add the dab as selection to the srcdev
+// KisPainter copySelection(srcdev->selection().data());
+// copySelection.bitBlt(0, 0, COMPOSITE_OVER, dab, 0, 0, sw, sh);
+// copySelection.end();
+
+ // copy the srcdev onto a new device, after applying the dab selection
+ copyPainter.begin(m_target);
+
+ copyPainter.bltMask(0, 0, COMPOSITE_OVER, m_srcdev, dab,
+ OPACITY_OPAQUE, 0, 0, sw, sh);
+ copyPainter.end();
+
+ TQRect dabRect = TQRect(0, 0, brush->tqmaskWidth(info), brush->tqmaskHeight(info));
+ TQRect dstRect = TQRect(x, y, dabRect.width(), dabRect.height());
+
+ KisImage * image = device->image();
+
+ if (image != 0) {
+ dstRect &= image->bounds();
+ }
+
+ if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return;
+
+ TQ_INT32 sx = dstRect.x() - x;
+ TQ_INT32 sy = dstRect.y() - y;
+ sw = dstRect.width();
+ sh = dstRect.height();
+
+ if (m_source->hasSelection()) {
+ m_painter->bltSelection(dstRect.x(), dstRect.y(), m_painter->compositeOp(), m_target,
+ m_source->selection(), m_painter->opacity(), sx, sy, sw, sh);
+ }
+ else {
+ m_painter->bitBlt(dstRect.x(), dstRect.y(), m_painter->compositeOp(), m_target, m_painter->opacity(), sx, sy, sw, sh);
+ }
+
+
+ m_painter->addDirtyRect(dstRect);
+}
diff --git a/chalk/plugins/paintops/defaultpaintops/kis_duplicateop.h b/chalk/plugins/paintops/defaultpaintops/kis_duplicateop.h
new file mode 100644
index 00000000..965e0dc9
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/kis_duplicateop.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Clarence Dang <dang@kde.org>
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_DUPLICATEOP_H_
+#define KIS_DUPLICATEOP_H_
+
+#include "kis_paintop.h"
+
+class KisPoint;
+class KisPainter;
+
+class KisDuplicateOpFactory : public KisPaintOpFactory {
+
+public:
+ KisDuplicateOpFactory() {}
+ virtual ~KisDuplicateOpFactory() {}
+
+ virtual KisPaintOp * createOp(const KisPaintOpSettings *settings, KisPainter * painter);
+ virtual KisID id() { return KisID("duplicate", i18n("Duplicate")); }
+ virtual bool userVisible(KisColorSpace *) { return false; }
+
+};
+
+class KisDuplicateOp : public KisPaintOp {
+
+ typedef KisPaintOp super;
+
+
+ public:
+
+ KisDuplicateOp(KisPainter * painter);
+ virtual ~KisDuplicateOp();
+
+
+ void paintAt(const KisPoint &pos, const KisPaintInformation& info);
+ private:
+ double minimizeEnergy(const double* m, double* sol, int w, int h);
+ private:
+ KisPaintDeviceSP m_target, m_srcdev;
+
+};
+
+#endif // KIS_DUPLICATEOP_H_
diff --git a/chalk/plugins/paintops/defaultpaintops/kis_eraseop.cc b/chalk/plugins/paintops/defaultpaintops/kis_eraseop.cc
new file mode 100644
index 00000000..13045139
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/kis_eraseop.cc
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Clarence Dang <dang@kde.org>
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <tqrect.h>
+
+#include <kdebug.h>
+
+#include "kis_brush.h"
+#include "kis_global.h"
+#include "kis_paint_device.h"
+#include "kis_layer.h"
+#include "kis_painter.h"
+#include "kis_types.h"
+#include "kis_paintop.h"
+#include "kis_iterators_pixel.h"
+#include "kis_colorspace.h"
+#include "kis_selection.h"
+#include "kis_eraseop.h"
+
+KisPaintOp * KisEraseOpFactory::createOp(const KisPaintOpSettings */*settings*/, KisPainter * painter)
+{
+ KisPaintOp * op = new KisEraseOp(painter);
+ Q_CHECK_PTR(op);
+ return op;
+}
+
+
+KisEraseOp::KisEraseOp(KisPainter * painter)
+ : super(painter)
+{
+}
+
+KisEraseOp::~KisEraseOp()
+{
+}
+
+void KisEraseOp::paintAt(const KisPoint &pos, const KisPaintInformation& info)
+{
+// Erasing is traditionally in paint applications one of two things:
+// either it is painting in the 'background' color, or it is replacing
+// all pixels with transparent (black?) pixels.
+//
+// That's what this paint op does for now; however, anyone who has
+// ever worked with paper and soft pencils knows that a sharp piece of
+// eraser rubber is a pretty useful too for making sharp to fuzzy lines
+// in the graphite layer, or equally useful: for smudging skin tones.
+//
+// A smudge tool for Chalk is in the making, but when working with
+// a tablet, the eraser tip should be at least as functional as a rubber eraser.
+// That means that only after repeated or forceful application should all the
+// 'paint' or 'graphite' be removed from the surface -- a kind of pressure
+// sensitive, incremental smudge.
+//
+// And there should be an option to not have the eraser work on certain
+// kinds of material. Layers are just a hack for this; putting your ink work
+// in one layer and your pencil in another is not the same as really working
+// with the combination.
+
+ if (!m_painter) return;
+
+ KisPaintDeviceSP device = m_painter->device();
+ if (!device) return;
+
+ KisBrush *brush = m_painter->brush();
+ if (! brush->canPaintFor(info) )
+ return;
+ KisPoint hotSpot = brush->hotSpot(info);
+ KisPoint pt = pos - hotSpot;
+
+ TQ_INT32 destX;
+ double xFraction;
+ TQ_INT32 destY;
+ double yFraction;
+
+ splitCoordinate(pt.x(), &destX, &xFraction);
+ splitCoordinate(pt.y(), &destY, &yFraction);
+
+ KisAlphaMaskSP tqmask = brush->tqmask(info, xFraction, yFraction);
+
+ KisPaintDeviceSP dab = new KisPaintDevice(device->colorSpace(), "erase op dab");
+ Q_CHECK_PTR(dab);
+
+ TQ_INT32 tqmaskWidth = tqmask->width();
+ TQ_INT32 tqmaskHeight = tqmask->height();
+
+ TQRect dstRect;
+
+ KisRectIteratorPixel it = dab->createRectIterator(0, 0, tqmaskWidth, tqmaskHeight, true);
+ KisColorSpace* cs = dab->colorSpace();
+ while (!it.isDone()) {
+ cs->setAlpha(it.rawData(), TQ_UINT8_MAX - tqmask->alphaAt(it.x(), it.y()), 1);
+ ++it;
+ }
+
+ TQRect dabRect = TQRect(0, 0, tqmaskWidth, tqmaskHeight);
+ dstRect = TQRect(destX, destY, dabRect.width(), dabRect.height());
+
+ KisImage * image = device->image();
+
+ if (image != 0) {
+ dstRect &= image->bounds();
+ }
+
+ if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return;
+
+ TQ_INT32 sx = dstRect.x() - destX;
+ TQ_INT32 sy = dstRect.y() - destY;
+ TQ_INT32 sw = dstRect.width();
+ TQ_INT32 sh = dstRect.height();
+
+ if (m_source->hasSelection()) {
+ m_painter->bltSelection(dstRect.x(), dstRect.y(), COMPOSITE_ERASE, dab.data(),
+ m_source->selection(), m_painter->opacity(), sx, sy, sw, sh);
+ }
+ else {
+ m_painter->bitBlt(dstRect.x(), dstRect.y(), COMPOSITE_ERASE, dab.data(), m_painter->opacity(), sx, sy, sw, sh);
+ }
+
+ m_painter->addDirtyRect(dstRect);
+}
+
diff --git a/chalk/plugins/paintops/defaultpaintops/kis_eraseop.h b/chalk/plugins/paintops/defaultpaintops/kis_eraseop.h
new file mode 100644
index 00000000..8c88a122
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/kis_eraseop.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Clarence Dang <dang@kde.org>
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_ERASEOP_H_
+#define KIS_ERASEOP_H_
+
+#include "kis_paintop.h"
+
+class KisPoint;
+class KisPainter;
+
+class KisEraseOpFactory : public KisPaintOpFactory {
+
+public:
+ KisEraseOpFactory() {}
+ virtual ~KisEraseOpFactory() {}
+
+ virtual KisPaintOp * createOp(const KisPaintOpSettings *settings, KisPainter * painter);
+ virtual KisID id() { return KisID("eraser", i18n("Pixel Eraser")); }
+ virtual TQString pixmap() { return "eraser.png"; }
+};
+
+
+class KisEraseOp : public KisPaintOp {
+
+ typedef KisPaintOp super;
+
+public:
+
+ KisEraseOp(KisPainter * painter);
+ virtual ~KisEraseOp();
+
+ void paintAt(const KisPoint &pos, const KisPaintInformation& info);
+
+};
+
+#endif // KIS_ERASEOP_H_
diff --git a/chalk/plugins/paintops/defaultpaintops/kis_penop.cc b/chalk/plugins/paintops/defaultpaintops/kis_penop.cc
new file mode 100644
index 00000000..0fcbca02
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/kis_penop.cc
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Clarence Dang <dang@kde.org>
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <tqrect.h>
+
+#include <kdebug.h>
+
+#include "kis_brush.h"
+#include "kis_global.h"
+#include "kis_paint_device.h"
+#include "klocale.h"
+#include "kis_layer.h"
+#include "kis_painter.h"
+#include "kis_types.h"
+#include "kis_paintop.h"
+#include "kis_iterator.h"
+#include "kis_selection.h"
+#include "kis_iterators_pixel.h"
+
+#include "kis_penop.h"
+
+
+KisPaintOp * KisPenOpFactory::createOp(const KisPaintOpSettings */*settings*/, KisPainter * painter)
+{
+ KisPaintOp * op = new KisPenOp(painter);
+ Q_CHECK_PTR(op);
+ return op;
+}
+
+
+KisPenOp::KisPenOp(KisPainter * painter)
+ : super(painter)
+{
+}
+
+KisPenOp::~KisPenOp()
+{
+}
+
+void KisPenOp::paintAt(const KisPoint &pos, const KisPaintInformation& info)
+{
+ if (!m_painter) return;
+ KisPaintDeviceSP device = m_painter->device();
+ if (!device) return;
+ KisBrush * brush = m_painter->brush();
+ if (!brush) return;
+ if (! brush->canPaintFor(info) )
+ return;
+
+ KisPoint hotSpot = brush->hotSpot(info);
+ KisPoint pt = pos - hotSpot;
+
+ TQ_INT32 x = pt.roundX();
+ TQ_INT32 y = pt.roundY();
+
+ KisPaintDeviceSP dab = 0;
+ if (brush->brushType() == IMAGE ||
+ brush->brushType() == PIPE_IMAGE) {
+ dab = brush->image(device->colorSpace(), info);
+ }
+ else {
+ // Compute tqmask without sub-pixel positioning
+ KisAlphaMaskSP tqmask = brush->tqmask(info);
+ dab = computeDab(tqmask);
+ }
+
+ m_painter->setPressure(info.pressure);
+ TQRect dabRect = TQRect(0, 0, brush->tqmaskWidth(info), brush->tqmaskHeight(info));
+ TQRect dstRect = TQRect(x, y, dabRect.width(), dabRect.height());
+
+ KisImage * image = device->image();
+
+ if (image != 0) {
+ dstRect &= image->bounds();
+ }
+
+ if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return;
+
+ KisColorSpace * cs = dab->colorSpace();
+
+ // Set all alpha > opaque/2 to opaque, the rest to transparent.
+ // XXX: Using 4/10 as the 1x1 circle brush paints nothing with 0.5.
+
+ KisRectIteratorPixel pixelIt = dab->createRectIterator(dabRect.x(), dabRect.y(), dabRect.width(), dabRect.height(), true);
+
+ while (!pixelIt.isDone()) {
+ TQ_UINT8 alpha = cs->getAlpha(pixelIt.rawData());
+
+ if (alpha < (4 * OPACITY_OPAQUE) / 10) {
+ cs->setAlpha(pixelIt.rawData(), OPACITY_TRANSPARENT, 1);
+ } else {
+ cs->setAlpha(pixelIt.rawData(), OPACITY_OPAQUE, 1);
+ }
+
+ ++pixelIt;
+ }
+
+ TQ_INT32 sx = dstRect.x() - x;
+ TQ_INT32 sy = dstRect.y() - y;
+ TQ_INT32 sw = dstRect.width();
+ TQ_INT32 sh = dstRect.height();
+
+ if (m_source->hasSelection()) {
+ m_painter->bltSelection(dstRect.x(), dstRect.y(), m_painter->compositeOp(), dab.data(),
+ m_source->selection(), m_painter->opacity(), sx, sy, sw, sh);
+ }
+ else {
+ m_painter->bitBlt(dstRect.x(), dstRect.y(), m_painter->compositeOp(), dab.data(), m_painter->opacity(), sx, sy, sw, sh);
+ }
+
+ m_painter->addDirtyRect(dstRect);
+}
diff --git a/chalk/plugins/paintops/defaultpaintops/kis_penop.h b/chalk/plugins/paintops/defaultpaintops/kis_penop.h
new file mode 100644
index 00000000..ac03a501
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/kis_penop.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Clarence Dang <dang@kde.org>
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_PENOP_H_
+#define KIS_PENOP_H_
+
+#include <tqlabel.h>
+#include <tqwidget.h>
+#include "kis_paintop.h"
+
+class KisPoint;
+class KisPainter;
+
+class KisPenOpFactory : public KisPaintOpFactory {
+
+public:
+ KisPenOpFactory() {}
+ virtual ~KisPenOpFactory() {}
+
+ virtual KisPaintOp * createOp(const KisPaintOpSettings *settings, KisPainter * painter);
+ virtual KisID id(){ return KisID("pen", i18n("Pixel Pencil")); }
+ virtual TQString pixmap() { return "pencil.png"; }
+};
+
+
+class KisPenOp : public KisPaintOp {
+
+ typedef KisPaintOp super;
+
+public:
+
+ KisPenOp(KisPainter * painter);
+ virtual ~KisPenOp();
+
+ void paintAt(const KisPoint &pos, const KisPaintInformation& info);
+
+};
+
+#endif // KIS_PENOP_H_
diff --git a/chalk/plugins/paintops/defaultpaintops/kis_smudgeop.cc b/chalk/plugins/paintops/defaultpaintops/kis_smudgeop.cc
new file mode 100644
index 00000000..2e50bebb
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/kis_smudgeop.cc
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_smudgeop.h"
+
+#include <string.h>
+
+#include <tqrect.h>
+#include <tqwidget.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqcheckbox.h>
+#include <tqtabwidget.h>
+#include <tqtoolbutton.h>
+#include <tqslider.h>
+
+#include <kdebug.h>
+
+#include "kis_colorspace_factory_registry.h"
+#include "kcurve.h"
+#include "kis_brush.h"
+#include "kis_global.h"
+#include "kis_paint_device.h"
+#include "kis_layer.h"
+#include "kis_meta_registry.h"
+#include "kis_painter.h"
+#include "kis_types.h"
+#include "kis_paintop.h"
+#include "kis_input_device.h"
+#include "kis_selection.h"
+
+#include "kis_dlgbrushcurvecontrol.h"
+
+KisPaintOp * KisSmudgeOpFactory::createOp(const KisPaintOpSettings *settings, KisPainter * painter)
+{
+ const KisSmudgeOpSettings *brushopSettings = dynamic_cast<const KisSmudgeOpSettings *>(settings);
+ Q_ASSERT(settings == 0 || brushopSettings != 0);
+
+ KisPaintOp * op = new KisSmudgeOp(brushopSettings, painter);
+ Q_CHECK_PTR(op);
+ return op;
+}
+
+KisSmudgeOpSettings::KisSmudgeOpSettings(TQWidget *tqparent, bool isTablet)
+ : super(tqparent)
+{
+ m_optionsWidget = new TQWidget(tqparent, "brush option widget");
+ TQHBoxLayout * l = new TQHBoxLayout(m_optionsWidget);
+ l->setAutoAdd(true);
+ m_rateLabel = new TQLabel(i18n("Rate: "), m_optionsWidget);
+ m_rateSlider = new TQSlider(0,100,1, 50, Qt::Horizontal, m_optionsWidget);
+ if(isTablet)
+ {
+ m_pressureVariation = new TQLabel(i18n("Pressure variation: "), m_optionsWidget);
+ m_size = new TQCheckBox(i18n("Size"), m_optionsWidget);
+ m_size->setChecked(true);
+ m_opacity = new TQCheckBox(i18n("Opacity"), m_optionsWidget);
+ m_rate = new TQCheckBox(i18n("Rate"), m_optionsWidget);
+ m_curveControl = new WdgBrushCurveControl(m_optionsWidget);
+ // We abuse the darken curve here for rate
+ m_curveControl->tabWidget->setTabLabel(m_curveControl->tabWidget->page(2), i18n("Rate"));
+ m_curveControl->tabWidget->setTabToolTip(m_curveControl->tabWidget->page(2),
+ i18n("Modifies the rate. Bottom is 0% of the rate top is 100% of the original rate."));
+ TQToolButton* moreButton = new TQToolButton(TQt::UpArrow, m_optionsWidget);
+ moreButton->tqsetSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding);
+ moreButton->setMinimumSize(TQSize(24,24)); // Bah, I had hoped the above line would make this unneeded
+ connect(moreButton, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotCustomCurves()));
+ } else {
+ m_pressureVariation = 0;
+ m_size = 0;
+ m_rate = 0;
+ m_opacity = 0;
+ m_curveControl = 0;
+ }
+
+ m_customRate = false;
+ m_customSize = false;
+ m_customOpacity = false;
+ // the curves will get filled in when the slot gets accepted
+}
+
+void KisSmudgeOpSettings::slotCustomCurves() {
+ if (m_curveControl->exec() == TQDialog::Accepted) {
+ m_customRate = m_curveControl->darkenCheckbox->isChecked();
+ m_customSize = m_curveControl->sizeCheckbox->isChecked();
+ m_customOpacity = m_curveControl->opacityCheckbox->isChecked();
+
+ if (m_customRate) {
+ transferCurve(m_curveControl->darkenCurve, m_rateCurve);
+ }
+ if (m_customSize) {
+ transferCurve(m_curveControl->sizeCurve, m_sizeCurve);
+ }
+ if (m_customOpacity) {
+ transferCurve(m_curveControl->opacityCurve, m_opacityCurve);
+ }
+ }
+}
+
+void KisSmudgeOpSettings::transferCurve(KCurve* curve, double* target) {
+ double value;
+ for (int i = 0; i < 256; i++) {
+ value = curve->getCurveValue( i / 255.0);
+ if (value < PRESSURE_MIN)
+ target[i] = PRESSURE_MIN;
+ else if (value > PRESSURE_MAX)
+ target[i] = PRESSURE_MAX;
+ else
+ target[i] = value;
+ }
+}
+
+int KisSmudgeOpSettings::rate() const
+{
+ return m_rateSlider->value();
+}
+
+bool KisSmudgeOpSettings::varyRate() const
+{
+ return m_rate ? m_rate->isChecked() : false;
+}
+
+bool KisSmudgeOpSettings::varySize() const
+{
+ return m_size ? m_size->isChecked() : true;
+}
+
+bool KisSmudgeOpSettings::varyOpacity() const
+{
+ return m_opacity ? m_opacity->isChecked() : false;
+}
+
+KisPaintOpSettings* KisSmudgeOpFactory::settings(TQWidget * tqparent, const KisInputDevice& inputDevice)
+{
+ if (inputDevice == KisInputDevice::mouse()) {
+ // No options for mouse, only tablet devices
+ return new KisSmudgeOpSettings(tqparent, false);
+ } else {
+ return new KisSmudgeOpSettings(tqparent, true);
+ }
+}
+
+KisSmudgeOp::KisSmudgeOp(const KisSmudgeOpSettings *settings, KisPainter *painter)
+ : super(painter)
+ , m_firstRun(true)
+ , m_rate(50)
+ , m_pressureSize(true)
+ , m_pressureRate(false)
+ , m_pressureOpacity(false)
+ , m_customRate(false)
+ , m_customSize(false)
+ , m_customOpacity(false)
+ , m_target(0)
+ , m_srcdev(0)
+{
+ if (settings != 0) {
+ m_rate = settings->rate();
+ m_pressureRate = settings->varyRate();
+ m_pressureSize = settings->varySize();
+ m_pressureOpacity = settings->varyOpacity();
+ m_customRate = settings->customRate();
+ m_customSize = settings->customSize();
+ m_customOpacity = settings->customOpacity();
+ if (m_customSize) {
+ memcpy(m_sizeCurve, settings->sizeCurve(), 256 * sizeof(double));
+ }
+ if (m_customOpacity) {
+ memcpy(m_opacityCurve, settings->opacityCurve(), 256 * sizeof(double));
+ }
+ if (m_customRate) {
+ memcpy(m_rateCurve, settings->rateCurve(), 256 * sizeof(double));
+ }
+ }
+ KisPaintDeviceSP device = m_painter->device();
+ m_srcdev = new KisPaintDevice(device->colorSpace(), "duplicate source dev");
+ m_target = new KisPaintDevice(device->colorSpace(), "duplicate target dev");
+}
+
+KisSmudgeOp::~KisSmudgeOp()
+{
+}
+
+void KisSmudgeOp::paintAt(const KisPoint &pos, const KisPaintInformation& info)
+{
+ KisPaintInformation adjustedInfo(info);
+ if (!m_pressureSize)
+ adjustedInfo.pressure = PRESSURE_DEFAULT;
+ else if (m_customSize)
+ adjustedInfo.pressure = scaleToCurve(adjustedInfo.pressure, m_sizeCurve);
+
+ // Painting should be implemented according to the following algorithm:
+ // retrieve brush
+ // if brush == tqmask
+ // retrieve tqmask
+ // else if brush == image
+ // retrieve image
+ // subsample (tqmask | image) for position -- pos should be double!
+ // apply filters to tqmask (colour | gradient | pattern | etc.
+ // composite filtered tqmask into temporary layer
+ // composite temporary layer into target layer
+ // @see: doc/brush.txt
+
+ if (!m_painter->device()) return;
+
+ KisBrush *brush = m_painter->brush();
+
+ Q_ASSERT(brush);
+ if (!brush) return;
+ if (! brush->canPaintFor(adjustedInfo) )
+ return;
+
+ KisPaintDeviceSP device = m_painter->device();
+
+ KisPoint hotSpot = brush->hotSpot(adjustedInfo);
+ KisPoint pt = pos - hotSpot;
+
+ // Split the coordinates into integer plus fractional parts. The integer
+ // is where the dab will be positioned and the fractional part determines
+ // the sub-pixel positioning.
+ TQ_INT32 x;
+ double xFraction;
+ TQ_INT32 y;
+ double yFraction;
+
+ splitCoordinate(pt.x(), &x, &xFraction);
+ splitCoordinate(pt.y(), &y, &yFraction);
+
+ KisPaintDeviceSP dab = 0;
+
+ TQ_UINT8 origOpacity = m_painter->opacity();
+
+ if (m_pressureOpacity) {
+ if (!m_customOpacity)
+ m_painter->setOpacity((TQ_INT8)(origOpacity * info.pressure));
+ else
+ m_painter->setOpacity((TQ_INT8)(origOpacity * scaleToCurve(info.pressure, m_opacityCurve)));
+ }
+
+ if (brush->brushType() == IMAGE || brush->brushType() == PIPE_IMAGE) {
+ dab = brush->image(device->colorSpace(), adjustedInfo, xFraction, yFraction);
+ dab->convertTo(KisMetaRegistry::instance()->csRegistry()->getAlpha8());
+ }
+ else {
+ KisAlphaMaskSP tqmask = brush->tqmask(adjustedInfo, xFraction, yFraction);
+ dab = computeDab(tqmask, KisMetaRegistry::instance()->csRegistry()->getAlpha8());
+ }
+
+
+ m_painter->setPressure(adjustedInfo.pressure);
+
+ TQRect dabRect = TQRect(0, 0, brush->tqmaskWidth(adjustedInfo),
+ brush->tqmaskHeight(adjustedInfo));
+ TQRect dstRect = TQRect(x, y, dabRect.width(), dabRect.height());
+
+ KisImage * image = device->image();
+
+ if (image != 0) {
+ dstRect &= image->bounds();
+ }
+
+ TQ_INT32 sw = dab->extent().width();
+ TQ_INT32 sh = dab->extent().height();
+
+ KisPainter copyPainter(m_srcdev);
+ int opacity = OPACITY_OPAQUE;
+ if(!m_firstRun)
+ {
+ opacity = rate();
+ if (m_pressureRate) {
+ if (m_customRate) {
+ opacity = CLAMP((TQ_UINT8)(double(opacity) * scaleToCurve(info.pressure, m_rateCurve)), OPACITY_TRANSPARENT, OPACITY_OPAQUE);
+ } else {
+ opacity = CLAMP((TQ_UINT8)(double(opacity) * info.pressure), OPACITY_TRANSPARENT, OPACITY_OPAQUE);
+ }
+ }
+ opacity = OPACITY_OPAQUE - opacity;
+ } else {
+ m_firstRun = false;
+ }
+ copyPainter.bitBlt(0, 0, COMPOSITE_OVER, device, opacity, pt.x(), pt.y(), sw, sh);
+ copyPainter.end();
+
+ m_target = new KisPaintDevice(device->colorSpace(), "duplicate target dev");
+
+ copyPainter.begin(m_target);
+
+ copyPainter.bltMask(0, 0, COMPOSITE_OVER, m_srcdev, dab,
+ OPACITY_OPAQUE, 0, 0, sw, sh);
+ copyPainter.end();
+
+
+ if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return;
+
+ TQ_INT32 sx = dstRect.x() - x;
+ TQ_INT32 sy = dstRect.y() - y;
+ sw = dstRect.width();
+ sh = dstRect.height();
+
+ if (m_source->hasSelection()) {
+ m_painter->bltSelection(dstRect.x(), dstRect.y(), m_painter->compositeOp(), m_target,
+ m_source->selection(), m_painter->opacity(), sx, sy, sw, sh);
+ }
+ else {
+ m_painter->bitBlt(dstRect.x(), dstRect.y(), m_painter->compositeOp(), m_target, m_painter->opacity(), sx, sy, sw, sh);
+ }
+
+ m_painter->addDirtyRect(dstRect);
+
+ m_painter->setOpacity(origOpacity);
+
+}
+
+#include "kis_smudgeop.moc"
diff --git a/chalk/plugins/paintops/defaultpaintops/kis_smudgeop.h b/chalk/plugins/paintops/defaultpaintops/kis_smudgeop.h
new file mode 100644
index 00000000..d9c8872d
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/kis_smudgeop.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_SMUDGEOP_H_
+#define KIS_SMUDGEOP_H_
+
+#include "kis_paintop.h"
+#include <tqobject.h>
+
+class TQWidget;
+class TQCheckBox;
+class TQLabel;
+class TQSlider;
+class KisPoint;
+class KisPainter;
+class KCurve;
+class WdgBrushCurveControl;
+
+class KisSmudgeOpFactory : public KisPaintOpFactory {
+
+public:
+ KisSmudgeOpFactory() {}
+ virtual ~KisSmudgeOpFactory() {}
+
+ virtual KisPaintOp * createOp(const KisPaintOpSettings *settings, KisPainter * painter);
+ virtual KisID id() { return KisID("smudge", i18n("Smudge Brush")); }
+ virtual TQString pixmap() { return "paintbrush.png"; }
+ virtual KisPaintOpSettings *settings(TQWidget * tqparent, const KisInputDevice& inputDevice);
+};
+
+class KisSmudgeOpSettings : public TQObject, public KisPaintOpSettings {
+ Q_OBJECT
+ TQ_OBJECT
+ typedef KisPaintOpSettings super;
+public:
+ KisSmudgeOpSettings(TQWidget *tqparent, bool isTablet);
+
+ int rate() const;
+ bool varyRate() const;
+ bool varySize() const;
+ bool varyOpacity() const;
+
+ bool customRate() const { return m_customRate; }
+ bool customSize() const { return m_customSize; }
+ bool customOpacity() const { return m_customOpacity; }
+ const double* rateCurve() const { return m_rateCurve; }
+ const double* sizeCurve() const { return m_sizeCurve; }
+ const double* opacityCurve() const { return m_opacityCurve; }
+
+ virtual TQWidget *widget() const { return m_optionsWidget; }
+private slots:
+ void slotCustomCurves();
+private:
+ void transferCurve(KCurve* curve, double* target);
+ TQWidget *m_optionsWidget;
+ TQLabel* m_rateLabel;
+ TQSlider* m_rateSlider;
+ TQLabel * m_pressureVariation;
+ TQCheckBox * m_rate;
+ TQCheckBox * m_size;
+ TQCheckBox * m_opacity;
+ WdgBrushCurveControl* m_curveControl;
+
+ bool m_customSize;
+ bool m_customRate;
+ bool m_customOpacity;
+ double m_rateCurve[256];
+ double m_sizeCurve[256];
+ double m_opacityCurve[256];
+};
+
+class KisSmudgeOp : public KisPaintOp {
+
+ typedef KisPaintOp super;
+
+public:
+
+ KisSmudgeOp(const KisSmudgeOpSettings *settings, KisPainter * painter);
+ virtual ~KisSmudgeOp();
+
+ void paintAt(const KisPoint &pos, const KisPaintInformation& info);
+
+ int rate() { return (m_rate * 255) / 100; }
+private:
+ KisPaintDeviceSP m_target, m_srcdev;
+ inline double scaleToCurve(double pressure, double* curve) const {
+ int offset = CLAMP(int(255.0 * pressure), 0, 255);
+ return curve[offset];
+ }
+ bool m_firstRun;
+ int m_rate;
+ bool m_pressureRate;
+ bool m_pressureSize;
+ bool m_pressureOpacity;
+ bool m_customRate;
+ bool m_customSize;
+ bool m_customOpacity;
+ double m_rateCurve[256];
+ double m_sizeCurve[256];
+ double m_opacityCurve[256];
+};
+
+#endif // KIS_BRUSHOP_H_
diff --git a/chalk/plugins/paintops/defaultpaintops/paintbrush.png b/chalk/plugins/paintops/defaultpaintops/paintbrush.png
new file mode 100644
index 00000000..accc0411
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/paintbrush.png
Binary files differ
diff --git a/chalk/plugins/paintops/defaultpaintops/pencil.png b/chalk/plugins/paintops/defaultpaintops/pencil.png
new file mode 100644
index 00000000..08a2f4cf
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/pencil.png
Binary files differ
diff --git a/chalk/plugins/paintops/defaultpaintops/src/README b/chalk/plugins/paintops/defaultpaintops/src/README
new file mode 100644
index 00000000..769ced65
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/src/README
@@ -0,0 +1,2 @@
+These svg images are the basis of the paintop pixmaps; they were taken from
+the OpenClipArt repository and are in the public domain.
diff --git a/chalk/plugins/paintops/defaultpaintops/src/pencil_01.svg b/chalk/plugins/paintops/defaultpaintops/src/pencil_01.svg
new file mode 100644
index 00000000..40319104
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/src/pencil_01.svg
@@ -0,0 +1,637 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ height="297mm"
+ id="svg1"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="37.290001"
+ inkscape:version="0.40"
+ sodipodi:docbase="/home/boud"
+ sodipodi:docname="pencil_01.svg"
+ sodipodi:version="0.32"
+ width="210mm"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient5522">
+ <stop
+ id="stop5523"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.96862745;" />
+ <stop
+ id="stop5525"
+ offset="1.0000000"
+ style="stop-color:#a2a2a2;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4895">
+ <stop
+ id="stop4896"
+ offset="0.0000000"
+ style="stop-color:#bfbfbf;stop-opacity:0.96875000;" />
+ <stop
+ id="stop4898"
+ offset="0.81250000"
+ style="stop-color:#000000;stop-opacity:1.0000000;" />
+ <stop
+ id="stop4897"
+ offset="1.0000000"
+ style="stop-color:#000000;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4256">
+ <stop
+ id="stop4257"
+ offset="0.0000000"
+ style="stop-color:#000000;stop-opacity:1.0000000;" />
+ <stop
+ id="stop4260"
+ offset="0.24902344"
+ style="stop-color:#000000;stop-opacity:1.0000000;" />
+ <stop
+ id="stop4262"
+ offset="0.53125000"
+ style="stop-color:#878787;stop-opacity:0.62352943;" />
+ <stop
+ id="stop4261"
+ offset="0.67773438"
+ style="stop-color:#5a5a5a;stop-opacity:1.0000000;" />
+ <stop
+ id="stop4258"
+ offset="1.0000000"
+ style="stop-color:#070707;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2387">
+ <stop
+ id="stop2388"
+ offset="0.0000000"
+ style="stop-color:#d5d5bc;stop-opacity:1.0000000;" />
+ <stop
+ id="stop2389"
+ offset="1.0000000"
+ style="stop-color:#dfdfb9;stop-opacity:0.34117648;" />
+ <stop
+ id="stop2390"
+ offset="1.0000000"
+ style="stop-color:#c2c2b2;stop-opacity:0.60392159;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1754">
+ <stop
+ id="stop1755"
+ offset="0.0000000"
+ style="stop-color:#fdfdc1;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1761"
+ offset="1.0000000"
+ style="stop-color:#dfdfb9;stop-opacity:0.34117648;" />
+ <stop
+ id="stop1756"
+ offset="1.0000000"
+ style="stop-color:#c2c2b2;stop-opacity:0.60392159;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient9845">
+ <stop
+ id="stop9846"
+ offset="0.0000000"
+ style="stop-color:#e2e5bf;stop-opacity:1.0000000;" />
+ <stop
+ id="stop9849"
+ offset="1.0000000"
+ style="stop-color:#edde91;stop-opacity:1.0000000;" />
+ <stop
+ id="stop9850"
+ offset="1.0000000"
+ style="stop-color:#e6e7d9;stop-opacity:1.0000000;" />
+ <stop
+ id="stop10479"
+ offset="1.0000000"
+ style="stop-color:#eeefe0;stop-opacity:1.0000000;" />
+ <stop
+ id="stop9847"
+ offset="1.0000000"
+ style="stop-color:#f7f7e8;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient9215">
+ <stop
+ id="stop9216"
+ offset="0.0000000"
+ style="stop-color:#5a5a5a;stop-opacity:0.26041666;" />
+ <stop
+ id="stop9217"
+ offset="0.25000000"
+ style="stop-color:#bdbdbd;stop-opacity:0.50000000;" />
+ <stop
+ id="stop9218"
+ offset="0.50000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+ <stop
+ id="stop9220"
+ offset="0.75000000"
+ style="stop-color:#aaaaaa;stop-opacity:0.53125000;" />
+ <stop
+ id="stop9219"
+ offset="1.0000000"
+ style="stop-color:#6a6a6a;stop-opacity:0.33333334;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient6713">
+ <stop
+ id="stop6714"
+ offset="0.0000000"
+ style="stop-color:#d5d51f;stop-opacity:0.46666667;" />
+ <stop
+ id="stop6715"
+ offset="0.25000000"
+ style="stop-color:#ffff9d;stop-opacity:0.64583331;" />
+ <stop
+ id="stop6716"
+ offset="0.50000000"
+ style="stop-color:#ffffb7;stop-opacity:0.79215688;" />
+ <stop
+ id="stop6717"
+ offset="1.0000000"
+ style="stop-color:#eaea1f;stop-opacity:0.34117648;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient5461">
+ <stop
+ id="stop5462"
+ offset="0.0000000"
+ style="stop-color:#ecd620;stop-opacity:1.0000000;" />
+ <stop
+ id="stop5466"
+ offset="0.50000000"
+ style="stop-color:#f5dd2d;stop-opacity:1.0000000;" />
+ <stop
+ id="stop5463"
+ offset="1.0000000"
+ style="stop-color:#fff01a;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3579">
+ <stop
+ id="stop3580"
+ offset="0.0000000"
+ style="stop-color:#d5d5d5;stop-opacity:0.46666667;" />
+ <stop
+ id="stop4205"
+ offset="0.25000000"
+ style="stop-color:#ffffff;stop-opacity:0.73958331;" />
+ <stop
+ id="stop3583"
+ offset="0.50000000"
+ style="stop-color:#ffffff;stop-opacity:0.79166669;" />
+ <stop
+ id="stop3581"
+ offset="1.0000000"
+ style="stop-color:#6a6a6a;stop-opacity:0.93750000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1706">
+ <stop
+ id="stop1707"
+ offset="0.0000000"
+ style="stop-color:#cdcdcd;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1708"
+ offset="1.0000000"
+ style="stop-color:#f5f0f5;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ gradientTransform="matrix(2.820962,0.000000,6.312385e-5,2.601095e-2,298.8738,76.89546)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3582"
+ inkscape:collect="always"
+ x1="35.424759"
+ x2="35.641914"
+ xlink:href="#linearGradient3579"
+ y1="18130.623"
+ y2="17965.547" />
+ <linearGradient
+ gradientTransform="matrix(0.202664,0.000000,0.000000,0.362058,298.8738,76.89546)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient5465"
+ inkscape:collect="always"
+ x1="1268.3737"
+ x2="1268.6208"
+ xlink:href="#linearGradient5461"
+ y1="1336.0245"
+ y2="1300.7721" />
+ <linearGradient
+ gradientTransform="matrix(6.942050e-2,0.000000,1.553402e-6,2.336613e-2,553.6438,124.8435)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient6090"
+ inkscape:collect="always"
+ x1="35.424759"
+ x2="35.641914"
+ xlink:href="#linearGradient6713"
+ y1="18130.623"
+ y2="17965.547" />
+ <linearGradient
+ gradientTransform="matrix(0.323512,0.000000,7.239130e-6,2.601095e-2,571.1883,76.96085)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient8593"
+ inkscape:collect="always"
+ x1="35.424759"
+ x2="35.641914"
+ xlink:href="#linearGradient9215"
+ y1="18130.623"
+ y2="17965.547" />
+ <linearGradient
+ gradientTransform="matrix(0.362900,0.000000,0.000000,0.202193,298.8738,76.89546)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient9857"
+ inkscape:collect="always"
+ spreadMethod="pad"
+ x1="-345.43631"
+ x2="-345.17053"
+ xlink:href="#linearGradient9845"
+ y1="2366.5361"
+ y2="2354.8115" />
+ <radialGradient
+ cx="-233.32603"
+ cy="3321.7747"
+ fx="-213.39992"
+ fy="3310.0935"
+ gradientTransform="matrix(0.517807,0.000000,0.000000,0.141706,298.8738,76.89546)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1753"
+ inkscape:collect="always"
+ r="31.490158"
+ xlink:href="#linearGradient1754" />
+ <radialGradient
+ cx="-316.48395"
+ cy="-2710.2300"
+ fx="-290.97665"
+ fy="-2729.1069"
+ gradientTransform="matrix(0.413154,0.000000,0.000000,-0.177599,298.8738,76.89546)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1763"
+ inkscape:collect="always"
+ r="28.744236"
+ xlink:href="#linearGradient2387" />
+ <linearGradient
+ gradientTransform="matrix(0.480053,0.000000,0.000000,0.152850,298.8738,76.89540)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4259"
+ inkscape:collect="always"
+ x1="-328.35983"
+ x2="-328.35986"
+ xlink:href="#linearGradient4256"
+ y1="3145.9695"
+ y2="3091.0151" />
+ <radialGradient
+ cx="2255.8301"
+ cy="894.17383"
+ fx="2254.7786"
+ fy="894.33282"
+ gradientTransform="matrix(0.137506,0.000000,0.000000,0.533619,289.9911,76.13070)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient4894"
+ inkscape:collect="always"
+ r="72.563972"
+ xlink:href="#linearGradient4895" />
+ <linearGradient
+ gradientTransform="matrix(0.101819,0.000000,0.000000,0.966086,196.9883,76.89546)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient5526"
+ inkscape:collect="always"
+ x1="3950.2200"
+ x2="3970.1528"
+ xlink:href="#linearGradient5522"
+ y1="494.74939"
+ y2="494.83701" />
+ </defs>
+ <sodipodi:namedview
+ bordercolor="#666666"
+ borderopacity="1.0"
+ id="base"
+ inkscape:current-layer="layer7"
+ inkscape:cx="303.76092"
+ inkscape:cy="410.97376"
+ inkscape:grid-bbox="false"
+ inkscape:grid-points="false"
+ inkscape:guide-bbox="false"
+ inkscape:guide-points="false"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:window-height="710"
+ inkscape:window-width="1012"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:zoom="2.0000000"
+ pagecolor="#ffffff"
+ showgrid="false"
+ showguides="false">
+ <sodipodi:guide
+ id="guide6719"
+ orientation="horizontal"
+ position="-411.00582" />
+ <sodipodi:guide
+ id="guide6720"
+ orientation="horizontal"
+ position="-500.98515" />
+ <sodipodi:guide
+ id="guide6721"
+ orientation="horizontal"
+ position="-439.29009" />
+ <sodipodi:guide
+ id="guide6722"
+ orientation="horizontal"
+ position="-481.89327" />
+ <sodipodi:guide
+ id="guide8591"
+ orientation="vertical"
+ position="957.24580" />
+ </sodipodi:namedview>
+ <g
+ id="layer7"
+ inkscape:groupmode="layer"
+ inkscape:label="grafit">
+ <path
+ d="M 148.83456,547.90696 L 157.67340,548.68521 L 159.10971,555.17082 L 155.68466,557.89477 L 149.82893,558.67302 L 146.07243,559.06215 L 123.86486,553.22513 L 148.83456,547.90696 z "
+ id="path3013"
+ style="color:#000000;fill:url(#linearGradient4259);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.067719966pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ </g>
+ <g
+ id="layer5"
+ inkscape:groupmode="layer"
+ inkscape:label="sciete_drewno 0">
+ <path
+ d="M 199.81128,569.39078 C 193.61337,567.86215 187.05087,567.43411 178.71753,566.27230 C 170.53826,565.13204 173.53622,565.57447 165.90503,564.07102 C 158.30087,562.57292 152.36337,561.31943 144.96753,558.75127 C 147.51962,558.38439 151.63420,555.99968 154.18628,555.63280 C 155.07170,555.08248 157.30018,554.25609 157.30018,552.29942 C 157.30018,551.06283 156.11643,550.23527 154.87275,549.48489 C 153.54091,548.68128 149.17824,548.89390 148.18866,547.97670 C 153.68422,546.32010 168.53524,542.85318 176.53003,541.69138 C 184.47252,540.53720 191.47795,540.04042 200.90503,538.57290 C 200.17587,548.84553 200.54045,559.11815 199.81128,569.39078 z "
+ id="path9222"
+ sodipodi:nodetypes="czzcczzczcc"
+ style="fill:url(#linearGradient9857);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:0.25000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ </g>
+ <g
+ id="layer6"
+ inkscape:groupmode="layer"
+ inkscape:label="polysk">
+ <path
+ d="M 193.02874,548.16636 C 193.06610,547.28902 191.47519,545.75059 190.37709,545.31274 C 187.57137,544.19402 184.34329,543.37209 181.31728,543.49678 C 175.94640,543.71802 170.45340,544.99141 165.18641,546.35045 C 163.75062,546.72091 162.18663,547.59479 161.20893,548.68521 C 160.71349,549.23782 160.14893,551.19033 160.76699,551.27943 C 164.34738,551.79565 169.47529,550.31469 173.80427,550.50118 C 177.50390,550.66061 181.20734,552.31715 184.85282,552.31715 C 186.65795,552.31715 188.48666,551.34876 190.15612,550.50118 C 191.21197,549.96512 192.99244,549.01852 193.02874,548.16636 z "
+ id="path1128"
+ sodipodi:nodetypes="csssssssss"
+ style="opacity:0.80206186;fill:url(#radialGradient1753);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.25000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ <path
+ d="M 179.02203,557.59082 C 179.04925,558.59448 183.19386,562.68933 182.39409,563.19022 C 180.35065,564.47001 172.69628,563.07552 170.49239,562.93294 C 166.58069,562.67982 162.58005,561.22298 158.74401,559.66824 C 157.69830,559.24448 156.55922,558.24469 155.84715,556.99724 C 155.48631,556.36509 155.07513,554.13135 155.52528,554.02939 C 158.13293,553.43886 161.86768,555.13314 165.02054,554.91976 C 167.71504,554.73738 170.41232,552.84222 173.06738,552.84222 C 174.38209,552.84222 175.71397,553.95014 176.92986,554.91976 C 177.69885,555.53301 178.99560,556.61592 179.02203,557.59082 z "
+ id="path1762"
+ sodipodi:nodetypes="csssssssss"
+ style="opacity:0.78556699;fill:url(#radialGradient1763);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.25000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ </g>
+ <g
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="szary_tulow 1"
+ style="display:block">
+ <path
+ d="M 200.26345,546.32445 C 316.62843,546.32445 435.09573,546.32445 551.46071,546.32445 C 551.46071,549.42291 551.46071,559.47628 551.46071,562.57480 C 550.75336,565.25801 550.75336,561.81680 550.75336,564.91526 C 434.38838,564.91526 316.62843,564.91526 200.26345,564.91526 C 200.26345,563.36603 197.40747,560.84125 192.74343,559.26561 C 188.07940,557.68996 180.41183,557.06351 179.28717,555.72548 C 180.23188,554.91565 187.89945,554.83382 192.60847,553.07333 C 197.31750,551.31283 200.26345,547.87368 200.26345,546.32445 z "
+ id="rect1061"
+ sodipodi:nodetypes="cccccscsc"
+ style="color:#000000;fill:#d2d2d2;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:0.31228563;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.38622126;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ <path
+ d="M 200.54626,538.65508 C 316.91125,538.65508 433.02176,536.56375 549.38673,536.56375 C 550.21028,540.32388 550.96053,542.46928 551.46071,546.96346 C 435.09574,546.96346 316.65677,546.96346 200.29178,546.96346 C 200.29178,546.09686 198.32960,546.16513 194.42590,545.35013 C 190.46169,544.52251 182.70217,542.01992 181.57751,541.27143 C 183.46694,540.36539 195.77770,539.43774 200.54626,538.65508 z "
+ id="path1066"
+ sodipodi:nodetypes="ccccscc"
+ style="color:#000000;fill:#bebebe;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:0.31228563;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.38622126;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ <path
+ d="M 200.03730,563.99354 C 316.40229,563.99354 435.09574,562.56306 551.46071,562.56306 C 550.72496,565.22778 550.25391,567.01986 549.40828,569.67642 C 433.04330,569.67642 315.14667,570.85172 199.78282,569.67642 C 193.83317,568.50428 190.23851,567.80163 187.98919,566.77772 C 189.87862,566.15801 200.03730,565.17912 200.03730,563.99354 z "
+ id="path1067"
+ sodipodi:nodetypes="cccccc"
+ style="color:#000000;fill:#9b9b9b;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:0.31228563;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.38622126;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ </g>
+ <g
+ id="layer2"
+ inkscape:groupmode="layer"
+ inkscape:label="blysk 2"
+ style="display:block">
+ <path
+ d="M 194.58869,545.26983 L 551.34313,545.59263 L 551.46071,548.49015 L 199.30871,548.38150 C 199.67876,547.94447 200.10935,547.12501 200.20401,546.65769 C 199.28577,546.01110 197.70842,546.05120 196.37274,545.78229 L 194.58869,545.26983 z "
+ id="rect2956"
+ sodipodi:nodetypes="ccccccc"
+ style="color:#000000;fill:url(#linearGradient3582);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:0.31228563;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.38622126;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ </g>
+ <g
+ id="layer3"
+ inkscape:groupmode="layer"
+ inkscape:label="zloto 3">
+ <path
+ d="M 549.33498,536.56375 C 552.95421,536.56375 554.44773,536.56375 558.06696,536.56375 C 558.75468,540.03032 559.50496,543.42352 560.19268,546.96346 C 556.57346,546.96346 555.07993,546.96346 551.46071,546.96346 C 550.89803,543.35008 549.96021,540.17713 549.33498,536.56375 z "
+ id="rect4209"
+ sodipodi:nodetypes="ccccc"
+ style="color:#000000;fill:#d3bc3f;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:0.31228563;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.38622126;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ <path
+ d="M 551.39818,562.56306 C 555.05911,562.56306 556.53176,562.56306 560.19268,562.56306 C 559.44243,565.21481 559.06731,566.98575 558.19198,569.63750 C 554.53108,569.63750 552.87086,569.63750 549.20993,569.63750 C 550.35413,566.11575 550.69053,565.17119 551.39818,562.56306 z "
+ id="rect4210"
+ sodipodi:nodetypes="ccccc"
+ style="color:#000000;fill:#d3bc3f;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:0.31228563;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.38622126;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ <rect
+ height="15.599600"
+ id="rect4208"
+ style="color:#000000;fill:url(#linearGradient5465);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:0.31228563;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.38622126;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block"
+ width="8.7319660"
+ x="551.46075"
+ y="546.96350"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ <path
+ d="M 551.21196,545.59310 L 559.93478,545.60219 L 560.19013,546.96675 L 560.19158,548.48604 L 551.21131,548.38848 L 551.21643,546.28007 L 551.21196,545.59310 z "
+ id="path6089"
+ sodipodi:nodetypes="ccccccc"
+ style="opacity:0.69896907;color:#000000;fill:url(#linearGradient6090);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:0.31228563;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.38622126;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ </g>
+ <g
+ id="layer4"
+ inkscape:groupmode="layer"
+ inkscape:label="czarna_koncowka 4">
+ <rect
+ height="15.630233"
+ id="rect6723"
+ style="color:#000000;fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:0.31228563;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.38622126;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block"
+ width="39.995728"
+ x="560.11658"
+ y="546.93414"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ <path
+ d="M 558.10023,536.55723 L 598.06833,536.55723 L 600.05708,546.93411 L 560.11658,546.93411 L 558.10023,536.55723 z "
+ id="rect6724"
+ sodipodi:nodetypes="ccccc"
+ style="color:#000000;fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:0.31228563;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.38622126;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ <path
+ d="M 560.06136,562.56435 L 600.05708,562.56435 L 598.06833,569.56876 L 558.07261,569.56876 L 560.06136,562.56435 z "
+ id="rect6725"
+ sodipodi:nodetypes="ccccc"
+ style="color:#000000;fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:0.31228563;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.38622126;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ <path
+ d="M 559.80053,545.49730 L 599.78261,545.62556 L 600.18986,546.96082 L 600.12756,548.42582 L 560.12901,548.47929 L 560.12531,546.97544 L 559.80053,545.49730 z "
+ id="path8592"
+ sodipodi:nodetypes="ccccccc"
+ style="color:#000000;fill:url(#linearGradient8593);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:0.31228563;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.38622126;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ </g>
+ <g
+ id="layer8"
+ inkscape:groupmode="layer"
+ inkscape:label="czarne_zakonczenie">
+ <path
+ d="M 598.01311,536.55723 C 600.20441,537.42196 600.08063,537.15475 602.54301,539.54052 C 605.03228,541.95242 606.46523,546.99904 606.46523,552.47934 C 606.46523,557.95963 604.98378,563.72181 602.21156,566.65028 C 599.46661,569.54992 600.14916,568.87697 598.01311,569.56876 C 598.69443,567.23400 599.21006,566.27195 599.55993,562.49949 C 599.90978,558.72709 599.95583,551.20377 599.61516,546.86925 C 599.27448,542.53473 598.71286,540.01617 598.01311,536.55723 z "
+ id="rect4267"
+ sodipodi:nodetypes="czzzczzc"
+ style="color:#000000;fill:#000000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.067719966pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ <path
+ d="M 598.05216,536.60308 C 600.24346,537.46780 600.11968,537.20059 602.58206,539.58637 C 605.07133,541.99826 606.50428,547.04488 606.50428,552.52518 C 606.50428,558.00548 605.02283,563.76766 602.25061,566.69612 C 599.50566,569.59576 600.18821,568.92282 598.05216,569.61460 C 598.73348,567.27984 599.13861,566.18807 599.48848,562.41566 C 599.83836,558.64320 599.55293,550.92535 599.37798,546.59083 C 599.20313,542.25889 598.75191,540.06202 598.05216,536.60308 z "
+ id="path4269"
+ sodipodi:nodetypes="czzzczzc"
+ style="color:#000000;fill:url(#radialGradient4894);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.25000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ <path
+ d="M 598.03473,536.58259 C 599.38111,536.60420 599.36721,538.38435 599.74316,539.65763 C 600.09923,540.86358 600.43966,542.74318 600.64446,544.30814 C 600.77491,545.30499 601.05068,550.76698 601.01163,551.99376 C 600.99138,552.62961 600.81768,557.50652 600.72191,558.66757 C 600.61303,559.98727 600.46746,563.66986 599.60671,566.58394 C 598.75026,569.48358 598.76591,569.61578 598.03473,569.59418 C 598.31521,567.25935 599.18061,565.87349 599.44186,562.33037 C 599.70341,558.78297 599.71816,557.03639 599.67588,554.07746 C 599.63296,551.07251 599.45918,548.25682 599.38413,546.18128 C 599.30906,544.05989 598.91526,539.97673 598.03473,536.58259 z "
+ id="path4899"
+ sodipodi:nodetypes="czszszczszc"
+ style="color:#000000;fill:url(#linearGradient5526);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.13853176pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block"
+ inkscape:export-filename="/home/boud/pencil.png"
+ inkscape:export-xdpi="37.290001"
+ inkscape:export-ydpi="25.269030" />
+ </g>
+ <metadata
+ id="metadata1378">
+ <rdf:RDF
+ id="RDF1379">
+ <cc:Work
+ rdf:about=""
+ id="Work1380">
+ <dc:title
+ id="title1381">pencil</dc:title>
+ <dc:description
+ id="description1383" />
+ <dc:subject
+ id="subject1384">
+ <rdf:Bag
+ id="Bag1385">
+ <rdf:li
+ id="li1386" />
+ <rdf:li
+ id="li1387">office</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ <dc:publisher
+ id="publisher1389">
+ <cc:Agent
+ rdf:about="http://www.openclipart.org"
+ id="Agent1390">
+ <dc:title
+ id="title1391">Karol Szczerba</dc:title>
+ </cc:Agent>
+ </dc:publisher>
+ <dc:creator
+ id="creator1393">
+ <cc:Agent
+ rdf:about=""
+ id="Agent1394">
+ <dc:title
+ id="title1395">Karol Szczerba</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:rights
+ id="rights1397">
+ <cc:Agent
+ rdf:about=""
+ id="Agent1398">
+ <dc:title
+ id="title1399">Karol Szczerba</dc:title>
+ </cc:Agent>
+ </dc:rights>
+ <dc:date
+ id="date1401" />
+ <dc:format
+ id="format1402">image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+ id="type1404" />
+ <cc:license
+ rdf:resource="Public Domain"
+ id="license1405">
+ <dc:date
+ id="date1406" />
+ </cc:license>
+ <dc:language
+ id="language1407">en</dc:language>
+ </cc:Work>
+ <cc:License
+ rdf:about="Public Domain"
+ id="License1409">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction"
+ id="permits1410" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution"
+ id="permits1411" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks"
+ id="permits1412" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+</svg>
diff --git a/chalk/plugins/paintops/defaultpaintops/src/pencil_jonathan_dietrich_01.svg b/chalk/plugins/paintops/defaultpaintops/src/pencil_jonathan_dietrich_01.svg
new file mode 100644
index 00000000..4b29bb9a
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/src/pencil_jonathan_dietrich_01.svg
@@ -0,0 +1,434 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ height="1.0000000in"
+ id="svg1"
+ inkscape:version="0.40"
+ sodipodi:docbase="/home/boud"
+ sodipodi:docname="pencil_jonathan_dietrich_01.svg"
+ sodipodi:version="0.32"
+ width="8.0000000in"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <metadata
+ id="metadata2">
+ <rdf:RDF
+ id="RDF3">
+ <cc:Work
+ rdf:about=""
+ id="Work4">
+ <dc:title
+ id="title5">Pencil</dc:title>
+ <dc:description
+ id="description7">HASH(0x885a0cc)</dc:description>
+ <dc:subject
+ id="subject9">
+ <rdf:Bag
+ id="Bag10">
+ <rdf:li
+ id="li11">pencil</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ <dc:publisher
+ id="publisher13">
+ <cc:Agent
+ rdf:about="http://www.openclipart.org"
+ id="Agent14">
+ <dc:title
+ id="title15">Jonathan Dietrich</dc:title>
+ </cc:Agent>
+ </dc:publisher>
+ <dc:creator
+ id="creator17">
+ <cc:Agent
+ id="Agent18">
+ <dc:title
+ id="title19">Jonathan Dietrich</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:rights
+ id="rights21">
+ <cc:Agent
+ id="Agent22">
+ <dc:title
+ id="title23">Jonathan Dietrich</dc:title>
+ </cc:Agent>
+ </dc:rights>
+ <dc:date
+ id="date25">HASH(0x846b07c)</dc:date>
+ <dc:format
+ id="format27">image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+ id="type29" />
+ <cc:license
+ rdf:resource="http://web.resource.org/cc/PublicDomain"
+ id="license30" />
+ <dc:language
+ id="language31">en</dc:language>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://web.resource.org/cc/PublicDomain"
+ id="License33">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction"
+ id="permits34" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution"
+ id="permits35" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks"
+ id="permits36" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient1662">
+ <stop
+ id="stop1663"
+ offset="0.0000000"
+ style="stop-color:#000000;stop-opacity:0.0000000;" />
+ <stop
+ id="stop1666"
+ offset="0.50000000"
+ style="stop-color:#000000;stop-opacity:0.15686275;" />
+ <stop
+ id="stop1664"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1654">
+ <stop
+ id="stop1655"
+ offset="0.0000000"
+ style="stop-color:#a27d54;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1656"
+ offset="1.0000000"
+ style="stop-color:#f5bd7f;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1650">
+ <stop
+ id="stop1651"
+ offset="0.0000000"
+ style="stop-color:#bf6663;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1652"
+ offset="1.0000000"
+ style="stop-color:#ff8884;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1646">
+ <stop
+ id="stop1647"
+ offset="0.0000000"
+ style="stop-color:#969696;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1648"
+ offset="1.0000000"
+ style="stop-color:#ededed;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1630">
+ <stop
+ id="stop1631"
+ offset="0.0000000"
+ style="stop-color:#d2b200;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1658"
+ offset="0.50000000"
+ style="stop-color:#ffc300;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1659"
+ offset="0.75000000"
+ style="stop-color:#ffed00;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1632"
+ offset="1.0000000"
+ style="stop-color:#ffdd00;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ gradientTransform="matrix(-3.254365,0.000000,0.000000,0.316670,759.8405,-110.7512)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1633"
+ inkscape:collect="always"
+ x1="126.08783"
+ x2="126.08781"
+ xlink:href="#linearGradient1630"
+ y1="528.57239"
+ y2="377.06293" />
+ <linearGradient
+ gradientTransform="matrix(-1.364241,0.000000,0.000000,0.755408,759.8405,-110.7512)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1649"
+ inkscape:collect="always"
+ x1="505.71970"
+ x2="505.71970"
+ xlink:href="#linearGradient1646"
+ y1="221.53720"
+ y2="157.34721" />
+ <linearGradient
+ gradientTransform="matrix(-1.056744,0.000000,0.000000,0.975220,777.4291,-110.7513)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1653"
+ inkscape:collect="always"
+ x1="708.08087"
+ x2="707.66553"
+ xlink:href="#linearGradient1650"
+ y1="172.28430"
+ y2="122.22205" />
+ <linearGradient
+ gradientTransform="matrix(-1.658785,0.000000,0.000000,0.621272,750.7865,-111.0021)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1657"
+ inkscape:collect="always"
+ x1="50.804340"
+ x2="60.266266"
+ xlink:href="#linearGradient1654"
+ y1="269.75226"
+ y2="193.19295" />
+ <linearGradient
+ gradientTransform="matrix(-16.21046,0.000000,0.000000,6.357360e-2,758.2825,-106.7460)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1673"
+ inkscape:collect="always"
+ x1="25.595356"
+ x2="25.595356"
+ xlink:href="#linearGradient1662"
+ y1="2122.9712"
+ y2="2157.5330" />
+ <linearGradient
+ gradientTransform="matrix(-16.21046,0.000000,0.000000,6.357360e-2,762.2010,-121.8183)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1675"
+ inkscape:collect="always"
+ x1="25.595356"
+ x2="25.595356"
+ xlink:href="#linearGradient1662"
+ y1="2122.9712"
+ y2="2157.5330" />
+ <linearGradient
+ gradientTransform="matrix(-16.21046,0.000000,0.000000,6.357360e-2,761.1623,-89.12134)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1677"
+ inkscape:collect="always"
+ x1="25.595356"
+ x2="25.595356"
+ xlink:href="#linearGradient1662"
+ y1="2122.9712"
+ y2="2157.5330" />
+ <linearGradient
+ gradientTransform="matrix(-0.523707,0.000000,0.000000,1.946019,755.9293,-109.9526)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1681"
+ inkscape:collect="always"
+ x1="1327.0875"
+ x2="1351.4697"
+ xlink:href="#linearGradient1646"
+ y1="80.989799"
+ y2="62.197636" />
+ <linearGradient
+ gradientTransform="matrix(-0.523707,0.000000,0.000000,1.946019,761.7922,-109.9526)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1683"
+ inkscape:collect="always"
+ x1="1327.0875"
+ x2="1351.4697"
+ xlink:href="#linearGradient1646"
+ y1="80.989799"
+ y2="62.197636" />
+ <linearGradient
+ gradientTransform="matrix(-0.523707,0.000000,0.000000,1.946019,767.6551,-109.9526)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1685"
+ inkscape:collect="always"
+ x1="1327.0875"
+ x2="1351.4697"
+ xlink:href="#linearGradient1646"
+ y1="80.989799"
+ y2="62.197636" />
+ <linearGradient
+ gradientTransform="matrix(-0.523707,0.000000,0.000000,1.946019,791.1066,-109.9526)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1693"
+ inkscape:collect="always"
+ x1="1327.0875"
+ x2="1351.4697"
+ xlink:href="#linearGradient1646"
+ y1="80.989799"
+ y2="62.197636" />
+ <linearGradient
+ gradientTransform="matrix(-0.523707,0.000000,0.000000,1.946019,796.9695,-109.9526)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1697"
+ inkscape:collect="always"
+ x1="1327.0875"
+ x2="1351.4697"
+ xlink:href="#linearGradient1646"
+ y1="80.989799"
+ y2="62.197636" />
+ <linearGradient
+ gradientTransform="matrix(-0.523707,0.000000,0.000000,1.946019,802.8323,-109.9526)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1699"
+ inkscape:collect="always"
+ x1="1327.0875"
+ x2="1351.4697"
+ xlink:href="#linearGradient1646"
+ y1="80.989799"
+ y2="62.197636" />
+ </defs>
+ <sodipodi:namedview
+ bordercolor="#666666"
+ borderopacity="1.0"
+ id="base"
+ inkscape:current-layer="layer1"
+ inkscape:cx="360.00000"
+ inkscape:cy="45.000000"
+ inkscape:guide-bbox="true"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:window-height="999"
+ inkscape:window-width="1283"
+ inkscape:window-x="47"
+ inkscape:window-y="27"
+ inkscape:zoom="1.6541667"
+ pagecolor="#ffffff"
+ showguides="true" />
+ <g
+ id="layer1"
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1">
+ <path
+ d="M 592.38982,8.7978966 L 114.27426,8.2474158 C 114.27426,8.2474158 102.52077,7.7798401 102.52077,33.335829 C 102.52077,56.689895 113.53982,57.790857 113.53982,57.790857 L 594.77674,57.790857 C 594.77674,57.790857 602.71148,55.787702 601.66922,55.291203 C 600.62695,54.794711 599.23728,55.804875 597.84759,54.124745 C 596.45790,52.444617 595.06823,50.000885 594.02596,46.449979 C 592.98371,42.899074 592.41869,35.516246 592.41869,29.407432 C 592.41869,23.298620 592.84600,21.510571 593.68170,18.177576 C 594.51740,14.844590 595.63167,12.691402 596.74594,11.301822 C 597.86021,9.9122350 597.50562,10.800085 598.34131,10.521495 C 599.17702,10.242916 592.38982,8.7978966 592.38982,8.7978966 z "
+ id="path1006"
+ inkscape:export-filename="/home/boud/eraser.png"
+ inkscape:export-xdpi="25.269030"
+ inkscape:export-ydpi="25.269030"
+ sodipodi:nodetypes="cccccssscsssc"
+ style="fill:url(#linearGradient1633);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.21643910pt;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1.0000000" />
+ <path
+ d="M 598.21122,14.439873 L 106.65310,14.245243"
+ id="path1674"
+ inkscape:export-filename="/home/boud/eraser.png"
+ inkscape:export-xdpi="25.269030"
+ inkscape:export-ydpi="25.269030"
+ sodipodi:nodetypes="cc"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:url(#linearGradient1675);stroke-width:2.1643910;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ d="M 597.95155,46.747604 L 103.66700,46.942235"
+ id="path1676"
+ inkscape:export-filename="/home/boud/eraser.png"
+ inkscape:export-xdpi="25.269030"
+ inkscape:export-ydpi="25.269030"
+ sodipodi:nodetypes="cc"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:url(#linearGradient1677);stroke-width:2.1643910;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ d="M 594.29274,29.414859 L 101.69598,29.317549"
+ id="path1661"
+ inkscape:export-filename="/home/boud/eraser.png"
+ inkscape:export-xdpi="25.269030"
+ inkscape:export-ydpi="25.269030"
+ sodipodi:nodetypes="cc"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:url(#linearGradient1673);stroke-width:2.1643910;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ d="M 56.212243,8.2425325 L 14.333823,8.2474191 C 14.333823,8.2474191 2.5803330,9.4312952 2.5803330,33.335842 C 2.5803330,57.790880 13.599383,57.790880 13.599383,57.790880 L 56.196493,57.790880 C 56.196493,57.790880 45.079033,56.567471 45.079033,32.132201 C 45.079033,7.6969293 56.212243,8.2425325 56.212243,8.2425325 z "
+ id="path1640"
+ inkscape:export-filename="/home/boud/eraser.png"
+ inkscape:export-xdpi="25.269030"
+ inkscape:export-ydpi="25.269030"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient1653);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.25000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+ <path
+ d="M 115.46247,8.2425204 L 54.419283,8.2474070 C 54.419283,8.2474070 42.665793,9.4312826 42.665793,33.335820 C 42.665793,57.790847 53.684843,57.790847 53.684843,57.790847 L 115.37718,57.790847 C 115.37718,57.790847 104.25973,56.567439 104.25973,32.132179 C 104.25973,7.6969174 115.46247,8.2425204 115.46247,8.2425204 z "
+ id="path1645"
+ inkscape:export-filename="/home/boud/eraser.png"
+ inkscape:export-xdpi="25.269030"
+ inkscape:export-ydpi="25.269030"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient1649);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.21643910pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+ <path
+ d="M 592.60935,8.8259330 L 714.80057,33.322417 L 594.72085,57.818893 C 594.72085,57.818893 594.37129,55.805894 593.04868,53.791332 C 592.02163,52.226987 587.43587,49.264318 587.53925,47.243595 C 587.64030,45.268231 593.00050,42.626259 593.00050,39.471510 C 593.00050,35.835686 583.73322,34.330639 583.73322,29.727408 C 583.73322,25.948115 591.74741,23.534144 591.74741,21.076333 C 591.74741,17.684997 586.94880,16.159860 586.82708,14.541172 C 586.70796,12.956956 592.93177,11.676165 593.26691,10.738677 C 593.50364,10.076490 592.60935,8.8259330 592.60935,8.8259330 z "
+ id="path1007"
+ inkscape:export-filename="/home/boud/eraser.png"
+ inkscape:export-xdpi="25.269030"
+ inkscape:export-ydpi="25.269030"
+ sodipodi:nodetypes="cccssscsssc"
+ style="fill:url(#linearGradient1657);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.21643910pt;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1.0000000" />
+ <path
+ d="M 689.51035,28.508228 L 713.56524,33.327058 L 689.94377,38.145879 C 689.94377,38.145879 687.75680,37.905214 687.75680,33.098433 C 687.75680,28.291653 689.51035,28.508228 689.51035,28.508228 z "
+ id="path1008"
+ inkscape:export-filename="/home/boud/eraser.png"
+ inkscape:export-xdpi="25.269030"
+ inkscape:export-ydpi="25.269030"
+ sodipodi:nodetypes="ccccc"
+ style="fill:#000000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.21643915pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+ <path
+ d="M 62.399193,8.3905104 L 60.827183,8.3953619 C 60.827183,8.3953619 49.138973,9.5726643 49.138973,33.344421 C 49.138973,57.663608 60.096823,57.663608 60.096823,57.663608 L 62.314383,57.663608 C 62.314383,57.663608 50.871353,57.705039 50.871353,33.405503 C 50.871353,9.1059758 62.399193,8.3905104 62.399193,8.3905104 z "
+ id="path1678"
+ inkscape:export-filename="/home/boud/eraser.png"
+ inkscape:export-xdpi="25.269030"
+ inkscape:export-ydpi="25.269030"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient1681);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.25000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+ <path
+ d="M 68.262063,8.3905104 L 66.690053,8.3953619 C 66.690053,8.3953619 55.001843,9.5726643 55.001843,33.344421 C 55.001843,57.663608 65.959693,57.663608 65.959693,57.663608 L 68.177253,57.663608 C 68.177253,57.663608 56.734223,57.705039 56.734223,33.405503 C 56.734223,9.1059758 68.262063,8.3905104 68.262063,8.3905104 z "
+ id="path1682"
+ inkscape:export-filename="/home/boud/eraser.png"
+ inkscape:export-xdpi="25.269030"
+ inkscape:export-ydpi="25.269030"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient1683);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.25000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+ <path
+ d="M 74.124933,8.3905104 L 72.552923,8.3953619 C 72.552923,8.3953619 60.864713,9.5726643 60.864713,33.344421 C 60.864713,57.663608 71.822563,57.663608 71.822563,57.663608 L 74.040123,57.663608 C 74.040123,57.663608 62.597103,57.705039 62.597103,33.405503 C 62.597103,9.1059758 74.124933,8.3905104 74.124933,8.3905104 z "
+ id="path1684"
+ inkscape:export-filename="/home/boud/eraser.png"
+ inkscape:export-xdpi="25.269030"
+ inkscape:export-ydpi="25.269030"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient1685);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.25000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+ <path
+ d="M 97.576423,8.3905104 L 96.004413,8.3953619 C 96.004413,8.3953619 84.316203,9.5726643 84.316203,33.344421 C 84.316203,57.663608 95.274053,57.663608 95.274053,57.663608 L 97.491613,57.663608 C 97.491613,57.663608 86.048593,57.705039 86.048593,33.405503 C 86.048593,9.1059758 97.576423,8.3905104 97.576423,8.3905104 z "
+ id="path1692"
+ inkscape:export-filename="/home/boud/eraser.png"
+ inkscape:export-xdpi="25.269030"
+ inkscape:export-ydpi="25.269030"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient1693);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.25000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+ <path
+ d="M 103.43930,8.3905104 L 101.86728,8.3953619 C 101.86728,8.3953619 90.179073,9.5726643 90.179073,33.344421 C 90.179073,57.663608 101.13692,57.663608 101.13692,57.663608 L 103.35448,57.663608 C 103.35448,57.663608 91.911463,57.705039 91.911463,33.405503 C 91.911463,9.1059758 103.43930,8.3905104 103.43930,8.3905104 z "
+ id="path1696"
+ inkscape:export-filename="/home/boud/eraser.png"
+ inkscape:export-xdpi="25.269030"
+ inkscape:export-ydpi="25.269030"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient1697);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.25000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+ <path
+ d="M 109.30217,8.3905104 L 107.73016,8.3953619 C 107.73016,8.3953619 96.041953,9.5726643 96.041953,33.344421 C 96.041953,57.663608 106.99979,57.663608 106.99979,57.663608 L 109.21736,57.663608 C 109.21736,57.663608 97.774333,57.705039 97.774333,33.405503 C 97.774333,9.1059758 109.30217,8.3905104 109.30217,8.3905104 z "
+ id="path1698"
+ inkscape:export-filename="/home/boud/eraser.png"
+ inkscape:export-xdpi="25.269030"
+ inkscape:export-ydpi="25.269030"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient1699);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.25000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+ <path
+ d="M 91.939683,8.2289912 L 76.778513,8.2911122 C 76.778513,8.2911122 65.065543,9.4709063 65.065543,33.293029 C 65.065543,57.663743 76.046613,57.663743 76.046613,57.663743 L 91.931073,57.720994 C 91.931073,57.720994 80.775573,56.444553 80.775573,32.093537 C 80.775573,7.7425207 91.939683,8.2289912 91.939683,8.2289912 z "
+ id="path1700"
+ inkscape:export-filename="/home/boud/eraser.png"
+ inkscape:export-xdpi="25.269030"
+ inkscape:export-ydpi="25.269030"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:#000000;fill-opacity:0.87005651;fill-rule:evenodd;stroke:#000000;stroke-width:0.21643901pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+ </g>
+</svg>
diff --git a/chalk/plugins/paintops/defaultpaintops/src/pennello_mauro_olivo_01.svg b/chalk/plugins/paintops/defaultpaintops/src/pennello_mauro_olivo_01.svg
new file mode 100644
index 00000000..b79fcd57
--- /dev/null
+++ b/chalk/plugins/paintops/defaultpaintops/src/pennello_mauro_olivo_01.svg
@@ -0,0 +1,616 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ height="297mm"
+ id="svg1"
+ inkscape:version="0.40"
+ sodipodi:docbase="/home/boud"
+ sodipodi:docname="pennello_mauro_olivo_01.svg"
+ sodipodi:version="0.32"
+ width="210mm"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ inkscape:export-filename="/home/boud/brush.png"
+ inkscape:export-xdpi="19.260000"
+ inkscape:export-ydpi="19.260000">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient15131">
+ <stop
+ id="stop15132"
+ offset="0.0000000"
+ style="stop-color:#004800;stop-opacity:1.0000000;" />
+ <stop
+ id="stop15146"
+ offset="0.50000000"
+ style="stop-color:#7fbd7f;stop-opacity:0.49803922;" />
+ <stop
+ id="stop15147"
+ offset="0.75000000"
+ style="stop-color:#bfdebf;stop-opacity:0.24705882;" />
+ <stop
+ id="stop15148"
+ offset="0.87500000"
+ style="stop-color:#dfeedf;stop-opacity:0.12156863;" />
+ <stop
+ id="stop15149"
+ offset="0.93750000"
+ style="stop-color:#eff6ef;stop-opacity:0.058823530;" />
+ <stop
+ id="stop15150"
+ offset="0.96875000"
+ style="stop-color:#f7faf7;stop-opacity:0.027450981;" />
+ <stop
+ id="stop15151"
+ offset="0.98437500"
+ style="stop-color:#fbfcfb;stop-opacity:0.011764706;" />
+ <stop
+ id="stop15152"
+ offset="0.99000001"
+ style="stop-color:#fdfdfd;stop-opacity:0.0039215689;" />
+ <stop
+ id="stop15133"
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1800">
+ <stop
+ id="stop1801"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.62626261;" />
+ <stop
+ id="stop1802"
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1664">
+ <stop
+ id="stop1665"
+ offset="0.0000000"
+ style="stop-color:#000000;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1666"
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1659">
+ <stop
+ id="stop1660"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.77777779;" />
+ <stop
+ id="stop1661"
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1653">
+ <stop
+ id="stop1654"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.61616164;" />
+ <stop
+ id="stop1655"
+ offset="1.0000000"
+ style="stop-color:#2eff19;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1628">
+ <stop
+ id="stop1629"
+ offset="0.0000000"
+ style="stop-color:#717674;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1630"
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1617">
+ <stop
+ id="stop1618"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1619"
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1608">
+ <stop
+ id="stop1609"
+ offset="0.0000000"
+ style="stop-color:#004500;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1611"
+ offset="0.50000000"
+ style="stop-color:#00814c;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1610"
+ offset="1.0000000"
+ style="stop-color:#a54800;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1598">
+ <stop
+ id="stop1599"
+ offset="0.0000000"
+ style="stop-color:#000000;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1601"
+ offset="0.50000000"
+ style="stop-color:#7f7f7f;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1600"
+ offset="1"
+ style="stop-color:#fff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1595">
+ <stop
+ id="stop1596"
+ offset="0.0000000"
+ style="stop-color:#a25d00;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1657"
+ offset="0.50000000"
+ style="stop-color:#ddae4c;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1597"
+ offset="1.0000000"
+ style="stop-color:#ffe698;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1592">
+ <stop
+ id="stop1593"
+ offset="0.0000000"
+ style="stop-color:#de8900;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1594"
+ offset="1"
+ style="stop-color:#fff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1584">
+ <stop
+ id="stop1585"
+ offset="0"
+ style="stop-color:#000;stop-opacity:1;" />
+ <stop
+ id="stop1586"
+ offset="1"
+ style="stop-color:#fff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient1588"
+ inkscape:collect="always"
+ x1="1193.5865"
+ x2="1330.3144"
+ xlink:href="#linearGradient1595"
+ y1="112.08835"
+ y2="112.08835"
+ gradientTransform="scale(0.301850,3.312902)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ cx="556.83325"
+ cy="673.03480"
+ fx="558.31175"
+ fy="673.03480"
+ id="radialGradient1607"
+ inkscape:collect="always"
+ r="121.23903"
+ xlink:href="#linearGradient1608"
+ gradientTransform="scale(0.665788,1.501979)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="linearGradient1613"
+ inkscape:collect="always"
+ x1="511.84784"
+ x2="664.54880"
+ xlink:href="#linearGradient1598"
+ y1="462.29474"
+ y2="458.95388"
+ gradientTransform="scale(0.603506,1.656985)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ id="radialGradient1621"
+ inkscape:collect="always"
+ xlink:href="#linearGradient1617"
+ gradientTransform="scale(0.747545,1.337712)"
+ cx="478.63759"
+ cy="683.14977"
+ fx="478.63759"
+ fy="683.14977"
+ r="17.256384"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ cx="478.63759"
+ cy="683.14977"
+ fx="478.63759"
+ fy="683.14977"
+ id="radialGradient1658"
+ inkscape:collect="always"
+ r="17.256384"
+ xlink:href="#linearGradient1659"
+ gradientTransform="scale(0.747545,1.337712)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ cx="446.43968"
+ cy="1039.6351"
+ fx="446.79044"
+ fy="1040.7757"
+ id="radialGradient15130"
+ inkscape:collect="always"
+ r="79.796235"
+ xlink:href="#linearGradient15131"
+ gradientTransform="scale(1.083274,0.923127)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ cx="478.63759"
+ cy="683.14977"
+ fx="478.63759"
+ fy="683.14977"
+ id="radialGradient15163"
+ inkscape:collect="always"
+ r="13.148508"
+ xlink:href="#linearGradient1659"
+ gradientTransform="scale(0.747545,1.337712)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1617"
+ id="radialGradient1656"
+ gradientTransform="scale(0.747545,1.337712)"
+ cx="478.63759"
+ cy="683.14977"
+ fx="478.63759"
+ fy="683.14977"
+ r="17.256384"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1659"
+ id="radialGradient1657"
+ cx="478.63759"
+ cy="683.14977"
+ fx="478.63759"
+ fy="683.14977"
+ r="17.256384"
+ gradientTransform="scale(0.747545,1.337712)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1659"
+ id="radialGradient1659"
+ cx="478.63759"
+ cy="683.14977"
+ fx="478.63759"
+ fy="683.14977"
+ r="17.256384"
+ gradientTransform="scale(0.747545,1.337712)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1659"
+ id="radialGradient1673"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.747545,1.337712)"
+ cx="478.63759"
+ cy="683.14977"
+ fx="478.63759"
+ fy="683.14977"
+ r="17.256384" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1617"
+ id="radialGradient1674"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.747545,1.337712)"
+ cx="478.63759"
+ cy="683.14977"
+ fx="478.63759"
+ fy="683.14977"
+ r="17.256384" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1659"
+ id="radialGradient1675"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.747545,1.337712)"
+ cx="478.63759"
+ cy="683.14977"
+ fx="478.63759"
+ fy="683.14977"
+ r="13.148508" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1659"
+ id="radialGradient1676"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.747545,1.337712)"
+ cx="478.63759"
+ cy="683.14977"
+ fx="478.63759"
+ fy="683.14977"
+ r="17.256384" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1598"
+ id="linearGradient1677"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.603506,1.656985)"
+ x1="511.84784"
+ y1="462.29474"
+ x2="664.54880"
+ y2="458.95388" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1659"
+ id="radialGradient1678"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.747545,1.337712)"
+ cx="478.63759"
+ cy="683.14977"
+ fx="478.63759"
+ fy="683.14977"
+ r="17.256384" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1617"
+ id="radialGradient1679"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.747545,1.337712)"
+ cx="478.63759"
+ cy="683.14977"
+ fx="478.63759"
+ fy="683.14977"
+ r="17.256384" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1608"
+ id="radialGradient1680"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(5.549835e-3,0.634975,-1.773650,1.011171e-2,1038.823,138.4314)"
+ cx="556.83325"
+ cy="673.03480"
+ fx="558.31175"
+ fy="673.03480"
+ r="121.23903" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1595"
+ id="linearGradient1681"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.841587e-3,0.305219,-2.863318,2.364665e-2,776.1582,114.7272)"
+ x1="1193.5865"
+ y1="112.08835"
+ x2="1330.3144"
+ y2="112.08835" />
+ </defs>
+ <sodipodi:namedview
+ bordercolor="#666666"
+ borderopacity="1.0"
+ id="base"
+ inkscape:cx="297.63779"
+ inkscape:cy="454.90245"
+ inkscape:guide-bbox="false"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:window-height="942"
+ inkscape:window-width="1272"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:zoom="0.92054809"
+ pagecolor="#ffffff"
+ showborder="false"
+ showguides="false">
+ <sodipodi:guide
+ id="guide918"
+ orientation="horizontal"
+ position="506.59301" />
+ <sodipodi:guide
+ id="guide919"
+ orientation="horizontal"
+ position="500.99186" />
+ <sodipodi:guide
+ id="guide922"
+ orientation="horizontal"
+ position="360.02955" />
+ <sodipodi:guide
+ id="guide923"
+ orientation="horizontal"
+ position="365.31953" />
+ <sodipodi:guide
+ id="guide1572"
+ orientation="vertical"
+ position="85.253558" />
+ <sodipodi:guide
+ id="guide1573"
+ orientation="vertical"
+ position="71.174989" />
+ <sodipodi:guide
+ id="guide1574"
+ orientation="vertical"
+ position="99.332127" />
+ </sodipodi:namedview>
+ <path
+ d="M 769.97658,486.81260 C 769.90085,474.26161 753.99967,473.66070 735.62179,471.66366 C 517.14574,458.36371 361.34879,450.03856 177.81682,469.40472 C 159.52842,469.55575 144.86624,479.78157 144.94196,492.33256 C 145.01769,504.88357 159.80181,514.86620 178.09021,514.71516 C 361.85415,533.79423 548.39498,517.77619 735.95259,501.12302 C 754.23073,499.27093 769.35872,498.56352 769.97658,486.81260 z "
+ id="rect1581"
+ sodipodi:nodetypes="ccccccc"
+ style="fill:url(#linearGradient1681);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.1734303pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.49572650" />
+ <path
+ d="M 48.073160,478.03067 C 48.087914,489.97403 48.102681,501.91738 48.117448,513.86073 C 0.85876303,531.35767 -46.500497,537.34604 -81.647766,525.45820 C -104.01644,519.50544 -131.86117,520.45766 -139.00549,501.34675 C -143.09055,490.41920 -129.73846,496.31038 -120.21496,484.29524 C -55.360244,444.22124 48.073160,478.03067 48.073160,478.03067 z "
+ id="path1576"
+ sodipodi:nodetypes="cccscc"
+ style="fill:url(#radialGradient1680);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.58188543pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.36752138" />
+ <path
+ d="M 370.70305 913.85773 A 12.899923 23.084074 0 1 1 344.90321,913.85773 A 12.899923 23.084074 0 1 1 370.70305 913.85773 z"
+ id="path1622"
+ sodipodi:cx="357.80313"
+ sodipodi:cy="913.85773"
+ sodipodi:rx="12.899923"
+ sodipodi:ry="23.084074"
+ sodipodi:type="arc"
+ style="fill:url(#radialGradient1679);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ transform="matrix(6.101001e-3,1.011162,-12.20179,0.100768,11619.90,37.23681)" />
+ <path
+ d="M 370.70305 913.85773 A 12.899923 23.084074 0 1 1 344.90321,913.85773 A 12.899923 23.084074 0 1 1 370.70305 913.85773 z"
+ id="path1668"
+ sodipodi:cx="357.80313"
+ sodipodi:cy="913.85773"
+ sodipodi:rx="12.899923"
+ sodipodi:ry="23.084074"
+ sodipodi:type="arc"
+ style="fill:url(#radialGradient1678);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ transform="matrix(1.392760e-2,1.633299,-4.410336,2.577152e-2,3963.448,-103.3312)" />
+ <g
+ id="g1671"
+ style="stroke:#000000;stroke-opacity:0.49572650"
+ transform="matrix(6.101001e-3,1.011162,-0.864293,7.137744e-3,776.1582,114.7272)">
+ <path
+ d="M 343.52237,671.33150 C 343.32633,673.73849 341.75770,676.43905 341.57758,678.84728 C 342.57148,679.70505 343.19413,680.92386 343.19413,682.29375 C 343.19413,683.87456 342.31922,685.22430 341.04643,686.07572 C 324.55199,705.35504 357.35073,801.15078 340.97715,833.96892 L 342.91701,837.59839 L 341.46212,840.89236 L 344.67176,849.62815 L 392.99165,849.34080 L 395.31616,840.98387 L 393.74580,837.59839 L 395.84731,833.87742 C 378.83530,791.73991 412.50569,719.52485 395.66256,686.10622 C 394.35910,685.25837 393.44558,683.89688 393.44558,682.29375 C 393.44558,680.88864 394.13863,679.67684 395.17760,678.81678 C 395.01118,676.41812 393.45882,673.73393 393.27900,671.33150 C 375.74167,671.33148 361.05969,671.33150 343.52237,671.33150 z "
+ id="rect910"
+ sodipodi:nodetypes="ccccccccccccccccc"
+ style="fill:url(#linearGradient1677);fill-opacity:1.0000000;fill-rule:evenodd;stroke-width:0.84926434pt;stroke-linecap:butt;stroke-linejoin:miter" />
+ <path
+ d="M 343.36975,682.48174 L 393.50367,682.42041"
+ id="path1649"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:2.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000" />
+ <path
+ d="M 342.72547,837.67100 L 393.98325,837.51088 L 393.98325,837.51088 L 393.98325,837.51088"
+ id="path1650"
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke-width:2.0092726;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000" />
+ </g>
+ <path
+ d="M 370.70305 913.85773 A 12.899923 23.084074 0 1 1 344.90321,913.85773 A 12.899923 23.084074 0 1 1 370.70305 913.85773 z"
+ id="path1803"
+ sodipodi:cx="357.80313"
+ sodipodi:cy="913.85773"
+ sodipodi:rx="12.899923"
+ sodipodi:ry="23.084074"
+ sodipodi:type="arc"
+ style="fill:url(#radialGradient1676);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ transform="matrix(8.429002e-3,1.397000,-2.669140,2.204299e-2,2565.017,-13.88688)" />
+ <path
+ d="M 370.70305 913.85773 A 12.899923 23.084074 0 1 1 344.90321,913.85773 A 12.899923 23.084074 0 1 1 370.70305 913.85773 z"
+ id="path15162"
+ sodipodi:cx="357.80313"
+ sodipodi:cy="913.85773"
+ sodipodi:rx="12.899923"
+ sodipodi:ry="23.084074"
+ sodipodi:type="arc"
+ style="fill:url(#radialGradient1675);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ transform="matrix(1.151647e-2,1.317638,-3.646822,2.079076e-2,3303.435,0.107690)" />
+ <path
+ d="M 370.70305 913.85773 A 12.899923 23.084074 0 1 1 344.90321,913.85773 A 12.899923 23.084074 0 1 1 370.70305 913.85773 z"
+ id="path15164"
+ sodipodi:cx="357.80313"
+ sodipodi:cy="913.85773"
+ sodipodi:rx="12.899923"
+ sodipodi:ry="23.084074"
+ sodipodi:type="arc"
+ style="fill:url(#radialGradient1674);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ transform="matrix(6.101001e-3,1.011162,-12.20179,0.100768,11605.82,55.08689)" />
+ <path
+ d="M 370.70305 913.85773 A 12.899923 23.084074 0 1 1 344.90321,913.85773 A 12.899923 23.084074 0 1 1 370.70305 913.85773 z"
+ id="path15165"
+ sodipodi:cx="357.80313"
+ sodipodi:cy="913.85773"
+ sodipodi:rx="12.899923"
+ sodipodi:ry="23.084074"
+ sodipodi:type="arc"
+ style="fill:url(#radialGradient1673);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ transform="matrix(8.429002e-3,1.397000,-2.669140,2.204299e-2,2557.975,-37.22922)" />
+ <metadata
+ id="metadata1620">
+ <rdf:RDF
+ id="RDF1621">
+ <cc:Work
+ rdf:about=""
+ id="Work1622">
+ <dc:title
+ id="title1623">pennello</dc:title>
+ <dc:description
+ id="description1625">Created with The Inkscape</dc:description>
+ <dc:subject
+ id="subject1627">
+ <rdf:Bag
+ id="Bag1628">
+ <rdf:li
+ id="li1629" />
+ <rdf:li
+ id="li1630">office</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ <dc:publisher
+ id="publisher1632">
+ <cc:Agent
+ rdf:about="http://www.openclipart.org"
+ id="Agent1633">
+ <dc:title
+ id="title1634">Mauro Olivo</dc:title>
+ </cc:Agent>
+ </dc:publisher>
+ <dc:creator
+ id="creator1636">
+ <cc:Agent
+ rdf:about=""
+ id="Agent1637">
+ <dc:title
+ id="title1638">Mauro Olivo</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:rights
+ id="rights1640">
+ <cc:Agent
+ rdf:about=""
+ id="Agent1641">
+ <dc:title
+ id="title1642">Mauro Olivo</dc:title>
+ </cc:Agent>
+ </dc:rights>
+ <dc:date
+ id="date1644" />
+ <dc:format
+ id="format1645">image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+ id="type1647" />
+ <cc:license
+ rdf:resource="Public Domain"
+ id="license1648">
+ <dc:date
+ id="date1649" />
+ </cc:license>
+ <dc:language
+ id="language1650">en</dc:language>
+ </cc:Work>
+ <cc:License
+ rdf:about="Public Domain"
+ id="License1652">
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Reproduction"
+ id="permits1653" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/Distribution"
+ id="permits1654" />
+ <cc:permits
+ rdf:resource="http://web.resource.org/cc/DerivativeWorks"
+ id="permits1655" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+</svg>
diff --git a/chalk/plugins/tools/Makefile.am b/chalk/plugins/tools/Makefile.am
new file mode 100644
index 00000000..eb40c4e9
--- /dev/null
+++ b/chalk/plugins/tools/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = defaulttools selectiontools tool_crop tool_curves tool_filter \
+ tool_polygon tool_polyline tool_selectsimilar tool_star tool_transform \
+ tool_perspectivegrid tool_perspectivetransform
diff --git a/chalk/plugins/tools/defaulttools/Makefile.am b/chalk/plugins/tools/defaulttools/Makefile.am
new file mode 100644
index 00000000..b8998604
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/Makefile.am
@@ -0,0 +1,83 @@
+kde_services_DATA = chalkdefaulttools.desktop
+
+# all_includes must remain last!
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkdefaulttools_la_SOURCES = \
+ default_tools.cc \
+ kis_tool_colorpicker.cc \
+ kis_tool_move.cc \
+ kis_tool_zoom.cc \
+ kis_tool_brush.cc \
+ kis_tool_line.cc \
+ kis_tool_duplicate.cc \
+ kis_tool_fill.cc \
+ kis_tool_rectangle.cc \
+ kis_tool_ellipse.cc \
+ kis_tool_pan.cc \
+ kis_tool_text.cc \
+ kis_tool_gradient.cc \
+ wdgcolorpicker.ui
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = chalkdefaulttools.la
+
+noinst_HEADERS = \
+ default_tools.h \
+ kis_tool_fill.h \
+ kis_tool_brush.h \
+ kis_tool_gradient.h \
+ kis_tool_rectangle.h \
+ kis_tool_colorpicker.h \
+ kis_tool_line.h \
+ kis_tool_text.h \
+ kis_tool_duplicate.h \
+ kis_tool_move.h \
+ kis_tool_zoom.h \
+ kis_tool_ellipse.h \
+ kis_tool_pan.h
+
+
+chalkdefaulttools_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkdefaulttools_la_LIBADD = ../../../libchalkcommon.la $(LIB_KOPAINTER) $(LIB_KOFFICECORE)
+
+chalkdefaulttools_la_METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
+
+chalkpics_DATA = \
+ tool_rectangle_cursor.png \
+ tool_ellipse_cursor.png \
+ tool_line_cursor.png \
+ tool_freehand_cursor.png \
+ tool_duplicate_cursor.png \
+ tool_fill_cursor.png \
+ tool_color_fill.png \
+ tool_text_cursor.png \
+ tool_gradient_cursor.png \
+ tool_gradient.png \
+ tool_line.png \
+ tool_rectangle.png \
+ tool_ellipse.png \
+ tool_pan.png \
+ tool_freehand.png \
+ tool_text.png \
+ openhand_cursor.xpm \
+ closedhand_cursor.xpm \
+ tool_zoom_plus_cursor.png \
+ tool_zoom_minus_cursor.png \
+ tool_move.png \
+ tool_colorpicker.png \
+ tool_duplicate.png \
+ tool_zoom.png
+
+
+chalkpicsdir = $(kde_datadir)/chalk/pics
+
diff --git a/chalk/plugins/tools/defaulttools/chalkdefaulttools.desktop b/chalk/plugins/tools/defaulttools/chalkdefaulttools.desktop
new file mode 100644
index 00000000..6472d637
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/chalkdefaulttools.desktop
@@ -0,0 +1,56 @@
+[Desktop Entry]
+Name=Default Tools
+Name[bg]=Инструменти по подразбиране
+Name[br]=Ostilhoù dre ziouer
+Name[ca]=Eines per defecte
+Name[cy]=Offer Rhagosodol
+Name[da]=Standardværktøjer
+Name[de]=Standardwerkzeuge
+Name[el]=Προκαθορισμένα εργαλεία
+Name[eo]=Aprioraj Iloj
+Name[es]=Herramientas predefinidas
+Name[et]=Vaiketööriistad
+Name[eu]=Tresna lehenetsiak
+Name[fa]=ابزارهای پیش‌فرض
+Name[fi]=Oletustyökalut
+Name[fr]=Outils par défaut
+Name[fy]=Standert ark
+Name[ga]=Uirlisí Réamhshocraithe
+Name[gl]=Ferramentas Predefinidas
+Name[he]=כלים המוגדרים כברירת מחדל
+Name[hi]=डिफ़ॉल्ट औज़ार
+Name[hr]=Zadani alati
+Name[hu]=Alapértelmezett eszközök
+Name[is]=Sjálfgefin tól
+Name[it]=Strumenti predefiniti
+Name[ja]=標準ツール
+Name[km]=ឧបករណ៍​លំនាំដើម
+Name[lt]=Numatyti įrankiai
+Name[lv]=Noklusējuma rīks
+Name[ms]=Alat Piawai
+Name[nb]=Standardverktøy
+Name[nds]=Standardwarktüüch
+Name[ne]=पूर्वनिर्धारित उपकरणहरू
+Name[nl]=Standaardgereedschappen
+Name[nn]=Standardverktøy
+Name[pl]=Domyślne narzędzia
+Name[pt]=Ferramentas Predefinidas
+Name[pt_BR]=Ferramentas Padrão
+Name[ru]=Стандартный инструментарий
+Name[se]=Standárdreaiddut
+Name[sk]=Štandardné nástroje
+Name[sl]=Privzeta orodja
+Name[sr]=Подразумевани алати
+Name[sr@Latn]=Podrazumevani alati
+Name[sv]=Standardverktyg
+Name[ta]=முன்னிருப்பு கருவிகள்
+Name[tr]=Öntanımlı Araçlar
+Name[uk]=Типові інструменти
+Name[uz]=Andoza vositalar
+Name[uz@cyrillic]=Андоза воситалар
+Name[zh_CN]=默认工具
+Name[zh_TW]=預設工具
+ServiceTypes=Chalk/Tool
+Type=Service
+X-KDE-Library=chalkdefaulttools
+X-Chalk-Version=2
diff --git a/chalk/plugins/tools/defaulttools/closedhand_cursor.xpm b/chalk/plugins/tools/defaulttools/closedhand_cursor.xpm
new file mode 100644
index 00000000..b3d98f85
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/closedhand_cursor.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char *closedhand_cursor[]={
+"22 22 3 1",
+". c None",
+"# c #000000",
+"a c #ffffff",
+"......................",
+"......................",
+"......................",
+"......................",
+".......##.##.##.......",
+"......#aa#aa#aa###....",
+"......#aa#aa#aa#aa#...",
+"......#aa#aa#aa#aa#...",
+".....##aaaaaaaa#aa#...",
+"....#a#aaaaaaaaaaa#...",
+"....#a#aaaaaaaaaaa#...",
+"....#a#aaaaaaaaaaa#...",
+"....#aaaaaaaaaaaaa#...",
+".....#aaaaaaaaaaaa#...",
+".....#aaaaaaaaaaa#....",
+"......#aaaaaaaaaa#....",
+"......#aaaaaaaaaa#....",
+".......#aaaaaaaa#.....",
+".......#aaaaaaaa#.....",
+".......##########.....",
+"......................",
+"......................"};
diff --git a/chalk/plugins/tools/defaulttools/default_tools.cc b/chalk/plugins/tools/defaulttools/default_tools.cc
new file mode 100644
index 00000000..61d06e98
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/default_tools.cc
@@ -0,0 +1,88 @@
+/*
+ * default_tools.cc -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_tool.h>
+#include <kis_tool_registry.h>
+#include "default_tools.h"
+
+#include "kis_tool_fill.h"
+#include "kis_tool_brush.h"
+#include "kis_tool_freehand.h"
+#include "kis_tool_gradient.h"
+#include "kis_tool_rectangle.h"
+#include "kis_tool_colorpicker.h"
+#include "kis_tool_line.h"
+#include "kis_tool_text.h"
+#include "kis_tool_duplicate.h"
+#include "kis_tool_move.h"
+#include "kis_tool_zoom.h"
+#include "kis_tool_ellipse.h"
+#include "kis_tool_pan.h"
+
+
+typedef KGenericFactory<DefaultTools> DefaultToolsFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkdefaulttools, DefaultToolsFactory( "chalk" ) )
+
+
+DefaultTools::DefaultTools(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(DefaultToolsFactory::instance());
+
+ if ( tqparent->inherits("KisToolRegistry") )
+ {
+ KisToolRegistry * r = dynamic_cast<KisToolRegistry*>(tqparent);
+
+ r->add(new KisToolFillFactory());
+ r->add(new KisToolGradientFactory());
+ r->add(new KisToolBrushFactory());
+ r->add(new KisToolColorPickerFactory());
+ r->add(new KisToolLineFactory());
+ r->add(new KisToolTextFactory());
+ r->add(new KisToolDuplicateFactory());
+ r->add(new KisToolMoveFactory());
+ r->add(new KisToolZoomFactory());
+ r->add(new KisToolEllipseFactory());
+ r->add(new KisToolRectangleFactory());
+ r->add(new KisToolPanFactory());
+
+ }
+}
+
+DefaultTools::~DefaultTools()
+{
+}
+
+#include "default_tools.moc"
diff --git a/chalk/plugins/tools/defaulttools/default_tools.h b/chalk/plugins/tools/defaulttools/default_tools.h
new file mode 100644
index 00000000..c50a9147
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/default_tools.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2003 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 DEFAULT_TOOLS_H_
+#define DEFAULT_TOOLS_H_
+
+#include <kparts/plugin.h>
+
+/**
+ * A module wrapper around Chalk's default tools.
+ * Despite the fact that new tools are created for every new view,
+ * it is not possible to make tools standard parts of the type of the
+ * imagesize plugin, because we need to create a new set of tools for every
+ * pointer device (mouse, stylus, eraser, puck, etc.). So this plugin is
+ * a module which is loaded once into Chalk. For every tool there is a factory
+ * class that is registered with the tool registry, and that is used to create
+ * new instances of the tools.
+ */
+class DefaultTools : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ DefaultTools(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~DefaultTools();
+
+};
+
+#endif // DEFAULT_TOOLS_H_
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_brush.cc b/chalk/plugins/tools/defaulttools/kis_tool_brush.cc
new file mode 100644
index 00000000..373e0a07
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_brush.cc
@@ -0,0 +1,167 @@
+/*
+ * kis_tool_brush.cc - part of Chalk
+ *
+ * Copyright (c) 2003-2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <tqevent.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqwidget.h>
+#include <tqtimer.h>
+#include <tqpushbutton.h>
+#include <tqpainter.h>
+#include <tqrect.h>
+#include <tqcheckbox.h>
+
+#include <kdebug.h>
+#include <kaction.h>
+#include <kcommand.h>
+#include <klocale.h>
+
+#include "kis_config.h"
+#include "kis_brush.h"
+#include "kis_paintop.h"
+#include "kis_paintop_registry.h"
+#include "kis_cmb_composite.h"
+#include "kis_cursor.h"
+#include "kis_painter.h"
+#include "kis_tool_brush.h"
+#include "kis_canvas_subject.h"
+#include "kis_boundary.h"
+#include "kis_move_event.h"
+#include "kis_canvas.h"
+#include "kis_layer.h"
+
+KisToolBrush::KisToolBrush()
+ : super(i18n("Brush"))
+{
+ setName("tool_brush");
+ setCursor(KisCursor::load("tool_freehand_cursor.png", 5, 5));
+ m_rate = 100; // Conveniently hardcoded for now
+ m_timer = new TQTimer(this);
+ Q_CHECK_PTR(m_timer);
+
+ connect(m_timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(timeoutPaint()));
+
+}
+
+KisToolBrush::~KisToolBrush()
+{
+ delete m_timer;
+ m_timer = 0;
+}
+
+void KisToolBrush::timeoutPaint()
+{
+ if (currentImage() && painter()) {
+ painter()->paintAt(m_prevPos, m_prevPressure, m_prevXTilt, m_prevYTilt);
+ currentImage()->activeLayer()->setDirty(painter()->dirtyRect());
+ }
+}
+
+
+void KisToolBrush::update(KisCanvasSubject *subject)
+{
+ super::update(subject);
+}
+
+void KisToolBrush::initPaint(KisEvent *e)
+{
+ super::initPaint(e);
+
+ if (!m_painter) {
+ kdWarning() << "Didn't create a painter! Something is wrong!\n";
+ return;
+ }
+ KisPaintOp * op = KisPaintOpRegistry::instance()->paintOp(m_subject->currentPaintop(), m_subject->currentPaintopSettings(), m_painter);
+ if (!op) return;
+
+ m_subject->canvasController()->kiscanvas()->update(); // remove the outline
+
+ painter()->setPaintOp(op); // And now the painter owns the op and will destroy it.
+
+ if (op->incremental()) {
+ m_timer->start( m_rate );
+ }
+}
+
+
+void KisToolBrush::endPaint()
+{
+ m_timer->stop();
+ super::endPaint();
+}
+
+
+void KisToolBrush::setup(KActionCollection *collection)
+{
+
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Brush"),
+ "tool_freehand", TQt::Key_B, this,
+ TQT_SLOT(activate()), collection,
+ name());
+ m_action->setToolTip(i18n("Draw freehand"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+void KisToolBrush::move(KisMoveEvent *e) {
+ KisToolFreehand::move(e);
+ KisConfig cfg;
+ if (m_mode != PAINT && cfg.cursorStyle() == CURSOR_STYLE_OUTLINE)
+ paintOutline(e->pos());
+}
+
+void KisToolBrush::leave(TQEvent */*e*/) {
+ m_subject->canvasController()->kiscanvas()->update(); // remove the outline
+}
+
+
+void KisToolBrush::slotSetPaintingMode( int mode )
+{
+ if (mode == TQButton::On) {
+ // Direct painting
+ m_paintIncremental = true;
+ }
+ else {
+ m_paintIncremental = false;
+ }
+}
+
+
+TQWidget* KisToolBrush::createOptionWidget(TQWidget* tqparent)
+{
+ TQWidget *widget = super::createOptionWidget(tqparent);
+ m_chkDirect = new TQCheckBox(i18n("Paint direct"), widget, "chkDirect");
+ m_chkDirect->setChecked(true);
+ connect(m_chkDirect, TQT_SIGNAL(stateChanged(int)), this, TQT_SLOT(slotSetPaintingMode(int)));
+
+ m_optionLayout = new TQGridLayout(widget, 3, 2, 0, 6);
+ Q_CHECK_PTR(m_optionLayout);
+
+ super::addOptionWidgetLayout(m_optionLayout);
+ m_optionLayout->addWidget(m_chkDirect, 0, 0);
+
+ return widget;
+}
+
+#include "kis_tool_brush.moc"
+
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_brush.h b/chalk/plugins/tools/defaulttools/kis_tool_brush.h
new file mode 100644
index 00000000..a23e8d12
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_brush.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2003-2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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_TOOL_BRUSH_H_
+#define KIS_TOOL_BRUSH_H_
+
+
+#include "kis_tool_freehand.h"
+
+#include "kis_tool_factory.h"
+#include "koffice_export.h"
+
+class TQTimer;
+class KisPoint;
+class TQHBoxLayout;
+class TQPainter;
+class TQRect;
+class TQCheckBox;
+class TQGridLayout;
+
+class KRITACORE_EXPORT KisToolBrush : public KisToolFreehand {
+ Q_OBJECT
+ TQ_OBJECT
+ typedef KisToolFreehand super;
+
+public:
+ KisToolBrush();
+ virtual ~KisToolBrush();
+ virtual void update(KisCanvasSubject *subject);
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_SHAPE; }
+ virtual TQ_UINT32 priority() { return 0; }
+ TQWidget* createOptionWidget(TQWidget* tqparent);
+
+protected:
+
+ virtual void initPaint(KisEvent *e);
+ virtual void endPaint();
+ virtual void move(KisMoveEvent *e);
+ virtual void leave(TQEvent *e);
+
+private slots:
+
+ void timeoutPaint();
+ void slotSetPaintingMode( int mode );
+
+private:
+
+ TQ_INT32 m_rate;
+ TQTimer * m_timer;
+ TQGridLayout* m_optionLayout;
+ TQCheckBox * m_chkDirect;
+};
+
+class KisToolBrushFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolBrushFactory() : super() {};
+ virtual ~KisToolBrushFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolBrush();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("brush", i18n("Brush Tool")); }
+};
+
+
+#endif // KIS_TOOL_BRUSH_H_
+
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_colorpicker.cc b/chalk/plugins/tools/defaulttools/kis_tool_colorpicker.cc
new file mode 100644
index 00000000..32dbcf9d
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_colorpicker.cc
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 1999 Matthias Elter <me@kde.org>
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ *
+ * 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 <string.h>
+
+#include <tqpoint.h>
+#include <tqlayout.h>
+#include <tqcheckbox.h>
+#include <tqcombobox.h>
+#include <tqlistview.h>
+#include <tqspinbox.h>
+
+#include <kaction.h>
+#include <klocale.h>
+#include <tqcolor.h>
+#include <kmessagebox.h>
+
+#include "kis_layer.h"
+#include "kis_cursor.h"
+#include "kis_canvas_subject.h"
+#include "kis_image.h"
+#include "kis_paint_device.h"
+#include "kis_tool_colorpicker.h"
+#include "kis_tool_colorpicker.moc"
+#include "kis_button_press_event.h"
+#include "kis_canvas_subject.h"
+#include "kis_iterators_pixel.h"
+#include "kis_color.h"
+#include "kis_resourceserver.h"
+#include "kis_palette.h"
+#include "wdgcolorpicker.h"
+
+namespace {
+ // The location of the sample all visible layers in the combobox
+ const int SAMPLE_MERGED = 0;
+}
+
+KisToolColorPicker::KisToolColorPicker()
+ : super (i18n("Color Picker"))
+{
+ setName("tool_colorpicker");
+ setCursor(KisCursor::pickerCursor());
+ m_optionsWidget = 0;
+ m_subject = 0;
+ m_radius = 1;
+ m_addPalette = false;
+ m_updateColor = true;
+ m_normaliseValues = false;
+ m_pickedColor = KisColor();
+}
+
+KisToolColorPicker::~KisToolColorPicker()
+{
+}
+
+void KisToolColorPicker::update(KisCanvasSubject *subject)
+{
+ m_subject = subject;
+ super::update(m_subject);
+}
+
+void KisToolColorPicker::buttonPress(KisButtonPressEvent *e)
+{
+ if (m_subject) {
+ if (e->button() != Qt::LeftButton && e->button() != Qt::RightButton)
+ return;
+
+ KisImageSP img;
+
+ if (!m_subject || !(img = m_subject->currentImg()))
+ return;
+
+ KisPaintDeviceSP dev = img->activeDevice();
+
+ if (!dev) return;
+
+ bool sampleMerged = m_optionsWidget->cmbSources->currentItem() == SAMPLE_MERGED;
+ if (!sampleMerged) {
+ if (!img->activeLayer())
+ {
+ KMessageBox::information(0, i18n("Cannot pick a color as no layer is active."));
+ return;
+ }
+ if (!img->activeLayer()-> visible()) {
+ KMessageBox::information(0, i18n("Cannot pick a color as the active layer is not visible."));
+ return;
+ }
+ }
+
+ TQPoint pos = TQPoint(e->pos().floorX(), e->pos().floorY());
+
+ if (!img->bounds().tqcontains(pos)) {
+ return;
+ }
+
+ if (sampleMerged) {
+ dev = img->mergedImage();
+ }
+
+ if (m_radius == 1) {
+ m_pickedColor = dev->colorAt (pos.x(), pos.y());
+ } else {
+ // radius 2 ==> 9 pixels, 3 => 9 pixels, etc
+ static int counts[] = { 0, 1, 9, 25, 45, 69, 109, 145, 193, 249 };
+
+ KisColorSpace* cs = dev->colorSpace();
+ int pixelSize = cs->pixelSize();
+
+ TQ_UINT8* data = new TQ_UINT8[pixelSize];
+ TQ_UINT8** pixels = new TQ_UINT8*[counts[m_radius]];
+ TQ_UINT8* weights = new TQ_UINT8[counts[m_radius]];
+
+ int i = 0;
+ // dummy init
+ KisHLineIteratorPixel iter = dev->createHLineIterator(0, 0, 1, false);;
+ for (int y = - m_radius; y <= m_radius; y++) {
+ for (int x = - m_radius; x <= m_radius; x++) {
+ if (x*x + y*y < m_radius * m_radius) {
+ iter = dev->createHLineIterator(pos.x() + x, pos.y() + y, 1, false);
+
+ pixels[i] = new TQ_UINT8[pixelSize];
+ memcpy(pixels[i], iter.rawData(), pixelSize);
+
+ if (x == 0 && y == 0) {
+ // Because the sum of the weights must be 255,
+ // we cheat a bit, and weigh the center pixel differently in order
+ // to sum to 255 in total
+ // It's -(counts -1), because we'll add the center one implicitly
+ // through that calculation
+ weights[i] = 255 - (counts[m_radius]-1) * (255 / counts[m_radius]);
+ } else {
+ weights[i] = 255 / counts[m_radius];
+ }
+ i++;
+ }
+ }
+ }
+ // Weird, I can't do that directly :/
+ const TQ_UINT8** cpixels = const_cast<const TQ_UINT8**>(pixels);
+ cs->mixColors(cpixels, weights, counts[m_radius], data);
+ m_pickedColor = KisColor(data, cs);
+
+ for (i = 0; i < counts[m_radius]; i++)
+ delete[] pixels[i];
+ delete[] pixels;
+ delete[] data;
+ }
+
+ displayPickedColor();
+
+ if (m_updateColor) {
+ if (e->button() == Qt::LeftButton)
+ m_subject->setFGColor(m_pickedColor);
+ else
+ m_subject->setBGColor(m_pickedColor);
+ }
+
+ if (m_addPalette) {
+ // Convert to RGB to add to palette, we ought to have our own format :(
+ KisPaletteEntry ent;
+ ent.color = m_pickedColor.toTQColor();
+ // We don't ask for a name, too intrusive here
+
+ KisPalette* palette = m_palettes.at(m_optionsWidget-> cmbPalette->currentItem());
+ palette->add(ent);
+
+ if (!palette->save()) {
+ KMessageBox::error(0, i18n("Cannot write to palette file %1. Maybe it is read-only.").tqarg(palette->filename()), i18n("Palette"));
+ }
+ }
+ }
+}
+
+void KisToolColorPicker::displayPickedColor()
+{
+ if (m_pickedColor.data() && m_optionsWidget) {
+
+ TQValueVector<KisChannelInfo *> channels = m_pickedColor.colorSpace()->channels();
+ m_optionsWidget->listViewChannels->clear();
+
+ for (int i = channels.count() - 1; i >= 0 ; --i) {
+ TQString channelValueText;
+
+ if (m_normaliseValues) {
+ channelValueText = i18n("%1%").tqarg(m_pickedColor.colorSpace()->normalisedChannelValueText(m_pickedColor.data(), i));
+ } else {
+ channelValueText = m_pickedColor.colorSpace()->channelValueText(m_pickedColor.data(), i);
+ }
+
+ m_optionsWidget->listViewChannels->insertItem(new TQListViewItem(m_optionsWidget->listViewChannels,
+ channels[i]->name(),
+ channelValueText));
+ }
+ }
+}
+
+void KisToolColorPicker::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Color Picker"), "tool_colorpicker", TQt::Key_P, this, TQT_SLOT(activate()), collection, name());
+ m_action->setToolTip(i18n("Color picker"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+TQWidget* KisToolColorPicker::createOptionWidget(TQWidget* tqparent)
+{
+ m_optionsWidget = new ColorPickerOptionsWidget(tqparent);
+
+ m_optionsWidget->cbUpdateCurrentColour->setChecked(m_updateColor);
+
+ m_optionsWidget->cmbSources->setCurrentItem(0);
+
+ m_optionsWidget->cbNormaliseValues->setChecked(m_normaliseValues);
+ m_optionsWidget->cbPalette->setChecked(m_addPalette);
+ m_optionsWidget->radius->setValue(m_radius);
+
+ m_optionsWidget->listViewChannels->setSorting(-1);
+
+ connect(m_optionsWidget->cbUpdateCurrentColour, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotSetUpdateColor(bool)));
+ connect(m_optionsWidget->cbNormaliseValues, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotSetNormaliseValues(bool)));
+ connect(m_optionsWidget->cbPalette, TQT_SIGNAL(toggled(bool)),
+ TQT_SLOT(slotSetAddPalette(bool)));
+ connect(m_optionsWidget->radius, TQT_SIGNAL(valueChanged(int)),
+ TQT_SLOT(slotChangeRadius(int)));
+
+ KisResourceServerBase* srv = KisResourceServerRegistry::instance()->get("PaletteServer");
+
+ if (!srv) {
+ return m_optionsWidget;
+ }
+
+ TQValueList<KisResource*> palettes = srv->resources();
+
+ for(uint i = 0; i < palettes.count(); i++) {
+ KisPalette* palette = dynamic_cast<KisPalette*>(*palettes.at(i));
+ if (palette) {
+ m_optionsWidget->cmbPalette->insertItem(palette->name());
+ m_palettes.append(palette);
+ }
+ }
+
+ connect(srv, TQT_SIGNAL(resourceAdded(KisResource*)), this, TQT_SLOT(slotAddPalette(KisResource*)));
+
+ return m_optionsWidget;
+}
+
+TQWidget* KisToolColorPicker::optionWidget()
+{
+ return m_optionsWidget;
+}
+
+void KisToolColorPicker::slotSetUpdateColor(bool state)
+{
+ m_updateColor = state;
+}
+
+
+void KisToolColorPicker::slotSetNormaliseValues(bool state)
+{
+ m_normaliseValues = state;
+ displayPickedColor();
+}
+
+void KisToolColorPicker::slotSetAddPalette(bool state) {
+ m_addPalette = state;
+}
+
+void KisToolColorPicker::slotChangeRadius(int value) {
+ m_radius = value;
+}
+
+void KisToolColorPicker::slotAddPalette(KisResource* resource) {
+ KisPalette* palette = dynamic_cast<KisPalette*>(resource);
+ if (palette) {
+ m_optionsWidget-> cmbPalette->insertItem(palette->name());
+ m_palettes.append(palette);
+ }
+}
+
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_colorpicker.h b/chalk/plugins/tools/defaulttools/kis_tool_colorpicker.h
new file mode 100644
index 00000000..ab59ef17
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_colorpicker.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1999 Matthias Elter
+ * Copyright (c) 2002 Patrick Julien
+ *
+ * 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_TOOL_COLOR_PICKER_H_
+#define KIS_TOOL_COLOR_PICKER_H_
+
+#include "kis_tool_non_paint.h"
+#include "kis_tool_factory.h"
+#include "tqvaluevector.h"
+
+class ColorPickerOptionsWidget;
+class KisResource;
+class KisPalette;
+
+class KisToolColorPicker : public KisToolNonPaint {
+
+ Q_OBJECT
+ TQ_OBJECT
+ typedef KisToolNonPaint super;
+
+public:
+ KisToolColorPicker();
+ virtual ~KisToolColorPicker();
+
+public:
+ virtual void update(KisCanvasSubject *subject);
+ virtual void setup(KActionCollection *collection);
+ virtual void buttonPress(KisButtonPressEvent *e);
+ virtual TQWidget* createOptionWidget(TQWidget* tqparent);
+ virtual TQWidget* optionWidget();
+ virtual enumToolType toolType() { return TOOL_FILL; }
+ virtual TQ_UINT32 priority() { return 3; }
+
+public slots:
+ void slotSetUpdateColor(bool);
+ void slotSetNormaliseValues(bool);
+ void slotSetAddPalette(bool);
+ void slotChangeRadius(int);
+ void slotAddPalette(KisResource* resource);
+
+private:
+ void displayPickedColor();
+
+ bool m_updateColor;
+ bool m_addPalette;
+ bool m_normaliseValues;
+ int m_radius;
+ KisColor m_pickedColor;
+
+ ColorPickerOptionsWidget *m_optionsWidget;
+ KisCanvasSubject *m_subject;
+ TQValueVector<KisPalette*> m_palettes;
+};
+
+class KisToolColorPickerFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolColorPickerFactory() : super() {};
+ virtual ~KisToolColorPickerFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolColorPicker();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("colorpicker", i18n("Color Picker")); }
+};
+
+
+#endif // KIS_TOOL_COLOR_PICKER_H_
+
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_duplicate.cc b/chalk/plugins/tools/defaulttools/kis_tool_duplicate.cc
new file mode 100644
index 00000000..9619c6ae
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_duplicate.cc
@@ -0,0 +1,255 @@
+/*
+ * kis_tool_duplicate.cc - part of Chalk
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <tqbitmap.h>
+#include <tqcheckbox.h>
+#include <tqpainter.h>
+#include <tqlabel.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <knuminput.h>
+#include <klocale.h>
+
+#include "kis_brush.h"
+#include "kis_cursor.h"
+#include "kis_image.h"
+#include "kis_tool_duplicate.h"
+#include "kis_painter.h"
+#include "kis_vec.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_move_event.h"
+#include "kis_paintop.h"
+#include "kis_paintop_registry.h"
+#include "kis_canvas_subject.h"
+#include "kis_perspective_grid.h"
+
+#include "kis_canvas_painter.h"
+#include "kis_boundary_painter.h"
+
+KisToolDuplicate::KisToolDuplicate()
+ : super(i18n("Duplicate Brush")), m_isOffsetNotUptodate(true), m_position(TQPoint(-1,-1))
+{
+ setName("tool_duplicate");
+ m_subject = 0;
+ setCursor(KisCursor::load("tool_duplicate_cursor.png", 5, 5));
+}
+
+KisToolDuplicate::~KisToolDuplicate()
+{
+}
+
+void KisToolDuplicate::activate()
+{
+ m_position = TQPoint(-1,-1);
+ super::activate();
+ if( m_subject->currentImg()->perspectiveGrid()->countSubGrids() != 1 )
+ {
+ m_perspectiveCorrection->setEnabled( false );
+ m_perspectiveCorrection->setChecked( false );
+ } else {
+ m_perspectiveCorrection->setEnabled( true );
+ }
+}
+
+void KisToolDuplicate::buttonPress(KisButtonPressEvent *e)
+{
+ if (e->state() == ShiftButton) {
+ m_position = e->pos();
+ m_isOffsetNotUptodate = true;
+ } else {
+ if (m_position != TQPoint(-1, -1)) {
+ super::buttonPress(e);
+ }
+ }
+}
+
+
+void KisToolDuplicate::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Duplicate Brush"),
+ "tool_duplicate", TQt::Key_C, this,
+ TQT_SLOT(activate()), collection,
+ name());
+ m_action->setToolTip(i18n("Duplicate parts of the image. Shift-click to select the point to duplicate from to begin."));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+void KisToolDuplicate::initPaint(KisEvent *e)
+{
+ if( m_position != TQPoint(-1,-1))
+ {
+ if(m_isOffsetNotUptodate)
+ {
+ m_offset = e->pos() - m_position;
+ m_isOffsetNotUptodate = false;
+ }
+ m_paintIncremental = false;
+ super::initPaint(e);
+ painter()->setDuplicateOffset( m_offset );
+ KisPaintOp * op = KisPaintOpRegistry::instance()->paintOp("duplicate", 0, painter());
+ if (op && m_source) {
+ op->setSource(m_source);
+ painter()->setPaintOp(op);
+ }
+ m_positionStartPainting = e->pos();
+ painter()->setDuplicateStart( e->pos() );
+ }
+}
+
+void KisToolDuplicate::move(KisMoveEvent *e)
+{
+
+ // Paint the outline where we will (or are) copying from
+ if( m_position == TQPoint(-1,-1) )
+ return;
+
+ TQPoint srcPos;
+ if (m_mode == PAINT) {
+ // if we are in perspective correction mode, update the offset when moving
+ if(m_perspectiveCorrection->isChecked())
+ {
+ double startM[3][3];
+ double endM[3][3];
+ for(int i = 0; i < 3; i++)
+ {
+ for(int j = 0; j < 3; j++)
+ {
+ startM[i][j] = 0.;
+ endM[i][j] = 0.;
+ }
+ startM[i][i] = 1.;
+ endM[i][i] = 1.;
+ }
+
+ // First look for the grid corresponding to the start point
+ KisSubPerspectiveGrid* subGridStart = *m_subject->currentImg()->perspectiveGrid()->begin();//device->image()->perspectiveGrid()->gridAt(KisPoint(srcPoint.x() +hotSpot.x(),srcPoint.y() +hotSpot.y()));
+ TQRect r = TQRect(0,0, m_subject->currentImg()->width(), m_subject->currentImg()->height());
+
+ if(subGridStart)
+ {
+ double* b = KisPerspectiveMath::computeMatrixTransfoFromPerspective( r, *subGridStart->topLeft(), *subGridStart->topRight(), *subGridStart->bottomLeft(), *subGridStart->bottomRight());
+ for(int i = 0; i < 3; i++)
+ {
+ for(int j = 0; j < 3; j++)
+ {
+ startM[i][j] = b[3*i+j];
+ }
+ }
+
+ }
+ // Second look for the grid corresponding to the end point
+ KisSubPerspectiveGrid* subGridEnd = *m_subject->currentImg()->perspectiveGrid()->begin();// device->image()->perspectiveGrid()->gridAt(pos);
+ if(subGridEnd)
+ {
+ double* b = KisPerspectiveMath::computeMatrixTransfoToPerspective(*subGridEnd->topLeft(), *subGridEnd->topRight(), *subGridEnd->bottomLeft(), *subGridEnd->bottomRight(), r);
+ for(int i = 0; i < 3; i++)
+ {
+ for(int j = 0; j < 3; j++)
+ {
+ endM[i][j] = b[3*i+j];
+ }
+ }
+ }
+ // Compute the translation in the perspective transformation space:
+ KisPoint translat;
+ {
+ KisPoint positionStartPaintingT = KisPerspectiveMath::matProd(endM, m_positionStartPainting);
+ KisPoint currentPositionT = KisPerspectiveMath::matProd(endM, e->pos() );
+ KisPoint duplicateStartPoisitionT = KisPerspectiveMath::matProd(endM, m_positionStartPainting - m_offset);
+ KisPoint duplicateRealPosition = KisPerspectiveMath::matProd(startM, duplicateStartPoisitionT + (currentPositionT - positionStartPaintingT) );
+ KisPoint p = e->pos() - duplicateRealPosition;
+ srcPos = p.floorTQPoint();
+ }
+
+ }else {
+ srcPos = painter()->duplicateOffset().floorTQPoint();
+ }
+ } else {
+ if(m_isOffsetNotUptodate)
+ srcPos = e->pos().floorTQPoint() - m_position.floorTQPoint();
+ else
+ srcPos = m_offset.floorTQPoint();
+ }
+
+ TQ_INT32 x;
+ TQ_INT32 y;
+
+ // like KisPaintOp::splitCoordinate
+ x = (TQ_INT32)((e->x() < 0) ? e->x() - 1 : e->x());
+ y = (TQ_INT32)((e->y() < 0) ? e->y() - 1 : e->y());
+ srcPos = TQPoint(x - srcPos.x(), y - srcPos.y());
+
+ paintOutline(srcPos);
+ super::move(e);
+}
+
+void KisToolDuplicate::paintAt(const KisPoint &pos,
+ const double pressure,
+ const double xtilt,
+ const double ytilt)
+{
+ if( m_position != TQPoint(-1,-1))
+ {
+ if(m_isOffsetNotUptodate)
+ {
+ m_offset = pos - m_position;
+ m_isOffsetNotUptodate = false;
+ }
+ painter()->setDuplicateHealing( m_healing->isChecked() );
+ painter()->setDuplicateHealingRadius( m_healingRadius->value() );
+ painter()->setDuplicatePerspectiveCorrection( m_perspectiveCorrection->isChecked() );
+ painter()->paintAt( pos, pressure, xtilt, ytilt);
+ }
+}
+
+TQString KisToolDuplicate::quickHelp() const {
+ return i18n("To start, shift-click on the place you want to duplicate from. Then you can start painting. An indication of where you are copying from will be displayed while drawing and moving the mouse.");
+}
+
+TQWidget* KisToolDuplicate::createOptionWidget(TQWidget* tqparent)
+{
+ TQWidget* widget = KisToolPaint::createOptionWidget(tqparent);
+ m_healing = new TQCheckBox(widget);
+ m_healing->setChecked( false);
+ addOptionWidgetOption(m_healing, new TQLabel(i18n("Healing"), widget ));
+ m_healingRadius = new KIntNumInput(widget);
+
+ KisBrush *brush = m_subject->currentBrush();
+ int healingradius = 20;
+ if( brush )
+ {
+ healingradius = 2 * TQMAX(brush->width(),brush->height());
+ }
+
+ m_healingRadius->setValue( healingradius );
+ addOptionWidgetOption(m_healingRadius, new TQLabel(i18n("Healing radius"), widget ));
+ m_perspectiveCorrection = new TQCheckBox(widget);
+ addOptionWidgetOption(m_perspectiveCorrection, new TQLabel(i18n("Correct the perspective"), widget ));
+ return widget;
+}
+
+#include "kis_tool_duplicate.moc"
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_duplicate.h b/chalk/plugins/tools/defaulttools/kis_tool_duplicate.h
new file mode 100644
index 00000000..8a298318
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_duplicate.h
@@ -0,0 +1,92 @@
+/*
+ * kis_tool_duplicate.h - part of Chalk
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_TOOL_DUPLICATE_H__
+#define __KIS_TOOL_DUPLICATE_H__
+
+#include "kis_tool_freehand.h"
+#include "kis_tool_factory.h"
+
+class KisEvent;
+class KisButtonPressEvent;
+
+class TQCheckBox;
+class KIntNumInput;
+
+class KisToolDuplicate : public KisToolFreehand {
+
+ typedef KisToolFreehand super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolDuplicate();
+ virtual ~KisToolDuplicate();
+
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_FREEHAND; }
+ virtual TQ_UINT32 priority() { return 0; }
+ virtual void buttonPress(KisButtonPressEvent *e);
+ virtual void move(KisMoveEvent *e);
+
+ virtual void paintAt(const KisPoint &pos,
+ const double pressure,
+ const double xTilt,
+ const double yTilt);
+
+ virtual TQString quickHelp() const;
+ virtual TQWidget* createOptionWidget(TQWidget* tqparent);
+
+protected slots:
+ virtual void activate();
+
+protected:
+ virtual void initPaint(KisEvent *e);
+
+ // Tool starting duplicate
+ KisPoint m_offset; // This member give the offset from the click position to the point where we take the duplication
+ bool m_isOffsetNotUptodate; // Tells if the offset is update
+ KisPoint m_position; // Give the position of the last alt-click
+ KisPoint m_positionStartPainting;
+ TQCheckBox* m_healing;
+ KIntNumInput* m_healingRadius;
+ TQCheckBox* m_perspectiveCorrection;
+};
+
+
+class KisToolDuplicateFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolDuplicateFactory() : super() {};
+ virtual ~KisToolDuplicateFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolDuplicate();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("duplicate", i18n("Duplicate Tool")); }
+};
+
+
+
+#endif //__KIS_TOOL_DUPLICATE_H__
+
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_ellipse.cc b/chalk/plugins/tools/defaulttools/kis_tool_ellipse.cc
new file mode 100644
index 00000000..65593c23
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_ellipse.cc
@@ -0,0 +1,186 @@
+/*
+ * kis_tool_ellipse.cc - part of Krayon
+ *
+ * Copyright (c) 2000 John Califf <jcaliff@compuzone.net>
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Clarence Dang <dang@kde.org>
+ *
+ * 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 <tqpainter.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+#include "kis_painter.h"
+#include "kis_canvas_subject.h"
+#include "kis_canvas_controller.h"
+#include "kis_tool_ellipse.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_move_event.h"
+#include "kis_paintop_registry.h"
+#include "kis_undo_adapter.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+#include "kis_cursor.h"
+
+KisToolEllipse::KisToolEllipse()
+ : super(i18n ("Ellipse")),
+ m_dragging (false),
+ m_currentImage (0)
+{
+ setName("tool_ellipse");
+ setCursor(KisCursor::load("tool_ellipse_cursor.png", 6, 6));
+}
+
+KisToolEllipse::~KisToolEllipse()
+{
+}
+
+void KisToolEllipse::update (KisCanvasSubject *subject)
+{
+ super::update (subject);
+ if (m_subject)
+ m_currentImage = m_subject->currentImg ();
+}
+
+void KisToolEllipse::buttonPress(KisButtonPressEvent *event)
+{
+ if (m_currentImage && event->button() == Qt::LeftButton) {
+ m_dragging = true;
+ m_dragStart = m_dragCenter = m_dragEnd = event->pos();
+ draw(m_dragStart, m_dragEnd);
+ }
+}
+
+void KisToolEllipse::move(KisMoveEvent *event)
+{
+ if (m_dragging) {
+ // erase old lines on canvas
+ draw(m_dragStart, m_dragEnd);
+ // move (alt) or resize ellipse
+ if (event->state() & TQt::AltButton) {
+ KisPoint trans = event->pos() - m_dragEnd;
+ m_dragStart += trans;
+ m_dragEnd += trans;
+ } else {
+ KisPoint diag = event->pos() - (event->state() & TQt::ControlButton
+ ? m_dragCenter : m_dragStart);
+ // circle?
+ if (event->state() & TQt::ShiftButton) {
+ double size = TQMAX(fabs(diag.x()), fabs(diag.y()));
+ double w = diag.x() < 0 ? -size : size;
+ double h = diag.y() < 0 ? -size : size;
+ diag = KisPoint(w, h);
+ }
+
+ // resize around center point?
+ if (event->state() & TQt::ControlButton) {
+ m_dragStart = m_dragCenter - diag;
+ m_dragEnd = m_dragCenter + diag;
+ } else {
+ m_dragEnd = m_dragStart + diag;
+ }
+ }
+ // draw new lines on canvas
+ draw(m_dragStart, m_dragEnd);
+ m_dragCenter = KisPoint((m_dragStart.x() + m_dragEnd.x()) / 2,
+ (m_dragStart.y() + m_dragEnd.y()) / 2);
+ }
+}
+
+void KisToolEllipse::buttonRelease(KisButtonReleaseEvent *event)
+{
+ if (!m_subject || !m_currentImage)
+ return;
+
+ if (m_dragging && event->button() == Qt::LeftButton) {
+ // erase old lines on canvas
+ draw(m_dragStart, m_dragEnd);
+ m_dragging = false;
+
+ if (m_dragStart == m_dragEnd)
+ return;
+
+ if (!m_currentImage)
+ return;
+
+ if (!m_currentImage->activeDevice())
+ return;
+
+ KisPaintDeviceSP device = m_currentImage->activeDevice ();
+ KisPainter painter (device);
+ if (m_currentImage->undo()) painter.beginTransaction (i18n ("Ellipse"));
+
+ painter.setPaintColor(m_subject->fgColor());
+ painter.setBackgroundColor(m_subject->bgColor());
+ painter.setFillStyle(fillStyle());
+ painter.setBrush(m_subject->currentBrush());
+ painter.setPattern(m_subject->currentPattern());
+ painter.setOpacity(m_opacity);
+ painter.setCompositeOp(m_compositeOp);
+ KisPaintOp * op = KisPaintOpRegistry::instance()->paintOp(m_subject->currentPaintop(), m_subject->currentPaintopSettings(), &painter);
+ painter.setPaintOp(op); // Painter takes ownership
+
+ painter.paintEllipse(m_dragStart, m_dragEnd, PRESSURE_DEFAULT/*event->pressure()*/, event->xTilt(), event->yTilt());
+ device->setDirty( painter.dirtyRect() );
+ notifyModified();
+
+ KisUndoAdapter *adapter = m_currentImage->undoAdapter();
+ if (adapter) {
+ adapter->addCommand(painter.endTransaction());
+ }
+ }
+}
+
+void KisToolEllipse::draw(const KisPoint& start, const KisPoint& end )
+{
+ if (!m_subject || !m_currentImage)
+ return;
+
+ KisCanvasController *controller = m_subject->canvasController ();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter p (canvas);
+
+ p.setRasterOp (TQt::NotROP);
+ p.drawEllipse (TQRect (controller->windowToView (start).floorTQPoint(), controller->windowToView (end).floorTQPoint()));
+ p.end ();
+}
+
+void KisToolEllipse::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ KShortcut shortcut(TQt::Key_Plus);
+ shortcut.append(KShortcut(TQt::Key_F7));
+ m_action = new KRadioAction(i18n("&Ellipse"),
+ "tool_ellipse",
+ shortcut,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ m_action->setToolTip(i18n("Draw an ellipse"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+#include "kis_tool_ellipse.moc"
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_ellipse.h b/chalk/plugins/tools/defaulttools/kis_tool_ellipse.h
new file mode 100644
index 00000000..4f79fbd6
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_ellipse.h
@@ -0,0 +1,91 @@
+/*
+ * kis_tool_ellipse.h - part of Krayon
+ *
+ * Copyright (c) 2000 John Califf <jcaliff@compuzone.net>
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Clarence Dang <dang@kde.org>
+ *
+ * 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_TOOL_ELLIPSE_H__
+#define __KIS_TOOL_ELLIPSE_H__
+
+#include "kis_tool_shape.h"
+
+class KisCanvas;
+class KisPainter;
+class KisRect;
+
+class KisToolEllipse : public KisToolShape {
+
+ typedef KisToolShape super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolEllipse();
+ virtual ~KisToolEllipse();
+
+ //
+ // KisCanvasObserver interface
+ //
+
+ virtual void update (KisCanvasSubject *subject);
+
+ //
+ // KisToolPaint interface
+ //
+
+ virtual void setup(KActionCollection *collection);
+ virtual TQ_UINT32 priority() { return 3; }
+ virtual enumToolType toolType() { return TOOL_SHAPE; }
+ virtual void buttonPress(KisButtonPressEvent *event);
+ virtual void move(KisMoveEvent *event);
+ virtual void buttonRelease(KisButtonReleaseEvent *event);
+
+protected:
+ virtual void draw(const KisPoint& start, const KisPoint& stop);
+
+protected:
+ KisPoint m_dragCenter;
+ KisPoint m_dragStart;
+ KisPoint m_dragEnd;
+
+ bool m_dragging;
+ KisImageSP m_currentImage;
+};
+
+
+#include "kis_tool_factory.h"
+
+class KisToolEllipseFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolEllipseFactory() : super() {};
+ virtual ~KisToolEllipseFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolEllipse();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("ellipse", i18n("Ellipse Tool")); }
+};
+
+
+#endif //__KIS_TOOL_ELLIPSE_H__
+
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_fill.cc b/chalk/plugins/tools/defaulttools/kis_tool_fill.cc
new file mode 100644
index 00000000..1e2b82c5
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_fill.cc
@@ -0,0 +1,233 @@
+/*
+ * kis_tool_fill.cc - part of Krayon
+ *
+ * Copyright (c) 2000 John Califf <jcaliff@compuzone.net>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Bart Coppens <kde@bartcoppens.be>
+ *
+ * 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 <kaction.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kcommand.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqcheckbox.h>
+
+#include <tqcolor.h>
+
+#include "knuminput.h"
+
+#include "kis_layer.h"
+#include "kis_cursor.h"
+#include "kis_painter.h"
+#include "kis_tool_brush.h"
+#include "kis_cmb_composite.h"
+#include "kis_tool_fill.h"
+#include "kis_colorspace.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_move_event.h"
+#include "kis_pattern.h"
+#include "kis_fill_painter.h"
+#include "kis_progress_display_interface.h"
+#include "kis_undo_adapter.h"
+#include "kis_canvas_subject.h"
+#include "kis_selection.h"
+
+KisToolFill::KisToolFill()
+ : super(i18n("Fill")), m_wasPressed(false)
+{
+ setName("tool_fill");
+ m_subject = 0;
+ m_oldColor = 0;
+ m_threshold = 15;
+ m_usePattern = false;
+ m_unmerged = false;
+ m_fillOnlySelection = false;
+
+ setCursor(KisCursor::load("tool_fill_cursor.png", 6, 6));
+}
+
+void KisToolFill::update(KisCanvasSubject *subject)
+{
+ m_subject = subject;
+ m_currentImage = subject->currentImg();
+
+ super::update(m_subject);
+}
+
+KisToolFill::~KisToolFill()
+{
+}
+
+bool KisToolFill::flood(int startX, int startY)
+{
+ KisPaintDeviceSP device = m_currentImage->activeDevice();
+ if (!device) return false;
+
+ if (m_fillOnlySelection) {
+ TQRect rc = device->selection()->selectedRect();
+ KisPaintDeviceSP filled = new KisPaintDevice(device->colorSpace(), "filled");
+ KisFillPainter painter(filled);
+ if (m_usePattern)
+ painter.fillRect(rc.x(), rc.y(), rc.width(), rc.height(),
+ m_subject->currentPattern());
+ else
+ painter.fillRect(rc.x(), rc.y(), rc.width(), rc.height(),
+ m_subject->fgColor(), m_opacity);
+ painter.end();
+ KisPainter painter2(device);
+ if (m_currentImage->undo()) painter2.beginTransaction(i18n("Fill"));
+ painter2.bltSelection(rc.x(), rc.y() , m_compositeOp, filled, m_opacity,
+ rc.x(), rc.y(), rc.width(), rc.height());
+
+ device->setDirty(filled->extent());
+ notifyModified();
+
+ if (m_currentImage->undo()) {
+ m_currentImage->undoAdapter()->addCommand(painter2.endTransaction());
+ }
+ return true;
+ }
+
+ KisFillPainter painter(device);
+ if (m_currentImage->undo()) painter.beginTransaction(i18n("Flood Fill"));
+ painter.setPaintColor(m_subject->fgColor());
+ painter.setOpacity(m_opacity);
+ painter.setFillThreshold(m_threshold);
+ painter.setCompositeOp(m_compositeOp);
+ painter.setPattern(m_subject->currentPattern());
+ painter.setSampleMerged(!m_unmerged);
+ painter.setCareForSelection(true);
+
+ KisProgressDisplayInterface *progress = m_subject->progressDisplay();
+ if (progress) {
+ progress->setSubject(&painter, true, true);
+ }
+
+ if (m_usePattern)
+ painter.fillPattern(startX, startY);
+ else
+ painter.fillColor(startX, startY);
+
+ device->setDirty(painter.dirtyRect());
+ notifyModified();
+
+ if (m_currentImage->undo()) {
+ m_currentImage->undoAdapter()->addCommand(painter.endTransaction());
+ }
+
+ return true;
+}
+
+void KisToolFill::buttonPress(KisButtonPressEvent *e)
+{
+ m_startPos = e->pos();
+ m_wasPressed = true;
+}
+
+void KisToolFill::buttonRelease(KisButtonReleaseEvent *e)
+{
+ if (!m_subject) return;
+ if (!m_currentImage || !m_currentImage->activeDevice()) return;
+ if (e->button() != Qt::LeftButton) return;
+ if(!m_wasPressed) return;
+ m_wasPressed = false;
+ int x, y;
+ x = m_startPos.floorX();
+ y = m_startPos.floorY();
+ if (!m_currentImage->bounds().tqcontains(x, y)) {
+ return;
+ }
+ flood(x, y);
+ notifyModified();
+}
+
+TQWidget* KisToolFill::createOptionWidget(TQWidget* tqparent)
+{
+ TQWidget *widget = super::createOptionWidget(tqparent);
+
+ m_lbThreshold = new TQLabel(i18n("Threshold: "), widget);
+ m_slThreshold = new KIntNumInput( widget, "int_widget");
+ m_slThreshold->setRange( 1, 100);
+ m_slThreshold->setSteps( 3, 3);
+ m_slThreshold->setValue(m_threshold);
+ connect(m_slThreshold, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotSetThreshold(int)));
+
+ m_checkUsePattern = new TQCheckBox(i18n("Use pattern"), widget);
+ m_checkUsePattern->setChecked(m_usePattern);
+ connect(m_checkUsePattern, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotSetUsePattern(bool)));
+
+ m_checkSampleMerged = new TQCheckBox(i18n("Limit to current layer"), widget);
+ m_checkSampleMerged->setChecked(m_unmerged);
+ connect(m_checkSampleMerged, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotSetSampleMerged(bool)));
+
+ m_checkFillSelection = new TQCheckBox(i18n("Fill entire selection"), widget);
+ m_checkFillSelection->setChecked(m_fillOnlySelection);
+ connect(m_checkFillSelection, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotSetFillSelection(bool)));
+
+ addOptionWidgetOption(m_slThreshold, m_lbThreshold);
+
+ addOptionWidgetOption(m_checkFillSelection);
+ addOptionWidgetOption(m_checkSampleMerged);
+ addOptionWidgetOption(m_checkUsePattern);
+
+ return widget;
+}
+
+void KisToolFill::slotSetThreshold(int threshold)
+{
+ m_threshold = threshold;
+}
+
+void KisToolFill::slotSetUsePattern(bool state)
+{
+ m_usePattern = state;
+}
+
+void KisToolFill::slotSetSampleMerged(bool state)
+{
+ m_unmerged = state;
+}
+
+void KisToolFill::slotSetFillSelection(bool state)
+{
+ m_fillOnlySelection = state;
+ m_slThreshold->setEnabled(!state);
+ m_checkSampleMerged->setEnabled(!state);
+}
+
+void KisToolFill::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Fill"),
+ "tool_color_fill",
+ TQt::Key_F,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ m_action->setToolTip(i18n("Contiguous fill"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+#include "kis_tool_fill.moc"
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_fill.h b/chalk/plugins/tools/defaulttools/kis_tool_fill.h
new file mode 100644
index 00000000..61087243
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_fill.h
@@ -0,0 +1,109 @@
+/*
+ * kis_tool_fill.h - part of Krayon^Chalk
+ *
+ * Copyright (c) 2004 Bart Coppens <kde@bartcoppens.be>
+ *
+ * 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 __filltool_h__
+#define __filltool_h__
+
+#include <tqpoint.h>
+
+#include "kis_point.h"
+#include "kis_tool_paint.h"
+
+class KisPainter;
+class TQWidget;
+class TQLabel;
+class TQCheckBox;
+class KIntNumInput;
+class KActionCollection;
+
+class KisToolFill : public KisToolPaint {
+
+ typedef KisToolPaint super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ KisToolFill();
+ virtual ~KisToolFill();
+
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_FILL; }
+ virtual TQ_UINT32 priority() { return 0; }
+
+ virtual void update(KisCanvasSubject *subject);
+
+ virtual void buttonPress(KisButtonPressEvent*);
+ virtual void buttonRelease(KisButtonReleaseEvent*);
+
+ bool flood(int startX, int startY);
+
+ virtual TQWidget* createOptionWidget(TQWidget* tqparent);
+
+public slots:
+ virtual void slotSetThreshold(int);
+ virtual void slotSetUsePattern(bool);
+ virtual void slotSetSampleMerged(bool);
+ virtual void slotSetFillSelection(bool);
+
+private:
+ KisPoint m_startPos;
+ int m_threshold;
+ TQ_INT32 m_depth;
+ KisLayerSP m_lay;
+ TQ_UINT8* m_oldColor, *m_color;
+ KisPainter *m_painter;
+ KisCanvasSubject *m_subject;
+ KisImageSP m_currentImage;
+ bool *m_map, m_unmerged, m_usePattern, m_fillOnlySelection;
+ KisSelectionSP m_selection;
+
+ TQLabel *m_lbThreshold;
+ KIntNumInput *m_slThreshold;
+ TQCheckBox *m_checkUsePattern;
+ TQCheckBox *m_checkSampleMerged;
+ TQCheckBox *m_checkFillSelection;
+ bool m_wasPressed; // use for preventing bug:133148
+};
+
+
+#include "kis_tool_factory.h"
+
+class KisToolFillFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolFillFactory() : super() {};
+ virtual ~KisToolFillFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisToolFill * t = new KisToolFill();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("fill", i18n("Fill Tool")); }
+
+};
+
+
+
+
+#endif //__filltool_h__
+
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_gradient.cc b/chalk/plugins/tools/defaulttools/kis_tool_gradient.cc
new file mode 100644
index 00000000..4eb685a5
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_gradient.cc
@@ -0,0 +1,309 @@
+/*
+ * kis_tool_gradient.cc - part of Chalk
+ *
+ * Copyright (c) 2000 John Califf
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2003 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ *
+ * 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 <tqpainter.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqcheckbox.h>
+
+#include <kdebug.h>
+#include <kaction.h>
+#include <kcommand.h>
+#include <klocale.h>
+#include <knuminput.h>
+
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_canvas_subject.h"
+#include "kis_cmb_composite.h"
+#include "kis_cursor.h"
+#include "kis_double_widget.h"
+#include "kis_gradient_painter.h"
+#include "kis_move_event.h"
+#include "kis_painter.h"
+#include "kis_progress_display_interface.h"
+#include "kis_tool_gradient.h"
+#include "kis_undo_adapter.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+
+KisToolGradient::KisToolGradient()
+ : super(i18n("Gradient")),
+ m_dragging( false )
+{
+ setName("tool_gradient");
+ setCursor(KisCursor::load("tool_gradient_cursor.png", 6, 6));
+
+ m_startPos = KisPoint(0, 0);
+ m_endPos = KisPoint(0, 0);
+
+ m_reverse = false;
+ m_tqshape = KisGradientPainter::GradientShapeLinear;
+ m_repeat = KisGradientPainter::GradientRepeatNone;
+ m_antiAliasThreshold = 0.2;
+}
+
+KisToolGradient::~KisToolGradient()
+{
+}
+
+void KisToolGradient::update(KisCanvasSubject *subject)
+{
+ m_subject = subject;
+ super::update(m_subject);
+}
+
+void KisToolGradient::paint(KisCanvasPainter& gc)
+{
+ if (m_dragging)
+ paintLine(gc);
+}
+
+void KisToolGradient::paint(KisCanvasPainter& gc, const TQRect&)
+{
+ if (m_dragging)
+ paintLine(gc);
+}
+
+void KisToolGradient::buttonPress(KisButtonPressEvent *e)
+{
+ if (!m_subject || !m_subject->currentImg()) {
+ return;
+ }
+
+ if (e->button() == Qt::LeftButton) {
+ m_dragging = true;
+ m_startPos = e->pos();
+ m_endPos = e->pos();
+ }
+}
+
+void KisToolGradient::move(KisMoveEvent *e)
+{
+ if (m_dragging) {
+ if (m_startPos != m_endPos) {
+ paintLine();
+ }
+
+ if ((e->state() & TQt::ShiftButton) == TQt::ShiftButton) {
+ m_endPos = straightLine(e->pos());
+ }
+ else {
+ m_endPos = e->pos();
+ }
+
+ paintLine();
+ }
+}
+
+void KisToolGradient::buttonRelease(KisButtonReleaseEvent *e)
+{
+ if (m_dragging && e->button() == Qt::LeftButton) {
+
+ KisCanvasController *controller = m_subject->canvasController();
+ KisImageSP img = m_subject->currentImg();
+
+ m_dragging = false;
+
+ if (m_startPos == m_endPos) {
+ controller->updateCanvas();
+ m_dragging = false;
+ return;
+ }
+
+ if ((e->state() & TQt::ShiftButton) == TQt::ShiftButton) {
+ m_endPos = straightLine(e->pos());
+ }
+ else {
+ m_endPos = e->pos();
+ }
+
+ KisPaintDeviceSP device;
+
+ if (img && (device = img->activeDevice())) {
+
+ KisGradientPainter painter(device);
+
+ if (img->undo()) painter.beginTransaction(i18n("Gradient"));
+
+ painter.setPaintColor(m_subject->fgColor());
+ painter.setGradient(*(m_subject->currentGradient()));
+ painter.setOpacity(m_opacity);
+ painter.setCompositeOp(m_compositeOp);
+
+ KisProgressDisplayInterface *progress = m_subject->progressDisplay();
+
+ if (progress) {
+ progress->setSubject(&painter, true, true);
+ }
+
+ bool painted = painter.paintGradient(m_startPos, m_endPos, m_tqshape, m_repeat, m_antiAliasThreshold, m_reverse, 0, 0, m_subject->currentImg()->width(), m_subject->currentImg()->height());
+
+ if (painted) {
+ // does whole thing at moment
+ device->setDirty(painter.dirtyRect());
+
+ notifyModified();
+
+ if (img->undo()) {
+ img->undoAdapter()->addCommand(painter.endTransaction());
+ }
+ }
+
+ /* remove remains of the line drawn while moving */
+ if (controller->kiscanvas()) {
+ controller->kiscanvas()->update();
+ }
+
+ }
+ }
+}
+
+KisPoint KisToolGradient::straightLine(KisPoint point)
+{
+ KisPoint comparison = point - m_startPos;
+ KisPoint result;
+
+ if ( fabs(comparison.x()) > fabs(comparison.y())) {
+ result.setX(point.x());
+ result.setY(m_startPos.y());
+ } else {
+ result.setX( m_startPos.x() );
+ result.setY( point.y() );
+ }
+
+ return result;
+}
+
+void KisToolGradient::paintLine()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter gc(canvas);
+
+ paintLine(gc);
+ }
+}
+
+void KisToolGradient::paintLine(KisCanvasPainter& gc)
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+
+ KisPoint start = controller->windowToView(m_startPos);
+ KisPoint end = controller->windowToView(m_endPos);
+
+ RasterOp op = gc.rasterOp();
+ TQPen old = gc.pen();
+ TQPen pen(TQt::SolidLine);
+
+ gc.setRasterOp(TQt::NotROP);
+ gc.setPen(pen);
+ gc.drawLine(start.floorTQPoint(), end.floorTQPoint());
+ gc.setRasterOp(op);
+ gc.setPen(old);
+ }
+}
+
+TQWidget* KisToolGradient::createOptionWidget(TQWidget* tqparent)
+{
+ TQWidget *widget = super::createOptionWidget(tqparent);
+ Q_CHECK_PTR(widget);
+
+ m_lbShape = new TQLabel(i18n("Shape:"), widget);
+ m_lbRepeat = new TQLabel(i18n("Repeat:"), widget);
+
+ m_ckReverse = new TQCheckBox(i18n("Reverse"), widget, "reverse_check");
+ connect(m_ckReverse, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotSetReverse(bool)));
+
+ m_cmbShape = new TQComboBox(false, widget, "tqshape_combo");
+ connect(m_cmbShape, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotSetShape(int)));
+ m_cmbShape->insertItem(i18n("Linear"));
+ m_cmbShape->insertItem(i18n("Bi-Linear"));
+ m_cmbShape->insertItem(i18n("Radial"));
+ m_cmbShape->insertItem(i18n("Square"));
+ m_cmbShape->insertItem(i18n("Conical"));
+ m_cmbShape->insertItem(i18n("Conical Symmetric"));
+
+ m_cmbRepeat = new TQComboBox(false, widget, "repeat_combo");
+ connect(m_cmbRepeat, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotSetRepeat(int)));
+ m_cmbRepeat->insertItem(i18n("None"));
+ m_cmbRepeat->insertItem(i18n("Forwards"));
+ m_cmbRepeat->insertItem(i18n("Alternating"));
+
+ addOptionWidgetOption(m_cmbShape, m_lbShape);
+
+ addOptionWidgetOption(m_cmbRepeat, m_lbRepeat);
+
+ addOptionWidgetOption(m_ckReverse);
+
+ m_lbAntiAliasThreshold = new TQLabel(i18n("Anti-alias threshold:"), widget);
+
+ m_slAntiAliasThreshold = new KDoubleNumInput(widget, "threshold_slider");
+ m_slAntiAliasThreshold->setRange( 0, 1);
+ m_slAntiAliasThreshold->setValue(m_antiAliasThreshold);
+ connect(m_slAntiAliasThreshold, TQT_SIGNAL(valueChanged(double)), this, TQT_SLOT(slotSetAntiAliasThreshold(double)));
+
+ addOptionWidgetOption(m_slAntiAliasThreshold, m_lbAntiAliasThreshold);
+
+ return widget;
+}
+
+void KisToolGradient::slotSetShape(int tqshape)
+{
+ m_tqshape = static_cast<KisGradientPainter::enumGradientShape>(tqshape);
+}
+
+void KisToolGradient::slotSetRepeat(int repeat)
+{
+ m_repeat = static_cast<KisGradientPainter::enumGradientRepeat>(repeat);
+}
+
+void KisToolGradient::slotSetReverse(bool state)
+{
+ m_reverse = state;
+}
+
+void KisToolGradient::slotSetAntiAliasThreshold(double value)
+{
+ m_antiAliasThreshold = value;
+}
+
+void KisToolGradient::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Gradient"),
+ "tool_gradient", TQt::Key_G, this,
+ TQT_SLOT(activate()), collection,
+ name());
+ m_action->setToolTip(i18n("Draw a gradient"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+#include "kis_tool_gradient.moc"
+
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_gradient.h b/chalk/plugins/tools/defaulttools/kis_tool_gradient.h
new file mode 100644
index 00000000..59d78ad3
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_gradient.h
@@ -0,0 +1,124 @@
+/*
+ * kis_tool_line.h - part of Krayon
+ *
+ * Copyright (c) 2000 John Califf <jcaliff@comuzone.net>
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ *
+ * 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_TOOL_GRADIENT_H_
+#define KIS_TOOL_GRADIENT_H_
+
+#include "kis_tool_paint.h"
+
+#include "kis_global.h"
+#include "kis_types.h"
+#include "kis_gradient_painter.h"
+#include "kis_tool_factory.h"
+
+class KIntNumInput;
+class KDoubleNumInput;
+
+class KisCmbComposite;
+class KisPainter;
+
+class TQLabel;
+class TQPoint;
+class TQWidget;
+class TQCheckBox;
+
+
+
+class KisToolGradient : public KisToolPaint {
+
+ Q_OBJECT
+ TQ_OBJECT
+ typedef KisToolPaint super;
+
+public:
+ KisToolGradient();
+ virtual ~KisToolGradient();
+
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_FILL; }
+ virtual TQ_UINT32 priority() { return 1; }
+
+ virtual void update(KisCanvasSubject *subject);
+
+ virtual void buttonPress(KisButtonPressEvent *event);
+ virtual void move(KisMoveEvent *event);
+ virtual void buttonRelease(KisButtonReleaseEvent *event);
+
+ virtual void paint(KisCanvasPainter& gc);
+ virtual void paint(KisCanvasPainter& gc, const TQRect& rc);
+
+ TQWidget* createOptionWidget(TQWidget* tqparent);
+
+public slots:
+ void slotSetShape(int);
+ void slotSetRepeat(int);
+ void slotSetReverse(bool);
+ void slotSetAntiAliasThreshold(double);
+
+private:
+ void paintLine();
+ void paintLine(KisCanvasPainter& gc);
+
+ KisPoint straightLine(KisPoint point);
+
+ bool m_dragging;
+
+ KisPoint m_startPos;
+ KisPoint m_endPos;
+
+ KisCanvasSubject *m_subject;
+
+ KisGradientPainter::enumGradientShape m_tqshape;
+ KisGradientPainter::enumGradientRepeat m_repeat;
+
+ bool m_reverse;
+ double m_antiAliasThreshold;
+
+ TQLabel *m_lbShape;
+ TQLabel *m_lbRepeat;
+ TQCheckBox *m_ckReverse;
+ TQComboBox *m_cmbShape;
+ TQComboBox *m_cmbRepeat;
+ TQLabel *m_lbAntiAliasThreshold;
+ KDoubleNumInput *m_slAntiAliasThreshold;
+};
+
+class KisToolGradientFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolGradientFactory() : super() {};
+ virtual ~KisToolGradientFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolGradient();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("gradient", i18n("Gradient Tool")); }
+};
+
+
+
+#endif //KIS_TOOL_GRADIENT_H_
+
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_line.cc b/chalk/plugins/tools/defaulttools/kis_tool_line.cc
new file mode 100644
index 00000000..243052cf
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_line.cc
@@ -0,0 +1,254 @@
+/*
+ * kis_tool_line.cc - part of Krayon
+ *
+ * Copyright (c) 2000 John Califf
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2003 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <tqpainter.h>
+#include <tqlayout.h>
+#include <tqwidget.h>
+
+#include <kdebug.h>
+#include <kaction.h>
+#include <kcommand.h>
+#include <klocale.h>
+
+#include "kis_cursor.h"
+#include "kis_painter.h"
+#include "kis_tool_line.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_move_event.h"
+#include "kis_paintop_registry.h"
+#include "kis_canvas_subject.h"
+#include "kis_undo_adapter.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+#include "kis_cursor.h"
+#include "kis_layer.h"
+
+KisToolLine::KisToolLine()
+ : super(i18n("Line")),
+ m_dragging( false )
+{
+ setName("tool_line");
+ setCursor(KisCursor::load("tool_line_cursor.png", 6, 6));
+
+ m_painter = 0;
+ m_currentImage = 0;
+ m_startPos = KisPoint(0, 0);
+ m_endPos = KisPoint(0, 0);
+}
+
+KisToolLine::~KisToolLine()
+{
+}
+
+void KisToolLine::update(KisCanvasSubject *subject)
+{
+ m_subject = subject;
+ m_currentImage = subject->currentImg();
+
+ super::update(m_subject);
+}
+
+
+void KisToolLine::paint(KisCanvasPainter& gc)
+{
+ if (m_dragging)
+ paintLine(gc, TQRect());
+}
+
+void KisToolLine::paint(KisCanvasPainter& gc, const TQRect& rc)
+{
+ if (m_dragging)
+ paintLine(gc, rc);
+}
+
+void KisToolLine::buttonPress(KisButtonPressEvent *e)
+{
+ if (!m_subject || !m_currentImage) return;
+
+ if (!m_subject->currentBrush()) return;
+
+ if (e->button() == Qt::LeftButton) {
+ m_dragging = true;
+ //KisCanvasController *controller = m_subject->canvasController();
+ m_startPos = e->pos(); //controller->windowToView(e->pos());
+ m_endPos = e->pos(); //controller->windowToView(e->pos());
+ }
+}
+
+void KisToolLine::move(KisMoveEvent *e)
+{
+ if (m_dragging) {
+ if (m_startPos != m_endPos)
+ paintLine();
+ //KisCanvasController *controller = m_subject->canvasController();
+
+ if (e->state() & TQt::AltButton) {
+ KisPoint trans = e->pos() - m_endPos;
+ m_startPos += trans;
+ m_endPos += trans;
+ } else if (e->state() & TQt::ShiftButton)
+ m_endPos = straightLine(e->pos());
+ else
+ m_endPos = e->pos();//controller->windowToView(e->pos());
+ paintLine();
+ }
+}
+
+void KisToolLine::buttonRelease(KisButtonReleaseEvent *e)
+{
+ if (m_dragging && e->button() == Qt::LeftButton) {
+ m_dragging = false;
+ KisCanvasController *controller = m_subject->canvasController();
+ KisImageSP img = m_subject->currentImg();
+
+ if (m_startPos == m_endPos) {
+ controller->updateCanvas();
+ m_dragging = false;
+ return;
+ }
+
+ if ((e->state() & TQt::ShiftButton) == TQt::ShiftButton) {
+ m_endPos = straightLine(e->pos());
+ }
+ else {
+ m_endPos = e->pos();
+ }
+
+ KisPaintDeviceSP device;
+ if (m_currentImage &&
+ (device = m_currentImage->activeDevice()) &&
+ m_subject &&
+ m_subject->currentBrush())
+ {
+ delete m_painter;
+ m_painter = new KisPainter( device );
+ Q_CHECK_PTR(m_painter);
+
+ if (m_currentImage->undo()) m_painter->beginTransaction(i18n("Line"));
+
+ m_painter->setPaintColor(m_subject->fgColor());
+ m_painter->setBrush(m_subject->currentBrush());
+ m_painter->setOpacity(m_opacity);
+ m_painter->setCompositeOp(m_compositeOp);
+ KisPaintOp * op = KisPaintOpRegistry::instance()->paintOp(m_subject->currentPaintop(), m_subject->currentPaintopSettings(), m_painter);
+ m_painter->setPaintOp(op); // Painter takes ownership
+ m_painter->paintLine(m_startPos, PRESSURE_DEFAULT, 0, 0, m_endPos, PRESSURE_DEFAULT, 0, 0);
+ device->setDirty( m_painter->dirtyRect() );
+ notifyModified();
+
+ /* remove remains of the line drawn while moving */
+ if (controller->kiscanvas()) {
+ controller->kiscanvas()->update();
+ }
+
+ if (m_currentImage->undo() && m_painter) {
+ m_currentImage->undoAdapter()->addCommand(m_painter->endTransaction());
+ }
+ delete m_painter;
+ m_painter = 0;
+ } else {
+ if (m_painter)
+ controller->updateCanvas(m_painter->dirtyRect()); // Removes the last remaining line.
+ }
+ }
+
+}
+
+KisPoint KisToolLine::straightLine(KisPoint point)
+{
+ KisPoint comparison = point - m_startPos;
+ KisPoint result;
+
+ if ( fabs(comparison.x()) > fabs(comparison.y())) {
+ result.setX(point.x());
+ result.setY(m_startPos.y());
+ } else {
+ result.setX( m_startPos.x() );
+ result.setY( point.y() );
+ }
+
+ return result;
+}
+
+void KisToolLine::paintLine()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter gc(canvas);
+ TQRect rc;
+
+ paintLine(gc, rc);
+ }
+}
+
+void KisToolLine::paintLine(KisCanvasPainter& gc, const TQRect&)
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ RasterOp op = gc.rasterOp();
+ TQPen old = gc.pen();
+ TQPen pen(TQt::SolidLine);
+ KisPoint start;
+ KisPoint end;
+
+// Q_ASSERT(controller);
+ start = controller->windowToView(m_startPos);
+ end = controller->windowToView(m_endPos);
+// start.setX(start.x() - controller->horzValue());
+// start.setY(start.y() - controller->vertValue());
+// end.setX(end.x() - controller->horzValue());
+// end.setY(end.y() - controller->vertValue());
+// end.setX((end.x() - start.x()));
+// end.setY((end.y() - start.y()));
+// start *= m_subject->zoomFactor();
+// end *= m_subject->zoomFactor();
+ gc.setRasterOp(TQt::NotROP);
+ gc.setPen(pen);
+ gc.drawLine(start.floorTQPoint(), end.floorTQPoint());
+ gc.setRasterOp(op);
+ gc.setPen(old);
+ }
+}
+
+void KisToolLine::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Line"),
+ "tool_line", TQt::Key_L, this,
+ TQT_SLOT(activate()), collection,
+ name());
+ m_action->setToolTip(i18n("Draw a line"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+TQString KisToolLine::quickHelp() const {
+ return i18n("Alt+Drag will move the origin of the currently displayed line around, Shift+Drag will force you to draw straight lines");
+}
+
+#include "kis_tool_line.moc"
+
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_line.h b/chalk/plugins/tools/defaulttools/kis_tool_line.h
new file mode 100644
index 00000000..4ce0ff38
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_line.h
@@ -0,0 +1,100 @@
+/*
+ * kis_tool_line.h - part of Krayon
+ *
+ * Copyright (c) 2000 John Califf <jcaliff@comuzone.net>
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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_TOOL_LINE_H_
+#define KIS_TOOL_LINE_H_
+
+#include "kis_tool_paint.h"
+
+#include "kis_global.h"
+#include "kis_types.h"
+#include "kis_tool_factory.h"
+
+class KisBrush;
+class KisPainter;
+
+class TQPoint;
+class TQWidget;
+
+
+class KisToolLine : public KisToolPaint {
+
+ Q_OBJECT
+ TQ_OBJECT
+ typedef KisToolPaint super;
+
+ public:
+ KisToolLine();
+ virtual ~KisToolLine();
+
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_SHAPE; }
+ virtual TQ_UINT32 priority() { return 1; }
+ virtual void update(KisCanvasSubject *subject);
+
+ virtual void buttonPress(KisButtonPressEvent *event);
+ virtual void move(KisMoveEvent *event);
+ virtual void buttonRelease(KisButtonReleaseEvent *event);
+
+ virtual void paint(KisCanvasPainter& gc);
+ virtual void paint(KisCanvasPainter& gc, const TQRect& rc);
+
+ virtual TQString quickHelp() const;
+
+ private:
+ void paintLine();
+ void paintLine(KisCanvasPainter& gc, const TQRect& rc);
+
+ KisPoint straightLine(KisPoint point);
+
+
+ bool m_dragging;
+
+ KisPoint m_startPos;
+ KisPoint m_endPos;
+
+ KisCanvasSubject *m_subject;
+ KisImageSP m_currentImage;
+ KisPainter *m_painter;
+};
+
+
+class KisToolLineFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolLineFactory() : super() {};
+ virtual ~KisToolLineFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolLine();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("line", i18n("Line Tool")); }
+};
+
+
+
+
+#endif //KIS_TOOL_LINE_H_
+
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_move.cc b/chalk/plugins/tools/defaulttools/kis_tool_move.cc
new file mode 100644
index 00000000..7c8733c9
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_move.cc
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 1999 Matthias Elter <me@kde.org>
+ * 1999 Michael Koch <koch@kde.org>
+ * 2002 Patrick Julien <freak@codepimps.org>
+ * 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <stdlib.h>
+#include <tqpoint.h>
+#include <kaction.h>
+#include <klocale.h>
+#include <tqcolor.h>
+#include "kis_canvas_subject.h"
+#include "kis_cursor.h"
+#include "kis_image.h"
+#include "kis_paint_device.h"
+#include "kis_tool_move.h"
+#include "kis_tool_move.moc"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_move_event.h"
+#include "kis_selection.h"
+#include "kis_selection_manager.h"
+#include "kis_layer.h"
+
+KisToolMove::KisToolMove()
+ : super(i18n("Move Tool"))
+ , m_subject( 0 )
+ , m_keyEvent( 0 )
+{
+ setName("tool_move");
+
+ setCursor(KisCursor::moveCursor());
+ m_repeatTimer = new TQTimer(this);
+ connect( m_repeatTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( slotMove() ) );
+}
+
+KisToolMove::~KisToolMove()
+{
+}
+
+void KisToolMove::update(KisCanvasSubject *subject)
+{
+ m_subject = subject;
+ m_strategy.reset(subject);
+ super::update(subject);
+}
+
+void KisToolMove::buttonPress(KisButtonPressEvent *e)
+{
+ if (m_subject && e->button() == Qt::LeftButton) {
+ TQPoint pos = e->pos().floorTQPoint();
+ KisImageSP img = m_subject->currentImg();
+ KisLayerSP dev;
+
+ if (!img || !(dev = img->activeLayer()))
+ return;
+
+ m_strategy.startDrag(pos);
+ }
+}
+
+void KisToolMove::move(KisMoveEvent *e)
+{
+ if (m_subject && e->state() == Qt::LeftButton) {
+ TQPoint pos = e->pos().floorTQPoint();
+ if((e->state() & TQt::AltButton) || (e->state() & TQt::ControlButton)) {
+ if(fabs(pos.x() - m_dragStart.x()) > fabs(pos.y() - m_dragStart.y()))
+ pos.setY(m_dragStart.y());
+ else
+ pos.setX(m_dragStart.x());
+ }
+ m_strategy.drag(pos);
+ }
+}
+
+void KisToolMove::buttonRelease(KisButtonReleaseEvent *e)
+{
+ if (m_subject && e->button() == Qt::LeftButton) {
+ m_strategy.endDrag(e->pos().floorTQPoint());
+ }
+}
+
+void KisToolMove::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Move"),
+ "tool_move",
+ TQt::SHIFT+TQt::Key_V,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ m_action->setToolTip(i18n("Move"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+
+void KisToolMove::keyPress( TQKeyEvent *e )
+{
+ m_keyEvent = e;
+
+ if (m_subject) {
+
+ KisImageSP img = m_subject->currentImg();
+ KisLayerSP dev;
+
+ if (!img || !(dev = img->activeLayer()))
+ return;
+
+ m_dragStart = TQPoint( 0, 0 );
+ m_strategy.startDrag( m_dragStart );
+ m_steps = 1;
+ m_repeatTimer->start(200);
+
+ }
+}
+
+void KisToolMove::keyRelease(TQKeyEvent *)
+{
+ m_repeatTimer->stop();
+
+ if ( m_subject && m_keyEvent) {
+
+ if ( m_keyEvent->key() == TQt::Key_Left ) {
+ m_strategy.endDrag(TQPoint( -m_steps, 0 ));
+ }
+ else if ( m_keyEvent->key() == TQt::Key_Right ) {
+ m_strategy.endDrag(TQPoint(m_steps, 0) );
+ }
+ else if ( m_keyEvent->key() == TQt::Key_Up ) {
+ m_strategy.endDrag(TQPoint(0, -m_steps) );
+ }
+ else if ( m_keyEvent->key() == TQt::Key_Down ) {
+ m_strategy.endDrag(TQPoint(0, m_steps) );
+ }
+ }
+ m_steps = 0;
+ m_keyEvent = 0;
+
+}
+
+void KisToolMove::slotMove()
+{
+ if (m_subject && m_keyEvent) {
+
+ if ( m_keyEvent->key() == TQt::Key_Left ) {
+ m_strategy.drag(TQPoint(-m_steps, 0) );
+ }
+ else if ( m_keyEvent->key() == TQt::Key_Right ) {
+ m_strategy.drag(TQPoint(m_steps, 0) );
+ }
+ else if ( m_keyEvent->key() == TQt::Key_Up ) {
+ m_strategy.drag(TQPoint(0, -m_steps) );
+ }
+ else if ( m_keyEvent->key() == TQt::Key_Down ) {
+ m_strategy.drag(TQPoint(0, m_steps) );
+ }
+
+ ++m_steps;
+ }
+
+}
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_move.h b/chalk/plugins/tools/defaulttools/kis_tool_move.h
new file mode 100644
index 00000000..274cc3c7
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_move.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1999 Matthias Elter <me@kde.org>
+ * 1999 Michael Koch <koch@kde.org>
+ * 2003 Patrick Julien <freak@codepimps.org>
+ *
+ * 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_TOOL_MOVE_H_
+#define KIS_TOOL_MOVE_H_
+
+#include <tqtimer.h>
+
+#include "kis_strategy_move.h"
+#include "kis_tool_non_paint.h"
+#include "kis_tool_factory.h"
+
+class TQTimer;
+
+class KisToolMove : public KisToolNonPaint {
+
+ typedef KisToolNonPaint super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolMove();
+ virtual ~KisToolMove();
+
+public:
+ virtual void update(KisCanvasSubject *subject);
+
+public:
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_TRANSFORM; }
+ virtual TQ_UINT32 priority() { return 2; }
+
+ virtual void buttonPress(KisButtonPressEvent *e);
+ virtual void move(KisMoveEvent *e);
+ virtual void buttonRelease(KisButtonReleaseEvent *e);
+ virtual void keyPress(TQKeyEvent *e);
+ virtual void keyRelease(TQKeyEvent *e);
+
+private slots:
+
+ void slotMove();
+
+private:
+
+ KisCanvasSubject *m_subject;
+ KisStrategyMove m_strategy;
+ TQPoint m_dragStart;
+ TQTimer * m_repeatTimer;
+ TQKeyEvent * m_keyEvent;
+ int m_steps;
+};
+
+
+class KisToolMoveFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolMoveFactory() : super() {};
+ virtual ~KisToolMoveFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolMove();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("move", i18n("Move Tool")); }
+};
+
+
+
+#endif // KIS_TOOL_MOVE_H_
+
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_pan.cc b/chalk/plugins/tools/defaulttools/kis_tool_pan.cc
new file mode 100644
index 00000000..f7a92dcb
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_pan.cc
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ *
+ * 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 <kaction.h>
+#include <klocale.h>
+
+#include "kis_canvas_controller.h"
+#include "kis_canvas_subject.h"
+#include "kis_cursor.h"
+#include "kis_tool_pan.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_move_event.h"
+
+KisToolPan::KisToolPan()
+ : super(i18n("Pan Tool"))
+{
+ setName("tool_pan");
+ m_subject = 0;
+ m_dragging = false;
+ m_openHandCursor = KisCursor::openHandCursor();
+ m_closedHandCursor = KisCursor::closedHandCursor();
+ setCursor(m_openHandCursor);
+}
+
+KisToolPan::~KisToolPan()
+{
+}
+
+void KisToolPan::update(KisCanvasSubject *subject)
+{
+ m_subject = subject;
+ super::update(m_subject);
+}
+
+void KisToolPan::buttonPress(KisButtonPressEvent *e)
+{
+ if (m_subject && !m_dragging && e->button() == Qt::LeftButton) {
+ KisCanvasController *controller = m_subject->canvasController();
+
+ m_origScrollX = controller->horzValue();
+ m_origScrollY = controller->vertValue();
+ m_dragPos = controller->windowToView(e->pos());
+ m_dragging = true;
+ setCursor(m_closedHandCursor);
+ }
+}
+
+void KisToolPan::move(KisMoveEvent *e)
+{
+ if (m_subject && m_dragging) {
+ KisCanvasController *controller = m_subject->canvasController();
+
+ KisPoint currPos = controller->windowToView(e->pos());
+ KisPoint delta = currPos - m_dragPos;
+ controller->scrollTo(m_origScrollX - delta.floorX(), m_origScrollY - delta.floorY());
+ }
+}
+
+void KisToolPan::buttonRelease(KisButtonReleaseEvent *e)
+{
+ if (m_subject && m_dragging && e->button() == Qt::LeftButton) {
+ setCursor(m_openHandCursor);
+ m_dragging = false;
+ }
+}
+
+void KisToolPan::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Pan"), "tool_pan", TQt::SHIFT+TQt::Key_H, this, TQT_SLOT(activate()), collection, name());
+ m_action->setToolTip(i18n("Pan"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+#include "kis_tool_pan.moc"
+
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_pan.h b/chalk/plugins/tools/defaulttools/kis_tool_pan.h
new file mode 100644
index 00000000..36ed9dcc
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_pan.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ *
+ * 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_TOOL_PAN_H_
+#define KIS_TOOL_PAN_H_
+
+#include "kis_point.h"
+#include "kis_tool_non_paint.h"
+#include "kis_tool_factory.h"
+#include <koffice_export.h>
+
+class KisCanvasSubject;
+class KisPoint;
+
+class KRITATOOL_EXPORT KisToolPan : public KisToolNonPaint
+{
+
+ typedef KisToolNonPaint super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolPan();
+ virtual ~KisToolPan();
+
+ virtual void update(KisCanvasSubject *subject);
+
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_VIEW; }
+ virtual TQ_UINT32 priority() { return 1; }
+
+ virtual void buttonPress(KisButtonPressEvent *e);
+ virtual void move(KisMoveEvent *e);
+ virtual void buttonRelease(KisButtonReleaseEvent *e);
+
+ virtual bool wantsAutoScroll() const { return false; }
+
+private:
+ KisCanvasSubject *m_subject;
+ KisPoint m_dragPos;
+ TQ_INT32 m_origScrollX;
+ TQ_INT32 m_origScrollY;
+ bool m_dragging;
+ TQCursor m_openHandCursor;
+ TQCursor m_closedHandCursor;
+};
+
+class KisToolPanFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolPanFactory() : super() {};
+ virtual ~KisToolPanFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolPan();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("pan", i18n("Pan Tool")); }
+};
+
+
+#endif // KIS_TOOL_PAN_H_
+
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_rectangle.cc b/chalk/plugins/tools/defaulttools/kis_tool_rectangle.cc
new file mode 100644
index 00000000..b8387d78
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_rectangle.cc
@@ -0,0 +1,187 @@
+/*
+ * kis_tool_rectangle.cc - part of Chalk
+ *
+ * Copyright (c) 2000 John Califf <jcaliff@compuzone.net>
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Clarence Dang <dang@k.org>
+ *
+ * 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 <tqpainter.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_canvas_controller.h"
+#include "kis_canvas_subject.h"
+#include "kis_move_event.h"
+#include "kis_painter.h"
+#include "kis_paintop_registry.h"
+#include "kis_tool_rectangle.h"
+#include "kis_undo_adapter.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+#include "kis_cursor.h"
+#include "kis_layer.h"
+
+KisToolRectangle::KisToolRectangle()
+ : super(i18n ("Rectangle")),
+ m_dragging (false),
+ m_currentImage (0)
+{
+ setName("tool_rectangle");
+ setCursor(KisCursor::load("tool_rectangle_cursor.png", 6, 6));
+}
+
+KisToolRectangle::~KisToolRectangle()
+{
+}
+
+void KisToolRectangle::update (KisCanvasSubject *subject)
+{
+ super::update (subject);
+ if (m_subject)
+ m_currentImage = m_subject->currentImg ();
+}
+
+void KisToolRectangle::buttonPress(KisButtonPressEvent *event)
+{
+ if (m_currentImage && event->button() == Qt::LeftButton) {
+ m_dragging = true;
+ m_dragStart = m_dragCenter = m_dragEnd = event->pos();
+ draw(m_dragStart, m_dragEnd);
+ }
+}
+
+void KisToolRectangle::move(KisMoveEvent *event)
+{
+ if (m_dragging) {
+ // erase old lines on canvas
+ draw(m_dragStart, m_dragEnd);
+ // move (alt) or resize rectangle
+ if (event->state() & TQt::AltButton) {
+ KisPoint trans = event->pos() - m_dragEnd;
+ m_dragStart += trans;
+ m_dragEnd += trans;
+ } else {
+ KisPoint diag = event->pos() - (event->state() & TQt::ControlButton
+ ? m_dragCenter : m_dragStart);
+ // square?
+ if (event->state() & TQt::ShiftButton) {
+ double size = TQMAX(fabs(diag.x()), fabs(diag.y()));
+ double w = diag.x() < 0 ? -size : size;
+ double h = diag.y() < 0 ? -size : size;
+ diag = KisPoint(w, h);
+ }
+
+ // resize around center point?
+ if (event->state() & TQt::ControlButton) {
+ m_dragStart = m_dragCenter - diag;
+ m_dragEnd = m_dragCenter + diag;
+ } else {
+ m_dragEnd = m_dragStart + diag;
+ }
+ }
+ // draw new lines on canvas
+ draw(m_dragStart, m_dragEnd);
+ m_dragCenter = KisPoint((m_dragStart.x() + m_dragEnd.x()) / 2,
+ (m_dragStart.y() + m_dragEnd.y()) / 2);
+ }
+}
+
+void KisToolRectangle::buttonRelease(KisButtonReleaseEvent *event)
+{
+ if (!m_subject)
+ return;
+
+ if (!m_currentImage)
+ return;
+
+ KisPaintDeviceSP device = m_currentImage->activeDevice ();
+ if (!device) return;
+
+ if (m_dragging && event->button() == Qt::LeftButton) {
+ // erase old lines on canvas
+ draw(m_dragStart, m_dragEnd);
+ m_dragging = false;
+
+ if (m_dragStart == m_dragEnd)
+ return;
+
+ if (!m_currentImage)
+ return;
+
+
+ KisPainter painter (device);
+ if (m_currentImage->undo()) painter.beginTransaction (i18n ("Rectangle"));
+
+ painter.setPaintColor(m_subject->fgColor());
+ painter.setBackgroundColor(m_subject->bgColor());
+ painter.setFillStyle(fillStyle());
+ painter.setBrush(m_subject->currentBrush());
+ painter.setPattern(m_subject->currentPattern());
+ painter.setOpacity(m_opacity);
+ painter.setCompositeOp(m_compositeOp);
+ KisPaintOp * op = KisPaintOpRegistry::instance()->paintOp(m_subject->currentPaintop(), m_subject->currentPaintopSettings(), &painter);
+ painter.setPaintOp(op);
+
+ painter.paintRect(m_dragStart, m_dragEnd, PRESSURE_DEFAULT/*event->pressure()*/, event->xTilt(), event->yTilt());
+ device->setDirty( painter.dirtyRect() );
+ notifyModified();
+
+ if (m_currentImage->undo()) {
+ m_currentImage->undoAdapter()->addCommand(painter.endTransaction());
+ }
+ }
+}
+
+void KisToolRectangle::draw(const KisPoint& start, const KisPoint& end )
+{
+ if (!m_subject)
+ return;
+
+ KisCanvasController *controller = m_subject->canvasController ();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter p (canvas);
+
+ p.setRasterOp (TQt::NotROP);
+ p.drawRect (TQRect (controller->windowToView (start).floorTQPoint(), controller->windowToView (end).floorTQPoint()));
+ p.end ();
+}
+
+void KisToolRectangle::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Rectangle"),
+ "tool_rectangle",
+ TQt::Key_F6,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ m_action->setToolTip(i18n("Draw a rectangle"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+#include "kis_tool_rectangle.moc"
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_rectangle.h b/chalk/plugins/tools/defaulttools/kis_tool_rectangle.h
new file mode 100644
index 00000000..d9f898a9
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_rectangle.h
@@ -0,0 +1,96 @@
+/*
+ * kis_tool_rectangle.h - part of KImageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 1999 Michael Koch <koch@kde.org>
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Clarence Dang <dang@kde.org>
+ *
+ * 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_TOOL_RECTANGLE_H__
+#define __KIS_TOOL_RECTANGLE_H__
+
+#include <tqrect.h>
+
+#include "kis_tool_shape.h"
+#include "kis_types.h"
+#include "kis_tool_factory.h"
+#include "kis_point.h"
+
+class TQPainter;
+class KisPainter;
+
+class KisToolRectangle : public KisToolShape {
+
+ typedef KisToolShape super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolRectangle();
+ virtual ~KisToolRectangle();
+
+ //
+ // KisCanvasObserver interface
+ //
+
+ virtual void update (KisCanvasSubject *subject);
+
+ //
+ // KisToolPaint interface
+ //
+
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_SHAPE; }
+ virtual TQ_UINT32 priority() { return 2; }
+ virtual void buttonPress(KisButtonPressEvent *event);
+ virtual void move(KisMoveEvent *event);
+ virtual void buttonRelease(KisButtonReleaseEvent *event);
+
+protected:
+ virtual void draw(const KisPoint&, const KisPoint&);
+
+protected:
+ int m_lineThickness;
+
+ KisPoint m_dragCenter;
+ KisPoint m_dragStart;
+ KisPoint m_dragEnd;
+ TQRect m_final_lines;
+
+ bool m_dragging;
+ KisImageSP m_currentImage;
+};
+
+class KisToolRectangleFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolRectangleFactory() : super() {};
+ virtual ~KisToolRectangleFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolRectangle();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("rectangle", i18n("Rectangle Tool")); }
+};
+
+
+#endif // __KIS_TOOL_RECTANGLE_H__
+
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_text.cc b/chalk/plugins/tools/defaulttools/kis_tool_text.cc
new file mode 100644
index 00000000..df247917
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_text.cc
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2004 Bart Coppens <kde@bartcoppens.be>
+ *
+ * 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 <tqfont.h>
+#include <tqrect.h>
+#include <tqimage.h>
+#include <tqlayout.h>
+#include <tqwidget.h>
+#include <tqstring.h>
+#include <tqpixmap.h>
+#include <tqpainter.h>
+#include <tqpushbutton.h>
+#include <tqfontmetrics.h>
+#include <tqhbox.h>
+
+#include <kaction.h>
+#include <kinputdialog.h>
+#include <klocale.h>
+#include <kfontdialog.h>
+#include <ksqueezedtextlabel.h>
+
+#include <tqcolor.h>
+
+#include "kis_point.h"
+#include "kis_image.h"
+#include "kis_layer.h"
+#include "kis_group_layer.h"
+#include "kis_paint_layer.h"
+#include "kis_cursor.h"
+#include "kis_tool_text.h"
+#include "kis_paint_device.h"
+#include "kis_canvas_subject.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_color.h"
+#include "kis_undo_adapter.h"
+
+KisToolText::KisToolText()
+ : super(i18n("Text"))
+ , m_wasPressed( false )
+ , m_windowIsBeingShown( false )
+{
+ setName("tool_text");
+ m_subject = 0;
+ setCursor(KisCursor::load("tool_text_cursor.png", 6, 6));
+}
+
+KisToolText::~KisToolText()
+{
+}
+
+void KisToolText::update(KisCanvasSubject *subject)
+{
+ m_subject = subject;
+ super::update(subject);
+}
+
+void KisToolText::buttonPress(KisButtonPressEvent *e)
+{
+ if (m_subject && e->button() == Qt::LeftButton) {
+ m_wasPressed = true;
+ }
+}
+
+void KisToolText::buttonRelease(KisButtonReleaseEvent *e)
+{
+ if ( m_windowIsBeingShown ) return;
+
+ if (m_subject && e->button() == Qt::LeftButton) {
+ if(!m_wasPressed) return;
+ m_wasPressed = false;
+ KisImageSP img = m_subject->currentImg();
+
+ m_windowIsBeingShown = true;
+ bool ok;
+ TQString text = KInputDialog::getText(i18n("Font Tool"), i18n("Enter text:"),
+ TQString(), &ok);
+ if (!ok) {
+ m_windowIsBeingShown = false;
+ return;
+ }
+
+ KisUndoAdapter *undoAdapter = img->undoAdapter();
+ if (undoAdapter) {
+ undoAdapter->beginMacro(i18n("Text"));
+ }
+
+ TQFontMetrics metrics(m_font);
+ TQRect boundingRect = TQT_TQRECT_OBJECT(metrics.boundingRect(text)).normalize();
+ int xB = - boundingRect.x();
+ int yB = - boundingRect.y();
+
+ if (boundingRect.x() < 0 || boundingRect.y() < 0)
+ boundingRect.moveBy(- boundingRect.x(), - boundingRect.y());
+
+ TQPixmap pixels(boundingRect.width(), boundingRect.height());
+ {
+ TQPainter paint(&pixels);
+ paint.fillRect(boundingRect, TQt::white);
+ paint.setFont(m_font);
+ paint.setBrush(TQBrush(TQt::black));
+ paint.drawText(xB, yB, text);
+ }
+ TQImage image = pixels.convertToImage();
+
+ TQ_INT32 height = boundingRect.height();
+ TQ_INT32 width = boundingRect.width();
+ KisPaintLayer *layer = new KisPaintLayer(img, '"' + text + '"', OPACITY_OPAQUE);
+ KisGroupLayerSP tqparent = img->rootLayer();
+ if (img->activeLayer())
+ tqparent = img->activeLayer()->tqparent();
+ img->addLayer(layer, tqparent, img->activeLayer());
+ for (int y = 0; y < height; y++) {
+ for (int x = 0; x < width; x++) {
+ TQRgb pixel = image.pixel(x, y);
+ // use the 'blackness' as alpha :)
+ TQ_UINT8 alpha = 255 - tqRed(pixel) * OPACITY_OPAQUE / 255;
+ TQColor c = m_subject->fgColor().toTQColor();
+ layer->paintDevice()->setPixel(x, y, c, alpha);
+ }
+ }
+
+ layer->setOpacity(m_opacity);
+ layer->setCompositeOp(m_compositeOp);
+
+ layer->setVisible(false);
+ TQ_INT32 x = TQMAX(0, static_cast<int>(e->x() - width/2));
+ TQ_INT32 y = TQMAX(0, static_cast<int>(e->y() - height/2));
+ layer->setX(x);
+ layer->setY(y);
+ layer->setVisible(true);
+ layer->setDirty();
+
+ if (undoAdapter) {
+ undoAdapter->endMacro();
+ }
+
+ m_windowIsBeingShown = false;
+ }
+}
+
+void KisToolText::setFont() {
+ KFontDialog::getFont( m_font, false/*, TQWidget* tqparent! */ );
+ m_lbFontName->setText(TQString(m_font.family() + ", %1").tqarg(m_font.pointSize()));
+}
+
+TQWidget* KisToolText::createOptionWidget(TQWidget* tqparent)
+{
+ TQWidget *widget = super::createOptionWidget(tqparent);
+
+ m_lbFont = new TQLabel(i18n("Font: "), widget);
+
+ TQHBox *fontBox = new TQHBox(widget);
+ m_lbFontName = new KSqueezedTextLabel(TQString(m_font.family() + ", %1")
+ .tqarg(m_font.pointSize()), fontBox);
+ m_btnMoreFonts = new TQPushButton("...", fontBox);
+
+ connect(m_btnMoreFonts, TQT_SIGNAL(released()), this, TQT_SLOT(setFont()));
+
+ addOptionWidgetOption(fontBox, m_lbFont);
+
+ return widget;
+}
+
+void KisToolText::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("T&ext"),
+ "tool_text",
+ TQt::SHIFT+TQt::Key_T,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ m_action->setExclusiveGroup("tools");
+ m_action->setToolTip(i18n("Text"));
+ m_ownAction = true;
+ }
+}
+
+#include "kis_tool_text.moc"
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_text.h b/chalk/plugins/tools/defaulttools/kis_tool_text.h
new file mode 100644
index 00000000..b2aa7e18
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_text.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2004 Bart Coppens <kde@bartcoppens.be>
+ *
+ * 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_TOOL_TEXT_H_
+#define KIS_TOOL_TEXT_H_
+
+#include "kis_tool_paint.h"
+
+#include "kis_tool_factory.h"
+
+class TQFont;
+class TQLabel;
+class TQWidget;
+class TQPushButton;
+class KSqueezedTextLabel;
+
+
+
+class KisToolText : public KisToolPaint {
+ typedef KisToolPaint super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolText();
+ virtual ~KisToolText();
+
+ virtual void update(KisCanvasSubject *subject);
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_FILL; }
+ virtual TQ_UINT32 priority() { return 2; }
+ virtual void buttonPress(KisButtonPressEvent*);
+ virtual void buttonRelease(KisButtonReleaseEvent *e);
+
+ virtual TQWidget* createOptionWidget(TQWidget* tqparent);
+public slots:
+ virtual void setFont();
+
+private:
+ KisCanvasSubject *m_subject;
+ TQFont m_font;
+ TQLabel *m_lbFont;
+ KSqueezedTextLabel *m_lbFontName;
+ TQPushButton *m_btnMoreFonts;
+ bool m_wasPressed; // use for preventing bug:136151
+ bool m_windowIsBeingShown;
+};
+
+
+class KisToolTextFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolTextFactory() : super() {};
+ virtual ~KisToolTextFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolText();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("text", i18n("Text Tool")); }
+};
+
+
+#endif // KIS_TOOL_TEXT_H_
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_zoom.cc b/chalk/plugins/tools/defaulttools/kis_tool_zoom.cc
new file mode 100644
index 00000000..f866e5e2
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_zoom.cc
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 1999 Matthias Elter <me@kde.org>
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ *
+ * 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 <kaction.h>
+#include <klocale.h>
+#include <kapplication.h>
+
+#include "kis_image.h"
+#include "kis_paint_device.h"
+#include "kis_paint_layer.h"
+#include "kis_canvas_controller.h"
+#include "kis_canvas_subject.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+#include "kis_cursor.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_move_event.h"
+#include "kis_tool_zoom.h"
+
+
+KisToolZoom::KisToolZoom()
+ : super(i18n("Zoom Tool"))
+{
+ setName("tool_zoom");
+ m_subject = 0;
+ m_dragging = false;
+ m_startPos = TQPoint(0, 0);
+ m_endPos = TQPoint(0, 0);
+ m_plusCursor = KisCursor::load("tool_zoom_plus_cursor.png", 8, 8);
+ m_minusCursor = KisCursor::load("tool_zoom_minus_cursor.png", 8, 8);
+ setCursor(m_plusCursor);
+ connect(&m_timer, TQT_SIGNAL(timeout()), TQT_SLOT(slotTimer()));
+}
+
+KisToolZoom::~KisToolZoom()
+{
+}
+
+void KisToolZoom::update(KisCanvasSubject *subject)
+{
+ m_subject = subject;
+ super::update(m_subject);
+}
+
+void KisToolZoom::paint(KisCanvasPainter& gc)
+{
+ if (m_dragging)
+ paintOutline(gc, TQRect());
+}
+
+void KisToolZoom::paint(KisCanvasPainter& gc, const TQRect& rc)
+{
+ if (m_dragging)
+ paintOutline(gc, rc);
+}
+
+void KisToolZoom::buttonPress(KisButtonPressEvent *e)
+{
+ if (m_subject && m_subject->currentImg() && !m_dragging) {
+ if (e->button() == Qt::LeftButton) {
+ m_startPos = e->pos().floorTQPoint();
+ m_endPos = e->pos().floorTQPoint();
+ m_dragging = true;
+ }
+ }
+}
+
+void KisToolZoom::move(KisMoveEvent *e)
+{
+ if (m_subject && m_dragging) {
+ if (m_startPos != m_endPos)
+ paintOutline();
+
+ m_endPos = e->pos().floorTQPoint();
+ paintOutline();
+ }
+}
+
+void KisToolZoom::buttonRelease(KisButtonReleaseEvent *e)
+{
+ if (m_subject && m_dragging && e->button() == Qt::LeftButton) {
+
+ KisCanvasController *controller = m_subject->canvasController();
+ m_endPos = e->pos().floorTQPoint();
+ m_dragging = false;
+
+ TQPoint delta = m_endPos - m_startPos;
+
+ if (sqrt(delta.x() * delta.x() + delta.y() * delta.y()) < 10) {
+ if (e->state() & TQt::ControlButton) {
+ controller->zoomOut(m_endPos.x(), m_endPos.y());
+ } else {
+ controller->zoomIn(m_endPos.x(), m_endPos.y());
+ }
+ } else {
+ controller->zoomTo(TQRect(m_startPos, m_endPos));
+ }
+ }
+}
+
+void KisToolZoom::activate()
+{
+ super::activate();
+ m_timer.start(50);
+}
+
+void KisToolZoom::deactivate()
+{
+ m_timer.stop();
+}
+
+void KisToolZoom::slotTimer()
+{
+#if KDE_IS_VERSION(3,4,0)
+ int state = kapp->keyboardMouseState() & (TQt::ShiftButton|TQt::ControlButton|TQt::AltButton);
+#else
+ int state = kapp->keyboardModifiers() & (KApplication::ShiftModifier
+ |KApplication::ControlModifier|KApplication::Modifier1);
+#endif
+
+ if (state & TQt::ControlButton) {
+ m_subject->canvasController()->setCanvasCursor(m_minusCursor);
+ } else {
+ m_subject->canvasController()->setCanvasCursor(m_plusCursor);
+ }
+}
+
+void KisToolZoom::paintOutline()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter gc(canvas);
+ TQRect rc;
+
+ paintOutline(gc, rc);
+ }
+}
+
+void KisToolZoom::paintOutline(KisCanvasPainter& gc, const TQRect&)
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ RasterOp op = gc.rasterOp();
+ TQPen old = gc.pen();
+ TQPen pen(TQt::DotLine);
+ TQPoint start;
+ TQPoint end;
+
+ Q_ASSERT(controller);
+ start = controller->windowToView(m_startPos);
+ end = controller->windowToView(m_endPos);
+
+ gc.setRasterOp(TQt::NotROP);
+ gc.setPen(pen);
+ gc.drawRect(TQRect(start, end));
+ gc.setRasterOp(op);
+ gc.setPen(old);
+ }
+}
+
+void KisToolZoom::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Zoom"), "tool_zoom", TQt::Key_Z, this, TQT_SLOT(activate()), collection, name());
+ m_action->setToolTip(i18n("Zoom"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+#include "kis_tool_zoom.moc"
diff --git a/chalk/plugins/tools/defaulttools/kis_tool_zoom.h b/chalk/plugins/tools/defaulttools/kis_tool_zoom.h
new file mode 100644
index 00000000..3faa5bf1
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/kis_tool_zoom.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1999 Matthias Elter <me@kde.org>
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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_ZOOM_TOOL_H_
+#define KIS_ZOOM_TOOL_H_
+
+#include <tqtimer.h>
+
+#include "kis_tool_non_paint.h"
+
+#include "kis_tool_factory.h"
+
+class KisCanvasSubject;
+
+class KisToolZoom : public KisToolNonPaint {
+
+ typedef KisToolNonPaint super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolZoom();
+ virtual ~KisToolZoom();
+
+public:
+ virtual void update(KisCanvasSubject *subject);
+
+public:
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_VIEW; }
+ virtual TQ_UINT32 priority() { return 2; }
+
+ virtual void buttonPress(KisButtonPressEvent *e);
+ virtual void move(KisMoveEvent *e);
+ virtual void buttonRelease(KisButtonReleaseEvent *e);
+
+ virtual void paint(KisCanvasPainter& gc);
+ virtual void paint(KisCanvasPainter& gc, const TQRect& rc);
+
+private:
+ void paintOutline();
+ void paintOutline(KisCanvasPainter& gc, const TQRect& rc);
+
+
+public slots:
+
+ void activate();
+ void deactivate();
+
+
+private slots:
+ void slotTimer();
+
+private:
+ KisCanvasSubject *m_subject;
+ TQPoint m_startPos;
+ TQPoint m_endPos;
+ bool m_dragging;
+ TQCursor m_plusCursor;
+ TQCursor m_minusCursor;
+ TQTimer m_timer;
+};
+
+
+class KisToolZoomFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolZoomFactory() : super() {};
+ virtual ~KisToolZoomFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolZoom();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("zoom", i18n("Zoom Tool")); }
+};
+
+
+#endif // KIS_ZOOM_TOOL_H_
diff --git a/chalk/plugins/tools/defaulttools/openhand_cursor.xpm b/chalk/plugins/tools/defaulttools/openhand_cursor.xpm
new file mode 100644
index 00000000..607879d5
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/openhand_cursor.xpm
@@ -0,0 +1,28 @@
+/* XPM */
+static char *openhand_cursor[]={
+"22 22 3 1",
+". c None",
+"# c #000000",
+"a c #ffffff",
+"......................",
+"..........##..........",
+".........#aa###.......",
+".......###aa#aa#......",
+"......#aa#aa#aa##.....",
+"......#aa#aa#aa#a#....",
+"......#aa#aa#aa#aa#...",
+"..###.#aa#aa#aa#aa#...",
+"..#aa##aaaaaaaa#aa#...",
+"..#aaa#aaaaaaaaaaa#...",
+"...#aa#aaaaaaaaaaa#...",
+"....#a#aaaaaaaaaaa#...",
+"....#aaaaaaaaaaaaa#...",
+".....#aaaaaaaaaaaa#...",
+".....#aaaaaaaaaaa#....",
+"......#aaaaaaaaaa#....",
+"......#aaaaaaaaaa#....",
+".......#aaaaaaaa#.....",
+".......#aaaaaaaa#.....",
+".......##########.....",
+"......................",
+"......................"};
diff --git a/chalk/plugins/tools/defaulttools/tool_color_fill.png b/chalk/plugins/tools/defaulttools/tool_color_fill.png
new file mode 100644
index 00000000..fdbe9ae5
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_color_fill.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_colorpicker.png b/chalk/plugins/tools/defaulttools/tool_colorpicker.png
new file mode 100644
index 00000000..06164f7e
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_colorpicker.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_duplicate.png b/chalk/plugins/tools/defaulttools/tool_duplicate.png
new file mode 100644
index 00000000..1710cf5d
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_duplicate.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_duplicate_cursor.png b/chalk/plugins/tools/defaulttools/tool_duplicate_cursor.png
new file mode 100644
index 00000000..31418815
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_duplicate_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_ellipse.png b/chalk/plugins/tools/defaulttools/tool_ellipse.png
new file mode 100644
index 00000000..a8ac0bd1
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_ellipse.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_ellipse_cursor.png b/chalk/plugins/tools/defaulttools/tool_ellipse_cursor.png
new file mode 100644
index 00000000..b97f215b
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_ellipse_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_fill_cursor.png b/chalk/plugins/tools/defaulttools/tool_fill_cursor.png
new file mode 100644
index 00000000..66691cb1
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_fill_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_freehand.png b/chalk/plugins/tools/defaulttools/tool_freehand.png
new file mode 100644
index 00000000..c313410d
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_freehand.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_freehand_cursor.png b/chalk/plugins/tools/defaulttools/tool_freehand_cursor.png
new file mode 100644
index 00000000..194bb200
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_freehand_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_gradient.png b/chalk/plugins/tools/defaulttools/tool_gradient.png
new file mode 100644
index 00000000..a45075a8
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_gradient.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_gradient_cursor.png b/chalk/plugins/tools/defaulttools/tool_gradient_cursor.png
new file mode 100644
index 00000000..fd20079a
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_gradient_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_line.png b/chalk/plugins/tools/defaulttools/tool_line.png
new file mode 100644
index 00000000..49f6fe2b
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_line.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_line_cursor.png b/chalk/plugins/tools/defaulttools/tool_line_cursor.png
new file mode 100644
index 00000000..66ec6b05
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_line_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_move.png b/chalk/plugins/tools/defaulttools/tool_move.png
new file mode 100644
index 00000000..386224ed
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_move.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_pan.png b/chalk/plugins/tools/defaulttools/tool_pan.png
new file mode 100644
index 00000000..c45a9c69
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_pan.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_rectangle.png b/chalk/plugins/tools/defaulttools/tool_rectangle.png
new file mode 100644
index 00000000..4da56ecd
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_rectangle.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_rectangle_cursor.png b/chalk/plugins/tools/defaulttools/tool_rectangle_cursor.png
new file mode 100644
index 00000000..0dba614b
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_rectangle_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_text.png b/chalk/plugins/tools/defaulttools/tool_text.png
new file mode 100644
index 00000000..c1683fc0
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_text.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_text_cursor.png b/chalk/plugins/tools/defaulttools/tool_text_cursor.png
new file mode 100644
index 00000000..e241beaf
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_text_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_zoom.png b/chalk/plugins/tools/defaulttools/tool_zoom.png
new file mode 100644
index 00000000..10689553
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_zoom.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_zoom_minus_cursor.png b/chalk/plugins/tools/defaulttools/tool_zoom_minus_cursor.png
new file mode 100644
index 00000000..7089eaf3
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_zoom_minus_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/tool_zoom_plus_cursor.png b/chalk/plugins/tools/defaulttools/tool_zoom_plus_cursor.png
new file mode 100644
index 00000000..52c59b45
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/tool_zoom_plus_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/defaulttools/wdgcolorpicker.ui b/chalk/plugins/tools/defaulttools/wdgcolorpicker.ui
new file mode 100644
index 00000000..a2b9d7d3
--- /dev/null
+++ b/chalk/plugins/tools/defaulttools/wdgcolorpicker.ui
@@ -0,0 +1,167 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ColorPickerOptionsWidget</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>ColorPickerOptionsWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>263</width>
+ <height>307</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Color Picker</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="TQComboBox">
+ <item>
+ <property name="text">
+ <string>Sample All Visible Layers</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Current Layer</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>cmbSources</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>200</width>
+ <height>32767</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="TQCheckBox">
+ <property name="name">
+ <cstring>cbUpdateCurrentColour</cstring>
+ </property>
+ <property name="text">
+ <string>Update current color</string>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQCheckBox">
+ <property name="name">
+ <cstring>cbPalette</cstring>
+ </property>
+ <property name="text">
+ <string>Add to palette:</string>
+ </property>
+ </widget>
+ <widget class="TQComboBox">
+ <property name="name">
+ <cstring>cmbPalette</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQCheckBox">
+ <property name="name">
+ <cstring>cbNormaliseValues</cstring>
+ </property>
+ <property name="text">
+ <string>Show colors as percentages</string>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Sample radius:</string>
+ </property>
+ </widget>
+ <widget class="TQSpinBox">
+ <property name="name">
+ <cstring>radius</cstring>
+ </property>
+ <property name="maxValue">
+ <number>9</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQListView">
+ <column>
+ <property name="text">
+ <string>Channel</string>
+ </property>
+ <property name="clickable">
+ <bool>false</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Value</string>
+ </property>
+ <property name="clickable">
+ <bool>false</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>listViewChannels</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="selectionMode">
+ <enum>NoSelection</enum>
+ </property>
+ </widget>
+ </vbox>
+</widget>
+<tqlayoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/chalk/plugins/tools/selectiontools/Makefile.am b/chalk/plugins/tools/selectiontools/Makefile.am
new file mode 100644
index 00000000..dc0ad90e
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/Makefile.am
@@ -0,0 +1,56 @@
+kde_services_DATA = chalkselectiontools.desktop
+
+# all_includes must remain last!
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkselectiontools_la_SOURCES = kis_tool_move_selection.cc \
+ kis_tool_select_brush.cc kis_tool_select_contiguous.cc kis_tool_select_elliptical.cc \
+ kis_tool_select_eraser.cc kis_tool_select_outline.cc kis_tool_select_polygonal.cc \
+ kis_tool_select_rectangular.cc selection_tools.cc
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = chalkselectiontools.la
+
+noinst_HEADERS = \
+ selection_tools.h \
+ kis_tool_select_outline.h \
+ kis_tool_select_polygonal.h \
+ kis_tool_select_rectangular.h \
+ kis_tool_select_brush.h \
+ kis_tool_select_eraser.h \
+ kis_tool_select_contiguous.h \
+ kis_tool_select_elliptical.h
+
+
+chalkselectiontools_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalkselectiontools_la_LIBADD = ../../../libchalkcommon.la
+
+chalkselectiontools_la_METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
+
+chalkpics_DATA = \
+ tool_rect_selection.png \
+ tool_eraser_selection.png \
+ tool_brush_selection.png \
+ tool_contiguous_selection.png \
+ tool_elliptical_selection.png \
+ tool_outline_selection.png \
+ tool_polygonal_selection.png \
+ tool_rectangular_selection_cursor.png \
+ tool_eraser_selection_cursor.png \
+ tool_brush_selection_cursor.png \
+ tool_contiguous_selection_cursor.png \
+ tool_elliptical_selection_cursor.png \
+ tool_outline_selection_cursor.png \
+ tool_polygonal_selection_cursor.png
+
+chalkpicsdir = $(kde_datadir)/chalk/pics
+
diff --git a/chalk/plugins/tools/selectiontools/chalkselectiontools.desktop b/chalk/plugins/tools/selectiontools/chalkselectiontools.desktop
new file mode 100644
index 00000000..72a7f217
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/chalkselectiontools.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Name=Selection Tools
+Name[bg]=Инструмент за маркиране
+Name[br]=Ostilhoù choazh
+Name[ca]=Eines de selecció
+Name[cy]=Offer Detholi
+Name[da]=Markeringsværktøj
+Name[de]=Auswahlwerkzeuge
+Name[el]=Εργαλεία επιλογής
+Name[eo]=Elektado-iloj
+Name[es]=Herramientas de selección
+Name[et]=Valikutööriistad
+Name[eu]=Hautapen-tresnak
+Name[fa]=ابزارهای گزینش
+Name[fi]=Valintatyökalut
+Name[fr]=Outils de sélection
+Name[fy]=Seleksje-ark
+Name[ga]=Uirlisí Roghnúcháin
+Name[gl]=Ferramentas de Selección
+Name[he]=כלי בחירה
+Name[hu]=Kiválasztó eszközök
+Name[is]=Valtól
+Name[it]=Strumenti di selezione
+Name[ja]=選択ツール
+Name[km]=ឧបករណ៍​ជ្រើស​
+Name[lt]=Pažymėjimo įrankiai
+Name[lv]=Izvēles rīki
+Name[ms]=Alat Pemilihan
+Name[nb]=Velgeverktøy
+Name[nds]=Utwahlwarktüüch
+Name[ne]=चयन उपकरण
+Name[nl]=Selectiegereedschappen
+Name[nn]=Veljeverktøy
+Name[pl]=Narzędzia wyboru
+Name[pt]=Ferramentas de Selecção
+Name[pt_BR]=Ferramentas de Seleção
+Name[ru]=Инструменты выделения
+Name[se]=Válljenreaiddut
+Name[sk]=Štetec výberu
+Name[sl]=Orodja za izbiro
+Name[sr]=Алати за избор
+Name[sr@Latn]=Alati za izbor
+Name[sv]=Markeringsverktyg
+Name[uk]=Засоби виділення
+Name[uz]=Tanlash vositalari
+Name[uz@cyrillic]=Танлаш воситалари
+Name[zh_CN]=选择工具
+Name[zh_TW]=選取區工具
+ServiceTypes=Chalk/Tool
+Type=Service
+X-KDE-Library=chalkselectiontools
+X-Chalk-Version=2
diff --git a/chalk/plugins/tools/selectiontools/kis_tool_move_selection.cc b/chalk/plugins/tools/selectiontools/kis_tool_move_selection.cc
new file mode 100644
index 00000000..b7b123d7
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/kis_tool_move_selection.cc
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_tool_move_selection.h"
+
+#include <stdlib.h>
+#include <tqpoint.h>
+#include <kaction.h>
+#include <kcommand.h>
+#include <klocale.h>
+#include <tqcolor.h>
+#include "kis_canvas_subject.h"
+#include "kis_cursor.h"
+#include "kis_image.h"
+#include "kis_layer.h"
+#include "kis_paint_layer.h"
+#include "kis_paint_device.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_move_event.h"
+#include "kis_selection.h"
+#include "kis_selection_manager.h"
+#include "kis_undo_adapter.h"
+
+class KisSelectionOffsetCommand : public KNamedCommand {
+ typedef KNamedCommand super;
+
+public:
+ KisSelectionOffsetCommand(KisSelectionSP layer, const TQPoint& oldpos, const TQPoint& newpos);
+ virtual ~KisSelectionOffsetCommand();
+
+ virtual void execute();
+ virtual void unexecute();
+
+private:
+ void moveTo(const TQPoint& pos);
+
+private:
+ KisSelectionSP m_layer;
+ TQPoint m_oldPos;
+ TQPoint m_newPos;
+};
+
+ KisSelectionOffsetCommand::KisSelectionOffsetCommand(KisSelectionSP layer, const TQPoint& oldpos, const TQPoint& newpos) :
+ super(i18n("Move Layer"))
+ {
+ m_layer = layer;
+ m_oldPos = oldpos;
+ m_newPos = newpos;
+
+ }
+
+ KisSelectionOffsetCommand::~KisSelectionOffsetCommand()
+ {
+ }
+
+ void KisSelectionOffsetCommand::execute()
+ {
+ moveTo(m_newPos);
+ }
+
+ void KisSelectionOffsetCommand::unexecute()
+ {
+ moveTo(m_oldPos);
+ }
+
+ void KisSelectionOffsetCommand::moveTo(const TQPoint& pos)
+ {
+ if (m_layer->undoAdapter()) {
+ m_layer->undoAdapter()->setUndo(false);
+ }
+
+ m_layer->setX(pos.x());
+ m_layer->setY(pos.y());
+
+ m_layer->tqparentPaintDevice()->setDirty();
+
+ if (m_layer->undoAdapter()) {
+ m_layer->undoAdapter()->setUndo(true);
+ }
+ }
+
+
+KisToolMoveSelection::KisToolMoveSelection()
+ : super(i18n("Move Selection Tool"))
+{
+ setName("tool_move_selection");
+ m_subject = 0;
+ setCursor(KisCursor::moveCursor());
+}
+
+KisToolMoveSelection::~KisToolMoveSelection()
+{
+}
+
+void KisToolMoveSelection::update(KisCanvasSubject *subject)
+{
+ m_subject = subject;
+ super::update(subject);
+ m_dragging = false;
+}
+
+void KisToolMoveSelection::buttonPress(KisButtonPressEvent *e)
+{
+ m_dragging = false;
+ if (m_subject && e->button() == Qt::LeftButton) {
+ TQPoint pos = e->pos().floorTQPoint();
+ KisImageSP img = m_subject->currentImg();
+ KisPaintLayerSP lay;
+
+ if (!img || !(lay = dynamic_cast<KisPaintLayer*>( img->activeLayer().data() )))
+ return;
+
+ m_dragStart = pos;
+
+ if ( !lay->visible() || !lay->paintDevice()->hasSelection())
+ return;
+ KisSelectionSP sel = lay->paintDevice()->selection();
+
+ m_dragging = true;
+ m_dragStart.setX(pos.x());
+ m_dragStart.setY(pos.y());
+ m_layerStart.setX(sel->getX());
+ m_layerStart.setY(sel->getY());
+ m_layerPosition = m_layerStart;
+
+ }
+}
+
+void KisToolMoveSelection::move(KisMoveEvent *e)
+{
+ if (m_subject && m_dragging) {
+ TQPoint pos = e->pos().floorTQPoint();
+ if((e->state() & TQt::AltButton) || (e->state() & TQt::ControlButton)) {
+ if(fabs(pos.x() - m_dragStart.x()) > fabs(pos.y() - m_dragStart.y()))
+ pos.setY(m_dragStart.y());
+ else
+ pos.setX(m_dragStart.x());
+ }
+
+ KisImageSP img = m_subject->currentImg();
+ KisPaintLayerSP lay = dynamic_cast<KisPaintLayer*>(m_subject->currentImg()->activeLayer().data());
+ if(!lay) return;
+ KisSelectionSP sel = lay->paintDevice()->selection();
+
+ TQRect rc;
+
+ pos -= m_dragStart; // convert to delta
+ rc = sel->selectedRect();
+ sel->setX(sel->getX() + pos.x());
+ sel->setY(sel->getY() + pos.y());
+ rc = rc.unite(sel->selectedRect());
+
+ m_layerPosition = TQPoint(sel->getX(), sel->getY());
+ m_dragStart = e->pos().floorTQPoint();
+
+ lay->paintDevice()->setDirty(rc);
+ }
+
+}
+
+void KisToolMoveSelection::buttonRelease(KisButtonReleaseEvent *e)
+{
+ if (m_subject && e->button() == Qt::LeftButton && m_dragging) {
+ m_dragging = false;
+ KisImageSP img = m_subject->currentImg();
+ if(!img) return;
+ KisPaintLayerSP lay = dynamic_cast<KisPaintLayer*>(img->activeLayer().data());
+
+ if (lay->paintDevice()->hasSelection()) {
+ KisSelectionSP dev = lay->paintDevice()->selection();
+ m_dragging = false;
+
+ if (img->undo()) {
+ KCommand *cmd = new KisSelectionOffsetCommand( dev, m_layerStart, m_layerPosition);
+ Q_CHECK_PTR(cmd);
+ KisUndoAdapter *adapter = img->undoAdapter();
+ if (adapter) {
+ adapter->addCommand(cmd);
+ } else {
+ delete cmd;
+ }
+ }
+ img->setModified();
+ lay->setDirty();
+ }
+ }
+}
+
+void KisToolMoveSelection::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Move selection"),
+ "tool_move",
+ TQt::SHIFT+TQt::Key_V,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ m_action->setToolTip(i18n("Move the selection"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+#include "kis_tool_move_selection.moc"
diff --git a/chalk/plugins/tools/selectiontools/kis_tool_move_selection.h b/chalk/plugins/tools/selectiontools/kis_tool_move_selection.h
new file mode 100644
index 00000000..60d73a9b
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/kis_tool_move_selection.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_TOOL_MOVE_H_
+#define KIS_TOOL_MOVE_H_
+
+#include "kis_tool_non_paint.h"
+#include "kis_tool_factory.h"
+
+// XXX: Moving is not nearly smooth enough!
+class KisToolMoveSelection : public KisToolNonPaint {
+
+ typedef KisToolNonPaint super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolMoveSelection();
+ virtual ~KisToolMoveSelection();
+
+public:
+ virtual void update(KisCanvasSubject *subject);
+
+public:
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_SELECT; }
+ virtual TQ_UINT32 priority() { return 10; }
+
+ virtual void buttonPress(KisButtonPressEvent *e);
+ virtual void move(KisMoveEvent *e);
+ virtual void buttonRelease(KisButtonReleaseEvent *e);
+
+private:
+ KisCanvasSubject *m_subject;
+ TQPoint m_dragStart;
+ TQPoint m_layerStart;
+ TQPoint m_layerPosition;
+ bool m_dragging;
+};
+
+
+class KisToolMoveSelectionFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolMoveSelectionFactory() : super() {};
+ virtual ~KisToolMoveSelectionFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolMoveSelection();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("moveselection", i18n("Move Selection Tool")); }
+};
+
+
+
+#endif // KIS_TOOL_MOVE_H_
+
diff --git a/chalk/plugins/tools/selectiontools/kis_tool_select_brush.cc b/chalk/plugins/tools/selectiontools/kis_tool_select_brush.cc
new file mode 100644
index 00000000..ff5242d6
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/kis_tool_select_brush.cc
@@ -0,0 +1,168 @@
+/*
+ * kis_tool_select_brush.cc - part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <tqevent.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqwidget.h>
+#include <tqrect.h>
+
+#include <kdebug.h>
+#include <kaction.h>
+#include <kcommand.h>
+#include <klocale.h>
+
+#include "kis_brush.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_cmb_composite.h"
+#include "kis_cursor.h"
+#include "kis_doc.h"
+#include "kis_paintop.h"
+#include "kis_paintop_registry.h"
+#include "kis_move_event.h"
+#include "kis_painter.h"
+#include "kis_selection.h"
+#include "kis_tool_select_brush.h"
+#include "kis_types.h"
+#include "kis_layer.h"
+#include "kis_view.h"
+#include "kis_selection_options.h"
+#include "kis_selected_transaction.h"
+
+KisToolSelectBrush::KisToolSelectBrush()
+ : super(i18n("SelectBrush"))
+{
+ setName("tool_select_brush");
+ m_optWidget = 0;
+ setCursor(KisCursor::load("tool_brush_selection_cursor.png", 5, 5));
+ m_paintOnSelection = true;
+}
+
+KisToolSelectBrush::~KisToolSelectBrush()
+{
+}
+
+void KisToolSelectBrush::activate()
+{
+ super::activate();
+
+ if (!m_optWidget)
+ return;
+
+ m_optWidget->slotActivated();
+}
+
+void KisToolSelectBrush::initPaint(KisEvent* /*e*/)
+{
+ if (!m_currentImage || !m_currentImage->activeDevice()) return;
+
+ m_mode = PAINT;
+ m_dragDist = 0;
+
+ // Create painter
+ KisPaintDeviceSP dev = m_currentImage->activeDevice();
+ if (m_painter)
+ delete m_painter;
+ bool hasSelection = dev->hasSelection();
+ if (m_currentImage->undo()) m_transaction = new KisSelectedTransaction(i18n("Selection Brush"), dev);
+ if(! hasSelection)
+ {
+ dev->selection()->clear();
+ dev->emitSelectionChanged();
+ }
+ KisSelectionSP selection = dev->selection();
+
+ m_target = selection;
+ m_painter = new KisPainter(selection.data());
+ Q_CHECK_PTR(m_painter);
+ m_painter->setPaintColor(KisColor(TQt::black, selection->colorSpace()));
+ m_painter->setBrush(m_subject->currentBrush());
+ m_painter->setOpacity(OPACITY_OPAQUE);//m_subject->fgColor().colorSpace()->intensity8(m_subject->fgColor().data()));
+ m_painter->setCompositeOp(COMPOSITE_OVER);
+ KisPaintOp * op = KisPaintOpRegistry::instance()->paintOp("paintbrush", 0, painter());
+ painter()->setPaintOp(op); // And now the painter owns the op and will destroy it.
+
+ // Set the cursor -- ideally. this should be a tqmask created from the brush,
+ // now that X11 can handle colored cursors.
+#if 0
+ // Setting cursors has no effect until the tool is selected again; this
+ // should be fixed.
+ setCursor(KisCursor::brushCursor());
+#endif
+}
+
+void KisToolSelectBrush::endPaint()
+{
+ m_mode = HOVER;
+ if (m_currentImage && m_currentImage->activeLayer()) {
+ if (m_currentImage->undo() && m_painter) {
+ // If painting in mouse release, make sure painter
+ // is destructed or end()ed
+ m_currentImage->undoAdapter()->addCommand(m_transaction);
+ }
+ delete m_painter;
+ m_painter = 0;
+ if (m_currentImage->activeDevice())
+ m_currentImage->activeDevice()->emitSelectionChanged();
+ notifyModified();
+ }
+}
+
+
+void KisToolSelectBrush::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Selection Brush"),
+ "tool_brush_selection", "Ctrl+Shift+B", this,
+ TQT_SLOT(activate()), collection,
+ name());
+ Q_CHECK_PTR(m_action);
+ m_action->setToolTip(i18n("Paint a selection"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+TQWidget* KisToolSelectBrush::createOptionWidget(TQWidget* tqparent)
+{
+ Q_UNUSED(tqparent);
+ // Commented out due to the fact that this doesn't actually work if you change the action
+#if 0
+ m_optWidget = new KisSelectionOptions(tqparent, m_subject);
+ Q_CHECK_PTR(m_optWidget);
+ m_optWidget->setCaption(i18n("Selection Brush"));
+
+ TQVBoxLayout * l = dynamic_cast<TQVBoxLayout*>(m_optWidget->tqlayout());
+ l->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding));
+
+ return m_optWidget;
+#endif
+ return 0;
+}
+
+TQWidget* KisToolSelectBrush::optionWidget()
+{
+ return m_optWidget;
+}
+
+#include "kis_tool_select_brush.moc"
diff --git a/chalk/plugins/tools/selectiontools/kis_tool_select_brush.h b/chalk/plugins/tools/selectiontools/kis_tool_select_brush.h
new file mode 100644
index 00000000..374050f6
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/kis_tool_select_brush.h
@@ -0,0 +1,83 @@
+/*
+ * kis_tool_select_brush.h - part of Chalk
+ *
+ * Copyright (c) 2003-2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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_TOOL_SELECT_BRUSH_H_
+#define KIS_TOOL_SELECT_BRUSH_H_
+
+#include <kis_tool.h>
+#include <kis_tool_freehand.h>
+#include <kis_tool_factory.h>
+
+class TQWidget;
+class KisPoint;
+class KisSelectedTransaction;
+class KisSelectionOptions;
+
+/**
+ * The selection brush creates a selection by painting with the current
+ * brush tqshape. Not sure what kind of an icon could represent this...
+ * Depends a bit on how we're going to visualize selections.
+ */
+class KisToolSelectBrush : public KisToolFreehand {
+ Q_OBJECT
+ TQ_OBJECT
+ typedef KisToolFreehand super;
+
+public:
+ KisToolSelectBrush();
+ virtual ~KisToolSelectBrush();
+
+ virtual void setup(KActionCollection *collection);
+ virtual TQ_UINT32 priority() { return 1; }
+ virtual enumToolType toolType() { return TOOL_SELECT; }
+ virtual TQWidget* createOptionWidget(TQWidget* tqparent);
+ virtual TQWidget* optionWidget();
+
+public slots:
+ virtual void activate();
+
+protected:
+
+ virtual void initPaint(KisEvent *e);
+ virtual void endPaint();
+
+private:
+ KisSelectionOptions * m_optWidget;
+ KisSelectedTransaction *m_transaction;
+};
+
+class KisToolSelectBrushFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolSelectBrushFactory() : super() {};
+ virtual ~KisToolSelectBrushFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolSelectBrush();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("brushselect", i18n("Brush Select Tool")); }
+};
+
+
+#endif // KIS_TOOL_SELECT_BRUSH_H_
+
diff --git a/chalk/plugins/tools/selectiontools/kis_tool_select_contiguous.cc b/chalk/plugins/tools/selectiontools/kis_tool_select_contiguous.cc
new file mode 100644
index 00000000..c4c908fc
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/kis_tool_select_contiguous.cc
@@ -0,0 +1,234 @@
+/*
+ * kis_tool_select_contiguous - part of Krayon^WChalk
+ *
+ * Copyright (c) 1999 Michael Koch <koch@kde.org>
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <tqpainter.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqapplication.h>
+#include <tqcheckbox.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <knuminput.h>
+#include <kcolorbutton.h>
+
+#include <kis_cursor.h>
+#include <kis_selection_manager.h>
+#include <kis_canvas_subject.h>
+#include <kis_image.h>
+#include <kis_layer.h>
+#include <kis_paint_device.h>
+#include <kis_button_press_event.h>
+#include <kis_canvas_subject.h>
+#include <kis_selection_options.h>
+#include <kis_selection.h>
+#include <kis_paint_device.h>
+#include <kis_iterators_pixel.h>
+#include <kis_selection_options.h>
+#include <kis_canvas_observer.h>
+#include <kis_fill_painter.h>
+#include <kis_undo_adapter.h>
+#include <kis_selected_transaction.h>
+
+#include "kis_tool_select_contiguous.h"
+
+KisToolSelectContiguous::KisToolSelectContiguous() : super(i18n("Contiguous Select"))
+{
+ setName("tool_select_contiguous");
+ m_subject = 0;
+ m_optWidget = 0;
+ m_fuzziness = 20;
+ m_sampleMerged = false;
+ m_selectAction = SELECTION_ADD;
+
+ setCursor(KisCursor::load("tool_contiguous_selection_cursor.png", 6, 6));
+}
+
+KisToolSelectContiguous::~KisToolSelectContiguous()
+{
+}
+
+void KisToolSelectContiguous::activate()
+{
+ super::activate();
+
+ if (!m_optWidget)
+ return;
+
+ m_optWidget->slotActivated();
+}
+
+void KisToolSelectContiguous::buttonPress(KisButtonPressEvent * e)
+{
+ if (m_subject) {
+
+ KisImageSP img;
+ KisPaintDeviceSP dev;
+ TQPoint pos;
+
+ if (e->button() != Qt::LeftButton && e->button() != Qt::RightButton)
+ return;
+
+ if (!(img = m_subject->currentImg()))
+ return;
+
+ dev = img->activeDevice();
+
+ if (!dev || !img->activeLayer()->visible())
+ return;
+
+ TQApplication::setOverrideCursor(KisCursor::waitCursor());
+
+ pos = TQPoint(e->pos().floorX(), e->pos().floorY());
+
+ KisFillPainter fillpainter(dev);
+ fillpainter.setFillThreshold(m_fuzziness);
+ fillpainter.setSampleMerged(m_sampleMerged);
+ KisSelectionSP selection = fillpainter.createFloodSelection(pos.x(), pos.y());
+ KisSelectedTransaction *t = 0;
+ if (img->undo()) t = new KisSelectedTransaction(i18n("Contiguous Area Selection"), dev);
+
+ if (!dev->hasSelection()) {
+ dev->selection()->clear();
+ if(m_selectAction==SELECTION_SUBTRACT)
+ selection->invert();
+ }
+
+ switch (m_selectAction) {
+ case SELECTION_SUBTRACT:
+ dev->subtractSelection(selection);
+ break;
+ case SELECTION_ADD:
+ default:
+ dev->addSelection(selection);
+ break;
+
+ }
+
+ dev->setDirty(selection->selectedRect()); // A bit too wide, but that's not that bad
+ dev->emitSelectionChanged();
+
+
+ if (img->undo())
+ img->undoAdapter()->addCommand(t);
+
+ TQApplication::restoreOverrideCursor();
+ }
+
+}
+
+void KisToolSelectContiguous::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Contiguous Area Selection"),
+ "tool_contiguous_selection" ,
+ 0,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ Q_CHECK_PTR(m_action);
+ m_action->setToolTip(i18n("Select a contiguous area"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+void KisToolSelectContiguous::update(KisCanvasSubject *subject)
+{
+ super::update(subject);
+ m_subject = subject;
+}
+
+void KisToolSelectContiguous::slotSetFuzziness(int fuzziness)
+{
+ m_fuzziness = fuzziness;
+}
+
+
+void KisToolSelectContiguous::slotSetAction(int action)
+{
+ if (action >= SELECTION_ADD && action <= SELECTION_SUBTRACT)
+ m_selectAction =(enumSelectionMode)action;
+// XXX: Fix cursors when then are done.
+// switch(m_selectAction) {
+// case SELECTION_ADD:
+// m_subject->setCanvasCursor(KisCursor::pickerPlusCursor());
+// break;
+// case SELECTION_SUBTRACT:
+// m_subject->setCanvasCursor(KisCursor::pickerMinusCursor());
+// };
+}
+
+
+TQWidget* KisToolSelectContiguous::createOptionWidget(TQWidget* tqparent)
+{
+ m_optWidget = new KisSelectionOptions(tqparent, m_subject);
+ Q_CHECK_PTR(m_optWidget);
+ m_optWidget->setCaption(i18n("Contiguous Area Selection"));
+
+ TQVBoxLayout * l = dynamic_cast<TQVBoxLayout*>(m_optWidget->tqlayout());
+ l->setSpacing( 6 );
+
+ connect (m_optWidget, TQT_SIGNAL(actionChanged(int)), this, TQT_SLOT(slotSetAction(int)));
+
+ TQHBoxLayout * hbox = new TQHBoxLayout(l);
+ Q_CHECK_PTR(hbox);
+
+ TQLabel * lbl = new TQLabel(i18n("Fuzziness: "), m_optWidget);
+ hbox->addWidget(lbl);
+
+ KIntNumInput * input = new KIntNumInput(m_optWidget, "fuzziness");
+ Q_CHECK_PTR(input);
+
+ input->setRange(0, 200, 10, true);
+ input->setValue(20);
+ hbox->addWidget(input);
+ connect(input, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotSetFuzziness(int)));
+
+ TQCheckBox* samplemerged = new TQCheckBox(i18n("Sample merged"), m_optWidget);
+ l->addWidget( samplemerged );
+ samplemerged->setChecked(m_sampleMerged);
+ connect(samplemerged, TQT_SIGNAL(stateChanged(int)),
+ this, TQT_SLOT(slotSetSampleMerged(int)));
+
+ l->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding));
+
+ return m_optWidget;
+}
+
+TQWidget* KisToolSelectContiguous::optionWidget()
+{
+ return m_optWidget;
+}
+
+void KisToolSelectContiguous::slotSetSampleMerged(int state)
+{
+ if (state == TQButton::NoChange)
+ return;
+ m_sampleMerged = (state == TQButton::On);
+}
+
+#include "kis_tool_select_contiguous.moc"
diff --git a/chalk/plugins/tools/selectiontools/kis_tool_select_contiguous.h b/chalk/plugins/tools/selectiontools/kis_tool_select_contiguous.h
new file mode 100644
index 00000000..e4beb6b7
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/kis_tool_select_contiguous.h
@@ -0,0 +1,95 @@
+/*
+ * kis_tool_select_contiguous.h - part of KImageShop^WKrayon^Chalk
+ *
+ * Copyright (c) 1999 Michael Koch <koch@kde.org>
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ *
+ * 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_TOOL_SELECT_CONTIGUOUS_H__
+#define __KIS_TOOL_SELECT_CONTIGUOUS_H__
+
+#include <kis_tool.h>
+#include <kis_tool_non_paint.h>
+#include <kis_tool_factory.h>
+#include <kis_selection.h>
+
+class KisCanvasSubject;
+class TQWidget;
+class TQVBoxLayout;
+class TQCheckBox;
+class KisSelectionOptions;
+
+/**
+ * The 'magic wand' selection tool -- in fact just
+ * a floodfill that only creates a selection.
+ */
+class KisToolSelectContiguous : public KisToolNonPaint {
+
+ typedef KisToolNonPaint super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolSelectContiguous();
+ virtual ~KisToolSelectContiguous();
+
+public:
+ virtual void update(KisCanvasSubject *subject);
+
+ virtual void setup(KActionCollection *collection);
+ virtual TQ_UINT32 priority() { return 7; }
+ virtual enumToolType toolType() { return TOOL_SELECT; };
+
+ virtual TQWidget* createOptionWidget(TQWidget* tqparent);
+ virtual TQWidget* optionWidget();
+
+ virtual void buttonPress(KisButtonPressEvent *event);
+
+public slots:
+ virtual void slotSetFuzziness(int);
+ virtual void slotSetAction(int);
+ virtual void slotSetSampleMerged(int);
+ virtual void activate();
+
+
+private:
+ KisCanvasSubject *m_subject;
+ KisSelectionOptions * m_optWidget;
+
+ int m_fuzziness;
+ enumSelectionMode m_selectAction;
+ bool m_sampleMerged;
+};
+
+class KisToolSelectContiguousFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolSelectContiguousFactory() : super() {};
+ virtual ~KisToolSelectContiguousFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolSelectContiguous();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("contiguousselect", i18n("Contiguous Select Tool")); }
+};
+
+
+#endif //__KIS_TOOL_SELECT_CONTIGUOUS_H__
+
diff --git a/chalk/plugins/tools/selectiontools/kis_tool_select_elliptical.cc b/chalk/plugins/tools/selectiontools/kis_tool_select_elliptical.cc
new file mode 100644
index 00000000..efdae2f3
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/kis_tool_select_elliptical.cc
@@ -0,0 +1,321 @@
+/*
+ * kis_tool_select_elliptical.cc -- part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 <tqapplication.h>
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqlayout.h>
+
+#include <kdebug.h>
+#include <kaction.h>
+#include <kcommand.h>
+#include <klocale.h>
+
+#include "kis_autobrush_resource.h"
+#include "kis_canvas_controller.h"
+#include "kis_canvas_subject.h"
+#include "kis_cursor.h"
+#include "kis_image.h"
+#include "kis_painter.h"
+#include "kis_tool_select_elliptical.h"
+#include "kis_layer.h"
+#include "kis_undo_adapter.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_move_event.h"
+#include "kis_selection.h"
+#include "kis_selection_options.h"
+#include "kis_selected_transaction.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+
+KisToolSelectElliptical::KisToolSelectElliptical()
+ : super(i18n("Elliptical Select"))
+{
+ setName("tool_select_elliptical");
+ setCursor(KisCursor::load("tool_elliptical_selection_cursor.png", 6, 6));
+
+ m_subject = 0;
+ m_selecting = false;
+ m_centerPos = KisPoint(0, 0);
+ m_startPos = KisPoint(0, 0);
+ m_endPos = KisPoint(0, 0);
+ m_optWidget = 0;
+ m_selectAction = SELECTION_ADD;
+}
+
+KisToolSelectElliptical::~KisToolSelectElliptical()
+{
+}
+
+void KisToolSelectElliptical::activate()
+{
+ super::activate();
+
+ if (!m_optWidget)
+ return;
+
+ m_optWidget->slotActivated();
+}
+
+void KisToolSelectElliptical::update(KisCanvasSubject *subject)
+{
+ m_subject = subject;
+ super::update(m_subject);
+}
+
+void KisToolSelectElliptical::paint(KisCanvasPainter& gc)
+{
+ if (m_selecting)
+ paintOutline(gc, TQRect());
+}
+
+void KisToolSelectElliptical::paint(KisCanvasPainter& gc, const TQRect& rc)
+{
+ if (m_selecting)
+ paintOutline(gc, rc);
+}
+
+void KisToolSelectElliptical::clearSelection()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisImageSP img = m_subject->currentImg();
+
+ Q_ASSERT(controller);
+
+// if (img && img->floatingSelection().data() != 0) {
+// img->unsetFloatingSelection();
+// controller->canvas()->update();
+// }
+
+ m_startPos = KisPoint(0, 0);
+ m_endPos = KisPoint(0, 0);
+ m_selecting = false;
+ }
+}
+
+void KisToolSelectElliptical::buttonPress(KisButtonPressEvent *e)
+{
+ if (m_subject) {
+ KisImageSP img = m_subject->currentImg();
+
+ if (img && img->activeDevice() && e->button() == Qt::LeftButton) {
+ clearSelection();
+ m_startPos = m_endPos = m_centerPos = e->pos();
+ m_selecting = true;
+ paintOutline();
+ }
+ }
+}
+
+void KisToolSelectElliptical::move(KisMoveEvent *e)
+{
+ if (m_subject && m_selecting) {
+ paintOutline();
+ // move (alt) or resize ellipse
+ if (e->state() & TQt::AltButton) {
+ KisPoint trans = e->pos() - m_endPos;
+ m_startPos += trans;
+ m_endPos += trans;
+ } else {
+ KisPoint diag = e->pos() - (e->state() & TQt::ControlButton
+ ? m_centerPos : m_startPos);
+ // circle?
+ if (e->state() & TQt::ShiftButton) {
+ double size = TQMAX(fabs(diag.x()), fabs(diag.y()));
+ double w = diag.x() < 0 ? -size : size;
+ double h = diag.y() < 0 ? -size : size;
+ diag = KisPoint(w, h);
+ }
+
+ // resize around center point?
+ if (e->state() & TQt::ControlButton) {
+ m_startPos = m_centerPos - diag;
+ m_endPos = m_centerPos + diag;
+ } else {
+ m_endPos = m_startPos + diag;
+ }
+ }
+ paintOutline();
+ m_centerPos = KisPoint((m_startPos.x() + m_endPos.x()) / 2,
+ (m_startPos.y() + m_endPos.y()) / 2);
+ }
+}
+
+void KisToolSelectElliptical::buttonRelease(KisButtonReleaseEvent *e)
+{
+ if (m_subject && m_selecting && e->button() == Qt::LeftButton) {
+
+ paintOutline();
+
+ if (m_startPos == m_endPos) {
+ clearSelection();
+ } else {
+ TQApplication::setOverrideCursor(KisCursor::waitCursor());
+ KisImageSP img = m_subject->currentImg();
+
+ if (!img)
+ return;
+
+ if (m_endPos.y() < 0)
+ m_endPos.setY(0);
+
+ if (m_endPos.y() > img->height())
+ m_endPos.setY(img->height());
+
+ if (m_endPos.x() < 0)
+ m_endPos.setX(0);
+
+ if (m_endPos.x() > img->width())
+ m_endPos.setX(img->width());
+
+ if (img && img->activeDevice()) {
+ KisPaintDeviceSP dev = img->activeDevice();
+ KisSelectedTransaction *t = 0;
+ if (img->undo()) t = new KisSelectedTransaction(i18n("Elliptical Selection"), dev);
+
+ bool hasSelection = dev->hasSelection();
+ if(! hasSelection)
+ {
+ dev->selection()->clear();
+ if(m_selectAction==SELECTION_SUBTRACT)
+ dev->selection()->invert();
+ }
+ TQRect rc( m_startPos.floorTQPoint(), m_endPos.floorTQPoint());
+ rc = rc.normalize();
+
+ KisSelectionSP tmpSel = new KisSelection(dev);
+ KisAutobrushCircleShape tqshape(rc.width(),rc.height(), 1, 1);
+ TQ_UINT8 value;
+ for (int y = 0; y <= rc.height(); y++)
+ for (int x = 0; x <= rc.width(); x++)
+ {
+ value = MAX_SELECTED - tqshape.valueAt(x,y);
+ tmpSel->setSelected( x+rc.x(), y+rc.y(), value);
+ }
+ switch(m_selectAction)
+ {
+ case SELECTION_ADD:
+ dev->addSelection(tmpSel);
+ break;
+ case SELECTION_SUBTRACT:
+ dev->subtractSelection(tmpSel);
+ break;
+ }
+
+ if(hasSelection) {
+ dev->setDirty(rc);
+ dev->emitSelectionChanged(rc);
+ } else {
+ dev->setDirty();
+ dev->emitSelectionChanged();
+ }
+
+ if (img->undo())
+ img->undoAdapter()->addCommand(t);
+
+ TQApplication::restoreOverrideCursor();
+ }
+ }
+ m_selecting = false;
+ }
+}
+
+void KisToolSelectElliptical::paintOutline()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter gc(canvas);
+ TQRect rc;
+
+ paintOutline(gc, rc);
+ }
+}
+
+void KisToolSelectElliptical::paintOutline(KisCanvasPainter& gc, const TQRect&)
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ RasterOp op = gc.rasterOp();
+ TQPen old = gc.pen();
+ TQPen pen(TQt::DotLine);
+ TQPoint start;
+ TQPoint end;
+
+ Q_ASSERT(controller);
+ start = controller->windowToView(m_startPos).floorTQPoint();
+ end = controller->windowToView(m_endPos).floorTQPoint();
+
+ gc.setRasterOp(TQt::NotROP);
+ gc.setPen(pen);
+ gc.drawEllipse(TQRect(start, end));
+ gc.setRasterOp(op);
+ gc.setPen(old);
+ }
+}
+
+void KisToolSelectElliptical::slotSetAction(int action) {
+ if (action >= SELECTION_ADD && action <= SELECTION_SUBTRACT)
+ m_selectAction =(enumSelectionMode)action;
+}
+
+void KisToolSelectElliptical::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Elliptical Selection"),
+ "tool_elliptical_selection" ,
+ TQt::Key_J,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ Q_CHECK_PTR(m_action);
+ m_action->setToolTip(i18n("Select an elliptical area"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+TQWidget* KisToolSelectElliptical::createOptionWidget(TQWidget* tqparent)
+{
+ m_optWidget = new KisSelectionOptions(tqparent, m_subject);
+ Q_CHECK_PTR(m_optWidget);
+ m_optWidget->setCaption(i18n("Elliptical Selection"));
+
+ connect (m_optWidget, TQT_SIGNAL(actionChanged(int)), this, TQT_SLOT(slotSetAction(int)));
+
+ TQVBoxLayout * l = dynamic_cast<TQVBoxLayout*>(m_optWidget->tqlayout());
+ l->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding));
+
+ return m_optWidget;
+}
+
+TQWidget* KisToolSelectElliptical::optionWidget()
+{
+ return m_optWidget;
+}
+
+
+
+#include "kis_tool_select_elliptical.moc"
diff --git a/chalk/plugins/tools/selectiontools/kis_tool_select_elliptical.h b/chalk/plugins/tools/selectiontools/kis_tool_select_elliptical.h
new file mode 100644
index 00000000..f0d1a039
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/kis_tool_select_elliptical.h
@@ -0,0 +1,99 @@
+/*
+ * kis_tool_select_elliptical.h - part of Krayon^WChalk
+ *
+ * Copyright (c) 2000 John Califf <jcaliff@compuzone.net>
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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_TOOL_SELECT_ELLIPTICAL_H__
+#define __KIS_TOOL_SELECT_ELLIPTICAL_H__
+
+#include <tqpoint.h>
+
+#include "kis_point.h"
+#include "kis_selection.h"
+#include "kis_tool_factory.h"
+#include "kis_tool_non_paint.h"
+
+class KisSelectionOptions;
+
+class KisToolSelectElliptical : public KisToolNonPaint {
+
+ typedef KisToolNonPaint super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolSelectElliptical();
+ virtual ~KisToolSelectElliptical();
+
+ virtual void update(KisCanvasSubject *subject);
+
+ virtual void setup(KActionCollection *collection);
+ virtual TQ_UINT32 priority() { return 4; }
+ virtual TQWidget * createOptionWidget(TQWidget* tqparent);
+ virtual TQWidget* optionWidget();
+ virtual enumToolType toolType() { return TOOL_SELECT; }
+
+ virtual void paint(KisCanvasPainter& gc);
+ virtual void paint(KisCanvasPainter& gc, const TQRect& rc);
+ virtual void buttonPress(KisButtonPressEvent *e);
+ virtual void move(KisMoveEvent *e);
+ virtual void buttonRelease(KisButtonReleaseEvent *e);
+
+public slots:
+ virtual void slotSetAction(int);
+ virtual void activate();
+
+
+private:
+ void clearSelection();
+ void paintOutline();
+ void paintOutline(KisCanvasPainter& gc, const TQRect& rc);
+
+private:
+ KisCanvasSubject *m_subject;
+ KisPoint m_centerPos;
+ KisPoint m_startPos;
+ KisPoint m_endPos;
+ bool m_selecting;
+ KisSelectionOptions * m_optWidget;
+ enumSelectionMode m_selectAction;
+};
+
+class KisToolSelectEllipticalFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolSelectEllipticalFactory() : super() {};
+ virtual ~KisToolSelectEllipticalFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolSelectElliptical();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("ellipticalselect", i18n("Elliptical Select Tool")); }
+};
+
+
+
+
+
+#endif //__KIS_TOOL_SELECT_ELLIPTICAL_H__
+
diff --git a/chalk/plugins/tools/selectiontools/kis_tool_select_eraser.cc b/chalk/plugins/tools/selectiontools/kis_tool_select_eraser.cc
new file mode 100644
index 00000000..58a7778c
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/kis_tool_select_eraser.cc
@@ -0,0 +1,156 @@
+/*
+ * kis_tool_select_brush.cc - part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <tqevent.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqwidget.h>
+
+#include <kdebug.h>
+#include <kaction.h>
+#include <kcommand.h>
+#include <klocale.h>
+
+#include "kis_brush.h"
+#include "kis_layer.h"
+#include "kis_paintop.h"
+#include "kis_paintop_registry.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_cmb_composite.h"
+#include "kis_cursor.h"
+#include "kis_doc.h"
+#include "kis_move_event.h"
+#include "kis_painter.h"
+#include "kis_selection.h"
+#include "kis_tool_select_eraser.h"
+#include "kis_types.h"
+#include "kis_view.h"
+#include "kis_selection_options.h"
+
+KisToolSelectEraser::KisToolSelectEraser()
+ : super(i18n("SelectEraser"))
+{
+ setName("tool_select_eraser");
+ setCursor(KisCursor::load("tool_eraser_selection_cursor.png", 5, 5));
+ m_optWidget = 0;
+ m_paintOnSelection = true;
+}
+
+KisToolSelectEraser::~KisToolSelectEraser()
+{
+}
+
+void KisToolSelectEraser::activate()
+{
+ super::activate();
+
+ if (!m_optWidget)
+ return;
+
+ m_optWidget->slotActivated();
+}
+
+void KisToolSelectEraser::initPaint(KisEvent */*e*/)
+{
+ if (!m_currentImage || !m_currentImage->activeDevice()) return;
+
+ m_mode = PAINT;
+ m_dragDist = 0;
+
+ // Create painter
+ KisPaintDeviceSP dev = m_currentImage->activeDevice();
+
+ if (dev == 0) return;
+
+ if (m_painter)
+ delete m_painter;
+ if(! dev->hasSelection())
+ {
+ dev->selection()->clear();
+ dev->emitSelectionChanged();
+ }
+ KisSelectionSP selection = dev->selection();
+
+ m_target = selection;
+ m_painter = new KisPainter(selection.data());
+ Q_CHECK_PTR(m_painter);
+ m_painter->beginTransaction(i18n("Selection Eraser"));
+ m_painter->setPaintColor(KisColor(TQt::white, selection->colorSpace()));
+ m_painter->setBrush(m_subject->currentBrush());
+ m_painter->setOpacity(OPACITY_OPAQUE);
+ m_painter->setCompositeOp(COMPOSITE_ERASE);
+ KisPaintOp * op = KisPaintOpRegistry::instance()->paintOp("eraser", 0, painter());
+ painter()->setPaintOp(op); // And now the painter owns the op and will destroy it.
+
+ // Set the cursor -- ideally. this should be a tqmask created from the brush,
+ // now that X11 can handle colored cursors.
+#if 0
+ // Setting cursors has no effect until the tool is selected again; this
+ // should be fixed.
+ setCursor(KisCursor::eraserCursor());
+#endif
+}
+
+void KisToolSelectEraser::endPaint() {
+ super::endPaint();
+ if (m_currentImage && m_currentImage->activeDevice())
+ m_currentImage->activeDevice()->emitSelectionChanged();
+}
+void KisToolSelectEraser::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("Selection &Eraser"),
+ "tool_eraser_selection", "Ctrl+Shift+E", this,
+ TQT_SLOT(activate()), collection,
+ name());
+ Q_CHECK_PTR(m_action);
+ m_action->setToolTip(i18n("Erase parts of a selection"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+TQWidget* KisToolSelectEraser::createOptionWidget(TQWidget* tqparent)
+{
+ Q_UNUSED(tqparent);
+ // Commented out due to the fact that this doesn't actually work if you change the action
+#if 0
+ m_optWidget = new KisSelectionOptions(tqparent, m_subject);
+ Q_CHECK_PTR(m_optWidget);
+ m_optWidget->setCaption(i18n("Selection Eraser"));
+
+ TQVBoxLayout * l = dynamic_cast<TQVBoxLayout*>(m_optWidget->tqlayout());
+ l->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding));
+
+ return m_optWidget;
+#endif
+ return 0;
+}
+
+TQWidget* KisToolSelectEraser::optionWidget()
+{
+ return m_optWidget;
+}
+
+#include "kis_tool_select_eraser.moc"
+
diff --git a/chalk/plugins/tools/selectiontools/kis_tool_select_eraser.h b/chalk/plugins/tools/selectiontools/kis_tool_select_eraser.h
new file mode 100644
index 00000000..85bd5509
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/kis_tool_select_eraser.h
@@ -0,0 +1,82 @@
+/*
+ * kis_tool_select_eraser.h - part of Chalk
+ *
+ * Copyright (c) 2003-2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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_TOOL_SELECT_ERASER_H_
+#define KIS_TOOL_SELECT_ERASER_H_
+
+#include <kis_tool_factory.h>
+#include <kis_tool_freehand.h>
+
+class KisPoint;
+class KisSelectionOptions;
+
+
+/**
+ * The selection eraser makes a selection smaller by painting with the
+ * current eraser tqshape. Not sure what kind of an icon could represent
+ * this... Depends a bit on how we're going to visualize selections.
+ */
+class KisToolSelectEraser : public KisToolFreehand {
+ Q_OBJECT
+ TQ_OBJECT
+ typedef KisToolFreehand super;
+
+public:
+ KisToolSelectEraser();
+ virtual ~KisToolSelectEraser();
+
+ virtual void setup(KActionCollection *collection);
+ virtual TQ_UINT32 priority() { return 2; }
+ virtual enumToolType toolType() { return TOOL_SELECT; }
+ virtual TQWidget* createOptionWidget(TQWidget* tqparent);
+ virtual TQWidget* optionWidget();
+
+public slots:
+ virtual void activate();
+
+protected:
+
+ virtual void initPaint(KisEvent *e);
+ virtual void endPaint();
+private:
+ KisSelectionOptions * m_optWidget;
+
+};
+
+
+class KisToolSelectEraserFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolSelectEraserFactory() : super() {};
+ virtual ~KisToolSelectEraserFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolSelectEraser();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("eraserselect", i18n("Eraser Select Tool")); }
+};
+
+
+
+#endif // KIS_TOOL_SELECT_ERASER_H_
+
diff --git a/chalk/plugins/tools/selectiontools/kis_tool_select_outline.cc b/chalk/plugins/tools/selectiontools/kis_tool_select_outline.cc
new file mode 100644
index 00000000..b81762fb
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/kis_tool_select_outline.cc
@@ -0,0 +1,295 @@
+/*
+ * kis_tool_select_freehand.h - part of Krayon^WChalk
+ *
+ * Copyright (c) 2000 John Califf <jcaliff@compuzone.net>
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <tqapplication.h>
+#include <tqpainter.h>
+#include <tqregion.h>
+#include <tqwidget.h>
+#include <tqlayout.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <kcommand.h>
+#include <klocale.h>
+
+#include <kis_layer.h>
+#include <kis_selection_options.h>
+#include <kis_canvas_controller.h>
+#include <kis_canvas_subject.h>
+#include <kis_cursor.h>
+#include <kis_image.h>
+#include <kis_tool_select_outline.h>
+#include <kis_vec.h>
+#include <kis_undo_adapter.h>
+#include <kis_button_press_event.h>
+#include <kis_button_release_event.h>
+#include <kis_move_event.h>
+#include "kis_selected_transaction.h"
+#include "kis_painter.h"
+#include "kis_paintop_registry.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+
+KisToolSelectOutline::KisToolSelectOutline()
+ : super(i18n("Select Outline"))
+{
+ setName("tool_select_outline");
+ setCursor(KisCursor::load("tool_outline_selection_cursor.png", 5, 5));
+
+ m_subject = 0;
+ m_dragging = false;
+ m_optWidget = 0;
+ m_selectAction = SELECTION_ADD;
+}
+
+KisToolSelectOutline::~KisToolSelectOutline()
+{
+}
+
+void KisToolSelectOutline::activate()
+{
+ super::activate();
+
+ if (!m_optWidget)
+ return;
+
+ m_optWidget->slotActivated();
+}
+
+void KisToolSelectOutline::update (KisCanvasSubject *subject)
+{
+ m_subject = subject;
+ super::update(m_subject);
+}
+
+void KisToolSelectOutline::buttonPress(KisButtonPressEvent *event)
+{
+ if (event->button() == Qt::LeftButton) {
+ m_dragging = true;
+
+ m_dragStart = event->pos();
+ m_dragEnd = event->pos();
+ m_points.clear();
+ m_points.append(m_dragStart);
+ }
+}
+
+void KisToolSelectOutline::move(KisMoveEvent *event)
+{
+ if (m_dragging) {
+ m_dragStart = m_dragEnd;
+ m_dragEnd = event->pos();
+ m_points.append (m_dragEnd);
+ // draw new lines on canvas
+ draw();
+ }
+}
+
+void KisToolSelectOutline::buttonRelease(KisButtonReleaseEvent *event)
+{
+ if (!m_subject)
+ return;
+
+ if (m_dragging && event->button() == Qt::LeftButton) {
+ m_dragging = false;
+ deactivate();
+
+ KisImageSP img = m_subject->currentImg();
+
+ if (img && img->activeDevice()) {
+ TQApplication::setOverrideCursor(KisCursor::waitCursor());
+ KisPaintDeviceSP dev = img->activeDevice();
+ bool hasSelection = dev->hasSelection();
+ KisSelectedTransaction *t = 0;
+ if (img->undo()) t = new KisSelectedTransaction(i18n("Outline Selection"), dev);
+ KisSelectionSP selection = dev->selection();
+
+ if (!hasSelection) {
+ selection->clear();
+ }
+
+ KisPainter painter(selection.data());
+
+ painter.setPaintColor(KisColor(TQt::black, selection->colorSpace()));
+ painter.setFillStyle(KisPainter::FillStyleForegroundColor);
+ painter.setStrokeStyle(KisPainter::StrokeStyleNone);
+ painter.setBrush(m_subject->currentBrush());
+ painter.setOpacity(OPACITY_OPAQUE);
+ KisPaintOp * op = KisPaintOpRegistry::instance()->paintOp("paintbrush", 0, &painter);
+ painter.setPaintOp(op); // And now the painter owns the op and will destroy it.
+
+ switch (m_selectAction) {
+ case SELECTION_ADD:
+ painter.setCompositeOp(COMPOSITE_OVER);
+ break;
+ case SELECTION_SUBTRACT:
+ painter.setCompositeOp(COMPOSITE_SUBTRACT);
+ break;
+ default:
+ break;
+ }
+
+ painter.paintPolygon(m_points);
+
+
+ if(hasSelection) {
+ TQRect dirty(painter.dirtyRect());
+ dev->setDirty(dirty);
+ dev->emitSelectionChanged(dirty);
+ } else {
+ dev->setDirty();
+ dev->emitSelectionChanged();
+ }
+
+ if (img->undo())
+ img->undoAdapter()->addCommand(t);
+
+ TQApplication::restoreOverrideCursor();
+ }
+
+ m_points.clear();
+ }
+}
+
+void KisToolSelectOutline::paint(KisCanvasPainter& gc)
+{
+ draw(gc);
+}
+
+void KisToolSelectOutline::paint(KisCanvasPainter& gc, const TQRect&)
+{
+ draw(gc);
+}
+
+void KisToolSelectOutline::draw()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter gc(canvas);
+
+ draw(gc);
+ }
+}
+
+void KisToolSelectOutline::draw(KisCanvasPainter& gc)
+{
+ if (!m_subject)
+ return;
+
+ if (m_dragging && !m_points.empty()) {
+ TQPen pen(TQt::white, 0, TQt::DotLine);
+
+ gc.setPen(pen);
+ gc.setRasterOp(TQt::XorROP);
+
+ KisCanvasController *controller = m_subject->canvasController();
+ KisPoint start, end;
+ TQPoint startPos;
+ TQPoint endPos;
+
+ startPos = controller->windowToView(m_dragStart.floorTQPoint());
+ endPos = controller->windowToView(m_dragEnd.floorTQPoint());
+ gc.drawLine(startPos, endPos);
+ }
+}
+
+void KisToolSelectOutline::deactivate()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter gc(canvas);
+
+ TQPen pen(TQt::white, 0, TQt::DotLine);
+
+ gc.setPen(pen);
+ gc.setRasterOp(TQt::XorROP);
+
+ KisPoint start, end;
+ TQPoint startPos;
+ TQPoint endPos;
+
+ for (KisPointVector::iterator it = m_points.begin(); it != m_points.end(); ++it) {
+
+ if (it == m_points.begin())
+ {
+ start = (*it);
+ } else {
+ end = (*it);
+
+ startPos = controller->windowToView(start.floorTQPoint());
+ endPos = controller->windowToView(end.floorTQPoint());
+
+ gc.drawLine(startPos, endPos);
+
+ start = end;
+ }
+ }
+ }
+}
+
+void KisToolSelectOutline::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Outline Selection"),
+ "tool_outline_selection",
+ 0,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ Q_CHECK_PTR(m_action);
+ m_action->setExclusiveGroup("tools");
+ m_action->setToolTip(i18n("Select an outline"));
+ m_ownAction = true;
+ }
+}
+
+
+TQWidget* KisToolSelectOutline::createOptionWidget(TQWidget* tqparent)
+{
+ m_optWidget = new KisSelectionOptions(tqparent, m_subject);
+ Q_CHECK_PTR(m_optWidget);
+ m_optWidget->setCaption(i18n("Outline Selection"));
+
+ connect (m_optWidget, TQT_SIGNAL(actionChanged(int)), this, TQT_SLOT(slotSetAction(int)));
+
+ TQVBoxLayout * l = dynamic_cast<TQVBoxLayout*>(m_optWidget->tqlayout());
+ l->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding));
+
+ return m_optWidget;
+}
+
+TQWidget* KisToolSelectOutline::optionWidget()
+{
+ return m_optWidget;
+}
+
+void KisToolSelectOutline::slotSetAction(int action) {
+ if (action >= SELECTION_ADD && action <= SELECTION_SUBTRACT)
+ m_selectAction =(enumSelectionMode)action;
+}
+
+#include "kis_tool_select_outline.moc"
+
diff --git a/chalk/plugins/tools/selectiontools/kis_tool_select_outline.h b/chalk/plugins/tools/selectiontools/kis_tool_select_outline.h
new file mode 100644
index 00000000..74ecab78
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/kis_tool_select_outline.h
@@ -0,0 +1,101 @@
+/*
+ * kis_tool_select_freehand.h - part of Krayon^WChalk
+ *
+ * Copyright (c) 2000 John Califf <jcaliff@compuzone.net>
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 __selecttoolfreehand_h__
+#define __selecttoolfreehand_h__
+
+#include <tqpoint.h>
+#include <tqpointarray.h>
+
+#include "kis_point.h"
+#include "kis_tool_non_paint.h"
+#include "kis_tool_factory.h"
+#include "kis_selection.h"
+
+class KisSelectionOptions;
+
+class KisToolSelectOutline : public KisToolNonPaint {
+
+ typedef KisToolNonPaint super;
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ KisToolSelectOutline();
+ virtual ~KisToolSelectOutline();
+
+ virtual void update (KisCanvasSubject *subject);
+
+ virtual void setup(KActionCollection *collection);
+ virtual TQ_UINT32 priority() { return 6; }
+ virtual enumToolType toolType() { return TOOL_SELECT; }
+
+ virtual void buttonPress(KisButtonPressEvent *event);
+ virtual void move(KisMoveEvent *event);
+ virtual void buttonRelease(KisButtonReleaseEvent *event);
+
+ TQWidget* createOptionWidget(TQWidget* tqparent);
+ virtual TQWidget* optionWidget();
+
+public slots:
+ virtual void slotSetAction(int);
+ virtual void activate();
+ void deactivate();
+
+protected:
+ virtual void paint(KisCanvasPainter& gc);
+ virtual void paint(KisCanvasPainter& gc, const TQRect& rc);
+ void draw(KisCanvasPainter& gc);
+ void draw();
+
+
+protected:
+ KisPoint m_dragStart;
+ KisPoint m_dragEnd;
+
+ bool m_dragging;
+private:
+ typedef TQValueVector<KisPoint> KisPointVector;
+ KisCanvasSubject *m_subject;
+ KisPointVector m_points;
+ KisSelectionOptions * m_optWidget;
+ enumSelectionMode m_selectAction;
+};
+
+
+class KisToolSelectOutlineFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolSelectOutlineFactory() : super() {};
+ virtual ~KisToolSelectOutlineFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolSelectOutline();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("selectoutline", i18n("Select Outline tool")); }
+};
+
+
+#endif //__selecttoolfreehand_h__
+
diff --git a/chalk/plugins/tools/selectiontools/kis_tool_select_polygonal.cc b/chalk/plugins/tools/selectiontools/kis_tool_select_polygonal.cc
new file mode 100644
index 00000000..7bac7cc3
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/kis_tool_select_polygonal.cc
@@ -0,0 +1,315 @@
+/*
+ * kis_tool_select_polygonal.h - part of Krayon^WChalk
+ *
+ * Copyright (c) 2000 John Califf <jcaliff@compuzone.net>
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <tqapplication.h>
+#include <tqpainter.h>
+#include <tqregion.h>
+#include <tqwidget.h>
+#include <tqlayout.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <kcommand.h>
+#include <klocale.h>
+
+#include <kis_layer.h>
+#include <kis_selection_options.h>
+#include <kis_canvas_controller.h>
+#include <kis_canvas_subject.h>
+#include <kis_cursor.h>
+#include <kis_image.h>
+#include <kis_tool_select_polygonal.h>
+#include <kis_vec.h>
+#include <kis_undo_adapter.h>
+#include <kis_button_press_event.h>
+#include <kis_button_release_event.h>
+#include <kis_move_event.h>
+#include "kis_selected_transaction.h"
+#include "kis_painter.h"
+#include "kis_paintop_registry.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+
+KisToolSelectPolygonal::KisToolSelectPolygonal()
+ : super(i18n("Select Polygonal"))
+{
+ setName("tool_select_polygonal");
+ setCursor(KisCursor::load("tool_polygonal_selection_cursor.png", 6, 6));
+
+ m_subject = 0;
+ m_dragging = false;
+ m_optWidget = 0;
+ m_selectAction = SELECTION_ADD;
+}
+
+KisToolSelectPolygonal::~KisToolSelectPolygonal()
+{
+}
+
+void KisToolSelectPolygonal::activate()
+{
+ m_points.clear();
+ super::activate();
+
+ if (!m_optWidget)
+ return;
+
+ m_optWidget->slotActivated();
+}
+
+void KisToolSelectPolygonal::deactivate()
+{
+ draw();
+ m_points.clear();
+ m_dragging = false;
+}
+
+
+void KisToolSelectPolygonal::update (KisCanvasSubject *subject)
+{
+ m_subject = subject;
+ super::update(m_subject);
+}
+
+void KisToolSelectPolygonal::buttonPress(KisButtonPressEvent *event)
+{
+ if (event->button() == Qt::LeftButton) {
+ m_dragging = true;
+
+ if (m_points.isEmpty())
+ {
+ m_dragStart = event->pos();
+ m_dragEnd = event->pos();
+ m_points.append(m_dragStart);
+ } else {
+ m_dragStart = m_dragEnd;
+ m_dragEnd = event->pos();
+ draw();
+ }
+ } else if (event->button() == Qt::LeftButton && event->state() == ShiftButton) {
+ finish();
+ }
+}
+
+
+void KisToolSelectPolygonal::doubleClick( KisDoubleClickEvent * )
+{
+ finish();
+}
+
+void KisToolSelectPolygonal::finish()
+{
+ // erase old lines on canvas
+ draw();
+ m_dragging = false;
+
+ KisImageSP img = m_subject->currentImg();
+
+ if (img && img->activeDevice()) {
+ TQApplication::setOverrideCursor(KisCursor::waitCursor());
+ KisPaintDeviceSP dev = img->activeDevice();
+
+ bool hasSelection = dev->hasSelection();
+ KisSelectedTransaction *t = 0;
+ if (img->undo()) t = new KisSelectedTransaction(i18n("Polygonal Selection"), dev);
+ KisSelectionSP selection = dev->selection();
+
+ if (!hasSelection)
+ {
+ selection->clear();
+ }
+
+ KisPainter painter(selection.data());
+ painter.setPaintColor(KisColor(TQt::black, selection->colorSpace()));
+ painter.setFillStyle(KisPainter::FillStyleForegroundColor);
+ painter.setStrokeStyle(KisPainter::StrokeStyleNone);
+ painter.setBrush(m_subject->currentBrush());
+ painter.setOpacity(OPACITY_OPAQUE);
+ KisPaintOp * op = KisPaintOpRegistry::instance()->paintOp("paintbrush", 0, &painter);
+ painter.setPaintOp(op); // And now the painter owns the op and will destroy it.
+
+ switch(m_selectAction)
+ {
+ case SELECTION_ADD:
+ painter.setCompositeOp(COMPOSITE_OVER);
+ break;
+ case SELECTION_SUBTRACT:
+ painter.setCompositeOp(COMPOSITE_SUBTRACT);
+ break;
+ default:
+ break;
+ }
+
+ painter.paintPolygon(m_points);
+
+ if(hasSelection) {
+ TQRect rect(painter.dirtyRect());
+ dev->setDirty(rect);
+ dev->emitSelectionChanged(rect);
+ } else {
+ dev->setDirty();
+ dev->emitSelectionChanged();
+ }
+
+ if (img->undo()) img->undoAdapter()->addCommand(t);
+
+ TQApplication::restoreOverrideCursor();
+ }
+
+ m_points.clear();
+
+}
+
+void KisToolSelectPolygonal::move(KisMoveEvent *event)
+{
+ if (m_dragging) {
+ // erase old lines on canvas
+ draw();
+ // get current mouse position
+ m_dragEnd = event->pos();
+ // draw new lines on canvas
+ draw();
+ }
+}
+
+void KisToolSelectPolygonal::buttonRelease(KisButtonReleaseEvent *event)
+{
+ if (!m_subject)
+ return;
+
+ if (m_dragging && event->button() == Qt::LeftButton) {
+ m_dragging = false;
+ m_points.append (m_dragEnd);
+ }
+
+ if (m_dragging && event->button() == Qt::RightButton) {
+
+ }
+}
+
+void KisToolSelectPolygonal::paint(KisCanvasPainter& gc)
+{
+ draw(gc);
+}
+
+void KisToolSelectPolygonal::paint(KisCanvasPainter& gc, const TQRect&)
+{
+ draw(gc);
+}
+
+void KisToolSelectPolygonal::draw()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter gc(canvas);
+
+ draw(gc);
+ }
+}
+
+void KisToolSelectPolygonal::draw(KisCanvasPainter& gc)
+{
+ if (!m_subject)
+ return;
+
+ TQPen pen(TQt::white, 0, TQt::DotLine);
+
+ gc.setPen(pen);
+ gc.setRasterOp(TQt::XorROP);
+
+ KisCanvasController *controller = m_subject->canvasController();
+ KisPoint start, end;
+ TQPoint startPos;
+ TQPoint endPos;
+
+ if (m_dragging) {
+ startPos = controller->windowToView(m_dragStart.floorTQPoint());
+ endPos = controller->windowToView(m_dragEnd.floorTQPoint());
+ gc.drawLine(startPos, endPos);
+ } else {
+ for (KisPointVector::iterator it = m_points.begin(); it != m_points.end(); ++it) {
+
+ if (it == m_points.begin())
+ {
+ start = (*it);
+ } else {
+ end = (*it);
+
+ startPos = controller->windowToView(start.floorTQPoint());
+ endPos = controller->windowToView(end.floorTQPoint());
+
+ gc.drawLine(startPos, endPos);
+
+ start = end;
+ }
+ }
+ }
+}
+
+
+void KisToolSelectPolygonal::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Polygonal Selection"),
+ "tool_polygonal_selection" ,
+ 0,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ Q_CHECK_PTR(m_action);
+ m_action->setExclusiveGroup("tools");
+ m_action->setToolTip(i18n("Select a polygonal area"));
+ m_ownAction = true;
+ }
+}
+
+
+TQWidget* KisToolSelectPolygonal::createOptionWidget(TQWidget* tqparent)
+{
+ m_optWidget = new KisSelectionOptions(tqparent, m_subject);
+ Q_CHECK_PTR(m_optWidget);
+ m_optWidget->setCaption(i18n("Polygonal Selection"));
+
+ connect (m_optWidget, TQT_SIGNAL(actionChanged(int)), this, TQT_SLOT(slotSetAction(int)));
+
+ TQVBoxLayout * l = dynamic_cast<TQVBoxLayout*>(m_optWidget->tqlayout());
+ l->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding));
+
+ return m_optWidget;
+}
+
+TQWidget* KisToolSelectPolygonal::optionWidget()
+{
+ return m_optWidget;
+}
+
+void KisToolSelectPolygonal::slotSetAction(int action) {
+ if (action >= SELECTION_ADD && action <= SELECTION_SUBTRACT)
+ m_selectAction =(enumSelectionMode)action;
+}
+
+
+
+#include "kis_tool_select_polygonal.moc"
diff --git a/chalk/plugins/tools/selectiontools/kis_tool_select_polygonal.h b/chalk/plugins/tools/selectiontools/kis_tool_select_polygonal.h
new file mode 100644
index 00000000..65a32ee6
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/kis_tool_select_polygonal.h
@@ -0,0 +1,106 @@
+/*
+ * kis_tool_select_polygonal.h - part of Krayon^WChalk
+ *
+ * Copyright (c) 2000 John Califf <jcaliff@compuzone.net>
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 __selecttoolpolygonal_h__
+#define __selecttoolpolygonal_h__
+
+#include "kis_point.h"
+#include "kis_tool_non_paint.h"
+#include "kis_tool_factory.h"
+#include "kis_selection.h"
+
+class KisSelectionOptions;
+
+class KisToolSelectPolygonal : public KisToolNonPaint {
+
+ typedef KisToolNonPaint super;
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ KisToolSelectPolygonal();
+ virtual ~KisToolSelectPolygonal();
+
+ //
+ // KisCanvasObserver interface
+ //
+
+ virtual void update (KisCanvasSubject *subject);
+
+ //
+ // KisToolPaint interface
+ //
+
+ virtual void setup(KActionCollection *collection);
+ virtual TQ_UINT32 priority() { return 5; }
+ virtual enumToolType toolType() { return TOOL_SELECT; }
+ virtual void buttonPress(KisButtonPressEvent *event);
+ virtual void move(KisMoveEvent *event);
+ virtual void buttonRelease(KisButtonReleaseEvent *event);
+ virtual void doubleClick(KisDoubleClickEvent * event);
+
+ void finish();
+ TQWidget* createOptionWidget(TQWidget* tqparent);
+ virtual TQWidget* optionWidget();
+
+public slots:
+ virtual void slotSetAction(int);
+ virtual void activate();
+ void deactivate();
+
+protected:
+ virtual void paint(KisCanvasPainter& gc);
+ virtual void paint(KisCanvasPainter& gc, const TQRect& rc);
+ void draw(KisCanvasPainter& gc);
+ void draw();
+
+protected:
+ KisPoint m_dragStart;
+ KisPoint m_dragEnd;
+
+ bool m_dragging;
+private:
+ typedef TQValueVector<KisPoint> KisPointVector;
+ KisCanvasSubject *m_subject;
+ KisPointVector m_points;
+ KisSelectionOptions * m_optWidget;
+ enumSelectionMode m_selectAction;
+};
+
+
+class KisToolSelectPolygonalFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolSelectPolygonalFactory() : super() {};
+ virtual ~KisToolSelectPolygonalFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolSelectPolygonal();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("polygonalselect", i18n("Polygonal Select Tool")); }
+};
+
+
+#endif //__selecttoolpolygonal_h__
+
diff --git a/chalk/plugins/tools/selectiontools/kis_tool_select_rectangular.cc b/chalk/plugins/tools/selectiontools/kis_tool_select_rectangular.cc
new file mode 100644
index 00000000..aa7052af
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/kis_tool_select_rectangular.cc
@@ -0,0 +1,323 @@
+
+/*
+ * kis_tool_select_rectangular.cc -- part of Chalk
+ *
+ * Copyright (c) 1999 Michael Koch <koch@kde.org>
+ * 2001 John Califf <jcaliff@compuzone.net>
+ * 2002 Patrick Julien <freak@codepimps.org>
+ *
+ * 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 <tqapplication.h>
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqlayout.h>
+
+#include <kdebug.h>
+#include <kaction.h>
+#include <kcommand.h>
+#include <klocale.h>
+
+#include "kis_canvas_controller.h"
+#include "kis_canvas_subject.h"
+#include "kis_cursor.h"
+#include "kis_image.h"
+#include "kis_painter.h"
+#include "kis_layer.h"
+#include "kis_tool_select_rectangular.h"
+#include "kis_undo_adapter.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_move_event.h"
+#include "kis_selection.h"
+#include "kis_selection_options.h"
+#include <kis_selected_transaction.h>
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+
+KisToolSelectRectangular::KisToolSelectRectangular()
+ : super(i18n("Rectangular Select Tool"))
+{
+ setName("tool_select_rectangular");
+ setCursor(KisCursor::load("tool_rectangular_selection_cursor.png", 6, 6));
+ m_subject = 0;
+ m_selecting = false;
+ m_centerPos = KisPoint(0, 0);
+ m_startPos = KisPoint(0, 0);
+ m_endPos = KisPoint(0, 0);
+ m_optWidget = 0;
+ m_selectAction = SELECTION_ADD;
+}
+
+KisToolSelectRectangular::~KisToolSelectRectangular()
+{
+}
+
+void KisToolSelectRectangular::activate()
+{
+ super::activate();
+
+ if (!m_optWidget)
+ return;
+
+ m_optWidget->slotActivated();
+}
+
+void KisToolSelectRectangular::update(KisCanvasSubject *subject)
+{
+ m_subject = subject;
+ super::update(m_subject);
+}
+
+void KisToolSelectRectangular::paint(KisCanvasPainter& gc)
+{
+ if (m_selecting)
+ paintOutline(gc, TQRect());
+}
+
+void KisToolSelectRectangular::paint(KisCanvasPainter& gc, const TQRect& rc)
+{
+ if (m_selecting)
+ paintOutline(gc, rc);
+}
+
+void KisToolSelectRectangular::clearSelection()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisImageSP img = m_subject->currentImg();
+
+ Q_ASSERT(controller);
+
+ m_centerPos = KisPoint(0, 0);
+ m_startPos = KisPoint(0, 0);
+ m_endPos = KisPoint(0, 0);
+ m_selecting = false;
+ }
+}
+
+void KisToolSelectRectangular::buttonPress(KisButtonPressEvent *e)
+{
+ if (m_subject) {
+ KisImageSP img = m_subject->currentImg();
+
+ if (img && img->activeDevice() && e->button() == Qt::LeftButton) {
+ clearSelection();
+ m_startPos = m_endPos = m_centerPos = e->pos();
+ m_selecting = true;
+ }
+ }
+}
+
+void KisToolSelectRectangular::move(KisMoveEvent *e)
+{
+ if (m_subject && m_selecting) {
+ paintOutline();
+ // move (alt) or resize rectangle
+ if (e->state() & TQt::AltButton) {
+ KisPoint trans = e->pos() - m_endPos;
+ m_startPos += trans;
+ m_endPos += trans;
+ } else {
+ KisPoint diag = e->pos() - (e->state() & TQt::ControlButton
+ ? m_centerPos : m_startPos);
+ // square?
+ if (e->state() & TQt::ShiftButton) {
+ double size = TQMAX(fabs(diag.x()), fabs(diag.y()));
+ double w = diag.x() < 0 ? -size : size;
+ double h = diag.y() < 0 ? -size : size;
+ diag = KisPoint(w, h);
+ }
+
+ // resize around center point?
+ if (e->state() & TQt::ControlButton) {
+ m_startPos = m_centerPos - diag;
+ m_endPos = m_centerPos + diag;
+ } else {
+ m_endPos = m_startPos + diag;
+ }
+ }
+ paintOutline();
+ m_centerPos = KisPoint((m_startPos.x() + m_endPos.x()) / 2,
+ (m_startPos.y() + m_endPos.y()) / 2);
+ }
+}
+
+void KisToolSelectRectangular::buttonRelease(KisButtonReleaseEvent *e)
+{
+ if (m_subject && m_selecting && e->button() == Qt::LeftButton) {
+
+ paintOutline();
+
+ if (m_startPos == m_endPos) {
+ clearSelection();
+ } else {
+ KisImageSP img = m_subject->currentImg();
+
+ if (!img)
+ return;
+
+ if (m_endPos.y() < 0)
+ m_endPos.setY(0);
+
+ if (m_endPos.y() > img->height())
+ m_endPos.setY(img->height());
+
+ if (m_endPos.x() < 0)
+ m_endPos.setX(0);
+
+ if (m_endPos.x() > img->width())
+ m_endPos.setX(img->width());
+ if (img && img->activeDevice()) {
+
+ TQApplication::setOverrideCursor(KisCursor::waitCursor());
+ KisPaintDeviceSP dev = img->activeDevice();
+ bool hasSelection = dev->hasSelection();
+
+ KisSelectedTransaction *t = 0;
+ if (img->undo()) t = new KisSelectedTransaction(i18n("Rectangular Selection"), dev);
+ KisSelectionSP selection = dev->selection();
+ TQRect rc(m_startPos.floorTQPoint(), m_endPos.floorTQPoint());
+ rc = rc.normalize();
+
+ // We don't want the border of the 'rectangle' to be included in our selection
+ rc.setSize(rc.size() - TQSize(1,1));
+
+ if(! hasSelection)
+ {
+ selection->clear();
+ if(m_selectAction==SELECTION_SUBTRACT)
+ selection->invert();
+ }
+
+ KisSelectionSP tmpSel = new KisSelection(dev);
+ tmpSel->select(rc);
+ switch(m_selectAction)
+ {
+ case SELECTION_ADD:
+ dev->addSelection(tmpSel);
+ break;
+ case SELECTION_SUBTRACT:
+ dev->subtractSelection(tmpSel);
+ break;
+ default:
+ break;
+ }
+
+
+ if(hasSelection) {
+ dev->setDirty(rc);
+ dev->emitSelectionChanged(rc);
+ } else {
+ dev->setDirty();
+ dev->emitSelectionChanged();
+ }
+
+ if (img->undo())
+ img->undoAdapter()->addCommand(t);
+
+ KisCanvasController *controller = m_subject -> canvasController();
+ controller -> kiscanvas() -> update();
+
+ TQApplication::restoreOverrideCursor();
+ }
+ }
+
+ m_selecting = false;
+ }
+}
+
+void KisToolSelectRectangular::paintOutline()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter gc(canvas);
+ TQRect rc;
+
+ paintOutline(gc, rc);
+ }
+}
+
+void KisToolSelectRectangular::paintOutline(KisCanvasPainter& gc, const TQRect&)
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ RasterOp op = gc.rasterOp();
+ TQPen old = gc.pen();
+ TQPen pen(TQt::DotLine);
+ TQPoint start;
+ TQPoint end;
+
+ Q_ASSERT(controller);
+ start = controller->windowToView(m_startPos.floorTQPoint());
+ end = controller->windowToView(m_endPos.floorTQPoint());
+
+ gc.setRasterOp(TQt::NotROP);
+ gc.setPen(pen);
+ gc.drawRect(TQRect(start, end));
+ gc.setRasterOp(op);
+ gc.setPen(old);
+ }
+}
+
+void KisToolSelectRectangular::slotSetAction(int action) {
+ if (action >= SELECTION_ADD && action <= SELECTION_SUBTRACT)
+ m_selectAction =(enumSelectionMode)action;
+}
+
+void KisToolSelectRectangular::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Rectangular Selection"),
+ "tool_rect_selection",
+ TQt::Key_R,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ Q_CHECK_PTR(m_action);
+ m_action->setExclusiveGroup("tools");
+ m_action->setToolTip(i18n("Select a rectangular area"));
+ m_ownAction = true;
+ }
+}
+
+TQWidget* KisToolSelectRectangular::createOptionWidget(TQWidget* tqparent)
+{
+ m_optWidget = new KisSelectionOptions(tqparent, m_subject);
+ Q_CHECK_PTR(m_optWidget);
+ m_optWidget->setCaption(i18n("Rectangular Selection"));
+
+ connect (m_optWidget, TQT_SIGNAL(actionChanged(int)), this, TQT_SLOT(slotSetAction(int)));
+
+ TQVBoxLayout * l = dynamic_cast<TQVBoxLayout*>(m_optWidget->tqlayout());
+ l->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding));
+
+ return m_optWidget;
+}
+
+TQWidget* KisToolSelectRectangular::optionWidget()
+{
+ return m_optWidget;
+}
+
+
+
+
+#include "kis_tool_select_rectangular.moc"
diff --git a/chalk/plugins/tools/selectiontools/kis_tool_select_rectangular.h b/chalk/plugins/tools/selectiontools/kis_tool_select_rectangular.h
new file mode 100644
index 00000000..eb286cca
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/kis_tool_select_rectangular.h
@@ -0,0 +1,95 @@
+/*
+ * kis_tool_select_rectangular.h - part of Chalk
+ *
+ * Copyright (c) 1999 Michael Koch <koch@kde.org>
+ * 2002 Patrick Julien <freak@codepimps.org>
+ *
+ * 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_TOOL_SELECT_RECTANGULAR_H_
+#define KIS_TOOL_SELECT_RECTANGULAR_H_
+
+#include "kis_point.h"
+#include "kis_tool_non_paint.h"
+#include "kis_selection.h"
+#include "kis_tool_factory.h"
+
+class KisSelectionOptions;
+
+class KisToolSelectRectangular : public KisToolNonPaint {
+
+ typedef KisToolNonPaint super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolSelectRectangular();
+ virtual ~KisToolSelectRectangular();
+
+ virtual void update(KisCanvasSubject *subject);
+
+ virtual void setup(KActionCollection *collection);
+ virtual TQ_UINT32 priority() { return 3; }
+ virtual enumToolType toolType() { return TOOL_SELECT; }
+ virtual TQWidget * createOptionWidget(TQWidget* tqparent);
+ virtual TQWidget* optionWidget();
+
+ virtual void paint(KisCanvasPainter& gc);
+ virtual void paint(KisCanvasPainter& gc, const TQRect& rc);
+ virtual void buttonPress(KisButtonPressEvent *e);
+ virtual void move(KisMoveEvent *e);
+ virtual void buttonRelease(KisButtonReleaseEvent *e);
+
+public slots:
+ virtual void slotSetAction(int);
+ virtual void activate();
+
+
+private:
+ void clearSelection();
+ void paintOutline();
+ void paintOutline(KisCanvasPainter& gc, const TQRect& rc);
+
+private:
+ KisCanvasSubject *m_subject;
+ KisPoint m_centerPos;
+ KisPoint m_startPos;
+ KisPoint m_endPos;
+ bool m_selecting;
+ KisSelectionOptions * m_optWidget;
+ enumSelectionMode m_selectAction;
+
+};
+
+class KisToolSelectRectangularFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolSelectRectangularFactory() : super() {};
+ virtual ~KisToolSelectRectangularFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolSelectRectangular();
+ t->setup(ac);
+ Q_CHECK_PTR(t);
+ return t;
+ }
+ virtual KisID id() { return KisID("rectangularselect", i18n("Rectangular Select Tool")); }
+};
+
+
+
+#endif // KIS_TOOL_SELECT_RECTANGULAR_H_
+
diff --git a/chalk/plugins/tools/selectiontools/selection_tools.cc b/chalk/plugins/tools/selectiontools/selection_tools.cc
new file mode 100644
index 00000000..db4df1ab
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/selection_tools.cc
@@ -0,0 +1,77 @@
+/*
+ * selection_tools.cc -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_tool.h>
+#include <kis_tool_registry.h>
+
+#include "selection_tools.h"
+
+#include "kis_tool_select_outline.h"
+#include "kis_tool_select_polygonal.h"
+#include "kis_tool_select_rectangular.h"
+#include "kis_tool_select_contiguous.h"
+#include "kis_tool_select_elliptical.h"
+#include "kis_tool_select_eraser.h"
+#include "kis_tool_select_brush.h"
+#include "kis_tool_move_selection.h"
+
+typedef KGenericFactory<SelectionTools> SelectionToolsFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkselectiontools, SelectionToolsFactory( "chalk" ) )
+
+
+SelectionTools::SelectionTools(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(SelectionToolsFactory::instance());
+
+ if ( tqparent->inherits("KisToolRegistry") )
+ {
+ KisToolRegistry * r = dynamic_cast<KisToolRegistry*>(tqparent);
+ r->add(new KisToolSelectOutlineFactory());
+ r->add(new KisToolSelectPolygonalFactory());
+ r->add(new KisToolSelectRectangularFactory());
+ r->add(new KisToolSelectBrushFactory());
+ r->add(new KisToolSelectContiguousFactory());
+ r->add(new KisToolSelectEllipticalFactory());
+ r->add(new KisToolSelectEraserFactory());
+ r->add(new KisToolMoveSelectionFactory());
+ }
+}
+
+SelectionTools::~SelectionTools()
+{
+}
+
+#include "selection_tools.moc"
diff --git a/chalk/plugins/tools/selectiontools/selection_tools.h b/chalk/plugins/tools/selectiontools/selection_tools.h
new file mode 100644
index 00000000..2e448e3e
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/selection_tools.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2003 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 SELECTION_TOOLS_H_
+#define SELECTION_TOOLS_H_
+
+#include <kparts/plugin.h>
+
+/**
+ * A module wrapper around Chalk's selection tools.
+ * Despite the fact that new tools are created for every new view,
+ * it is not possible to make tools standard parts of the type of the
+ * imagesize plugin, because we need to create a new set of tools for every
+ * pointer device (mouse, stylus, eraser, puck, etc.). So this plugin is
+ * a module which is loaded once into Chalk. For every tool there is a factory
+ * class that is registered with the tool registry, and that is used to create
+ * new instances of the tools.
+ */
+class SelectionTools : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ SelectionTools(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~SelectionTools();
+
+};
+
+#endif // SELECTION_TOOLS_H_
diff --git a/chalk/plugins/tools/selectiontools/tool_brush_selection.png b/chalk/plugins/tools/selectiontools/tool_brush_selection.png
new file mode 100644
index 00000000..3d1bba3f
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_brush_selection.png
Binary files differ
diff --git a/chalk/plugins/tools/selectiontools/tool_brush_selection.svg b/chalk/plugins/tools/selectiontools/tool_brush_selection.svg
new file mode 100644
index 00000000..228a411f
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_brush_selection.svg
@@ -0,0 +1,827 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:export-ydpi="33.000000"
+ inkscape:export-xdpi="33.000000"
+ inkscape:export-filename="/home/danny/tool_brush_selection.png"
+ sodipodi:docname="tool_brush_selection.svg"
+ sodipodi:docbase="/home/danny/work/kde/koffice/chalk/chalk"
+ inkscape:version="0.41"
+ sodipodi:version="0.32"
+ id="svg4694"
+ height="48.000000pt"
+ width="48.000000pt">
+ <defs
+ id="defs3">
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7969"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.592685,0.379735,0.000000,-30.45690,-1.224420)"
+ cx="-23.859682"
+ cy="95.221397"
+ fx="-23.859682"
+ fy="95.221397"
+ r="8.5514765" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7967"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.503650,0.399417,0.000000,-30.45690,-1.829360)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7965"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.592685,0.379735,0.000000,-30.45690,-21.22442)"
+ cx="-23.859682"
+ cy="95.221397"
+ fx="-23.859682"
+ fy="95.221397"
+ r="8.5514765" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7963"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.503650,0.399417,0.000000,-30.45690,-21.82936)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7961"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.592685,0.379735,0.000000,26.44710,-11.22442)"
+ cx="-23.859682"
+ cy="95.221397"
+ fx="-23.859682"
+ fy="95.221397"
+ r="8.5514765" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7959"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.503650,0.399417,0.000000,26.44710,-11.82936)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7957"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.633416,0.000000,0.000000,0.379735,-44.86332,44.21180)"
+ cx="25.952410"
+ cy="52.497688"
+ fx="25.923746"
+ fy="51.904903"
+ r="14.270030" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7955"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.503650,0.000000,0.000000,0.399417,-44.86332,44.21180)"
+ x1="22.425571"
+ y1="35.206337"
+ x2="22.396454"
+ y2="41.545322" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7953"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.633416,0.000000,0.000000,0.379735,-22.86332,44.21180)"
+ cx="25.952410"
+ cy="52.497688"
+ fx="25.923746"
+ fy="51.904903"
+ r="14.270030" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7951"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.503650,0.000000,0.000000,0.399417,-22.86332,44.21180)"
+ x1="22.425571"
+ y1="35.206337"
+ x2="22.396454"
+ y2="41.545322" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7949"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.633416,0.000000,0.000000,0.379735,-38.65916,-12.48664)"
+ cx="25.952410"
+ cy="52.497688"
+ fx="25.923746"
+ fy="51.904903"
+ r="14.270030" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7947"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.503650,0.000000,0.000000,0.399417,-38.65916,-12.48664)"
+ x1="22.425571"
+ y1="35.206337"
+ x2="22.396454"
+ y2="41.545322" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7945"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.503650,0.399417,0.000000,26.44710,4.170640)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7943"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.878497,0.000000,0.000000,1.138308,-18.65916,-0.486640)"
+ cx="92.643608"
+ cy="55.457653"
+ fx="92.643608"
+ fy="55.457653"
+ r="9.9914455" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7941"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.592685,0.379735,0.000000,26.44710,-31.22442)"
+ cx="-23.859682"
+ cy="95.221397"
+ fx="-23.859682"
+ fy="95.221397"
+ r="8.5514765" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7939"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.503650,0.399417,0.000000,26.44710,-31.82936)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7937"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.633416,0.000000,0.000000,0.379735,-16.65916,-12.48664)"
+ cx="25.952410"
+ cy="52.497688"
+ fx="25.923746"
+ fy="51.904903"
+ r="14.270030" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7935"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.503650,0.000000,0.000000,0.399417,-16.65916,-12.48664)"
+ x1="22.425571"
+ y1="35.206337"
+ x2="22.396454"
+ y2="41.545322" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7933"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.665867,1.501801)"
+ cx="8.0907059"
+ cy="9.5002232"
+ fx="8.0907059"
+ fy="9.5002232"
+ r="5.8189325" />
+ <linearGradient
+ id="light90to0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.90833336;"
+ offset="0.0000000"
+ id="stop1890" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="1.0000000"
+ id="stop1892" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7931"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.791643,0.000000,0.000000,1.263196,-1.626700,-5.630763)"
+ x1="4.4536543"
+ y1="6.5494914"
+ x2="14.101834"
+ y2="13.431447" />
+ <linearGradient
+ id="garylighttowite">
+ <stop
+ id="stop5106"
+ offset="0.0000000"
+ style="stop-color:#4f4f4f;stop-opacity:1.0000000;" />
+ <stop
+ id="stop5107"
+ offset="1.0000000"
+ style="stop-color:#7e7f7f;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ y2="213.83318"
+ x2="197.10010"
+ y1="237.55226"
+ x1="169.41396"
+ gradientTransform="matrix(0.981884,0.000000,0.000000,1.249452,-125.2257,-270.2224)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4240"
+ xlink:href="#garylighttowite"
+ inkscape:collect="always" />
+ <linearGradient
+ id="blacktowhite">
+ <stop
+ id="stop2476"
+ offset="0.0000000"
+ style="stop-color:#000000;stop-opacity:1.0000000;" />
+ <stop
+ id="stop2475"
+ offset="1.0000000"
+ style="stop-color:#e6e6e6;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ y2="305.51498"
+ x2="-126.66700"
+ y1="316.87579"
+ x1="-134.10509"
+ gradientTransform="matrix(0.409156,-1.467734,0.742641,0.334392,-125.2257,-270.2224)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4238"
+ xlink:href="#blacktowhite"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient940">
+ <stop
+ style="stop-color:#7d5700;stop-opacity:1;"
+ offset="0.00000000"
+ id="stop941" />
+ <stop
+ style="stop-color:#c58500;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop942" />
+ </linearGradient>
+ <linearGradient
+ y2="327.82533"
+ x2="477.19157"
+ y1="252.79109"
+ x1="405.98953"
+ gradientTransform="matrix(9.300968e-2,-0.317362,0.155311,2.621206e-2,-185.0894,-152.1973)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4235"
+ xlink:href="#linearGradient940"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient944">
+ <stop
+ style="stop-color:#c34700;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop945" />
+ <stop
+ style="stop-color:#ddc800;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop946" />
+ </linearGradient>
+ <linearGradient
+ y2="333.50655"
+ x2="492.61439"
+ y1="270.32615"
+ x1="410.61638"
+ gradientTransform="matrix(9.300968e-2,-0.317362,0.155311,2.621206e-2,-185.0894,-152.1973)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient4233"
+ xlink:href="#linearGradient944"
+ inkscape:collect="always" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient1439"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.142981,0.309244,0.000000,-25.19724,11.47156)"
+ cx="-23.859682"
+ cy="95.221397"
+ fx="-23.859682"
+ fy="95.221397"
+ r="8.5514765" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient1442"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.069389,0.325272,0.000000,-25.19724,10.97154)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient1446"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.142981,0.309244,0.000000,-25.19724,-5.806103)"
+ cx="-23.859682"
+ cy="95.221397"
+ fx="-23.859682"
+ fy="95.221397"
+ r="8.5514765" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient1449"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.069389,0.325272,0.000000,-25.19724,-6.306116)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient1453"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.142981,0.309244,0.000000,21.05881,1.966237)"
+ cx="-23.859682"
+ cy="95.221397"
+ fx="-23.859682"
+ fy="95.221397"
+ r="8.5514765" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient1456"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.069389,0.325272,0.000000,21.05881,1.466224)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient1460"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.144567,0.000000,0.000000,0.313870,-38.39521,48.31870)"
+ cx="25.952410"
+ cy="52.497688"
+ fx="25.923746"
+ fy="51.904903"
+ r="14.270030" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient1463"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.038890,0.000000,0.000000,0.330138,-38.39521,48.31870)"
+ x1="22.425571"
+ y1="35.206337"
+ x2="22.396454"
+ y2="41.545322" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient1467"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.144567,0.000000,0.000000,0.313870,-19.66477,48.31870)"
+ cx="25.952410"
+ cy="52.497688"
+ fx="25.923746"
+ fy="51.904903"
+ r="14.270030" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient1470"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.038890,0.000000,0.000000,0.330138,-19.66477,48.31870)"
+ x1="22.425571"
+ y1="35.206337"
+ x2="22.396454"
+ y2="41.545322" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient1474"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.144567,0.000000,0.000000,0.313870,-30.98448,1.415420)"
+ cx="25.952410"
+ cy="52.497688"
+ fx="25.923746"
+ fy="51.904903"
+ r="14.270030" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient1477"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.038890,0.000000,0.000000,0.330138,-30.98448,1.415420)"
+ x1="22.425571"
+ y1="35.206337"
+ x2="22.396454"
+ y2="41.545322" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient1481"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.069389,0.325272,0.000000,21.14350,15.18416)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient1484"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.715419,0.000000,0.000000,0.940867,-15.58955,11.33469)"
+ cx="92.643608"
+ cy="55.457653"
+ fx="92.643608"
+ fy="55.457653"
+ r="9.9914455" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient1495"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.144567,0.000000,0.000000,0.313870,-12.33208,1.415420)"
+ cx="25.952410"
+ cy="52.497688"
+ fx="25.923746"
+ fy="51.904903"
+ r="14.270030" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient1498"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.038890,0.000000,0.000000,0.330138,-12.33208,1.415420)"
+ x1="22.425571"
+ y1="35.206337"
+ x2="22.396454"
+ y2="41.545322" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient1502"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.542260,0.000000,0.000000,1.241312,-0.394144,11.73692)"
+ cx="8.0907059"
+ cy="9.5002232"
+ fx="8.0907059"
+ fy="9.5002232"
+ r="5.8189325" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient1505"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.644688,0.000000,0.000000,1.044093,-1.718875,7.082818)"
+ x1="4.4536543"
+ y1="6.5494914"
+ x2="14.101834"
+ y2="13.431447" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#blacktowhite"
+ id="linearGradient1427"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.409156,-1.467734,0.742641,0.334392,-125.2257,-270.2224)"
+ x1="-134.10509"
+ y1="316.87579"
+ x2="-126.66700"
+ y2="305.51498" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#garylighttowite"
+ id="linearGradient1429"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.981884,0.000000,0.000000,1.249452,-125.2257,-270.2224)"
+ x1="169.41396"
+ y1="237.55226"
+ x2="197.10010"
+ y2="213.83318" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient944"
+ id="linearGradient1431"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(9.300968e-2,-0.317362,0.155311,2.621206e-2,-185.0894,-152.1973)"
+ x1="410.61638"
+ y1="270.32615"
+ x2="492.61439"
+ y2="333.50655" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient940"
+ id="linearGradient1433"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(9.300968e-2,-0.317362,0.155311,2.621206e-2,-185.0894,-152.1973)"
+ x1="405.98953"
+ y1="252.79109"
+ x2="477.19157"
+ y2="327.82533" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient1508"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.926025,0.000000,0.000000,0.943879,-3.764700,12.09394)"
+ cx="48.488476"
+ cy="46.914463"
+ fx="48.488476"
+ fy="46.914463"
+ r="31.677956" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient1511"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.937632,0.000000,0.000000,0.932194,-3.191675,13.02262)"
+ x1="10.878086"
+ y1="4.5492039"
+ x2="39.857029"
+ y2="36.873619" />
+ <linearGradient
+ y2="333.50655"
+ x2="492.61439"
+ y1="270.32615"
+ x1="410.61638"
+ gradientTransform="matrix(8.609199e-2,-0.291516,0.143760,2.407732e-2,-172.7295,-138.4789)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1421"
+ xlink:href="#linearGradient944"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="327.82533"
+ x2="477.19157"
+ y1="252.79109"
+ x1="405.98953"
+ gradientTransform="matrix(8.609199e-2,-0.291516,0.143760,2.407732e-2,-172.7295,-138.4789)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1423"
+ xlink:href="#linearGradient940"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="305.51498"
+ x2="-126.66700"
+ y1="316.87579"
+ x1="-134.10509"
+ gradientTransform="matrix(0.378725,-1.348200,0.687406,0.307159,-117.3182,-246.8919)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1425"
+ xlink:href="#blacktowhite"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="213.83318"
+ x2="197.10010"
+ y1="237.55226"
+ x1="169.41396"
+ gradientTransform="matrix(0.908855,0.000000,0.000000,1.147695,-117.3182,-246.8919)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1428"
+ xlink:href="#garylighttowite"
+ inkscape:collect="always" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-y="0"
+ inkscape:window-x="0"
+ inkscape:window-height="691"
+ inkscape:window-width="1020"
+ inkscape:grid-bbox="true"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:current-layer="layer1"
+ inkscape:cy="57.678721"
+ inkscape:cx="57.219249"
+ inkscape:zoom="8.5396765"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF
+ id="RDF5">
+ <cc:Work
+ id="Work6"
+ rdf:about="">
+ <dc:format
+ id="format7">image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+ id="type9" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1"
+ id="layer1">
+ <g
+ id="g3808">
+ <path
+ style="opacity:0.79446638;fill:#0028c6;fill-opacity:0.18099548;stroke:#000000;stroke-width:0.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.035294119"
+ d="M 6.2934619,13.951302 L 42.647661,13.951302 C 44.570005,13.951302 46.117596,15.941616 46.117596,18.413889 L 46.117596,53.617448 C 46.117596,56.089722 44.570005,58.080035 42.647661,58.080035 L 6.2934619,58.080035 C 4.3711186,58.080035 2.8235279,56.089722 2.8235279,53.617448 L 2.8235279,18.413889 C 2.8235279,15.941616 4.3711186,13.951302 6.2934619,13.951302 z "
+ id="rect7971" />
+ <path
+ style="opacity:0.79446638;fill:url(#linearGradient1511);fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.035294119"
+ d="M 6.8664881,14.879987 L 43.220688,14.879987 C 44.781208,38.443460 21.125930,25.243420 3.3965541,54.546133 L 3.3965541,19.342574 C 3.3965541,16.870301 4.9441448,14.879987 6.8664881,14.879987 z "
+ id="path8746"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="stroke-opacity:1.0000000;stroke-miterlimit:4.0000000;stroke-linejoin:round;stroke-linecap:round;stroke-width:4.3000002;stroke:none;fill-rule:evenodd;fill-opacity:1.0000000;fill:#353640"
+ d="M 16.843790,11.999986 C 15.654649,11.999986 14.690659,12.962574 14.690659,14.149986 C 14.690659,15.337398 15.654649,16.299986 16.843790,16.299986 L 24.687528,16.299986 C 25.876670,16.299986 26.840659,15.337398 26.840659,14.149986 C 26.840659,12.962574 25.876670,11.999986 24.687528,11.999986 L 16.843790,11.999986 z "
+ id="path3802"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="opacity:0.97233200;fill:url(#radialGradient1508);fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.035294119"
+ d="M 6.2934619,13.951302 L 42.647661,13.951302 C 44.570005,13.951302 46.117596,15.941616 46.117596,18.413889 L 46.117596,53.617448 C 46.117596,56.089722 44.570005,58.080035 42.647661,58.080035 L 6.2934619,58.080035 C 4.3711186,58.080035 2.8235279,56.089722 2.8235279,53.617448 L 2.8235279,18.413889 C 2.8235279,15.941616 4.3711186,13.951302 6.2934619,13.951302 z "
+ id="path9514" />
+ <path
+ style="fill:#353640;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 2.2036028,12.000753 C 1.6228812,11.985222 1.0606757,12.206108 0.64540735,12.612953 C 0.23013967,13.019798 -0.0027184452,13.577851 2.3951728e-05,14.159639 L 2.3951728e-05,20.996110 C 2.3951728e-05,22.188431 0.96515240,23.154996 2.1556989,23.154996 C 3.3462453,23.154996 4.3113738,22.188431 4.3113738,20.996110 L 4.3113738,16.342512 L 5.9401060,16.366499 C 6.7276964,16.418884 7.4804421,16.034101 7.9001215,15.364596 C 8.3198002,14.695092 8.3386812,13.848916 7.9492832,13.161304 C 7.5598858,12.473693 6.8250547,12.055619 6.0359137,12.072716 L 2.2036028,12.000753 z "
+ id="path7697" />
+ <path
+ style="fill:#353640;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 45.820092,16.892010 C 45.247569,16.895838 44.700302,17.128591 44.299981,17.538518 C 43.899660,17.948446 43.679468,18.501564 43.688369,19.074883 L 43.688369,28.214166 C 43.688369,29.406486 44.653498,30.373052 45.844045,30.373052 C 47.034590,30.373052 47.999719,29.406486 47.999719,28.214166 L 47.999719,19.074883 C 48.008808,18.493207 47.782088,17.932680 47.371342,17.521322 C 46.960596,17.109964 46.400904,16.882908 45.820092,16.892010 L 45.820092,16.892010 z "
+ id="path1937"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#353640;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 44.073235,28.743247 C 44.961756,28.915834 45.380256,26.067378 45.314366,21.725701 C 45.260374,18.227435 46.727595,19.638901 46.838213,17.743808 C 46.855261,17.451725 46.461887,17.299850 45.986113,17.314502 C 45.510339,17.329154 44.952165,17.510332 44.639613,17.884350 C 44.461008,18.031995 44.322268,18.243187 44.228120,18.490651 C 44.133973,18.738115 44.084419,19.021851 44.084191,19.314591 C 44.083962,19.607329 44.075061,26.404202 44.073235,28.743247 z "
+ id="path4304"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="opacity:0.79446638;fill:#353640;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 45.099708,27.978601 C 45.091646,28.876769 45.673295,29.612967 46.398859,29.622947 C 47.124423,29.632927 47.719145,28.912907 47.727206,28.014740 L 47.800192,18.997225 C 47.828734,18.401217 47.590002,17.834123 47.179013,17.521651 C 46.768024,17.209181 46.251475,17.202036 45.834946,17.503063 C 45.418421,17.804089 45.169513,18.364437 45.187290,18.961084 L 45.099708,27.978601 z "
+ id="path4306"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:#353640;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 45.820092,48.749786 C 45.247569,48.753613 44.700302,48.986367 44.299981,49.396295 C 43.899660,49.806222 43.679468,50.359340 43.688369,50.932659 L 43.688369,55.682207 L 42.011733,55.682207 C 40.821187,55.682207 39.856059,56.648773 39.856059,57.841093 C 39.856059,59.033414 40.821187,59.999979 42.011733,59.999979 L 45.844045,59.999979 C 46.416528,60.002488 46.966289,59.775839 47.371101,59.370424 C 47.775912,58.965009 48.002223,58.414430 47.999719,57.841093 L 47.999719,50.932659 C 48.008808,50.350983 47.782088,49.790456 47.371342,49.379097 C 46.960596,48.967740 46.400904,48.740683 45.820092,48.749786 z "
+ id="path7691" />
+ <path
+ style="fill:#353640;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 45.740380,33.011663 C 45.167856,33.015085 44.620590,33.223093 44.220268,33.589441 C 43.819947,33.955789 43.599756,34.450105 43.608656,34.962473 L 43.608656,43.130152 C 43.608656,44.195717 44.573785,45.059526 45.764331,45.059526 C 46.954877,45.059526 47.920006,44.195717 47.920006,43.130152 L 47.920006,34.962473 C 47.929095,34.442636 47.702375,33.941699 47.291630,33.574073 C 46.880884,33.206447 46.321191,33.003529 45.740380,33.011663 L 45.740380,33.011663 z "
+ id="path7765"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#353640;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 2.2053264,25.793584 C 1.6328028,25.796681 1.0855366,25.985006 0.68521492,26.316687 C 0.28489404,26.648367 0.064703248,27.095906 0.073603407,27.559789 L 0.073603407,34.954562 C 0.073603407,35.919291 1.0387318,36.701359 2.2292783,36.701359 C 3.4198248,36.701359 4.3849533,35.919291 4.3849533,34.954562 L 4.3849533,27.559789 C 4.3940420,27.089143 4.1673224,26.635610 3.7565769,26.302773 C 3.3458306,25.969936 2.7861376,25.786219 2.2053264,25.793584 L 2.2053264,25.793584 z "
+ id="path7775"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#353640;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 2.2053264,41.839095 C 1.6328028,41.842251 1.0855366,42.034192 0.68521492,42.372239 C 0.28489404,42.710286 0.064703248,43.166416 0.073603407,43.639205 L 0.073603407,51.175929 C 0.073603407,52.159177 1.0387318,52.956257 2.2292783,52.956257 C 3.4198248,52.956257 4.3849533,52.159177 4.3849533,51.175929 L 4.3849533,43.639205 C 4.3940420,43.159524 4.1673224,42.697285 3.7565769,42.358057 C 3.3458306,42.018832 2.7861376,41.831589 2.2053264,41.839095 L 2.2053264,41.839095 z "
+ id="path7781"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="stroke-opacity:1.0000000;stroke-miterlimit:4.0000000;stroke-linejoin:round;stroke-linecap:round;stroke-width:4.3000002;stroke:none;fill-rule:evenodd;fill-opacity:1.0000000;fill:#353640"
+ d="M 34.726123,11.999986 C 33.536982,11.999986 32.572992,12.962574 32.572992,14.149986 C 32.572992,15.337398 33.536982,16.299986 34.726123,16.299986 L 42.569861,16.299986 C 43.759003,16.299986 44.722992,15.337398 44.722992,14.149986 C 44.722992,12.962574 43.759003,11.999986 42.569861,11.999986 L 34.726123,11.999986 z "
+ id="path3804"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:#353640;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:4.3000002;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 7.5173157,55.699996 C 6.3281746,55.699996 5.3641852,56.662584 5.3641852,57.849996 C 5.3641852,59.037408 6.3281746,59.999996 7.5173157,59.999996 L 15.361054,59.999996 C 16.550196,59.999996 17.514185,59.037408 17.514185,57.849996 C 17.514185,56.662584 16.550196,55.699996 15.361054,55.699996 L 7.5173157,55.699996 z "
+ id="path1514"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="stroke-opacity:1.0000000;stroke-miterlimit:4.0000000;stroke-linejoin:round;stroke-linecap:round;stroke-width:4.3000002;stroke:none;fill-rule:evenodd;fill-opacity:1.0000000;fill:#353640"
+ d="M 24.984459,55.699996 C 23.795318,55.699996 22.831328,56.662584 22.831328,57.849996 C 22.831328,59.037408 23.795318,59.999996 24.984459,59.999996 L 32.828197,59.999996 C 34.017339,59.999996 34.981328,59.037408 34.981328,57.849996 C 34.981328,56.662584 34.017339,55.699996 32.828197,55.699996 L 24.984459,55.699996 z "
+ id="path3041"
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ <g
+ transform="matrix(1.134471,0.000000,0.000000,1.134471,-1.979056,-8.899644)"
+ id="g1392">
+ <g
+ id="g3005"
+ transform="matrix(0.966181,0.000000,0.000000,1.079600,-428.2439,-311.2579)">
+ <path
+ style="font-size:12.000000;fill:none;fill-opacity:0.29729697;fill-rule:evenodd;stroke:#000000;stroke-width:0.95595007pt;stroke-linejoin:round;stroke-opacity:0.095022626"
+ d="M 491.67350,290.74524 C 489.56264,292.14465 474.46858,315.88005 473.92350,319.90149 C 474.08915,319.99277 474.24280,320.54490 474.07975,320.46399 C 467.56083,324.58038 466.36005,333.74960 462.39225,337.49524 C 469.66515,335.09880 476.01586,329.63350 478.61100,323.08899 C 478.29575,322.85634 478.53111,322.59638 479.20475,323.15149 C 481.95923,320.93848 496.34001,306.25465 502.61100,296.27649 C 500.08842,293.80733 494.89908,293.21951 491.67350,290.74524 z "
+ id="path2954"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="font-size:12.000000;fill:none;fill-opacity:0.29729697;fill-rule:evenodd;stroke:#000000;stroke-width:1.7924063;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:0.027149322"
+ d="M 491.67350,290.74524 C 489.56264,292.14465 474.46858,315.88005 473.92350,319.90149 C 474.08915,319.99277 474.24280,320.54490 474.07975,320.46399 C 467.56083,324.58038 466.36005,333.74960 462.39225,337.49524 C 469.66515,335.09880 476.01586,329.63350 478.61100,323.08899 C 478.29575,322.85634 478.53111,322.59638 479.20475,323.15149 C 481.95923,320.93848 496.34001,306.25465 502.61100,296.27649 C 500.08842,293.80733 494.89908,293.21951 491.67350,290.74524 z "
+ id="path2993"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="font-size:12.000000;fill:none;fill-opacity:0.29729697;fill-rule:evenodd;stroke:#000000;stroke-width:2.2703812;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:0.027149322"
+ d="M 491.67350,290.74524 C 489.56264,292.14465 474.46858,315.88005 473.92350,319.90149 C 474.08915,319.99277 474.24280,320.54490 474.07975,320.46399 C 467.56083,324.58038 466.36005,333.74960 462.39225,337.49524 C 469.66515,335.09880 476.01586,329.63350 478.61100,323.08899 C 478.29575,322.85634 478.53111,322.59638 479.20475,323.15149 C 481.95923,320.93848 496.34001,306.25465 502.61100,296.27649 C 500.08842,293.80733 494.89908,293.21951 491.67350,290.74524 z "
+ id="path2995"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="font-size:12.000000;fill:none;fill-opacity:0.29729697;fill-rule:evenodd;stroke:#000000;stroke-width:2.7483566;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:0.027149322"
+ d="M 491.67350,290.74524 C 489.56264,292.14465 474.46858,315.88005 473.92350,319.90149 C 474.08915,319.99277 474.24280,320.54490 474.07975,320.46399 C 467.56083,324.58038 466.36005,333.74960 462.39225,337.49524 C 469.66515,335.09880 476.01586,329.63350 478.61100,323.08899 C 478.29575,322.85634 478.53111,322.59638 479.20475,323.15149 C 481.95923,320.93848 496.34001,306.25465 502.61100,296.27649 C 500.08842,293.80733 494.89908,293.21951 491.67350,290.74524 z "
+ id="path2997"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="font-size:12.000000;fill:none;fill-opacity:0.29729697;fill-rule:evenodd;stroke:#000000;stroke-width:3.4653189;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:0.027149322"
+ d="M 491.67350,290.74524 C 489.56264,292.14465 474.46858,315.88005 473.92350,319.90149 C 474.08915,319.99277 474.24280,320.54490 474.07975,320.46399 C 467.56083,324.58038 466.36005,333.74960 462.39225,337.49524 C 469.66515,335.09880 476.01586,329.63350 478.61100,323.08899 C 478.29575,322.85634 478.53111,322.59638 479.20475,323.15149 C 481.95923,320.93848 496.34001,306.25465 502.61100,296.27649 C 500.08842,293.80733 494.89908,293.21951 491.67350,290.74524 z "
+ id="path2999"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="font-size:12.000000;fill:none;fill-opacity:0.29729697;fill-rule:evenodd;stroke:#000000;stroke-width:4.5407624;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:0.027149322"
+ d="M 491.67350,290.74524 C 489.56264,292.14465 474.46858,315.88005 473.92350,319.90149 C 474.08915,319.99277 474.24280,320.54490 474.07975,320.46399 C 467.56083,324.58038 466.36005,333.74960 462.39225,337.49524 C 469.66515,335.09880 476.01586,329.63350 478.61100,323.08899 C 478.29575,322.85634 478.53111,322.59638 479.20475,323.15149 C 481.95923,320.93848 496.34001,306.25465 502.61100,296.27649 C 500.08842,293.80733 494.89908,293.21951 491.67350,290.74524 z "
+ id="path3001"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="font-size:12.000000;fill:none;fill-opacity:0.29729697;fill-rule:evenodd;stroke:#000000;stroke-width:4.5407624;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:0.027149322"
+ d="M 491.67350,290.74524 C 489.56264,292.14465 474.46858,315.88005 473.92350,319.90149 C 474.08915,319.99277 474.24280,320.54490 474.07975,320.46399 C 467.56083,324.58038 466.36005,333.74960 462.39225,337.49524 C 469.66515,335.09880 476.01586,329.63350 478.61100,323.08899 C 478.29575,322.85634 478.53111,322.59638 479.20475,323.15149 C 481.95923,320.93848 496.34001,306.25465 502.61100,296.27649 C 500.08842,293.80733 494.89908,293.21951 491.67350,290.74524 z "
+ id="path3003"
+ sodipodi:nodetypes="cccccccc" />
+ </g>
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path938"
+ d="M 30.205102,34.228614 C 23.906643,38.672669 22.743245,48.555533 18.909630,52.599327 C 25.936571,50.012119 32.081349,44.132293 34.588724,37.066839 C 33.364061,36.056960 31.643233,35.026039 30.205102,34.228614 z "
+ style="font-size:12.000000;fill:url(#linearGradient1421);fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient1423);stroke-width:0.78106284;stroke-linejoin:round;stroke-miterlimit:4.0000000" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path12835"
+ d="M 30.617265,35.339501 C 27.907735,37.564006 24.907867,42.276687 23.152123,48.230671 C 27.752064,46.074807 31.876663,41.684797 33.559712,37.157947 C 32.737666,36.510921 31.582586,35.850411 30.617265,35.339501 z "
+ style="font-size:12.000000;fill:#e1e1e1;fill-opacity:0.31372550;fill-rule:evenodd;stroke:none;stroke-width:0.77429527;stroke-linejoin:round;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path12853"
+ d="M 31.194413,35.339501 C 29.016341,37.170395 26.604888,41.049182 25.193520,45.949638 C 28.891201,44.175240 32.206788,40.562023 33.559712,36.836183 C 32.898902,36.303648 31.970392,35.760006 31.194413,35.339501 z "
+ style="font-size:12.000000;fill:#ebebeb;fill-opacity:0.31372550;fill-rule:evenodd;stroke:none;stroke-width:0.77429527;stroke-linejoin:round;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path12855"
+ d="M 31.535862,35.339501 C 29.672214,36.937525 27.608876,40.322968 26.401246,44.600137 C 29.565142,43.051430 32.402092,39.897767 33.559712,36.645817 C 32.994294,36.181017 32.199822,35.706522 31.535862,35.339501 z "
+ style="font-size:12.000000;fill:#f5f5f5;fill-opacity:0.31372550;fill-rule:evenodd;stroke:none;stroke-width:0.77429527;stroke-linejoin:round;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path12857"
+ d="M 31.877311,35.339501 C 30.328087,36.471786 29.148090,38.870538 28.144199,41.901137 C 30.774308,40.803799 32.597396,38.569265 33.559712,36.265096 C 33.089685,35.935753 32.429251,35.599555 31.877311,35.339501 z "
+ style="font-size:12.000000;fill:#ffffff;fill-opacity:0.31221721;fill-rule:evenodd;stroke:none;stroke-width:0.77429527;stroke-linejoin:round;stroke-opacity:1.0000000" />
+ <g
+ id="g2174">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path672"
+ d="M 30.061161,33.612605 C 31.056578,34.225526 33.958195,35.999839 35.166936,37.112820 C 37.828263,34.723643 51.706037,18.866520 57.764951,8.0940971 C 55.327672,5.4283921 50.326572,4.7999241 47.210077,2.1287023 C 45.170603,3.6395058 30.587806,29.271058 30.061161,33.612605 z "
+ style="font-size:12.000000;fill:url(#linearGradient1425);fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient1428);stroke-width:0.36612317;stroke-miterlimit:4.0000000" />
+ <g
+ id="g2947"
+ transform="matrix(0.265500,1.659133e-2,2.488336e-2,-0.224834,-116.5236,67.75015)">
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path678"
+ d="M 544.06785,185.23884 C 561.08243,232.34141 580.07425,278.58522 603.52211,323.56081 C 599.37466,326.36530 596.20938,328.27876 592.98790,329.80588 C 570.09983,281.67195 552.65324,238.19755 537.96578,188.87058 C 540.53253,187.99599 540.34623,186.72968 544.06785,185.23884 z "
+ style="font-size:12.000000;fill:#45454e;fill-opacity:0.29729697;fill-rule:evenodd;stroke-width:1.0000000pt" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path680"
+ d="M 543.15031,185.88232 C 560.16489,232.98489 578.52789,278.42020 601.97577,323.39579 C 596.82690,324.29588 596.15986,324.48065 592.75040,324.68463 C 569.86231,276.55070 553.21963,237.11949 538.53218,187.79252 C 541.01119,186.88289 539.42870,187.37316 543.15031,185.88232 z "
+ style="font-size:12.000000;fill:#45454e;fill-opacity:0.29729697;fill-rule:evenodd;stroke-width:1.0000000pt" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path681"
+ d="M 542.08466,186.70727 C 559.09925,233.80985 576.02594,277.39172 599.47383,322.36731 C 594.32494,323.26740 597.13301,321.61744 593.72352,321.82142 C 570.83545,273.68748 554.05263,236.74635 539.36517,187.41938 C 542.09871,187.02170 538.36305,188.19811 542.08466,186.70727 z "
+ style="font-size:12.000000;fill:#45454e;fill-opacity:0.29729697;fill-rule:evenodd;stroke-width:1.0000000pt" />
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/chalk/plugins/tools/selectiontools/tool_brush_selection_cursor.png b/chalk/plugins/tools/selectiontools/tool_brush_selection_cursor.png
new file mode 100644
index 00000000..96929d8f
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_brush_selection_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/selectiontools/tool_contiguous_selection.png b/chalk/plugins/tools/selectiontools/tool_contiguous_selection.png
new file mode 100644
index 00000000..fcc8f36d
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_contiguous_selection.png
Binary files differ
diff --git a/chalk/plugins/tools/selectiontools/tool_contiguous_selection_cursor.png b/chalk/plugins/tools/selectiontools/tool_contiguous_selection_cursor.png
new file mode 100644
index 00000000..0e3572cd
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_contiguous_selection_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/selectiontools/tool_elliptical_selection.png b/chalk/plugins/tools/selectiontools/tool_elliptical_selection.png
new file mode 100644
index 00000000..ad585848
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_elliptical_selection.png
Binary files differ
diff --git a/chalk/plugins/tools/selectiontools/tool_elliptical_selection.svg b/chalk/plugins/tools/selectiontools/tool_elliptical_selection.svg
new file mode 100644
index 00000000..31ff66f4
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_elliptical_selection.svg
@@ -0,0 +1,256 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="48.000000pt"
+ height="48.000000pt"
+ id="svg1409"
+ sodipodi:version="0.32"
+ inkscape:version="0.41"
+ sodipodi:docbase="/home/danny/work/kde/koffice/chalk/chalk"
+ sodipodi:docname="tool_elliptical_selection.svg"
+ inkscape:export-filename="/home/danny/work/kde/koffice/chalk/chalk/tool_elliptical_selection.png"
+ inkscape:export-xdpi="33.000000"
+ inkscape:export-ydpi="33.000000">
+ <defs
+ id="defs3">
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.325250,0.000000,0.000000,1.003779,-5.702957,1.287849)"
+ id="linearGradient9512"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ gradientUnits="userSpaceOnUse"
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.261963,0.000000,0.000000,1.016360,-7.978266,-0.517425)"
+ id="radialGradient10280"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ id="light90to0">
+ <stop
+ id="stop1890"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.90833336;" />
+ <stop
+ id="stop1892"
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient1331"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.325250,0.000000,0.000000,1.003779,-5.702957,1.287849)"
+ x1="10.878086"
+ y1="4.5492039"
+ x2="39.857029"
+ y2="36.873619" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient1333"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.261963,0.000000,0.000000,1.016360,-7.978266,-0.517425)"
+ cx="48.488476"
+ cy="46.914463"
+ fx="48.488476"
+ fy="46.914463"
+ r="31.677956" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.181248,0.000000,0.000000,0.943878,-77.46799,5.346100)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient2089"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.240487,0.000000,0.000000,0.932195,-75.33821,7.022631)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2092"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.240487,0.000000,0.000000,0.932195,-75.33821,7.022631)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3660"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.181248,0.000000,0.000000,0.943878,-77.46799,5.346100)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3662"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.472290,0.000000,0.000000,1.178586,-15.47463,-0.337081)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3665"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.546124,0.000000,0.000000,1.163997,-42.82010,1.756341)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3668"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.472290,0.000000,0.000000,1.178586,-15.47463,-0.337081)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3678"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.546124,0.000000,0.000000,1.163997,-12.82010,1.756341)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3682"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="4.3288472"
+ inkscape:cx="33.946093"
+ inkscape:cy="27.610797"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:document-units="px"
+ inkscape:grid-bbox="true"
+ inkscape:window-width="1020"
+ inkscape:window-height="691"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF
+ id="RDF5">
+ <cc:Work
+ rdf:about=""
+ id="Work6">
+ <dc:format
+ id="format7">image/svg+xml</dc:format>
+ <dc:type
+ id="type9"
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <path
+ id="rect7971"
+ d="M 30.000000,7.1250000 C 22.317773,7.1250000 15.355679,9.5078220 10.156250,13.500000 C 4.9568200,17.492177 1.4062500,23.269928 1.4062500,29.968750 C 1.4062500,36.667572 4.9568200,42.507823 10.156250,46.500000 C 15.355679,50.492180 22.317774,52.875000 30.000000,52.875000 C 37.682225,52.875002 44.675571,50.492178 49.875000,46.500000 C 55.074429,42.507825 58.593750,36.667572 58.593750,29.968750 C 58.593752,23.269928 55.074430,17.492177 49.875000,13.500000 C 44.675570,9.5078222 37.682226,7.1250000 30.000000,7.1250000 z "
+ style="opacity:0.79446638;fill:#0028c6;fill-opacity:0.18099548;stroke:#000000;stroke-width:0.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.035294119" />
+ <path
+ id="path8746"
+ d="M 30.000000,7.1250000 C 22.317773,7.1250000 15.355679,9.5078220 10.156250,13.500000 C 4.9568200,17.492177 1.4062500,23.269928 1.4062500,29.968750 C 1.4062500,35.373532 3.7824490,40.170227 7.4062500,43.937500 C 25.754627,28.015820 45.616873,27.218125 56.187500,20.750000 C 54.657054,17.958644 52.482639,15.502173 49.875000,13.500000 C 44.675570,9.5078222 37.682226,7.1250000 30.000000,7.1250000 z "
+ style="opacity:0.79446638;fill:url(#linearGradient3682);fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.035294119" />
+ <path
+ id="path9514"
+ d="M 30.000000,7.1250000 C 22.317773,7.1250000 15.355679,9.5078220 10.156250,13.500000 C 4.9568200,17.492177 1.4062500,23.269928 1.4062500,29.968750 C 1.4062500,36.667572 4.9568202,42.507823 10.156250,46.500000 C 15.355679,50.492180 22.317774,52.875000 30.000000,52.875000 C 37.682225,52.875002 44.675571,50.492178 49.875000,46.500000 C 55.074429,42.507825 58.593750,36.667572 58.593750,29.968750 C 58.593752,23.269928 55.074430,17.492177 49.875000,13.500000 C 44.675570,9.5078222 37.682226,7.1250000 30.000000,7.1250000 z "
+ style="opacity:0.97233200;fill:url(#radialGradient3678);fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.035294119" />
+ <g
+ transform="matrix(1.034994,0.000000,0.000000,0.947886,-1.049820,1.606088)"
+ id="g2879">
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path2095"
+ d="M 15.715627,7.8733917 C 14.686976,8.3945360 14.043469,9.5270380 14.459506,10.644495 C 14.875544,11.761955 16.112458,12.333045 17.222232,11.920064 C 20.059953,10.583282 22.969503,9.5338180 25.735394,8.7716720 C 26.485511,8.5331940 27.042274,7.8985157 27.184094,7.1202427 C 27.325911,6.3419677 27.029771,5.5463973 26.413534,5.0501646 C 25.797297,4.5539337 25.042091,4.5727734 24.237406,4.7473875 C 21.253154,5.3584125 18.484391,6.3285845 15.715627,7.8733917 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path2863"
+ d="M 15.040511,52.036580 C 14.011860,51.515436 13.368353,50.382934 13.784390,49.265477 C 14.200428,48.148017 15.437342,47.576927 16.547116,47.989908 C 19.384837,49.326690 22.294387,50.376154 25.060278,51.138300 C 25.810395,51.376778 26.367158,52.011456 26.508978,52.789729 C 26.650795,53.568004 26.354655,54.363575 25.738418,54.859807 C 25.122181,55.356038 24.366975,55.337199 23.562290,55.162585 C 20.578038,54.551560 17.809275,53.581388 15.040511,52.036580 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path2865"
+ d="M 44.959488,7.8733920 C 45.988139,8.3945360 46.631646,9.5270380 46.215609,10.644495 C 45.799571,11.761955 44.562657,12.333045 43.452883,11.920064 C 40.615162,10.583282 37.705612,9.5338180 34.939721,8.7716720 C 34.189604,8.5331940 33.632841,7.8985160 33.491021,7.1202430 C 33.349204,6.3419677 33.645344,5.5463973 34.261581,5.0501646 C 34.877818,4.5539337 35.633024,4.5727734 36.437709,4.7473875 C 39.421961,5.3584125 42.190724,6.3285845 44.959488,7.8733920 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path2867"
+ d="M 44.284370,52.036580 C 45.313021,51.515436 45.956528,50.382934 45.540491,49.265477 C 45.124453,48.148017 43.887539,47.576927 42.777765,47.989908 C 39.940044,49.326690 37.030494,50.376154 34.264603,51.138300 C 33.514486,51.376778 32.957723,52.011456 32.815903,52.789729 C 32.674086,53.568004 32.970226,54.363575 33.586463,54.859807 C 34.202700,55.356038 34.957906,55.337199 35.762591,55.162585 C 38.746843,54.551560 41.515606,53.581388 44.284370,52.036580 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path2869"
+ d="M 1.1508292,24.851646 C 0.79196783,25.947517 1.1377395,27.203345 2.2220836,27.699323 C 3.3064305,28.195304 4.5848824,27.724495 5.0775894,26.647745 C 6.1389136,23.695925 7.4541930,20.896480 8.8710548,18.401782 C 9.2328376,17.702738 9.1777437,16.860263 8.7277037,16.209658 C 8.2776597,15.559055 7.5057040,15.205904 6.7190689,15.290760 C 5.9324353,15.375617 5.4117458,15.922950 4.9662183,16.615419 C 3.2880935,19.157664 2.0162977,21.801490 1.1508292,24.851646 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path2871"
+ d="M 58.849170,35.058325 C 59.208032,33.962455 58.862260,32.706627 57.777916,32.210649 C 56.693569,31.714668 55.415117,32.185477 54.922410,33.262227 C 53.861086,36.214047 52.545807,39.013492 51.128945,41.508190 C 50.767162,42.207234 50.822256,43.049709 51.272296,43.700314 C 51.722340,44.350917 52.494296,44.704067 53.280930,44.619212 C 54.067564,44.534355 54.588254,43.987022 55.033782,43.294553 C 56.711907,40.752308 57.983702,38.108482 58.849170,35.058325 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path2873"
+ d="M 4.3255135,45.237875 C 4.8466574,46.266526 5.9791594,46.910033 7.0966154,46.493995 C 8.2140765,46.077958 8.7851655,44.841044 8.3721854,43.731270 C 7.0354024,40.893548 5.9859395,37.983999 5.2237936,35.218107 C 4.9853145,34.467990 4.3506365,33.911227 3.5723636,33.769407 C 2.7940894,33.627590 1.9985185,33.923730 1.5022854,34.539967 C 1.0060545,35.156204 1.0248945,35.911410 1.1995086,36.716095 C 1.8105334,39.700347 2.7807056,42.469110 4.3255135,45.237875 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path2875"
+ d="M 55.674487,14.672098 C 55.153343,13.643446 54.020841,12.999939 52.903385,13.415977 C 51.785924,13.832014 51.214835,15.068929 51.627815,16.178702 C 52.964598,19.016424 54.014061,21.925973 54.776208,24.691864 C 55.014687,25.441982 55.649364,25.998745 56.427637,26.140565 C 57.205913,26.282381 58.001483,25.986242 58.497714,25.370005 C 58.993947,24.753768 58.975106,23.998562 58.800494,23.193876 C 58.189469,20.209624 57.219295,17.440862 55.674487,14.672098 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ </g>
+ </g>
+</svg>
diff --git a/chalk/plugins/tools/selectiontools/tool_elliptical_selection_cursor.png b/chalk/plugins/tools/selectiontools/tool_elliptical_selection_cursor.png
new file mode 100644
index 00000000..5e02f87b
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_elliptical_selection_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/selectiontools/tool_eraser_selection.png b/chalk/plugins/tools/selectiontools/tool_eraser_selection.png
new file mode 100644
index 00000000..ffe2e440
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_eraser_selection.png
Binary files differ
diff --git a/chalk/plugins/tools/selectiontools/tool_eraser_selection.svg b/chalk/plugins/tools/selectiontools/tool_eraser_selection.svg
new file mode 100644
index 00000000..9c147c1b
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_eraser_selection.svg
@@ -0,0 +1,1993 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="48.000000pt"
+ height="48.000000pt"
+ id="svg11941"
+ sodipodi:version="0.32"
+ inkscape:version="0.41"
+ sodipodi:docbase="/home/danny/work/kde/koffice/chalk/chalk/new"
+ sodipodi:docname="tool_eraser_selection.svg"
+ inkscape:export-filename="/home/danny/work/kde/koffice/chalk/chalk/new/tool_eraser_selection.png"
+ inkscape:export-xdpi="33.000000"
+ inkscape:export-ydpi="33.000000">
+ <defs
+ id="defs3">
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient9512"
+ gradientTransform="matrix(0.996235,0.000000,0.000000,1.003779,-3.391158,13.41516)"
+ x1="10.878086"
+ y1="4.5492039"
+ x2="39.857029"
+ y2="36.873619"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient10280"
+ gradientTransform="matrix(0.983903,0.000000,0.000000,1.016360,-3.999998,12.41516)"
+ cx="48.488476"
+ cy="46.914463"
+ fx="48.488476"
+ fy="46.914463"
+ r="31.677956"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7969"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.592685,0.379735,0.000000,-30.45690,-1.224420)"
+ cx="-23.859682"
+ cy="95.221397"
+ fx="-23.859682"
+ fy="95.221397"
+ r="8.5514765" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7967"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.503650,0.399417,0.000000,-30.45690,-1.829360)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7965"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.592685,0.379735,0.000000,-30.45690,-21.22442)"
+ cx="-23.859682"
+ cy="95.221397"
+ fx="-23.859682"
+ fy="95.221397"
+ r="8.5514765" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7963"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.503650,0.399417,0.000000,-30.45690,-21.82936)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7961"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.592685,0.379735,0.000000,26.44710,-11.22442)"
+ cx="-23.859682"
+ cy="95.221397"
+ fx="-23.859682"
+ fy="95.221397"
+ r="8.5514765" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7959"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.503650,0.399417,0.000000,26.44710,-11.82936)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7957"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.633416,0.000000,0.000000,0.379735,-44.86332,44.21180)"
+ cx="25.952410"
+ cy="52.497688"
+ fx="25.923746"
+ fy="51.904903"
+ r="14.270030" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7955"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.503650,0.000000,0.000000,0.399417,-44.86332,44.21180)"
+ x1="22.425571"
+ y1="35.206337"
+ x2="22.396454"
+ y2="41.545322" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7953"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.633416,0.000000,0.000000,0.379735,-22.86332,44.21180)"
+ cx="25.952410"
+ cy="52.497688"
+ fx="25.923746"
+ fy="51.904903"
+ r="14.270030" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7951"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.503650,0.000000,0.000000,0.399417,-22.86332,44.21180)"
+ x1="22.425571"
+ y1="35.206337"
+ x2="22.396454"
+ y2="41.545322" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7949"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.633416,0.000000,0.000000,0.379735,-38.65916,-12.48664)"
+ cx="25.952410"
+ cy="52.497688"
+ fx="25.923746"
+ fy="51.904903"
+ r="14.270030" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7947"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.503650,0.000000,0.000000,0.399417,-38.65916,-12.48664)"
+ x1="22.425571"
+ y1="35.206337"
+ x2="22.396454"
+ y2="41.545322" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7945"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.503650,0.399417,0.000000,26.44710,4.170640)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7943"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.878497,0.000000,0.000000,1.138308,-18.65916,-0.486640)"
+ cx="92.643608"
+ cy="55.457653"
+ fx="92.643608"
+ fy="55.457653"
+ r="9.9914455" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7941"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.592685,0.379735,0.000000,26.44710,-31.22442)"
+ cx="-23.859682"
+ cy="95.221397"
+ fx="-23.859682"
+ fy="95.221397"
+ r="8.5514765" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7939"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.503650,0.399417,0.000000,26.44710,-31.82936)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7937"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.633416,0.000000,0.000000,0.379735,-16.65916,-12.48664)"
+ cx="25.952410"
+ cy="52.497688"
+ fx="25.923746"
+ fy="51.904903"
+ r="14.270030" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7935"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.503650,0.000000,0.000000,0.399417,-16.65916,-12.48664)"
+ x1="22.425571"
+ y1="35.206337"
+ x2="22.396454"
+ y2="41.545322" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient7933"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.665867,1.501801)"
+ cx="8.0907059"
+ cy="9.5002232"
+ fx="8.0907059"
+ fy="9.5002232"
+ r="5.8189325" />
+ <linearGradient
+ id="light90to0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.90833336;"
+ offset="0.0000000"
+ id="stop1890" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="1.0000000"
+ id="stop1892" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient7931"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.791643,0.000000,0.000000,1.263196,-1.626700,-5.630763)"
+ x1="4.4536543"
+ y1="6.5494914"
+ x2="14.101834"
+ y2="13.431447" />
+ <linearGradient
+ id="wihitetolightgray">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop1885" />
+ <stop
+ style="stop-color:#d5d4d4;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop1886" />
+ </linearGradient>
+ <linearGradient
+ id="orangemoretoyelow">
+ <stop
+ style="stop-color:#ff0d00;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop2671" />
+ <stop
+ style="stop-color:#ff3900;stop-opacity:1.0000000;"
+ offset="0.74641621"
+ id="stop2679" />
+ <stop
+ style="stop-color:#d05521;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop2672" />
+ </linearGradient>
+ <linearGradient
+ id="graytoblack">
+ <stop
+ style="stop-color:#7d7d7d;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop5097" />
+ <stop
+ style="stop-color:#000000;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop5098" />
+ </linearGradient>
+ <linearGradient
+ id="shadow100to0">
+ <stop
+ style="stop-color:#000000;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop3425" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0.0000000;"
+ offset="1.0000000"
+ id="stop3426" />
+ </linearGradient>
+ <linearGradient
+ id="light50to25to7">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.47450981;"
+ offset="0.0000000"
+ id="stop2791" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.25833333;"
+ offset="0.50000000"
+ id="stop2795" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.10833333;"
+ offset="1.0000000"
+ id="stop2793" />
+ </linearGradient>
+ <linearGradient
+ id="orangetoblackorange">
+ <stop
+ style="stop-color:#ff8b00;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop4207" />
+ <stop
+ style="stop-color:#4d0200;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop4209" />
+ </linearGradient>
+ <linearGradient
+ id="light100to0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop2764" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="1.0000000"
+ id="stop2765" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#wihitetolightgray"
+ id="radialGradient13045"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.281643,-1.886110e-2,0.000000,0.179517,-4.383105,-16.75305)"
+ cx="86.514435"
+ cy="332.37268"
+ fx="86.514435"
+ fy="332.37268"
+ r="83.259750" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light100to0"
+ id="linearGradient13047"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.281643,-1.886110e-2,0.000000,0.179517,-4.383105,-16.75305)"
+ x1="86.514435"
+ y1="335.76117"
+ x2="73.286217"
+ y2="247.07323" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#wihitetolightgray"
+ id="linearGradient13049"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ x1="132.72992"
+ y1="279.47504"
+ x2="84.003502"
+ y2="210.46336" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light100to0"
+ id="linearGradient13051"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ x1="136.55682"
+ y1="213.43617"
+ x2="54.607849"
+ y2="250.54321" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#wihitetolightgray"
+ id="linearGradient13053"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ x1="145.42192"
+ y1="264.70230"
+ x2="198.28532"
+ y2="218.74910" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light100to0"
+ id="linearGradient13055"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.180988,-1.212046e-2,0.000000,0.279356,-4.383105,-16.75305)"
+ x1="159.18221"
+ y1="219.68500"
+ x2="184.11906"
+ y2="234.35374" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#orangemoretoyelow"
+ id="linearGradient13057"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.273196,-8.526361e-2,0.000000,0.785425,-7.025630e-17,2.371150e-16)"
+ x1="36.606781"
+ y1="4.8842254"
+ x2="28.653791"
+ y2="47.244961" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light100to0"
+ id="linearGradient13059"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.286285,-1.917198e-2,0.000000,0.176607,-4.383105,-16.75305)"
+ x1="134.59328"
+ y1="300.55457"
+ x2="126.82574"
+ y2="189.89319" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#orangemoretoyelow"
+ id="linearGradient13061"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.870407,-5.828951e-2,0.000000,1.148888,-7.025630e-17,2.371150e-16)"
+ x1="77.830383"
+ y1="43.692036"
+ x2="40.120766"
+ y2="18.127838" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light100to0"
+ id="linearGradient13063"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.218024,-1.460066e-2,0.000000,0.231901,-4.383105,-16.75305)"
+ x1="188.09673"
+ y1="173.35371"
+ x2="269.30646"
+ y2="220.31316" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#graytoblack"
+ id="linearGradient13065"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.262073,-1.755056e-2,0.000000,0.217660,-4.383105,-17.56717)"
+ spreadMethod="reflect"
+ x1="138.68466"
+ y1="221.05045"
+ x2="90.955330"
+ y2="574.66980" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#shadow100to0"
+ id="linearGradient13067"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.273027,-1.828417e-2,0.000000,0.185183,-4.383100,-12.51208)"
+ x1="124.51332"
+ y1="199.20517"
+ x2="99.415497"
+ y2="224.95407" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#shadow100to0"
+ id="linearGradient13069"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.273027,-1.828417e-2,0.000000,0.185183,-4.383100,-12.51208)"
+ x1="124.51332"
+ y1="199.20517"
+ x2="99.415497"
+ y2="224.95407" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#shadow100to0"
+ id="linearGradient13071"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.273027,-1.828417e-2,0.000000,0.185183,-4.383100,-12.51208)"
+ x1="163.74318"
+ y1="301.15747"
+ x2="137.31036"
+ y2="301.15750" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light50to25to7"
+ id="radialGradient13073"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.282097,-1.889158e-2,0.000000,0.179229,-4.383100,-12.51208)"
+ cx="145.82777"
+ cy="265.90030"
+ fx="145.82777"
+ fy="265.90030"
+ r="24.113470" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#orangetoblackorange"
+ id="linearGradient13075"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.302207,-2.036411e-2,1.731823e-2,0.187588,-5.784573,-19.06245)"
+ spreadMethod="reflect"
+ x1="119.80309"
+ y1="179.83293"
+ x2="129.06503"
+ y2="189.54620" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#orangetoblackorange"
+ id="linearGradient13077"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.302207,-2.036411e-2,1.731823e-2,0.187588,-0.406378,-15.67507)"
+ spreadMethod="reflect"
+ x1="119.80309"
+ y1="179.83293"
+ x2="129.06503"
+ y2="189.54620" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#orangetoblackorange"
+ id="linearGradient13079"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.302207,-2.036411e-2,1.731823e-2,0.187588,4.903646,-12.38550)"
+ spreadMethod="reflect"
+ x1="119.80309"
+ y1="179.83293"
+ x2="129.06503"
+ y2="189.54620" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#orangetoblackorange"
+ id="linearGradient13081"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.250582,0.000000,0.000000,0.227641,-4.383105,-17.56717)"
+ spreadMethod="reflect"
+ x1="203.79491"
+ y1="203.68118"
+ x2="120.08266"
+ y2="229.92639" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light100to0"
+ id="linearGradient13083"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.331788,0.000000,0.000000,0.171926,-4.383100,-17.56719)"
+ x1="24.253796"
+ y1="213.05858"
+ x2="189.53893"
+ y2="213.05858" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light100to0"
+ id="linearGradient13085"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.182201,0.000000,0.000000,0.313078,-4.383100,-17.56719)"
+ x1="42.080868"
+ y1="215.05040"
+ x2="88.821419"
+ y2="172.01805" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light100to0"
+ id="linearGradient13087"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.331788,0.000000,0.000000,0.171926,-4.383100,-17.56719)"
+ x1="149.74805"
+ y1="120.63583"
+ x2="144.13652"
+ y2="216.48166" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#graytoblack"
+ id="radialGradient16881"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.281643,-1.886110e-2,0.000000,0.179517,-4.383105,-16.75305)"
+ cx="86.514435"
+ cy="332.37268"
+ fx="86.514435"
+ fy="332.37268"
+ r="83.259750" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#graytoblack"
+ id="linearGradient18401"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ x1="132.72992"
+ y1="279.47504"
+ x2="84.003502"
+ y2="210.46336" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#graytoblack"
+ id="linearGradient19163"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ x1="145.42192"
+ y1="264.70230"
+ x2="198.28532"
+ y2="218.74910" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient19963"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.142981,0.309244,0.000000,-25.58840,11.38378)"
+ cx="-23.859682"
+ cy="95.221397"
+ fx="-23.859682"
+ fy="95.221397"
+ r="8.5514765" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient19966"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.069389,0.325272,0.000000,-25.58840,10.88376)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient19970"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.142981,0.309244,0.000000,-25.58840,-5.893883)"
+ cx="-23.859682"
+ cy="95.221397"
+ fx="-23.859682"
+ fy="95.221397"
+ r="8.5514765" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient19973"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.069389,0.325272,0.000000,-25.58840,-6.393896)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient19977"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.142981,0.309244,0.000000,20.66765,1.878457)"
+ cx="-23.859682"
+ cy="95.221397"
+ fx="-23.859682"
+ fy="95.221397"
+ r="8.5514765" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient19980"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.069389,0.325272,0.000000,20.66765,1.378444)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient19984"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.144567,0.000000,0.000000,0.313870,-38.78637,48.23092)"
+ cx="25.952410"
+ cy="52.497688"
+ fx="25.923746"
+ fy="51.904903"
+ r="14.270030" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient19987"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.038890,0.000000,0.000000,0.330138,-38.78637,48.23092)"
+ x1="22.425571"
+ y1="35.206337"
+ x2="22.396454"
+ y2="41.545322" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient19991"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.144567,0.000000,0.000000,0.313870,-20.05593,48.23092)"
+ cx="25.952410"
+ cy="52.497688"
+ fx="25.923746"
+ fy="51.904903"
+ r="14.270030" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient19994"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.038890,0.000000,0.000000,0.330138,-20.05593,48.23092)"
+ x1="22.425571"
+ y1="35.206337"
+ x2="22.396454"
+ y2="41.545322" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient19998"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.144567,0.000000,0.000000,0.313870,-31.37563,1.327640)"
+ cx="25.952410"
+ cy="52.497688"
+ fx="25.923746"
+ fy="51.904903"
+ r="14.270030" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient20001"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.038890,0.000000,0.000000,0.330138,-31.37563,1.327640)"
+ x1="22.425571"
+ y1="35.206337"
+ x2="22.396454"
+ y2="41.545322" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient20005"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.000000,-2.069389,0.325272,0.000000,20.75234,15.09638)"
+ x1="-16.569721"
+ y1="81.885979"
+ x2="-21.621279"
+ y2="85.112236" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient20008"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.715419,0.000000,0.000000,0.940867,-15.98071,11.24691)"
+ cx="92.643608"
+ cy="55.457653"
+ fx="92.643608"
+ fy="55.457653"
+ r="9.9914455" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient20019"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.144567,0.000000,0.000000,0.313870,-12.72324,1.327640)"
+ cx="25.952410"
+ cy="52.497688"
+ fx="25.923746"
+ fy="51.904903"
+ r="14.270030" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient20022"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.038890,0.000000,0.000000,0.330138,-12.72324,1.327640)"
+ x1="22.425571"
+ y1="35.206337"
+ x2="22.396454"
+ y2="41.545322" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient20026"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.542260,0.000000,0.000000,1.241312,-0.785301,11.64914)"
+ cx="8.0907059"
+ cy="9.5002232"
+ fx="8.0907059"
+ fy="9.5002232"
+ r="5.8189325" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(0.996235,0.000000,0.000000,1.003779,-3.391158,13.41516)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1472"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(0.983903,0.000000,0.000000,1.016360,-3.999998,12.41516)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1474"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="83.259750"
+ fy="332.37268"
+ fx="86.514435"
+ cy="332.37268"
+ cx="86.514435"
+ gradientTransform="matrix(0.281643,-1.886110e-2,0.000000,0.179517,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1476"
+ xlink:href="#wihitetolightgray"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="247.07323"
+ x2="73.286217"
+ y1="335.76117"
+ x1="86.514435"
+ gradientTransform="matrix(0.281643,-1.886110e-2,0.000000,0.179517,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1478"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="210.46336"
+ x2="84.003502"
+ y1="279.47504"
+ x1="132.72992"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1480"
+ xlink:href="#wihitetolightgray"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="250.54321"
+ x2="54.607849"
+ y1="213.43617"
+ x1="136.55682"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1482"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="218.74910"
+ x2="198.28532"
+ y1="264.70230"
+ x1="145.42192"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1484"
+ xlink:href="#wihitetolightgray"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="234.35374"
+ x2="184.11906"
+ y1="219.68500"
+ x1="159.18221"
+ gradientTransform="matrix(0.180988,-1.212046e-2,0.000000,0.279356,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1486"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="47.244961"
+ x2="28.653791"
+ y1="4.8842254"
+ x1="36.606781"
+ gradientTransform="matrix(1.273196,-8.526361e-2,0.000000,0.785425,-1.806714e-15,-3.087808e-16)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1488"
+ xlink:href="#orangemoretoyelow"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="189.89319"
+ x2="126.82574"
+ y1="300.55457"
+ x1="134.59328"
+ gradientTransform="matrix(0.286285,-1.917198e-2,0.000000,0.176607,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1490"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="18.127838"
+ x2="40.120766"
+ y1="43.692036"
+ x1="77.830383"
+ gradientTransform="matrix(0.870407,-5.828951e-2,0.000000,1.148888,-1.806714e-15,-3.087808e-16)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1492"
+ xlink:href="#orangemoretoyelow"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="220.31316"
+ x2="269.30646"
+ y1="173.35371"
+ x1="188.09673"
+ gradientTransform="matrix(0.218024,-1.460066e-2,0.000000,0.231901,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1494"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="574.66980"
+ x2="90.955330"
+ y1="221.05045"
+ x1="138.68466"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.262073,-1.755056e-2,0.000000,0.217660,-4.383105,-17.56717)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1496"
+ xlink:href="#graytoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="224.95407"
+ x2="99.415497"
+ y1="199.20517"
+ x1="124.51332"
+ gradientTransform="matrix(0.273027,-1.828417e-2,0.000000,0.185183,-4.383100,-12.51208)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1498"
+ xlink:href="#shadow100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="224.95407"
+ x2="99.415497"
+ y1="199.20517"
+ x1="124.51332"
+ gradientTransform="matrix(0.273027,-1.828417e-2,0.000000,0.185183,-4.383100,-12.51208)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1500"
+ xlink:href="#shadow100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="301.15750"
+ x2="137.31036"
+ y1="301.15747"
+ x1="163.74318"
+ gradientTransform="matrix(0.273027,-1.828417e-2,0.000000,0.185183,-4.383100,-12.51208)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1502"
+ xlink:href="#shadow100to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="24.113470"
+ fy="265.90030"
+ fx="145.82777"
+ cy="265.90030"
+ cx="145.82777"
+ gradientTransform="matrix(0.282097,-1.889158e-2,0.000000,0.179229,-4.383100,-12.51208)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1504"
+ xlink:href="#light50to25to7"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="189.54620"
+ x2="129.06503"
+ y1="179.83293"
+ x1="119.80309"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.302207,-2.036411e-2,1.731823e-2,0.187588,-5.784573,-19.06245)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1506"
+ xlink:href="#orangetoblackorange"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="189.54620"
+ x2="129.06503"
+ y1="179.83293"
+ x1="119.80309"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.302207,-2.036411e-2,1.731823e-2,0.187588,-0.406378,-15.67507)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1508"
+ xlink:href="#orangetoblackorange"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="189.54620"
+ x2="129.06503"
+ y1="179.83293"
+ x1="119.80309"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.302207,-2.036411e-2,1.731823e-2,0.187588,4.903646,-12.38550)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1510"
+ xlink:href="#orangetoblackorange"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="229.92639"
+ x2="120.08266"
+ y1="203.68118"
+ x1="203.79491"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.250582,0.000000,0.000000,0.227641,-4.383105,-17.56717)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1512"
+ xlink:href="#orangetoblackorange"
+ inkscape:collect="always" />
+ <radialGradient
+ r="83.259750"
+ fy="332.37268"
+ fx="86.514435"
+ cy="332.37268"
+ cx="86.514435"
+ gradientTransform="matrix(0.281643,-1.886110e-2,0.000000,0.179517,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1514"
+ xlink:href="#graytoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="247.07323"
+ x2="73.286217"
+ y1="335.76117"
+ x1="86.514435"
+ gradientTransform="matrix(0.281643,-1.886110e-2,0.000000,0.179517,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1516"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="213.05858"
+ x2="189.53893"
+ y1="213.05858"
+ x1="24.253796"
+ gradientTransform="matrix(0.331788,0.000000,0.000000,0.171926,-4.383100,-17.56719)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1518"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="218.74910"
+ x2="198.28532"
+ y1="264.70230"
+ x1="145.42192"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1520"
+ xlink:href="#graytoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="234.35374"
+ x2="184.11906"
+ y1="219.68500"
+ x1="159.18221"
+ gradientTransform="matrix(0.180988,-1.212046e-2,0.000000,0.279356,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1522"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="210.46336"
+ x2="84.003502"
+ y1="279.47504"
+ x1="132.72992"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1524"
+ xlink:href="#graytoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="250.54321"
+ x2="54.607849"
+ y1="213.43617"
+ x1="136.55682"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1526"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="172.01805"
+ x2="88.821419"
+ y1="215.05040"
+ x1="42.080868"
+ gradientTransform="matrix(0.182201,0.000000,0.000000,0.313078,-4.383100,-17.56719)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1528"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="216.48166"
+ x2="144.13652"
+ y1="120.63583"
+ x1="149.74805"
+ gradientTransform="matrix(0.331788,0.000000,0.000000,0.171926,-4.383100,-17.56719)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1530"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(0.922906,0.000000,0.000000,0.953351,-3.844255,9.876188)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1575"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(0.934473,0.000000,0.000000,0.941550,-3.273160,10.81419)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1578"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(0.934473,0.000000,0.000000,0.941550,-3.273160,10.81419)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1474"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(0.922906,0.000000,0.000000,0.953351,-3.844255,9.876188)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1477"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(0.934473,0.000000,0.000000,0.941550,-3.273160,10.81419)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1527"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(0.922906,0.000000,0.000000,0.953351,-3.844255,9.876188)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1529"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="83.259750"
+ fy="332.37268"
+ fx="86.514435"
+ cy="332.37268"
+ cx="86.514435"
+ gradientTransform="matrix(0.281643,-1.886110e-2,0.000000,0.179517,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1531"
+ xlink:href="#wihitetolightgray"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="247.07323"
+ x2="73.286217"
+ y1="335.76117"
+ x1="86.514435"
+ gradientTransform="matrix(0.281643,-1.886110e-2,0.000000,0.179517,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1533"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="210.46336"
+ x2="84.003502"
+ y1="279.47504"
+ x1="132.72992"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1535"
+ xlink:href="#wihitetolightgray"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="250.54321"
+ x2="54.607849"
+ y1="213.43617"
+ x1="136.55682"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1537"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="218.74910"
+ x2="198.28532"
+ y1="264.70230"
+ x1="145.42192"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1539"
+ xlink:href="#wihitetolightgray"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="234.35374"
+ x2="184.11906"
+ y1="219.68500"
+ x1="159.18221"
+ gradientTransform="matrix(0.180988,-1.212046e-2,0.000000,0.279356,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1541"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="47.244961"
+ x2="28.653791"
+ y1="4.8842254"
+ x1="36.606781"
+ gradientTransform="matrix(1.273196,-8.526361e-2,0.000000,0.785425,-3.588275e-15,-4.926614e-16)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1543"
+ xlink:href="#orangemoretoyelow"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="189.89319"
+ x2="126.82574"
+ y1="300.55457"
+ x1="134.59328"
+ gradientTransform="matrix(0.286285,-1.917198e-2,0.000000,0.176607,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1545"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="18.127838"
+ x2="40.120766"
+ y1="43.692036"
+ x1="77.830383"
+ gradientTransform="matrix(0.870407,-5.828951e-2,0.000000,1.148888,4.887488e-6,1.380840e-15)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1547"
+ xlink:href="#orangemoretoyelow"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="220.31316"
+ x2="269.30646"
+ y1="173.35371"
+ x1="188.09673"
+ gradientTransform="matrix(0.218024,-1.460066e-2,0.000000,0.231901,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1549"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="574.66980"
+ x2="90.955330"
+ y1="221.05045"
+ x1="138.68466"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.262073,-1.755056e-2,0.000000,0.217660,-4.383105,-17.56717)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1551"
+ xlink:href="#graytoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="224.95407"
+ x2="99.415497"
+ y1="199.20517"
+ x1="124.51332"
+ gradientTransform="matrix(0.273027,-1.828417e-2,0.000000,0.185183,-4.383100,-12.51208)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1553"
+ xlink:href="#shadow100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="224.95407"
+ x2="99.415497"
+ y1="199.20517"
+ x1="124.51332"
+ gradientTransform="matrix(0.273027,-1.828417e-2,0.000000,0.185183,-4.383100,-12.51208)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1555"
+ xlink:href="#shadow100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="301.15750"
+ x2="137.31036"
+ y1="301.15747"
+ x1="163.74318"
+ gradientTransform="matrix(0.273027,-1.828417e-2,0.000000,0.185183,-4.383100,-12.51208)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1557"
+ xlink:href="#shadow100to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="24.113470"
+ fy="265.90030"
+ fx="145.82777"
+ cy="265.90030"
+ cx="145.82777"
+ gradientTransform="matrix(0.282097,-1.889158e-2,0.000000,0.179229,-4.383100,-12.51208)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1559"
+ xlink:href="#light50to25to7"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="189.54620"
+ x2="129.06503"
+ y1="179.83293"
+ x1="119.80309"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.302207,-2.036411e-2,1.731823e-2,0.187588,-5.784573,-19.06245)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1561"
+ xlink:href="#orangetoblackorange"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="189.54620"
+ x2="129.06503"
+ y1="179.83293"
+ x1="119.80309"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.302207,-2.036411e-2,1.731823e-2,0.187588,-0.406378,-15.67507)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1563"
+ xlink:href="#orangetoblackorange"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="189.54620"
+ x2="129.06503"
+ y1="179.83293"
+ x1="119.80309"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.302207,-2.036411e-2,1.731823e-2,0.187588,4.903646,-12.38550)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1565"
+ xlink:href="#orangetoblackorange"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="229.92639"
+ x2="120.08266"
+ y1="203.68118"
+ x1="203.79491"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.250582,0.000000,0.000000,0.227641,-4.383105,-17.56717)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1567"
+ xlink:href="#orangetoblackorange"
+ inkscape:collect="always" />
+ <radialGradient
+ r="83.259750"
+ fy="332.37268"
+ fx="86.514435"
+ cy="332.37268"
+ cx="86.514435"
+ gradientTransform="matrix(0.281643,-1.886110e-2,0.000000,0.179517,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1569"
+ xlink:href="#graytoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="247.07323"
+ x2="73.286217"
+ y1="335.76117"
+ x1="86.514435"
+ gradientTransform="matrix(0.281643,-1.886110e-2,0.000000,0.179517,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1571"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="213.05858"
+ x2="189.53893"
+ y1="213.05858"
+ x1="24.253796"
+ gradientTransform="matrix(0.331788,0.000000,0.000000,0.171926,-4.383100,-17.56719)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1573"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="218.74910"
+ x2="198.28532"
+ y1="264.70230"
+ x1="145.42192"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1575"
+ xlink:href="#graytoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="234.35374"
+ x2="184.11906"
+ y1="219.68500"
+ x1="159.18221"
+ gradientTransform="matrix(0.180988,-1.212046e-2,0.000000,0.279356,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1577"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="210.46336"
+ x2="84.003502"
+ y1="279.47504"
+ x1="132.72992"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1579"
+ xlink:href="#graytoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="250.54321"
+ x2="54.607849"
+ y1="213.43617"
+ x1="136.55682"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1581"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="172.01805"
+ x2="88.821419"
+ y1="215.05040"
+ x1="42.080868"
+ gradientTransform="matrix(0.182201,0.000000,0.000000,0.313078,-4.383100,-17.56719)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1583"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="216.48166"
+ x2="144.13652"
+ y1="120.63583"
+ x1="149.74805"
+ gradientTransform="matrix(0.331788,0.000000,0.000000,0.171926,-4.383100,-17.56719)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1585"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="216.48166"
+ x2="144.13652"
+ y1="120.63583"
+ x1="149.74805"
+ gradientTransform="matrix(0.251838,0.000000,0.000000,0.135659,7.587247,-14.29214)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2877"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="172.01805"
+ x2="88.821419"
+ y1="215.05040"
+ x1="42.080868"
+ gradientTransform="matrix(0.138296,0.000000,0.000000,0.247035,7.587247,-14.29214)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2880"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="210.46336"
+ x2="84.003502"
+ y1="279.47504"
+ x1="132.72992"
+ gradientTransform="matrix(0.148555,-1.034192e-2,0.000000,0.203839,7.587243,-13.64974)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2883"
+ xlink:href="#graytoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="250.54321"
+ x2="54.607849"
+ y1="213.43617"
+ x1="136.55682"
+ gradientTransform="matrix(0.148555,-1.034192e-2,0.000000,0.203839,7.587243,-13.64974)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2885"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="218.74910"
+ x2="198.28532"
+ y1="264.70230"
+ x1="145.42192"
+ gradientTransform="matrix(0.148555,-1.034192e-2,0.000000,0.203839,7.587243,-13.64974)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2888"
+ xlink:href="#graytoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="234.35374"
+ x2="184.11906"
+ y1="219.68500"
+ x1="159.18221"
+ gradientTransform="matrix(0.137376,-9.563697e-3,0.000000,0.220427,7.587243,-13.64974)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2890"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="213.05858"
+ x2="189.53893"
+ y1="213.05858"
+ x1="24.253796"
+ gradientTransform="matrix(0.251838,0.000000,0.000000,0.135659,7.587247,-14.29214)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2893"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="83.259750"
+ fy="332.37268"
+ fx="86.514435"
+ cy="332.37268"
+ cx="86.514435"
+ gradientTransform="matrix(0.213776,-1.488243e-2,0.000000,0.141649,7.587243,-13.64974)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient2896"
+ xlink:href="#graytoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="247.07323"
+ x2="73.286217"
+ y1="335.76117"
+ x1="86.514435"
+ gradientTransform="matrix(0.213776,-1.488243e-2,0.000000,0.141649,7.587243,-13.64974)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2898"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="229.92639"
+ x2="120.08266"
+ y1="203.68118"
+ x1="203.79491"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.190200,0.000000,0.000000,0.179621,7.587243,-14.29213)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2901"
+ xlink:href="#orangetoblackorange"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="189.54620"
+ x2="129.06503"
+ y1="179.83293"
+ x1="119.80309"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.229385,-1.606838e-2,1.314509e-2,0.148017,14.63618,-10.20351)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2904"
+ xlink:href="#orangetoblackorange"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="189.54620"
+ x2="129.06503"
+ y1="179.83293"
+ x1="119.80309"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.229385,-1.606838e-2,1.314509e-2,0.148017,10.60571,-12.79916)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2907"
+ xlink:href="#orangetoblackorange"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="189.54620"
+ x2="129.06503"
+ y1="179.83293"
+ x1="119.80309"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.229385,-1.606838e-2,1.314509e-2,0.148017,6.523484,-15.47198)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2910"
+ xlink:href="#orangetoblackorange"
+ inkscape:collect="always" />
+ <radialGradient
+ r="24.113470"
+ fy="265.90030"
+ fx="145.82777"
+ cy="265.90030"
+ cx="145.82777"
+ gradientTransform="matrix(0.214121,-1.490648e-2,0.000000,0.141421,7.587247,-10.30339)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient2913"
+ xlink:href="#light50to25to7"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="301.15750"
+ x2="137.31036"
+ y1="301.15747"
+ x1="163.74318"
+ gradientTransform="matrix(0.207236,-1.442720e-2,0.000000,0.146119,7.587247,-10.30339)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2916"
+ xlink:href="#shadow100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="224.95407"
+ x2="99.415497"
+ y1="199.20517"
+ x1="124.51332"
+ gradientTransform="matrix(0.207236,-1.442720e-2,0.000000,0.146119,7.587247,-10.30339)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2919"
+ xlink:href="#shadow100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="224.95407"
+ x2="99.415497"
+ y1="199.20517"
+ x1="124.51332"
+ gradientTransform="matrix(0.207236,-1.442720e-2,0.000000,0.146119,7.587247,-10.30339)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2922"
+ xlink:href="#shadow100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="574.66980"
+ x2="90.955330"
+ y1="221.05045"
+ x1="138.68466"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.198922,-1.384834e-2,0.000000,0.171745,7.587243,-14.29213)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2925"
+ xlink:href="#graytoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="18.127838"
+ x2="40.120766"
+ y1="43.692036"
+ x1="77.830383"
+ gradientTransform="matrix(0.660667,-4.599357e-2,0.000000,0.906535,10.91416,-0.430682)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2928"
+ xlink:href="#orangemoretoyelow"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="220.31316"
+ x2="269.30646"
+ y1="173.35371"
+ x1="188.09673"
+ gradientTransform="matrix(0.165487,-1.152071e-2,0.000000,0.182982,7.587243,-13.64974)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2930"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="47.244961"
+ x2="28.653791"
+ y1="4.8842254"
+ x1="36.606781"
+ gradientTransform="matrix(0.966397,-6.727759e-2,0.000000,0.619743,10.91416,-0.430682)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2933"
+ xlink:href="#orangemoretoyelow"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="189.89319"
+ x2="126.82574"
+ y1="300.55457"
+ x1="134.59328"
+ gradientTransform="matrix(0.217299,-1.512773e-2,0.000000,0.139352,7.587243,-13.64974)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2935"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="218.74910"
+ x2="198.28532"
+ y1="264.70230"
+ x1="145.42192"
+ gradientTransform="matrix(0.148555,-1.034192e-2,0.000000,0.203839,7.587243,-13.64974)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2938"
+ xlink:href="#wihitetolightgray"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="234.35374"
+ x2="184.11906"
+ y1="219.68500"
+ x1="159.18221"
+ gradientTransform="matrix(0.137376,-9.563697e-3,0.000000,0.220427,7.587243,-13.64974)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2940"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="210.46336"
+ x2="84.003502"
+ y1="279.47504"
+ x1="132.72992"
+ gradientTransform="matrix(0.148555,-1.034192e-2,0.000000,0.203839,7.587243,-13.64974)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2943"
+ xlink:href="#wihitetolightgray"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="250.54321"
+ x2="54.607849"
+ y1="213.43617"
+ x1="136.55682"
+ gradientTransform="matrix(0.148555,-1.034192e-2,0.000000,0.203839,7.587243,-13.64974)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2945"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="83.259750"
+ fy="332.37268"
+ fx="86.514435"
+ cy="332.37268"
+ cx="86.514435"
+ gradientTransform="matrix(0.213776,-1.488243e-2,0.000000,0.141649,7.587243,-13.64974)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient2948"
+ xlink:href="#wihitetolightgray"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="247.07323"
+ x2="73.286217"
+ y1="335.76117"
+ x1="86.514435"
+ gradientTransform="matrix(0.213776,-1.488243e-2,0.000000,0.141649,7.587243,-13.64974)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2950"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="6.8465874"
+ inkscape:cx="34.331449"
+ inkscape:cy="26.802583"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:document-units="px"
+ inkscape:grid-bbox="true"
+ inkscape:window-width="1020"
+ inkscape:window-height="691"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF
+ id="RDF5">
+ <cc:Work
+ rdf:about=""
+ id="Work6">
+ <dc:format
+ id="format7">image/svg+xml</dc:format>
+ <dc:type
+ id="type9"
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <g
+ transform="matrix(1.003380,0.000000,0.000000,0.989340,3.064371e-4,0.621087)"
+ id="g1457">
+ <path
+ style="opacity:0.79446638;fill:#0028c6;fill-opacity:0.18099548;stroke:#000000;stroke-width:0.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.035294119"
+ d="M 6.1800241,11.752191 L 42.411763,11.752191 C 44.327630,11.752191 45.870008,13.762478 45.870008,16.259562 L 45.870008,51.816406 C 45.870008,54.313489 44.327630,56.323777 42.411763,56.323777 L 6.1800241,56.323777 C 4.2641564,56.323777 2.7217788,54.313489 2.7217788,51.816406 L 2.7217788,16.259562 C 2.7217788,13.762478 4.2641564,11.752191 6.1800241,11.752191 z "
+ id="rect7971" />
+ <path
+ style="opacity:0.79446638;fill:url(#linearGradient1527);fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.035294119"
+ d="M 6.7511200,12.690196 L 42.982858,12.690196 C 44.538121,36.490139 20.962529,23.157631 3.2928747,52.754411 L 3.2928747,17.197567 C 3.2928747,14.700483 4.8352523,12.690196 6.7511200,12.690196 z "
+ id="path8746"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="opacity:0.97233200;fill:url(#radialGradient1529);fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.035294119"
+ d="M 6.1800241,11.752191 L 42.411763,11.752191 C 44.327630,11.752191 45.870008,13.762478 45.870008,16.259562 L 45.870008,51.816406 C 45.870008,54.313489 44.327630,56.323777 42.411763,56.323777 L 6.1800241,56.323777 C 4.2641564,56.323777 2.7217788,54.313489 2.7217788,51.816406 L 2.7217788,16.259562 C 2.7217788,13.762478 4.2641564,11.752191 6.1800241,11.752191 z "
+ id="path9514" />
+ <path
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 2.1039429,9.7820744 C 1.5251775,9.7663881 0.96486589,9.9894898 0.55099632,10.400419 C 0.13712749,10.811346 -0.094946223,11.374999 -0.092213059,11.962626 L -0.092213059,18.867704 C -0.092213059,20.071990 0.86966429,21.048255 2.0562004,21.048255 C 3.2427364,21.048255 4.2046137,20.071990 4.2046137,18.867704 L 4.2046137,14.167405 L 5.8278594,14.191633 C 6.6127969,14.244543 7.3630068,13.855899 7.7812725,13.179676 C 8.1995375,12.503453 8.2183549,11.648784 7.8302686,10.954272 C 7.4421830,10.259761 6.7098272,9.8374908 5.9233444,9.8547594 L 2.1039429,9.7820744 z "
+ id="path7697" />
+ <path
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 31.871403,9.7814365 C 30.684867,9.7680559 29.712302,10.733474 29.699119,11.937759 C 29.685935,13.142045 30.637125,14.129158 31.823661,14.142539 L 40.918611,14.263680 C 41.705975,14.311054 42.455138,13.914810 42.867933,13.232654 C 43.280728,12.550497 43.290167,11.693130 42.892492,11.001782 C 42.494816,10.310436 41.754563,9.8973008 40.966353,9.9268067 L 31.871403,9.7814365 z "
+ id="path7695"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 45.573507,14.722417 C 45.002912,14.726284 44.457490,14.961373 44.058517,15.375414 C 43.659544,15.789455 43.440095,16.348124 43.448965,16.927197 L 43.448965,26.158197 C 43.448965,27.362483 44.410843,28.338748 45.597379,28.338748 C 46.783915,28.338748 47.745792,27.362483 47.745792,26.158197 L 47.745792,16.927197 C 47.754850,16.339683 47.528894,15.773532 47.119532,15.358045 C 46.710170,14.942560 46.152362,14.713224 45.573507,14.722417 L 45.573507,14.722417 z "
+ id="path1937"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 43.832534,26.692588 C 44.718063,26.866907 45.135153,23.989865 45.069485,19.604618 C 45.015675,16.071244 46.477953,17.496876 46.588198,15.582764 C 46.605189,15.287749 46.213140,15.134351 45.738969,15.149149 C 45.264797,15.163948 44.708503,15.346945 44.397005,15.724716 C 44.219002,15.873843 44.080729,16.087154 43.986898,16.337102 C 43.893069,16.587049 43.843681,16.873633 43.843454,17.169310 C 43.843226,17.464986 43.834354,24.330069 43.832534,26.692588 z "
+ id="path4304"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="opacity:0.79446638;fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 44.855550,25.920267 C 44.847515,26.827450 45.427205,27.571035 46.150325,27.581116 C 46.873444,27.591196 47.466162,26.863950 47.474196,25.956769 L 47.546937,16.848759 C 47.575383,16.246770 47.337455,15.673986 46.927851,15.358378 C 46.518246,15.042772 46.003436,15.035555 45.588312,15.339602 C 45.173189,15.643650 44.925120,16.209621 44.942837,16.812256 L 44.855550,25.920267 z "
+ id="path4306"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 45.573507,46.899901 C 45.002912,46.903768 44.457490,47.138857 44.058517,47.552899 C 43.659544,47.966939 43.440095,48.525608 43.448965,49.104681 L 43.448965,53.901894 L 41.777977,53.901894 C 40.591441,53.901894 39.629564,54.878160 39.629564,56.082445 C 39.629564,57.286731 40.591441,58.262996 41.777977,58.262996 L 45.597379,58.262996 C 46.167934,58.265530 46.715843,58.036607 47.119291,57.627123 C 47.522739,57.217640 47.748288,56.661535 47.745792,56.082445 L 47.745792,49.104681 C 47.754850,48.517167 47.528894,47.951016 47.119532,47.535529 C 46.710170,47.120043 46.152362,46.890708 45.573507,46.899901 z "
+ id="path7691" />
+ <path
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 8.4272673,53.827824 C 7.3482262,53.827617 6.4736286,54.803772 6.4737979,56.008130 C 6.4739672,57.212488 7.3488398,58.188981 8.4278808,58.189188 L 16.699054,58.209355 C 17.415475,58.247986 18.092682,57.843449 18.461147,57.156753 C 18.829611,56.470055 18.829537,55.612637 18.460957,54.925746 C 18.092376,54.238857 17.415101,53.833965 16.698686,53.872219 L 8.4272673,53.827824 z "
+ id="path7751"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 2.1056606,23.987353 C 1.5350657,23.990831 0.98964301,24.202266 0.59066982,24.574649 C 0.19169742,24.947031 -0.027751643,25.449489 -0.018881465,25.970300 L -0.018881465,34.272523 C -0.018881465,35.355640 0.94299583,36.233678 2.1295319,36.233678 C 3.3160680,36.233678 4.2779453,35.355640 4.2779453,34.272523 L 4.2779453,25.970300 C 4.2870034,25.441898 4.0610476,24.932710 3.6516857,24.559028 C 3.2423230,24.185346 2.6845154,23.979085 2.1056606,23.987353 L 2.1056606,23.987353 z "
+ id="path7775"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 2.1056606,40.878909 C 1.5350657,40.882503 0.98964301,41.101035 0.59066982,41.485915 C 0.19169742,41.870795 -0.027751643,42.390117 -0.018881465,42.928405 L -0.018881465,51.509261 C -0.018881465,52.628729 0.94299583,53.536236 2.1295319,53.536236 C 3.3160680,53.536236 4.2779453,52.628729 4.2779453,51.509261 L 4.2779453,42.928405 C 4.2870034,42.382270 4.0610476,41.855993 3.6516857,41.469770 C 3.2423230,41.083547 2.6845154,40.870363 2.1056606,40.878909 L 2.1056606,40.878909 z "
+ id="path7781"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 45.443435,29.434493 C 44.872840,29.438087 44.327417,29.656619 43.928444,30.041499 C 43.529472,30.426379 43.310023,30.945701 43.318893,31.483989 L 43.318893,40.064845 C 43.318893,41.184313 44.280770,42.091820 45.467306,42.091820 C 46.653842,42.091820 47.615720,41.184313 47.615720,40.064845 L 47.615720,31.483989 C 47.624778,30.937854 47.398822,30.411577 46.989461,30.025353 C 46.580097,29.639131 46.022290,29.425947 45.443435,29.434493 L 45.443435,29.434493 z "
+ id="path20031"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 25.311357,53.827824 C 24.232316,53.827617 23.357718,54.803772 23.357888,56.008130 C 23.358058,57.212488 24.232930,58.188981 25.311971,58.189188 L 33.583144,58.209355 C 34.299565,58.247986 34.976772,57.843449 35.345237,57.156753 C 35.713701,56.470055 35.713627,55.612637 35.345047,54.925746 C 34.976466,54.238857 34.299191,53.833965 33.582776,53.872219 L 25.311357,53.827824 z "
+ id="path20029"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 14.055297,9.7458205 C 12.976256,9.7456132 12.101658,10.721769 12.101828,11.926126 C 12.101998,13.130484 12.976870,14.106977 14.055911,14.107184 L 22.327084,14.127352 C 23.043505,14.165982 23.720712,13.761445 24.089177,13.074750 C 24.457641,12.388051 24.457567,11.530633 24.088987,10.843742 C 23.720406,10.156853 23.043131,9.7519616 22.326716,9.7902153 L 14.055297,9.7458205 z "
+ id="path20033"
+ sodipodi:nodetypes="cccccccc" />
+ </g>
+ <g
+ id="g12821"
+ transform="matrix(0.696199,0.000000,0.000000,0.708248,21.27651,37.84947)">
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:8.4754333;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:0.036199097"
+ d="M 31.443570,-46.786978 L 51.456857,-35.004551 L 51.479527,-21.252720 L 9.5298710,6.4263662 L -10.332290,-5.2904158 L -10.426366,-19.280855 L 31.443570,-46.786978 z "
+ id="path12039"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:7.5159512;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:0.036199097"
+ d="M 31.443570,-46.786978 L 51.456857,-35.004551 L 51.479527,-21.252720 L 9.5298710,6.4263662 L -10.332290,-5.2904158 L -10.426366,-19.280855 L 31.443570,-46.786978 z "
+ id="path12807"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:6.6630769;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:0.036199097"
+ d="M 31.443570,-46.786978 L 51.456857,-35.004551 L 51.479527,-21.252720 L 9.5298710,6.4263662 L -10.332290,-5.2904158 L -10.426366,-19.280855 L 31.443570,-46.786978 z "
+ id="path12809"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:5.7035937;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:0.036199097"
+ d="M 31.443570,-46.786978 L 51.456857,-35.004551 L 51.479527,-21.252720 L 9.5298710,6.4263662 L -10.332290,-5.2904158 L -10.426366,-19.280855 L 31.443570,-46.786978 z "
+ id="path12811"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:4.7441106;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:0.036199097"
+ d="M 31.443570,-46.786978 L 51.456857,-35.004551 L 51.479527,-21.252720 L 9.5298710,6.4263662 L -10.332290,-5.2904158 L -10.426366,-19.280855 L 31.443570,-46.786978 z "
+ id="path12813"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.9978461;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:0.036199097"
+ d="M 31.443570,-46.786978 L 51.456857,-35.004551 L 51.479527,-21.252720 L 9.5298710,6.4263662 L -10.332290,-5.2904158 L -10.426366,-19.280855 L 31.443570,-46.786978 z "
+ id="path12815"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.1449723;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:0.036199097"
+ d="M 31.443570,-46.786978 L 51.456857,-35.004551 L 51.479527,-21.252720 L 9.5298710,6.4263662 L -10.332290,-5.2904158 L -10.426366,-19.280855 L 31.443570,-46.786978 z "
+ id="path12817"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.2920985;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:0.036199097"
+ d="M 31.443570,-46.786978 L 51.456857,-35.004551 L 51.479527,-21.252720 L 9.5298710,6.4263662 L -10.332290,-5.2904158 L -10.426366,-19.280855 L 31.443570,-46.786978 z "
+ id="path12819"
+ sodipodi:nodetypes="ccccccc" />
+ </g>
+ <path
+ style="fill:url(#radialGradient2948);fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient2950);stroke-width:0.64930671;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 23.527250,16.908295 L 37.675026,25.667111 L 27.947401,32.409638 L 13.744677,23.705348 L 23.527250,16.908295 z "
+ id="path2646"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:url(#linearGradient2943);fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient2945);stroke-width:0.67249632;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 13.651327,33.802483 L 27.799102,42.424340 L 27.947401,32.409638 L 13.744677,23.705348 L 13.651327,33.802483 z "
+ id="path3416"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:url(#linearGradient2938);fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient2940);stroke-width:0.62611729;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 37.600441,35.833072 L 27.799102,42.424340 L 27.947401,32.409638 L 37.693790,25.735937 L 37.600441,35.833072 z "
+ id="path4180"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:url(#linearGradient2933);fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient2935);stroke-width:0.62611729;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 23.527250,16.908295 L 37.675026,25.667111 L 57.525788,12.226416 L 43.323066,3.5221222 L 23.527250,16.908295 z "
+ id="path4942"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:url(#linearGradient2928);fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient2930);stroke-width:0.60292763;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 37.600441,35.833072 L 57.476250,22.279894 L 57.624549,12.265192 L 37.693790,25.735937 L 37.600441,35.833072 z "
+ id="path5704"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:url(#linearGradient2925);stroke-width:0.88120204;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 43.352337,3.4955980 L 57.540512,12.122573 L 57.556584,22.191526 L 27.816887,42.457876 L 13.735851,33.878966 L 13.669157,23.635306 L 43.352337,3.4955980 z "
+ id="path1875"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:url(#linearGradient2922);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 23.734387,16.986475 L 37.448802,25.682860 L 36.091459,26.613948 L 22.518028,17.728888 L 23.734387,16.986475 z "
+ id="path7264" />
+ <path
+ style="fill:url(#linearGradient2919);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 37.313783,35.763019 L 37.448802,25.682860 L 36.091459,26.613948 L 36.097422,36.505434 L 37.313783,35.763019 z "
+ id="path8032"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:url(#linearGradient2916);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 37.313783,35.763019 L 37.448802,25.682860 L 36.091459,26.613948 L 36.097422,36.505434 L 37.313783,35.763019 z "
+ id="path8034"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:url(#radialGradient2913);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 57.115009,12.516946 L 38.579922,24.672607 C 38.009737,24.948138 37.242032,24.872198 36.869365,24.677449 L 24.002836,16.952421 L 36.317683,25.134159 C 36.501577,25.461311 36.339813,26.086440 35.980531,26.314452 L 27.721177,32.425387 L 36.317683,26.807348 C 36.840184,26.432290 36.967650,26.997787 36.996354,27.387550 L 37.420097,35.709968 L 38.005097,26.689873 C 38.025215,26.178869 38.390989,25.598150 38.806146,25.379218 L 57.115009,12.516946 z "
+ id="path8798"
+ sodipodi:nodetypes="ccccccccccccc" />
+ <path
+ style="opacity:0.45059285;fill:url(#linearGradient2910);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:2.2241998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 28.382239,16.190139 L 30.728363,17.698172 L 45.678574,7.1338998 L 43.297377,5.6640350 L 28.382239,16.190139 z "
+ id="path9568"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="opacity:0.45059285;fill:url(#linearGradient2907);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:2.2241998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 34.354677,17.707185 L 36.700800,19.215217 L 49.760787,9.8067295 L 47.379591,8.3368655 L 34.354677,17.707185 z "
+ id="path9574"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="opacity:0.45059285;fill:url(#linearGradient2904);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:2.2241998;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 40.470919,18.807103 L 42.817042,20.315136 L 53.791267,12.402370 L 51.410071,10.932506 L 40.470919,18.807103 z "
+ id="path9578"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:url(#linearGradient2901);stroke-width:0.93599498;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 23.685829,16.889742 L 43.330622,3.5026466 L 57.587392,12.176218 L 57.457488,22.268067 L 37.675026,35.732929"
+ id="path11173"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="opacity:0.090909071;fill:url(#radialGradient2896);fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient2898);stroke-width:0.64930671;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 23.527250,16.908295 L 37.675026,25.667111 L 27.947401,32.409638 L 13.744677,23.705348 L 23.527250,16.908295 z "
+ id="path16121"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:url(#linearGradient2893);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 43.358168,3.5906688 C 47.363022,6.1094789 51.315631,8.4375519 55.320486,10.956360 C 51.791561,13.969140 45.182687,13.437804 38.802332,13.671877 C 32.487156,13.905952 20.599481,19.596563 17.429440,25.822301 C 16.184726,25.035740 15.079683,24.417290 13.834969,23.630728 C 23.705177,16.943161 33.487959,10.278236 43.358168,3.5906688 z "
+ id="path9625"
+ sodipodi:nodetypes="cczccc" />
+ <path
+ style="opacity:0.098814197;fill:url(#linearGradient2888);fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient2890);stroke-width:0.62611729;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 37.600441,35.833072 L 27.799102,42.424340 L 27.947401,32.409638 L 37.693790,25.735937 L 37.600441,35.833072 z "
+ id="path18403"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="opacity:0.15019758;fill:url(#linearGradient2883);fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient2885);stroke-width:0.67249632;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 13.651327,33.802483 L 27.799102,42.424340 L 27.947401,32.409638 L 13.744677,23.705348 L 13.651327,33.802483 z "
+ id="path18399"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:url(#linearGradient2880);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 13.844539,33.722286 C 17.849394,36.241097 17.487187,36.176390 22.469742,39.239096 C 22.916801,35.725090 17.275299,31.086427 17.429440,25.822301 C 16.184726,25.035740 15.082548,24.407572 13.837834,23.621015 C 13.682491,26.734833 13.858061,32.264076 13.844539,33.722286 z "
+ id="path9627"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:url(#linearGradient2877);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
+ d="M 43.371100,3.6038926 C 47.375955,6.1227026 51.315631,8.4375519 55.320486,10.956360 C 51.791561,13.969140 45.182687,13.437804 38.802332,13.671877 C 32.487156,13.905952 20.599481,19.596563 17.429440,25.822301 C 16.184726,25.035740 15.396273,24.249184 14.151558,23.462627 C 24.021766,16.775060 33.500892,10.291459 43.371100,3.6038926 z "
+ id="path10395"
+ sodipodi:nodetypes="cczccc" />
+ </g>
+</svg>
diff --git a/chalk/plugins/tools/selectiontools/tool_eraser_selection_cursor.png b/chalk/plugins/tools/selectiontools/tool_eraser_selection_cursor.png
new file mode 100644
index 00000000..e6b01060
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_eraser_selection_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/selectiontools/tool_outline_selection.png b/chalk/plugins/tools/selectiontools/tool_outline_selection.png
new file mode 100644
index 00000000..ca1cb1d1
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_outline_selection.png
Binary files differ
diff --git a/chalk/plugins/tools/selectiontools/tool_outline_selection.svg b/chalk/plugins/tools/selectiontools/tool_outline_selection.svg
new file mode 100644
index 00000000..2795dc86
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_outline_selection.svg
@@ -0,0 +1,329 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:export-ydpi="33.000000"
+ inkscape:export-xdpi="33.000000"
+ inkscape:export-filename="/home/cyrille/koffice/chalk/plugins/tools/selectiontools/tool_outline_selection.png"
+ sodipodi:docname="tool_outline_selection.svg"
+ sodipodi:docbase="/home/cyrille/koffice/chalk/plugins/tools/selectiontools"
+ inkscape:version="0.43"
+ sodipodi:version="0.32"
+ id="svg1409"
+ height="48.000000pt"
+ width="48.000000pt">
+ <defs
+ id="defs3">
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.261963,0.000000,0.000000,1.016360,-7.978266,-0.517425)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1333"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.325250,0.000000,0.000000,1.003779,-5.702957,1.287849)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1331"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient9512"
+ gradientTransform="matrix(1.325250,0.000000,0.000000,1.003779,-5.702957,1.287849)"
+ x1="10.878086"
+ y1="4.5492039"
+ x2="39.857029"
+ y2="36.873619"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient10280"
+ gradientTransform="matrix(1.261963,0.000000,0.000000,1.016360,-7.978266,-0.517425)"
+ cx="48.488476"
+ cy="46.914463"
+ fx="48.488476"
+ fy="46.914463"
+ r="31.677956"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="light90to0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.90833336;"
+ offset="0.0000000"
+ id="stop1890" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="1.0000000"
+ id="stop1892" />
+ </linearGradient>
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.181248,0.000000,0.000000,0.943878,-80.46799,5.346100)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient2086"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.240487,0.000000,0.000000,0.932195,-78.33821,7.022631)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2089"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.240487,0.000000,0.000000,0.932195,-78.33821,7.022631)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3732"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.181248,0.000000,0.000000,0.943878,-80.46799,5.346100)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3734"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.472290,0.000000,0.000000,1.176435,-85.47464,-0.281735)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3737"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.546124,0.000000,0.000000,1.161874,-42.82011,1.807868)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3740"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.546124,0.000000,0.000000,1.161874,-82.82011,1.807868)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3748"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.181248,0.000000,0.000000,0.943878,-86.67547,5.346100)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3888"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.240487,0.000000,0.000000,0.932195,-84.54569,7.022631)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3891"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.240487,0.000000,0.000000,0.932195,-84.54569,7.022631)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3899"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.181248,0.000000,0.000000,0.943878,-86.67547,5.346100)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3901"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.842551,0.000000,0.000000,1.472293,-26.91085,-7.897181)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3904"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.934954,0.000000,0.000000,1.454069,-43.58874,-5.282071)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3907"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.934954,0.000000,0.000000,1.454069,-23.58874,-5.282071)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3917"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.934954,0,0,1.454069,-23.58874,-5.282071)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3939"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.842551,0,0,1.472293,-26.91085,-7.897181)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3941"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient3103"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.843411,0,0,1.546427,-39.13262,-18.20529)"
+ cx="48.488476"
+ cy="46.914463"
+ fx="48.488476"
+ fy="46.914463"
+ r="31.677956" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient3106"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.935858,0,0,1.527286,-33.53707,-3.676156)"
+ x1="10.878086"
+ y1="4.5492039"
+ x2="39.857029"
+ y2="36.873619" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-y="29"
+ inkscape:window-x="235"
+ inkscape:window-height="691"
+ inkscape:window-width="1020"
+ inkscape:grid-bbox="true"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:current-layer="layer1"
+ inkscape:cy="22.245206"
+ inkscape:cx="25.345445"
+ inkscape:zoom="9.2345419"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0000000"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <sodipodi:guide
+ orientation="horizontal"
+ position="58.042944"
+ id="guide3109" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1"
+ id="layer1">
+ <g
+ id="g3133">
+ <path
+ sodipodi:nodetypes="cccccscccsccccc"
+ id="rect7971"
+ d="M 22.849394,11.112144 C 22.304047,11.141939 15.425943,11.91869 15.047262,12.331768 L 7.3541343,16.763497 C 8.0507357,13.290837 4.6772127,24.044979 4.9093571,24.829128 L 5.095179,32.48237 C 5.3390662,33.315932 10.443581,34.461964 11.265414,34.588229 C 12.087247,34.714496 16.080953,33.975209 17.072452,35.017738 L 21.804787,36.428944 L 28.316569,46.376029 C 28.84139,47.103755 42.100565,47.249663 42.941988,47.01984 C 43.783409,46.790016 50.779969,35.976608 50.900444,35.072628 L 49.143188,21.49569 C 48.929783,20.447666 44.468877,16.786367 43.524906,16.415097 L 31.648489,11.066661 C 32.438942,9.1963879 23.136303,11.096289 22.849394,11.112144 z "
+ style="opacity:0.79446639;fill:#0028c6;fill-opacity:0.18099551;stroke:#000000;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.03529412" />
+ <path
+ sodipodi:nodetypes="ccccccccccccc"
+ id="path8746"
+ d="M 12.535381,11.98598 C 11.990034,12.015775 7.4691951,16.810337 7.0905141,17.223415 L 4.8943079,23.826314 C 4.3534721,24.419518 3.8370628,31.013486 4.0692068,31.797635 L 8.0381077,33.802504 C 10.387324,34.191552 8.7498127,36.278559 14.421497,33.730917 L 17.425172,34.425233 L 22.799835,37.595929 C 32.678289,33.702865 38.728935,20.276373 45.811149,17.13009 L 47.192189,19.341024 C 47.332337,18.293 41.129487,15.11757 40.185516,14.7463 C 37.675337,13.581188 31.95859,11.853578 31.247222,10.709517 C 23.829936,10.823588 12.82229,11.970124 12.535381,11.98598 z "
+ style="opacity:0.79446639;fill:url(#linearGradient3106);fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.03529412" />
+ <path
+ sodipodi:nodetypes="cccscccc"
+ id="path9514"
+ d="M 24.746657,37.610946 L 22.950097,38.236511 L 28.386172,46.112853 C 28.910993,46.840579 33.910784,49.437334 34.752207,49.207511 C 35.593628,48.977687 43.373306,47.04937 43.493781,46.14539 L 49.251864,38.854219 C 51.341215,32.716608 49.361638,20.120029 48.417667,19.748759 C 48.417667,19.748759 24.285488,38.336184 24.746657,37.610946 z "
+ style="opacity:0.97233199;fill:url(#radialGradient3103);fill-opacity:1;stroke:none;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:0.98913044;stroke-dasharray:none" />
+ <path
+ id="path2106"
+ d="M 36.009663,49.13383 C 41.863248,48.780277 46.878058,43.635578 48.32345,40.661558 C 51.298229,34.540688 52.312887,27.958104 51.036579,25.168694 C 48.381437,19.365798 42.813441,14.821605 35.697096,12.295739 C 31.314921,10.740336 12.085136,10.662141 9.0276896,14.21912 C 5.2475997,18.616808 3.5467148,30.132245 6.0215885,33.31188 C 7.5774802,35.310838 15.400721,32.394315 20.603527,36.054782 C 27.129005,40.645824 27.079432,49.673211 36.009663,49.13383 z "
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#313436;stroke-width:4.55000019;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:9.10000038, 9.10000038;stroke-dashoffset:0;stroke-opacity:1;marker-start:none" />
+ </g>
+ </g>
+</svg>
diff --git a/chalk/plugins/tools/selectiontools/tool_outline_selection_cursor.png b/chalk/plugins/tools/selectiontools/tool_outline_selection_cursor.png
new file mode 100644
index 00000000..10ef65fe
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_outline_selection_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/selectiontools/tool_polygonal_selection.png b/chalk/plugins/tools/selectiontools/tool_polygonal_selection.png
new file mode 100644
index 00000000..eda50984
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_polygonal_selection.png
Binary files differ
diff --git a/chalk/plugins/tools/selectiontools/tool_polygonal_selection.svg b/chalk/plugins/tools/selectiontools/tool_polygonal_selection.svg
new file mode 100644
index 00000000..441dc125
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_polygonal_selection.svg
@@ -0,0 +1,364 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:export-ydpi="33.000000"
+ inkscape:export-xdpi="33.000000"
+ inkscape:export-filename="/home/danny/work/kde/koffice/chalk/chalk/tool_free_form_selection.png"
+ sodipodi:docname="tool_free_form_selection.svg"
+ sodipodi:docbase="/home/danny/work/kde/koffice/chalk/chalk"
+ inkscape:version="0.41"
+ sodipodi:version="0.32"
+ id="svg1409"
+ height="48.000000pt"
+ width="48.000000pt">
+ <defs
+ id="defs3">
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.261963,0.000000,0.000000,1.016360,-7.978266,-0.517425)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1333"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.325250,0.000000,0.000000,1.003779,-5.702957,1.287849)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1331"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient9512"
+ gradientTransform="matrix(1.325250,0.000000,0.000000,1.003779,-5.702957,1.287849)"
+ x1="10.878086"
+ y1="4.5492039"
+ x2="39.857029"
+ y2="36.873619"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient10280"
+ gradientTransform="matrix(1.261963,0.000000,0.000000,1.016360,-7.978266,-0.517425)"
+ cx="48.488476"
+ cy="46.914463"
+ fx="48.488476"
+ fy="46.914463"
+ r="31.677956"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="light90to0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.90833336;"
+ offset="0.0000000"
+ id="stop1890" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="1.0000000"
+ id="stop1892" />
+ </linearGradient>
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.181248,0.000000,0.000000,0.943878,-80.46799,5.346100)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient2086"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.240487,0.000000,0.000000,0.932195,-78.33821,7.022631)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2089"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.240487,0.000000,0.000000,0.932195,-78.33821,7.022631)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3732"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.181248,0.000000,0.000000,0.943878,-80.46799,5.346100)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3734"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.472290,0.000000,0.000000,1.176435,-85.47464,-0.281735)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3737"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.546124,0.000000,0.000000,1.161874,-42.82011,1.807868)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3740"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.546124,0.000000,0.000000,1.161874,-82.82011,1.807868)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3748"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.181248,0.000000,0.000000,0.943878,-86.67547,5.346100)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3888"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.240487,0.000000,0.000000,0.932195,-84.54569,7.022631)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3891"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.240487,0.000000,0.000000,0.932195,-84.54569,7.022631)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3899"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.181248,0.000000,0.000000,0.943878,-86.67547,5.346100)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3901"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.842551,0.000000,0.000000,1.472293,-26.91085,-7.897181)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3904"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.934954,0.000000,0.000000,1.454069,-43.58874,-5.282071)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3907"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.934954,0.000000,0.000000,1.454069,-23.58874,-5.282071)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3917"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.934954,0.000000,0.000000,1.454069,-23.58874,-5.282071)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3939"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.842551,0.000000,0.000000,1.472293,-26.91085,-7.897181)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3941"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-y="0"
+ inkscape:window-x="0"
+ inkscape:window-height="691"
+ inkscape:window-width="1020"
+ inkscape:grid-bbox="true"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:current-layer="layer1"
+ inkscape:cy="27.184176"
+ inkscape:cx="-0.65850022"
+ inkscape:zoom="5.3151547"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0000000"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF
+ id="RDF5">
+ <cc:Work
+ id="Work6"
+ rdf:about="">
+ <dc:format
+ id="format7">image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+ id="type9" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1"
+ id="layer1">
+ <g
+ transform="matrix(1.000467,0.000000,0.000000,1.050353,-1.379828e-2,-4.173866e-3)"
+ id="g3921">
+ <path
+ id="rect7971"
+ d="M 17.375000,2.0000000 C 16.829907,2.0283668 16.316004,2.2629749 15.937500,2.6562500 L 2.5937500,16.468750 C 2.0531670,17.033516 1.8617140,17.847192 2.0937500,18.593750 L 10.937500,48.937500 C 11.181273,49.731102 11.866051,50.317288 12.687500,50.437500 C 13.508949,50.557713 14.320296,50.190471 14.781250,49.500000 L 29.406250,27.281250 L 49.343750,53.750000 C 49.868326,54.442840 50.752719,54.750055 51.593750,54.531250 C 52.434778,54.312444 53.067082,53.610644 53.187500,52.750000 L 57.968750,18.281250 C 58.108832,17.283468 57.537280,16.322221 56.593750,15.968750 L 18.218750,2.1250000 C 17.948669,2.0274078 17.661775,1.9849050 17.375000,2.0000000 z "
+ style="opacity:0.79446638;fill:#0028c6;fill-opacity:0.18099548;stroke:#000000;stroke-width:0.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.035294119" />
+ <path
+ id="path8746"
+ d="M 17.375000,2.0000000 C 16.829907,2.0283668 16.316004,2.2629749 15.937500,2.6562500 L 2.5937500,16.468750 C 2.0531670,17.033516 1.8617140,17.847192 2.0937500,18.593750 L 8.8750000,41.843750 C 14.686753,37.780942 20.518465,34.613010 26.187500,32.187500 L 29.406250,27.281250 L 31.531250,30.093750 C 41.405093,26.387316 50.483592,24.120453 57.562500,21.125000 L 57.968750,18.281250 C 58.108832,17.283468 57.537280,16.322221 56.593750,15.968750 L 18.218750,2.1250000 C 17.948669,2.0274078 17.661775,1.9849050 17.375000,2.0000000 z "
+ style="opacity:0.79446638;fill:url(#linearGradient3939);fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.035294119" />
+ <path
+ id="path9514"
+ d="M 17.375000,2.0000000 C 16.829907,2.0283668 16.316004,2.2629749 15.937500,2.6562500 L 2.5937500,16.468750 C 2.0531669,17.033516 1.8617138,17.847192 2.0937500,18.593750 L 10.937500,48.937500 C 11.181273,49.731102 11.866051,50.317288 12.687500,50.437500 C 13.508949,50.557713 14.320296,50.190471 14.781250,49.500000 L 29.406250,27.281250 L 49.343750,53.750000 C 49.868326,54.442840 50.752719,54.750055 51.593750,54.531250 C 52.434778,54.312444 53.067082,53.610644 53.187500,52.750000 L 57.968750,18.281250 C 58.108832,17.283468 57.537280,16.322221 56.593750,15.968750 L 18.218750,2.1250000 C 17.948669,2.0274078 17.661775,1.9849050 17.375000,2.0000000 z "
+ style="opacity:0.97233200;fill:url(#radialGradient3941);fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.035294119" />
+ <path
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 8.6481316,10.370821 C 9.0694886,10.762535 9.6315137,10.971157 10.209233,10.950300 C 10.786951,10.929442 11.332479,10.680836 11.724507,10.259761 L 18.077610,3.6451297 C 18.906443,2.7821760 18.872528,1.4176197 18.001859,0.59730246 C 17.131190,-0.22301475 15.753473,-0.18845315 14.924639,0.67449856 L 8.5715367,7.2891303 C 8.1605414,7.7038582 7.9367018,8.2657613 7.9511347,8.8465013 C 7.9655693,9.4272353 8.2170464,9.9772121 8.6481316,10.370821 L 8.6481316,10.370821 z "
+ id="path2087"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ sodipodi:nodetypes="ccccccccccccc"
+ id="path2089"
+ d="M 5.5937500,11.343750 C 5.0368829,11.357720 4.4769170,11.568524 4.0625000,12.000000 C 4.0625000,12.000000 0.50659364,15.741591 0.50000000,15.750000 C 0.10513172,16.257539 -0.082274591,16.897542 0.062500000,17.531250 L 1.1250000,21.562500 C 1.2648167,22.129393 1.6218102,22.615962 2.1250000,22.906250 C 2.6281851,23.196535 3.2206730,23.287838 3.7812500,23.125000 C 4.3351411,22.969478 4.8105180,22.597711 5.0937500,22.093750 C 5.3769801,21.589792 5.4676180,20.991512 5.3125000,20.437500 L 4.5937500,17.718750 L 7.2187500,15.000000 C 8.0475832,14.137046 8.0269190,12.757817 7.1562500,11.937500 C 6.7209155,11.527341 6.1506171,11.329780 5.5937500,11.343750 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 7.8868333,38.699343 C 8.4407237,38.543821 8.9116405,38.172834 9.1948718,37.668873 C 9.4781022,37.164915 9.5501733,36.569759 9.3950554,36.015747 L 7.0598062,27.146594 C 6.7551456,25.989514 5.5728074,25.307429 4.4189752,25.623112 C 3.2651421,25.938795 2.5767516,27.132703 2.8814101,28.289785 L 5.2166600,37.158936 C 5.3564767,37.725829 5.7194324,38.209671 6.2226220,38.499959 C 6.7258074,38.790243 7.3262566,38.862181 7.8868333,38.699343 L 7.8868333,38.699343 z "
+ id="path2093"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 14.845837,48.569694 C 15.332393,48.876689 15.923312,48.977728 16.487199,48.850345 C 17.051085,48.722962 17.541200,48.377717 17.848556,47.891381 L 22.868183,40.215537 C 23.523050,39.214136 23.237259,37.879413 22.229852,37.234343 C 21.222444,36.589272 19.874906,36.878133 19.220039,37.879532 L 14.200411,45.555378 C 13.873242,46.038985 13.757226,46.632601 13.878855,47.200646 C 14.000483,47.768683 14.349372,48.262637 14.845837,48.569694 L 14.845837,48.569694 z "
+ id="path2097"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 53.502723,51.490318 C 54.074440,51.554532 54.650310,51.387895 55.102284,51.027459 C 55.554259,50.667026 55.844876,50.142670 55.909511,49.570995 L 57.081400,40.474736 C 57.234286,39.288026 56.395289,38.211345 55.207443,38.069894 C 54.019597,37.928443 52.932720,38.775791 52.779832,39.962498 L 51.607944,49.058758 C 51.524287,49.636614 51.678621,50.221440 52.035689,50.679664 C 52.392753,51.137884 52.922062,51.430367 53.502723,51.490318 L 53.502723,51.490318 z "
+ id="path2107"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 55.454158,36.325345 C 56.025875,36.389559 56.601745,36.222922 57.053719,35.862486 C 57.505694,35.502053 57.796311,34.977697 57.860946,34.406022 L 59.032835,25.309763 C 59.185721,24.123053 58.346724,23.046372 57.158878,22.904921 C 55.971032,22.763470 54.884155,23.610818 54.731267,24.797525 L 53.559379,33.893785 C 53.475722,34.471641 53.630056,35.056467 53.987124,35.514691 C 54.344188,35.972911 54.873497,36.265394 55.454158,36.325345 L 55.454158,36.325345 z "
+ id="path2109"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ sodipodi:nodetypes="cccccccccccccc"
+ id="path2111"
+ d="M 52.125000,12.718750 C 51.578617,12.512884 50.961744,12.530980 50.437500,12.781250 C 49.913260,13.031518 49.527067,13.477034 49.343750,14.031250 C 49.158194,14.575817 49.182597,15.168637 49.437500,15.687500 C 49.692398,16.206364 50.143066,16.626540 50.687500,16.812500 L 55.562500,18.562500 L 55.531250,18.718750 C 55.447594,19.296606 55.580432,19.885526 55.937500,20.343750 C 56.294564,20.801969 56.825589,21.096299 57.406250,21.156250 C 57.977968,21.220463 58.548026,21.047936 59.000000,20.687500 C 59.641312,20.209036 59.634683,19.555393 59.753290,19.028646 L 59.968750,17.312500 C 60.093283,16.325572 59.524592,15.382062 58.593750,15.031250 L 52.125000,12.718750 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 34.876639,8.8113360 C 34.689606,9.3553976 34.726993,9.9537253 34.980487,10.473277 C 35.233979,10.992831 35.682567,11.390545 36.226496,11.577981 L 44.850059,14.700384 C 45.975101,15.107737 47.208498,14.523022 47.604936,13.394384 C 48.001375,12.265747 47.410726,11.020582 46.285688,10.613227 L 37.662124,7.4908252 C 37.116299,7.2834789 36.511906,7.3069090 35.986986,7.5557573 C 35.462070,7.8046027 35.061458,8.2576184 34.876639,8.8113360 L 34.876639,8.8113360 z "
+ id="path2113"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 20.535381,3.6342430 C 20.347428,4.1779876 20.383803,4.7763777 20.636419,5.2963578 C 20.889032,5.8163388 21.336947,6.2148117 21.880557,6.4031665 L 30.498828,9.5401482 C 31.623180,9.9494029 32.857563,9.3667746 33.255910,8.2388091 C 33.654256,7.1108435 33.065714,5.8646820 31.941366,5.4554254 L 23.323095,2.3184446 C 22.777622,2.1101755 22.173190,2.1325835 21.647849,2.3805438 C 21.122514,2.6285012 20.721136,3.0808388 20.535381,3.6342430 L 20.535381,3.6342430 z "
+ id="path2115"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 11.883900,54.049469 C 12.437791,53.893947 12.908707,53.522960 13.191939,53.018999 C 13.475169,52.515041 13.547240,51.919885 13.392122,51.365873 L 11.056873,42.496720 C 10.752212,41.339640 9.5698742,40.657555 8.4160420,40.973238 C 7.2622089,41.288921 6.5738184,42.482829 6.8784769,43.639911 L 9.2137268,52.509062 C 9.3535435,53.075955 9.7164992,53.559797 10.219689,53.850085 C 10.722874,54.140369 11.323323,54.212307 11.883900,54.049469 L 11.883900,54.049469 z "
+ id="path2121"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ sodipodi:nodetypes="ccccccccccccccc"
+ id="path2099"
+ d="M 29.156250,24.562500 C 28.461523,24.581109 27.825733,24.923573 27.437500,25.500000 L 22.781250,32.593750 C 22.457548,33.079684 22.343061,33.651590 22.468750,34.218750 C 22.594438,34.785901 22.938852,35.290252 23.437500,35.593750 C 23.926238,35.897258 24.530788,36.006413 25.093750,35.875000 C 25.656710,35.743585 26.133631,35.394772 26.437500,34.906250 L 29.312500,30.468750 L 29.906250,31.250000 C 30.255702,31.717759 30.767252,32.022222 31.343750,32.093750 C 31.920244,32.165278 32.515769,31.993198 32.968750,31.625000 C 33.418422,31.266142 33.716522,30.730711 33.781250,30.156250 C 33.845978,29.581791 33.671031,29.012439 33.312500,28.562500 C 33.312500,28.562500 30.865791,25.401380 30.843750,25.375000 C 30.423614,24.870406 29.816399,24.544818 29.156250,24.562500 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 42.423622,44.325356 C 42.878330,43.972902 43.175108,43.452021 43.247964,42.878534 C 43.320822,42.305049 43.163721,41.726493 42.811598,41.271522 L 37.311605,33.932222 C 36.594069,32.974726 35.241996,32.787492 34.291657,33.514020 C 33.341318,34.240548 33.152594,35.605716 33.870127,36.563210 L 39.370120,43.902511 C 39.712913,44.375173 40.231215,44.686948 40.806642,44.766633 C 41.382064,44.846318 41.965473,44.687102 42.423622,44.325356 L 42.423622,44.325356 z "
+ id="path2103"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+ d="M 51.816951,56.666238 C 52.271659,56.313784 52.568437,55.792903 52.641293,55.219416 C 52.714151,54.645931 52.557050,54.067375 52.204927,53.612404 L 46.704934,46.273104 C 45.987398,45.315608 44.635325,45.128374 43.684986,45.854902 C 42.734647,46.581430 42.545923,47.946598 43.263456,48.904092 L 48.763449,56.243393 C 49.106242,56.716055 49.624544,57.027830 50.199971,57.107515 C 50.775393,57.187200 51.358802,57.027984 51.816951,56.666238 L 51.816951,56.666238 z "
+ id="path2105"
+ sodipodi:nodetypes="cccccccccc" />
+ </g>
+ </g>
+</svg>
diff --git a/chalk/plugins/tools/selectiontools/tool_polygonal_selection_cursor.png b/chalk/plugins/tools/selectiontools/tool_polygonal_selection_cursor.png
new file mode 100644
index 00000000..6bf000a7
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_polygonal_selection_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/selectiontools/tool_rect_selection.png b/chalk/plugins/tools/selectiontools/tool_rect_selection.png
new file mode 100644
index 00000000..7cb658c8
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_rect_selection.png
Binary files differ
diff --git a/chalk/plugins/tools/selectiontools/tool_rect_selection.svg b/chalk/plugins/tools/selectiontools/tool_rect_selection.svg
new file mode 100644
index 00000000..824bcc78
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_rect_selection.svg
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="48.000000pt"
+ height="48.000000pt"
+ id="svg1409"
+ sodipodi:version="0.32"
+ inkscape:version="0.41"
+ sodipodi:docbase="/home/danny/work/kde/koffice/chalk/chalk"
+ sodipodi:docname="tool_rect_selection.svg"
+ inkscape:export-filename="/home/danny/work/kde/koffice/chalk/chalk/tool_rect_selection.png"
+ inkscape:export-xdpi="33.000000"
+ inkscape:export-ydpi="33.000000">
+ <defs
+ id="defs3">
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.325250,0.000000,0.000000,1.003779,-5.702957,1.287849)"
+ id="linearGradient9512"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ gradientUnits="userSpaceOnUse"
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.261963,0.000000,0.000000,1.016360,-7.978266,-0.517425)"
+ id="radialGradient10280"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ id="light90to0">
+ <stop
+ id="stop1890"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.90833336;" />
+ <stop
+ id="stop1892"
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient1331"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.325250,0.000000,0.000000,1.003779,-5.702957,1.287849)"
+ x1="10.878086"
+ y1="4.5492039"
+ x2="39.857029"
+ y2="36.873619" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient1333"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.261963,0.000000,0.000000,1.016360,-7.978266,-0.517425)"
+ cx="48.488476"
+ cy="46.914463"
+ fx="48.488476"
+ fy="46.914463"
+ r="31.677956" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="5.5000000"
+ inkscape:cx="32.000000"
+ inkscape:cy="40.678134"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:document-units="px"
+ inkscape:grid-bbox="true"
+ inkscape:window-width="1020"
+ inkscape:window-height="691"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF
+ id="RDF5">
+ <cc:Work
+ rdf:about=""
+ id="Work6">
+ <dc:format
+ id="format7">image/svg+xml</dc:format>
+ <dc:type
+ id="type9"
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <g
+ id="g1310"
+ transform="matrix(0.936040,0.000000,0.000000,0.928685,-8.886478e-6,5.826625)">
+ <path
+ id="rect7971"
+ d="M 7.6485855,2.2878450 L 56.351415,2.2878450 C 58.926731,2.2878450 61.000000,4.4309970 61.000000,7.0931190 L 61.000000,45.000000 C 61.000000,47.662122 58.926731,49.805274 56.351415,49.805274 L 7.6485855,49.805274 C 5.0732693,49.805274 3.0000002,47.662122 3.0000002,45.000000 L 3.0000002,7.0931190 C 3.0000002,4.4309970 5.0732693,2.2878450 7.6485855,2.2878450 z "
+ style="opacity:0.79446638;fill:#0028c6;fill-opacity:0.18099548;stroke:#000000;stroke-width:0.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.035294119" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path8746"
+ d="M 8.5132467,3.2878450 L 59.896282,3.2878450 C 62.101921,28.660784 28.667547,14.447098 3.6088412,46.000000 L 3.6088412,8.0931190 C 3.6088412,5.4309970 5.7962062,3.2878450 8.5132467,3.2878450 z "
+ style="opacity:0.79446638;fill:url(#linearGradient1331);fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.035294119" />
+ <path
+ id="path9514"
+ d="M 5.7287330,1.4825710 L 55.271266,1.4825710 C 57.890984,1.4825710 59.999999,3.6257230 59.999999,6.2878450 L 59.999999,44.194726 C 59.999999,46.856848 57.890984,49.000000 55.271266,49.000000 L 5.7287330,49.000000 C 3.1090150,49.000000 1.0000000,46.856848 1.0000000,44.194726 L 1.0000000,6.2878450 C 1.0000000,3.6257230 3.1090150,1.4825710 5.7287330,1.4825710 z "
+ style="opacity:0.97233200;fill:url(#radialGradient1333);fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.035294119" />
+ <path
+ id="path7697"
+ d="M 2.3413348,0.18751303 C 1.7243174,0.17079029 1.1269735,0.40863721 0.68575030,0.84672471 C 0.24452789,1.2848122 -0.0028841323,1.8857183 2.9672780e-05,2.5121821 L 2.9672780e-05,9.8736341 C 2.9672780e-05,11.157514 1.0254798,12.198303 2.2904369,12.198303 C 3.5553939,12.198303 4.5808440,11.157514 4.5808440,9.8736341 L 4.5808440,4.8626808 L 6.3113739,4.8885105 C 7.1481898,4.9449167 7.9479829,4.5305867 8.3938928,3.8096698 C 8.8398019,3.0887537 8.8598630,2.1775984 8.4461271,1.4371840 C 8.0323920,0.69677054 7.2516331,0.24659228 6.4131698,0.26500200 L 2.3413348,0.18751303 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path7695"
+ d="M 47.176002,0.18683303 C 45.911045,0.17256762 44.874201,1.2017931 44.860146,2.4856724 C 44.846091,3.7695518 45.860147,4.8219057 47.125104,4.8361712 L 56.821161,4.9653194 C 57.660564,5.0158241 58.459241,4.5933914 58.899319,3.8661498 C 59.339396,3.1389073 59.349459,2.2248747 58.925501,1.4878344 C 58.501542,0.75079486 57.712364,0.31035500 56.872059,0.34181097 L 47.176002,0.18683303 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccccc"
+ id="path1937"
+ d="M 61.783704,5.4543804 C 61.175397,5.4585016 60.593926,5.7091294 60.168584,6.1505355 C 59.743242,6.5919408 59.509289,7.1875338 59.518746,7.8048791 L 59.518746,17.645978 C 59.518746,18.929858 60.544196,19.970647 61.809153,19.970647 C 63.074110,19.970647 64.099560,18.929858 64.099560,17.645978 L 64.099560,7.8048791 C 64.109217,7.1785351 63.868327,6.5749651 63.431909,6.1320183 C 62.995491,5.6890724 62.400817,5.4445792 61.783704,5.4543804 L 61.783704,5.4543804 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path7691"
+ d="M 61.783704,39.758546 C 61.175397,39.762668 60.593926,40.013295 60.168584,40.454702 C 59.743242,40.896107 59.509289,41.491700 59.518746,42.109045 L 59.518746,47.223317 L 57.737318,47.223317 C 56.472361,47.223317 55.446911,48.264107 55.446911,49.547986 C 55.446911,50.831866 56.472361,51.872655 57.737318,51.872655 L 61.809153,51.872655 C 62.417418,51.875356 63.001539,51.631303 63.431652,51.194756 C 63.861765,50.758209 64.102221,50.165350 64.099560,49.547986 L 64.099560,42.109045 C 64.109217,41.482701 63.868327,40.879131 63.431909,40.436184 C 62.995491,39.993238 62.400817,39.748745 61.783704,39.758546 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path7735"
+ d="M 14.126001,0.18683303 C 12.861044,0.17256762 11.824200,1.2017931 11.810145,2.4856724 C 11.796090,3.7695518 12.810146,4.8219057 14.075103,4.8361712 L 23.771160,4.9653194 C 24.610563,5.0158241 25.409240,4.5933914 25.849318,3.8661498 C 26.289395,3.1389073 26.299458,2.2248747 25.875500,1.4878344 C 25.451541,0.75079486 24.662363,0.31035500 23.822058,0.34181097 L 14.126001,0.18683303 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path7745"
+ d="M 24.746000,47.090119 C 23.481043,47.075854 22.444199,48.105079 22.430144,49.388958 C 22.416089,50.672838 23.430145,51.725192 24.695102,51.739457 L 34.391159,51.868605 C 35.230562,51.919110 36.029239,51.496677 36.469317,50.769436 C 36.909395,50.042193 36.919457,49.128161 36.495499,48.391120 C 36.071541,47.654081 35.282363,47.213641 34.442057,47.245097 L 24.746000,47.090119 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path7751"
+ d="M 7.2160002,47.090119 C 5.9510431,47.075854 4.9141995,48.105079 4.9001443,49.388958 C 4.8860891,50.672838 5.9001452,51.725192 7.1651023,51.739457 L 16.861159,51.868605 C 17.700562,51.919110 18.499239,51.496677 18.939317,50.769436 C 19.379395,50.042193 19.389457,49.128161 18.965499,48.391120 C 18.541541,47.654081 17.752363,47.213641 16.912057,47.245097 L 7.2160002,47.090119 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccccc"
+ id="path7765"
+ d="M 61.699014,22.811910 C 61.090707,22.816032 60.509236,23.066659 60.083894,23.508065 C 59.658552,23.949471 59.424599,24.545064 59.434056,25.162409 L 59.434056,35.003508 C 59.434056,36.287388 60.459506,37.328177 61.724463,37.328177 C 62.989420,37.328177 64.014870,36.287388 64.014870,35.003508 L 64.014870,25.162409 C 64.024527,24.536065 63.783637,23.932495 63.347219,23.489548 C 62.910801,23.046602 62.316127,22.802109 61.699014,22.811910 L 61.699014,22.811910 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccccc"
+ id="path7775"
+ d="M 2.3431661,15.039565 C 1.7348592,15.043687 1.1533882,15.294314 0.72804592,15.735720 C 0.30270448,16.177126 0.068751498,16.772719 0.078207928,17.390064 L 0.078207928,27.231163 C 0.078207928,28.515043 1.1036580,29.555832 2.3686151,29.555832 C 3.6335722,29.555832 4.6590223,28.515043 4.6590223,27.231163 L 4.6590223,17.390064 C 4.6686791,16.763720 4.4277893,16.160150 3.9913717,15.717203 C 3.5549532,15.274257 2.9602788,15.029764 2.3431661,15.039565 L 2.3431661,15.039565 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccccc"
+ id="path7781"
+ d="M 2.3431661,32.317224 C 1.7348592,32.321346 1.1533882,32.571973 0.72804592,33.013379 C 0.30270448,33.454785 0.068751498,34.050378 0.078207928,34.667723 L 0.078207928,44.508822 C 0.078207928,45.792702 1.1036580,46.833491 2.3686151,46.833491 C 3.6335722,46.833491 4.6590223,45.792702 4.6590223,44.508822 L 4.6590223,34.667723 C 4.6686791,34.041379 4.4277893,33.437809 3.9913717,32.994862 C 3.5549532,32.551916 2.9602788,32.307423 2.3431661,32.317224 L 2.3431661,32.317224 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path1546"
+ d="M 30.725998,0.18683303 C 29.461041,0.17256762 28.424197,1.2017931 28.410142,2.4856724 C 28.396087,3.7695518 29.410143,4.8219057 30.675100,4.8361712 L 40.371157,4.9653194 C 41.210560,5.0158241 42.009237,4.5933914 42.449315,3.8661498 C 42.889392,3.1389073 42.899455,2.2248747 42.475497,1.4878344 C 42.051538,0.75079486 41.262360,0.31035500 40.422055,0.34181097 L 30.725998,0.18683303 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path1558"
+ d="M 41.645996,47.090119 C 40.381039,47.075854 39.344195,48.105079 39.330140,49.388958 C 39.316085,50.672838 40.330141,51.725192 41.595098,51.739457 L 51.291155,51.868605 C 52.130558,51.919110 52.929235,51.496677 53.369313,50.769436 C 53.809391,50.042193 53.819453,49.128161 53.395495,48.391120 C 52.971537,47.654081 52.182359,47.213641 51.342053,47.245097 L 41.645996,47.090119 z "
+ style="fill:#313436;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ </g>
+ </g>
+</svg>
diff --git a/chalk/plugins/tools/selectiontools/tool_rectangular_selection_cursor.png b/chalk/plugins/tools/selectiontools/tool_rectangular_selection_cursor.png
new file mode 100644
index 00000000..548d8ace
--- /dev/null
+++ b/chalk/plugins/tools/selectiontools/tool_rectangular_selection_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_crop/Makefile.am b/chalk/plugins/tools/tool_crop/Makefile.am
new file mode 100644
index 00000000..66157332
--- /dev/null
+++ b/chalk/plugins/tools/tool_crop/Makefile.am
@@ -0,0 +1,37 @@
+kde_services_DATA = chalktoolcrop.desktop
+
+# all_includes must remain last!
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalktoolcrop_la_SOURCES = \
+ wdg_tool_crop.ui \
+ tool_crop.cc \
+ kis_tool_crop.cc
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = chalktoolcrop.la
+
+noinst_HEADERS = \
+ tool_crop.h \
+ kis_tool_crop.h
+
+chalktoolcrop_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalktoolcrop_la_LIBADD = ../../../libchalkcommon.la
+
+chalktoolcrop_la_METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
+
+chalkpics_DATA = \
+ tool_crop_cursor.png \
+ tool_crop.png
+
+chalkpicsdir = $(kde_datadir)/chalk/pics
+
diff --git a/chalk/plugins/tools/tool_crop/chalktoolcrop.desktop b/chalk/plugins/tools/tool_crop/chalktoolcrop.desktop
new file mode 100644
index 00000000..ef80a5e6
--- /dev/null
+++ b/chalk/plugins/tools/tool_crop/chalktoolcrop.desktop
@@ -0,0 +1,47 @@
+[Desktop Entry]
+Name=Crop Tool
+Name[bg]=Инструмент за изрязване
+Name[br]=Ostilh krennañ
+Name[ca]=Eina de tall
+Name[cy]=Hidlen Docio
+Name[da]=Beskæringsværktøj
+Name[de]=Zuschneidewerkzeug
+Name[el]=Εργαλείο αποκοπής
+Name[eo]=Tondado-ilo
+Name[es]=Herramienta para recortar
+Name[et]=Kärpimistööriist
+Name[eu]=Ebaki tresna
+Name[fa]=ابزار خط برش
+Name[fr]=Outil découpage
+Name[fy]=Bysnei-ark
+Name[ga]=Uirlis Bhearrtha
+Name[gl]=Ferramenta de Recorte
+Name[he]=כלי חיתוך
+Name[hu]=Levágó eszköz
+Name[is]=Sniðtól
+Name[it]=Strumento di taglio
+Name[ja]=切り取りツール
+Name[km]=ឧបករណ៍​ច្រឹប
+Name[ms]=Alat Pangkas
+Name[nb]=Beskjæringsverktøy
+Name[nds]=Tosniedwarktüüch
+Name[ne]=उपकरण काटछाँट गर्नुहोस्
+Name[nl]=Snijgereedschap
+Name[nn]=Beskjæringsverktøy
+Name[pl]=Narzędzie przycinania
+Name[pt]=Ferramenta de Recorte
+Name[pt_BR]=Ferramenta de Recorte
+Name[ru]=Обрезка
+Name[se]=Čuohpanreaiddut
+Name[sk]=Orezávač
+Name[sl]=Orodje za obrezavo
+Name[sr]=Алат за сасецање
+Name[sr@Latn]=Alat za sasecanje
+Name[sv]=Beskärningsverktyg
+Name[uk]=Засіб обрізування
+Name[zh_CN]=裁剪工具
+Name[zh_TW]=剪裁工具
+ServiceTypes=Chalk/Tool
+Type=Service
+X-KDE-Library=chalktoolcrop
+X-Chalk-Version=2
diff --git a/chalk/plugins/tools/tool_crop/kis_tool_crop.cc b/chalk/plugins/tools/tool_crop/kis_tool_crop.cc
new file mode 100644
index 00000000..30709fd7
--- /dev/null
+++ b/chalk/plugins/tools/tool_crop/kis_tool_crop.cc
@@ -0,0 +1,925 @@
+/*
+ * kis_tool_crop.cc -- part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <tqcheckbox.h>
+#include <tqcombobox.h>
+#include <tqobject.h>
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqpushbutton.h>
+#include <tqrect.h>
+
+#include <kdebug.h>
+#include <kaction.h>
+#include <kcommand.h>
+#include <klocale.h>
+#include <knuminput.h>
+#include <kdebug.h>
+
+#include <kis_global.h>
+#include <kis_painter.h>
+#include <kis_canvas_controller.h>
+#include <kis_canvas_subject.h>
+#include <kis_cursor.h>
+#include <kis_image.h>
+#include <kis_undo_adapter.h>
+#include <kis_button_press_event.h>
+#include <kis_button_release_event.h>
+#include <kis_move_event.h>
+#include <kis_selected_transaction.h>
+#include <kis_selection.h>
+#include <kis_layer.h>
+#include <kis_crop_visitor.h>
+
+#include "kis_tool_crop.h"
+#include "wdg_tool_crop.h"
+
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+
+
+
+KisToolCrop::KisToolCrop()
+ : super(i18n("Crop"))
+{
+ setName("tool_crop");
+ m_cropCursor = KisCursor::load("tool_crop_cursor.png", 6, 6);
+ setCursor(m_cropCursor);
+ m_subject = 0;
+ m_selecting = false;
+ m_rectCrop = TQRect(0, 0, 0, 0);
+ m_handleSize = 13;
+ m_haveCropSelection = false;
+ m_optWidget = 0;
+}
+
+KisToolCrop::~KisToolCrop()
+{
+}
+
+void KisToolCrop::update(KisCanvasSubject *subject)
+{
+ m_subject = subject;
+ super::update(m_subject);
+}
+
+void KisToolCrop::activate()
+{
+ super::activate();
+
+ // No current crop rectangle, try to use the selection of the device to make a rectangle
+ if (m_subject && m_subject->currentImg() && m_subject->currentImg()->activeDevice()) {
+ KisPaintDeviceSP device = m_subject->currentImg()->activeDevice();
+ if (!device->hasSelection()) {
+ //m_rectCrop = m_subject->currentImg()->bounds();
+ //validateSelection();
+ m_haveCropSelection = false;
+ m_selecting = false;
+ }
+ else {
+
+ m_rectCrop = device->selection()->selectedRect();
+ validateSelection();
+ crop();
+ }
+ }
+}
+
+void KisToolCrop::deactivate()
+{
+ clearRect();
+}
+
+
+void KisToolCrop::paint(KisCanvasPainter& gc)
+{
+ paintOutlineWithHandles(gc, TQRect());
+}
+
+void KisToolCrop::paint(KisCanvasPainter& gc, const TQRect& rc)
+{
+ paintOutlineWithHandles(gc, rc);
+}
+
+void KisToolCrop::clearRect()
+{
+ kdDebug() << "Clearing\n";
+ if (m_subject) {
+
+ KisCanvasController *controller = m_subject->canvasController();
+ KisImageSP img = m_subject->currentImg();
+
+ Q_ASSERT(controller);
+
+ controller->kiscanvas()->update();
+
+ m_rectCrop = TQRect(0,0,0,0);
+
+ updateWidgetValues();
+ m_selecting = false;
+ }
+}
+
+void KisToolCrop::buttonPress(KisButtonPressEvent *e)
+{
+ if (m_subject) {
+ KisImageSP img = m_subject->currentImg();
+
+ if (img && img->activeDevice() && e->button() == Qt::LeftButton) {
+
+ TQPoint pos = e->pos().floorTQPoint();
+ TQRect b = img->bounds();
+
+ if (pos.x() < b.x())
+ pos.setX(b.x());
+ else if (pos.x() > b.x() + b.width())
+ pos.setX(b.x() + b.width());
+
+ if (pos.y() < b.y())
+ pos.setY(b.y());
+ else if (pos.y() > b.y() + b.height())
+ pos.setY(b.y() + b.height());
+
+ m_selecting = true;
+
+ if( !m_haveCropSelection ) //if the selection is not set
+ {
+ m_rectCrop = TQRect( pos.x(), pos.y(), 0, 0);
+ paintOutlineWithHandles();
+ }
+ else
+ {
+ KisCanvasController *controller = m_subject->canvasController();
+ m_mouseOnHandleType = mouseOnHandle(controller ->windowToView(pos));
+ m_dragStart = pos;
+ }
+
+ updateWidgetValues();
+ }
+ }
+}
+
+void KisToolCrop::move(KisMoveEvent *e)
+{
+ if ( m_subject && m_subject->currentImg())
+ {
+ if( m_selecting ) //if the user selects
+ {
+ if( !m_haveCropSelection ) //if the cropSelection is not yet set
+ {
+ paintOutlineWithHandles();
+
+ m_rectCrop.setBottomRight( e->pos().floorTQPoint());
+
+ KisImageSP image = m_subject->currentImg();
+
+ m_rectCrop.setRight( TQMIN(m_rectCrop.right(), image->width()));
+ m_rectCrop.setBottom( TQMIN(m_rectCrop.bottom(), image->width()));
+ m_rectCrop = m_rectCrop.normalize();
+
+ paintOutlineWithHandles();
+ }
+ else //if the crop selection is set
+ {
+ m_dragStop = e->pos().floorTQPoint();
+ if (m_mouseOnHandleType != None && m_dragStart != m_dragStop ) {
+
+
+ TQ_INT32 imageWidth = m_subject->currentImg()->width();
+ TQ_INT32 imageHeight = m_subject->currentImg()->height();
+
+ paintOutlineWithHandles();
+
+ TQPoint pos = e->pos().floorTQPoint();
+ if( m_mouseOnHandleType == Inside )
+ {
+ m_rectCrop.moveBy( ( m_dragStop.x() - m_dragStart.x() ), ( m_dragStop.y() - m_dragStart.y() ) );
+ if( m_rectCrop.left() < 0 )
+ {
+ m_rectCrop.moveLeft( 0 );
+ }
+ if( m_rectCrop.right() > imageWidth )
+ {
+ m_rectCrop.moveRight( imageWidth );
+ }
+ if( m_rectCrop.top() < 0 )
+ {
+ m_rectCrop.moveTop( 0 );
+ }
+ if( m_rectCrop.bottom() > imageHeight )
+ {
+ m_rectCrop.moveBottom( imageHeight );
+ }
+ } else if(m_optWidget->boolRatio->isChecked())
+ {
+ TQPoint drag = m_dragStop - m_dragStart;
+ if( ! m_optWidget->boolWidth->isChecked() && !m_optWidget->boolHeight->isChecked() )
+ {
+ switch (m_mouseOnHandleType)
+ {
+ case (UpperLeft):
+ {
+ TQ_INT32 dep = (drag.x() + drag.y()) / 2;
+ m_rectCrop.setTop( m_rectCrop.top() + dep );
+ m_rectCrop.setLeft( (int) ( m_rectCrop.right() - m_optWidget->doubleRatio->value() * m_rectCrop.height() ) );
+ }
+ break;
+ case (LowerRight):
+ {
+ TQ_INT32 dep = (drag.x() + drag.y()) / 2;
+ m_rectCrop.setBottom( m_rectCrop.bottom() + dep );
+ m_rectCrop.setWidth( (int) ( m_optWidget->doubleRatio->value() * m_rectCrop.height() ) );
+ break;
+ }
+ case (UpperRight):
+ {
+ TQ_INT32 dep = (drag.x() - drag.y()) / 2;
+ m_rectCrop.setTop( m_rectCrop.top() - dep );
+ m_rectCrop.setWidth( (int) ( m_optWidget->doubleRatio->value() * m_rectCrop.height() ) );
+ break;
+ }
+ case (LowerLeft):
+ {
+ TQ_INT32 dep = (drag.x() - drag.y()) / 2;
+ m_rectCrop.setBottom( m_rectCrop.bottom() - dep );
+ m_rectCrop.setLeft( (int) ( m_rectCrop.right() - m_optWidget->doubleRatio->value() * m_rectCrop.height() ) );
+ break;
+ }
+ case (Upper):
+ m_rectCrop.setTop( pos.y() + m_dy );
+ m_rectCrop.setWidth( (int) (m_rectCrop.height() * m_optWidget->doubleRatio->value()) );
+ break;
+ case (Lower):
+ m_rectCrop.setBottom( pos.y() + m_dy );
+ m_rectCrop.setWidth( (int) (m_rectCrop.height() * m_optWidget->doubleRatio->value()) );
+ break;
+ case (Left):
+ m_rectCrop.setLeft( pos.x() + m_dx );
+ m_rectCrop.setHeight( (int) (m_rectCrop.width() / m_optWidget->doubleRatio->value()) );
+ break;
+ case (Right):
+ m_rectCrop.setRight( pos.x() + m_dx );
+ m_rectCrop.setHeight( (int) (m_rectCrop.width() / m_optWidget->doubleRatio->value()) );
+ break;
+ case (Inside): // never happen
+ break;
+ }
+ }
+ } else {
+ if( m_optWidget->boolWidth->isChecked() )
+ {
+ m_rectCrop.setWidth( m_optWidget->intWidth->value() + 1 );
+ } else {
+ switch (m_mouseOnHandleType)
+ {
+ case (LowerLeft):
+ case (Left):
+ case (UpperLeft):
+ m_rectCrop.setLeft( pos.x() + m_dx );
+ break;
+ case (Right):
+ case (UpperRight):
+ case (LowerRight):
+ m_rectCrop.setRight( pos.x() + m_dx );
+ break;
+ default:
+ break;
+ }
+ }
+ if( m_optWidget->boolHeight->isChecked() )
+ {
+ m_rectCrop.setHeight( m_optWidget->intHeight->value() + 1 );
+ } else {
+ switch (m_mouseOnHandleType)
+ {
+ case (UpperLeft):
+ case (Upper):
+ case (UpperRight):
+ m_rectCrop.setTop( pos.y() + m_dy );
+ break;
+ case (LowerRight):
+ case (LowerLeft):
+ case (Lower):
+ m_rectCrop.setBottom( pos.y() + m_dy );
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ if( m_rectCrop.height() < 0)
+ {
+ if( m_mouseOnHandleType == Lower)
+ m_mouseOnHandleType = Upper;
+ else if( m_mouseOnHandleType == LowerLeft)
+ m_mouseOnHandleType = UpperLeft;
+ else if( m_mouseOnHandleType == LowerRight)
+ m_mouseOnHandleType = UpperRight;
+ else if( m_mouseOnHandleType == Upper)
+ m_mouseOnHandleType = Lower;
+ else if( m_mouseOnHandleType == UpperLeft)
+ m_mouseOnHandleType = LowerLeft;
+ else if( m_mouseOnHandleType == UpperRight)
+ m_mouseOnHandleType = LowerRight;
+ }
+ if( m_rectCrop.width() < 0)
+ {
+ if( m_mouseOnHandleType == Right)
+ m_mouseOnHandleType = Left;
+ else if( m_mouseOnHandleType == UpperRight)
+ m_mouseOnHandleType = UpperLeft;
+ else if( m_mouseOnHandleType == LowerRight)
+ m_mouseOnHandleType = LowerLeft;
+ else if( m_mouseOnHandleType == Left)
+ m_mouseOnHandleType = Right;
+ else if( m_mouseOnHandleType == UpperLeft)
+ m_mouseOnHandleType = UpperRight;
+ else if( m_mouseOnHandleType == LowerLeft)
+ m_mouseOnHandleType = LowerRight;
+ }
+
+ m_rectCrop = m_rectCrop.normalize();
+ m_rectCrop = m_rectCrop.intersect( TQRect(0,0, imageWidth + 1, imageHeight + 1 ) );
+ m_dragStart = e->pos().floorTQPoint();
+ paintOutlineWithHandles();
+ }
+ }
+ updateWidgetValues();
+ }
+ else //if we are not selecting
+ {
+ if ( m_haveCropSelection ) //if the crop selection is set
+ {
+ KisCanvasController *controller = m_subject->canvasController();
+ TQ_INT32 type = mouseOnHandle(controller->windowToView(e->pos().floorTQPoint()));
+ //set resize cursor if we are on one of the handles
+ setMoveResizeCursor(type);
+ }
+ }
+ }
+}
+
+void KisToolCrop::updateWidgetValues(bool updateratio)
+{
+ TQRect r = realRectCrop();
+ setOptionWidgetX(r.x());
+ setOptionWidgetY(r.y());
+ setOptionWidgetWidth(r.width() );
+ setOptionWidgetHeight(r.height() );
+ if(updateratio && !m_optWidget->boolRatio->isChecked() )
+ setOptionWidgetRatio((double)r.width() / (double)r.height() );
+}
+
+void KisToolCrop::buttonRelease(KisButtonReleaseEvent *e)
+{
+ if (m_subject && m_subject->currentImg() && m_selecting && e->button() == Qt::LeftButton) {
+
+ m_selecting = false;
+ m_haveCropSelection = true;
+
+ paintOutlineWithHandles();
+ validateSelection();
+ paintOutlineWithHandles();
+ }
+}
+
+void KisToolCrop::doubleClick(KisDoubleClickEvent *)
+{
+ if (m_haveCropSelection) crop();
+}
+
+void KisToolCrop::validateSelection(bool updateratio)
+{
+ if (m_subject) {
+ KisImageSP image = m_subject->currentImg();
+
+ if (image) {
+ TQ_INT32 imageWidth = image->width();
+ TQ_INT32 imageHeight = image->height();
+ m_rectCrop.setLeft(TQMAX(0, m_rectCrop.left()));
+ m_rectCrop.setTop(TQMAX(0, m_rectCrop.top()));
+ m_rectCrop.setRight(TQMIN(imageWidth, m_rectCrop.right()));
+ m_rectCrop.setBottom(TQMIN(imageHeight, m_rectCrop.bottom()));
+
+ updateWidgetValues(updateratio);
+ }
+ }
+}
+
+void KisToolCrop::paintOutlineWithHandles()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter gc(canvas);
+ TQRect rc;
+
+ paintOutlineWithHandles(gc, rc);
+ }
+}
+
+void KisToolCrop::paintOutlineWithHandles(KisCanvasPainter& gc, const TQRect&)
+{
+ if (m_subject && (m_selecting || m_haveCropSelection)) {
+ KisCanvasController *controller = m_subject->canvasController();
+ RasterOp op = gc.rasterOp();
+ TQPen old = gc.pen();
+ TQPen pen(TQt::SolidLine);
+ pen.setWidth(1);
+ TQPoint start;
+ TQPoint end;
+
+ Q_ASSERT(controller);
+ start = controller->windowToView(m_rectCrop.topLeft());
+ end = controller->windowToView(m_rectCrop.bottomRight());
+
+ gc.setRasterOp(TQt::NotROP);
+ gc.setPen(pen);
+ //draw handles
+ m_handlesRegion = handles(TQRect(start, end));
+
+ TQ_INT32 startx;
+ TQ_INT32 starty;
+ TQ_INT32 endx;
+ TQ_INT32 endy;
+ if(start.x()<=end.x())
+ {
+ startx=start.x();
+ endx=end.x();
+ }
+ else
+ {
+ startx=end.x();
+ endx=start.x();
+ }
+ if(start.y()<=end.y())
+ {
+ starty=start.y();
+ endy=end.y();
+ }
+ else
+ {
+ starty=end.y();
+ endy=start.y();
+ }
+ //draw upper line of selection
+ gc.drawLine(startx + m_handleSize / 2 + 1, starty, startx + (endx - startx - m_handleSize) / 2 + 1, starty);
+ gc.drawLine(startx + (endx - startx + m_handleSize) / 2 + 1, starty, endx - m_handleSize / 2, starty);
+ //draw lower line of selection
+ gc.drawLine(startx + m_handleSize / 2 + 1, endy, startx + (endx - startx - m_handleSize) / 2 + 1, endy);
+ gc.drawLine(startx + (endx - startx + m_handleSize) / 2 + 1, endy, endx - m_handleSize / 2 , endy);
+ //draw right line of selection
+ gc.drawLine(startx, starty + m_handleSize / 2 + 1, startx, starty + (endy - starty - m_handleSize) / 2 + 1);
+ gc.drawLine(startx, starty + (endy - starty + m_handleSize) / 2 + 1, startx, endy - m_handleSize / 2);
+ //draw left line of selection
+ gc.drawLine(endx, starty + m_handleSize / 2 + 1, endx, starty + (endy - starty - m_handleSize) / 2 + 1);
+ gc.drawLine(endx, starty + (endy - starty + m_handleSize) / 2 + 1, endx, endy - m_handleSize / 2);
+
+ //draw guides
+ gc.drawLine(0,endy,startx - m_handleSize / 2,endy);
+ gc.drawLine(startx,endy + m_handleSize / 2 + 1, startx, controller->kiscanvas()->height());
+ gc.drawLine(endx,0,endx,starty - m_handleSize / 2);
+ gc.drawLine(endx + m_handleSize / 2 + 1,starty, controller->kiscanvas()->width(), starty);
+ TQMemArray <TQRect> rects = m_handlesRegion.tqrects ();
+ for (TQMemArray <TQRect>::ConstIterator it = rects.begin (); it != rects.end (); ++it)
+ {
+ gc.fillRect (*it, TQt::black);
+ }
+
+
+ gc.setRasterOp(op);
+ gc.setPen(old);
+ }
+}
+
+void KisToolCrop::crop() {
+ // XXX: Should cropping be part of KisImage/KisPaintDevice's API?
+
+ m_haveCropSelection = false;
+ setCursor(m_cropCursor);
+
+ KisImageSP img = m_subject->currentImg();
+
+ if (!img)
+ return;
+
+ TQRect rc = realRectCrop().normalize();
+
+ // The visitor adds the undo steps to the macro
+ if (m_optWidget->cmbType->currentItem() == 0) {
+
+ TQRect dirty = img->bounds();
+
+ // The layer(s) under the current layer will take care of adding
+ // undo information to the Crop macro.
+ if (img->undo())
+ img->undoAdapter()->beginMacro(i18n("Crop"));
+
+ KisCropVisitor v(rc, false);
+ KisLayerSP layer = img->activeLayer();
+ layer->accept(v);
+ layer->setDirty( dirty );
+ if (img->undo())
+ img->undoAdapter()->endMacro();
+
+ }
+ else {
+ // Resize creates the undo macro itself
+ img->resize(rc, true);
+ }
+
+ m_rectCrop = TQRect(0,0,0,0);
+
+ updateWidgetValues();
+}
+
+void KisToolCrop::setCropX(int x)
+{
+ if (!m_haveCropSelection) {
+ m_haveCropSelection = true;
+ }
+ else {
+ paintOutlineWithHandles(); // remove outlines
+ }
+
+ m_rectCrop.setX(x);
+
+ validateSelection();
+ paintOutlineWithHandles();
+}
+
+void KisToolCrop::setCropY(int y)
+{
+ if (!m_haveCropSelection) {
+ m_haveCropSelection = true;
+ }
+ else {
+ paintOutlineWithHandles(); // remove outlines
+ }
+
+ m_rectCrop.setY(y);
+
+ validateSelection();
+ paintOutlineWithHandles();
+
+}
+
+void KisToolCrop::setCropWidth(int w)
+{
+ if (!m_haveCropSelection) {
+ m_haveCropSelection = true;
+ }
+ else {
+ paintOutlineWithHandles(); // remove outlines
+ }
+
+ m_rectCrop.setWidth(w + 1);
+
+ if( m_optWidget->boolRatio->isChecked() )
+ {
+ m_rectCrop.setHeight( (int) ( w / m_optWidget->doubleRatio->value() ) );
+ } else {
+ setOptionWidgetRatio((double)m_rectCrop.width() / (double)m_rectCrop.height() );
+ }
+
+ validateSelection();
+ paintOutlineWithHandles();
+
+}
+
+void KisToolCrop::setCropHeight(int h)
+{
+ if (!m_haveCropSelection) {
+ m_haveCropSelection = true;
+ }
+ else {
+ paintOutlineWithHandles(); // remove outlines
+ }
+
+ m_rectCrop.setHeight(h + 1);
+
+ if( m_optWidget->boolRatio->isChecked() )
+ {
+ m_rectCrop.setWidth( (int) ( h * m_optWidget->doubleRatio->value() ) );
+ } else {
+ setOptionWidgetRatio((double)m_rectCrop.width() / (double)m_rectCrop.height() );
+ }
+
+ validateSelection();
+ paintOutlineWithHandles();
+
+}
+
+void KisToolCrop::setRatio(double )
+{
+ if( ! (m_optWidget->boolWidth->isChecked() && m_optWidget->boolHeight->isChecked() ))
+ {
+ if (!m_haveCropSelection) {
+ m_haveCropSelection = true;
+ }
+ else {
+ paintOutlineWithHandles(); // remove outlines
+ }
+ if( m_optWidget->boolWidth->isChecked() )
+ {
+ m_rectCrop.setHeight( (int) ( m_rectCrop.width() / m_optWidget->doubleRatio->value()) );
+ setOptionWidgetHeight( m_rectCrop.height() );
+ } else if(m_optWidget->boolHeight->isChecked()) {
+ m_rectCrop.setWidth( (int) (m_rectCrop.height() * m_optWidget->doubleRatio->value()) );
+ setOptionWidgetWidth( m_rectCrop.width() );
+ } else {
+ int newwidth = (int) (m_optWidget->doubleRatio->value() * m_rectCrop.height());
+ newwidth = (newwidth + m_rectCrop.width()) / 2;
+ m_rectCrop.setWidth( newwidth + 1);
+ setOptionWidgetWidth( newwidth );
+ m_rectCrop.setHeight( (int) (newwidth / m_optWidget->doubleRatio->value()) + 1 );
+ setOptionWidgetHeight( m_rectCrop.height() - 1 );
+ }
+ validateSelection(false);
+ paintOutlineWithHandles();
+ }
+}
+
+void KisToolCrop::setOptionWidgetX(TQ_INT32 x)
+{
+ // Disable signals otherwise we get the valueChanged signal, which we don't want
+ // to go through the logic for setting values that way.
+ m_optWidget->intX->blockSignals(true);
+ m_optWidget->intX->setValue(x);
+ m_optWidget->intX->blockSignals(false);
+}
+
+void KisToolCrop::setOptionWidgetY(TQ_INT32 y)
+{
+ m_optWidget->intY->blockSignals(true);
+ m_optWidget->intY->setValue(y);
+ m_optWidget->intY->blockSignals(false);
+}
+
+void KisToolCrop::setOptionWidgetWidth(TQ_INT32 x)
+{
+ m_optWidget->intWidth->blockSignals(true);
+ m_optWidget->intWidth->setValue(x);
+ m_optWidget->intWidth->blockSignals(false);
+}
+
+void KisToolCrop::setOptionWidgetHeight(TQ_INT32 y)
+{
+ m_optWidget->intHeight->blockSignals(true);
+ m_optWidget->intHeight->setValue(y);
+ m_optWidget->intHeight->blockSignals(false);
+}
+
+void KisToolCrop::setOptionWidgetRatio(double ratio)
+{
+ m_optWidget->doubleRatio->blockSignals(true);
+ m_optWidget->doubleRatio->setValue(ratio);
+ m_optWidget->doubleRatio->blockSignals(false);
+}
+
+
+TQWidget* KisToolCrop::createOptionWidget(TQWidget* tqparent)
+{
+ m_optWidget = new WdgToolCrop(tqparent);
+ Q_CHECK_PTR(m_optWidget);
+
+ connect(m_optWidget->bnCrop, TQT_SIGNAL(clicked()), this, TQT_SLOT(crop()));
+
+ connect(m_optWidget->intX, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(setCropX(int)));
+ connect(m_optWidget->intY, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(setCropY(int)));
+ connect(m_optWidget->intWidth, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(setCropWidth(int)));
+ connect(m_optWidget->intHeight, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(setCropHeight(int)));
+ connect(m_optWidget->doubleRatio, TQT_SIGNAL(valueChanged(double)), this, TQT_SLOT(setRatio( double )));
+
+ return m_optWidget;
+}
+
+TQWidget* KisToolCrop::optionWidget()
+{
+ return m_optWidget;
+}
+
+void KisToolCrop::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Crop"),
+ "tool_crop",
+ 0,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ Q_CHECK_PTR(m_action);
+
+ m_action->setToolTip(i18n("Crop an area"));
+ m_action->setExclusiveGroup("tools");
+
+ m_ownAction = true;
+ }
+}
+
+TQRect toTQRect(double x, double y, int w, int h)
+{
+ return TQRect(int(x), int(y), w, h);
+}
+
+TQRegion KisToolCrop::handles(TQRect rect)
+{
+ TQRegion handlesRegion;
+
+ //add handle at the lower right corner
+ handlesRegion += toTQRect( TQABS( rect.width() ) - m_handleSize / 2.0, TQABS( rect.height() ) - m_handleSize / 2.0, m_handleSize, m_handleSize );
+ //add handle at the upper right corner
+ handlesRegion += toTQRect( TQABS( rect.width() ) - m_handleSize / 2.0 , 0 - m_handleSize / 2.0, m_handleSize, m_handleSize );
+ //add rectangle at the lower left corner
+ handlesRegion += toTQRect( 0 - m_handleSize / 2.0 , TQABS( rect.height() ) - m_handleSize / 2.0, m_handleSize, m_handleSize );
+ //add rectangle at the upper left corner
+ handlesRegion += toTQRect( 0 - m_handleSize / 2.0, 0 - m_handleSize / 2.0, m_handleSize, m_handleSize );
+ //add handle at the lower edge of the rectangle
+ handlesRegion += toTQRect( ( TQABS( rect.width() ) - m_handleSize ) / 2.0 , TQABS( rect.height() ) - m_handleSize / 2.0, m_handleSize, m_handleSize );
+ //add handle at the right edge of the rectangle
+ handlesRegion += toTQRect( TQABS( rect.width() ) - m_handleSize / 2.0 , ( TQABS( rect.height() ) - m_handleSize ) / 2.0, m_handleSize, m_handleSize );
+ //add handle at the upper edge of the rectangle
+ handlesRegion += toTQRect( ( TQABS( rect.width() ) - m_handleSize ) / 2.0 , 0 - m_handleSize / 2.0, m_handleSize, m_handleSize );
+ //add handle at the left edge of the rectangle
+ handlesRegion += toTQRect( 0 - m_handleSize / 2.0, ( TQABS( rect.height() ) - m_handleSize ) / 2.0, m_handleSize, m_handleSize );
+
+ //move the handles to the correct position
+ if( rect.width() >= 0 && rect.height() >= 0)
+ {
+ handlesRegion.translate ( rect.x(), rect.y() );
+ }
+ else if( rect.width() < 0 && rect.height() >= 0)
+ {
+ handlesRegion.translate ( rect.x() - TQABS( rect.width() ), rect.y() );
+ }
+ else if( rect.width() >= 0 && rect.height() < 0)
+ {
+ handlesRegion.translate ( rect.x(), rect.y() - TQABS( rect.height() ) );
+ }
+ else if( rect.width() < 0 && rect.height() < 0)
+ {
+ handlesRegion.translate ( rect.x() - TQABS( rect.width() ), rect.y() - TQABS( rect.height() ) );
+ }
+ return handlesRegion;
+}
+
+TQ_INT32 KisToolCrop::mouseOnHandle(TQPoint currentViewPoint)
+{
+ KisCanvasController *controller = m_subject->canvasController();
+ Q_ASSERT(controller);
+ TQPoint start = controller->windowToView(m_rectCrop.topLeft());
+ TQPoint end = controller->windowToView(m_rectCrop.bottomRight());
+
+ TQ_INT32 startx;
+ TQ_INT32 starty;
+ TQ_INT32 endx;
+ TQ_INT32 endy;
+ if(start.x()<=end.x())
+ {
+ startx=start.x();
+ endx=end.x();
+ }
+ else
+ {
+ startx=end.x();
+ endx=start.x();
+ }
+ if(start.y()<=end.y())
+ {
+ starty=start.y();
+ endy=end.y();
+ }
+ else
+ {
+ starty=end.y();
+ endy=start.y();
+ }
+
+ if ( toTQRect ( startx - m_handleSize / 2.0, starty - m_handleSize / 2.0, m_handleSize, m_handleSize ).tqcontains( currentViewPoint ) )
+ {
+ if( !m_selecting )
+ {
+ m_dx= startx-currentViewPoint.x();
+ m_dy = starty - currentViewPoint.y();
+ }
+ return UpperLeft;
+ }
+ else if ( toTQRect ( startx - m_handleSize / 2.0, endy - m_handleSize / 2.0, m_handleSize, m_handleSize ).tqcontains( currentViewPoint ) )
+ {
+ if( !m_selecting )
+ {
+ m_dx = startx-currentViewPoint.x();
+ m_dy = endy-currentViewPoint.y();
+ }
+ return LowerLeft;
+ }
+ else if ( toTQRect ( endx - m_handleSize / 2.0, starty - m_handleSize / 2.0, m_handleSize, m_handleSize ).tqcontains( currentViewPoint ) )
+ {
+ if( !m_selecting )
+ {
+ m_dx = endx - currentViewPoint.x();
+ m_dy = starty - currentViewPoint.y() ;
+ }
+ return UpperRight;
+ }
+ else if ( toTQRect ( endx - m_handleSize / 2.0, endy - m_handleSize / 2.0, m_handleSize, m_handleSize ).tqcontains( currentViewPoint ) )
+ {
+ if( !m_selecting )
+ {
+ m_dx = endx - currentViewPoint.x();
+ m_dy= endy - currentViewPoint.y();
+ }
+ return LowerRight;
+ }
+ else if ( toTQRect ( startx + ( endx - startx - m_handleSize ) / 2.0, starty - m_handleSize / 2.0, m_handleSize, m_handleSize ).tqcontains( currentViewPoint ) )
+ {
+ if( !m_selecting )
+ {
+ m_dy = starty - currentViewPoint.y() ;
+ }
+ return Upper;
+ }
+ else if ( toTQRect ( startx + ( endx - startx - m_handleSize ) / 2.0, endy - m_handleSize / 2, m_handleSize, m_handleSize ).tqcontains( currentViewPoint ) )
+ {
+ if( !m_selecting )
+ {
+ m_dy = endy - currentViewPoint.y();
+ }
+ return Lower;
+ }
+ else if ( toTQRect ( startx - m_handleSize / 2.0, starty + ( endy - starty - m_handleSize ) / 2.0, m_handleSize, m_handleSize ).tqcontains( currentViewPoint ) )
+ {
+ if( !m_selecting )
+ {
+ m_dx = startx - currentViewPoint.x() ;
+ }
+ return Left;
+ }
+ else if ( toTQRect ( endx - m_handleSize / 2.0 , starty + ( endy - starty - m_handleSize ) / 2.0, m_handleSize, m_handleSize ).tqcontains( currentViewPoint ) )
+ {
+ if( !m_selecting )
+ {
+ m_dx = endx-currentViewPoint.x();
+ }
+ return Right;
+ }
+ else if ( toTQRect ( startx , starty, endx - startx , endy - starty ).tqcontains( currentViewPoint ) )
+ {
+ return Inside;
+ }
+ else return None;
+}
+
+void KisToolCrop::setMoveResizeCursor (TQ_INT32 handle)
+{
+ switch (handle)
+ {
+ case (UpperLeft):
+ case (LowerRight):
+ m_subject->canvasController()->setCanvasCursor(KisCursor::sizeFDiagCursor());
+ return;
+ case (LowerLeft):
+ case (UpperRight):
+ m_subject->canvasController()->setCanvasCursor(KisCursor::sizeBDiagCursor());
+ return;
+ case (Upper):
+ case (Lower):
+ m_subject->canvasController()->setCanvasCursor(KisCursor::sizeVerCursor());
+ return;
+ case (Left):
+ case (Right):
+ m_subject->canvasController()->setCanvasCursor(KisCursor::sizeHorCursor());
+ return;
+ case (Inside):
+ m_subject->canvasController()->setCanvasCursor(KisCursor::sizeAllCursor());
+ return;
+ }
+ m_subject->canvasController()->setCanvasCursor(KisCursor::arrowCursor());
+ return;
+}
+
+
+#include "kis_tool_crop.moc"
diff --git a/chalk/plugins/tools/tool_crop/kis_tool_crop.h b/chalk/plugins/tools/tool_crop/kis_tool_crop.h
new file mode 100644
index 00000000..7ad7c9fd
--- /dev/null
+++ b/chalk/plugins/tools/tool_crop/kis_tool_crop.h
@@ -0,0 +1,149 @@
+/*
+ * kis_tool_crop.h - part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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_TOOL_CROP_H_
+#define KIS_TOOL_CROP_H_
+
+#include <tqpoint.h>
+#include <tqregion.h>
+#include <kis_tool_non_paint.h>
+#include <kis_tool_factory.h>
+
+class TQRect;
+class TQCursor;
+class WdgToolCrop;
+
+/**
+ * Crop tool
+ *
+ * TODO: - crop from selection -- i.e, set crop outline to the exact bounds of the selection.
+ * - (when moving to TQt 4: replace rectangle with darker, dimmer overlay layer
+ * like we have for selections right now)
+ */
+class KisToolCrop : public KisToolNonPaint {
+
+ typedef KisToolNonPaint super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ KisToolCrop();
+ virtual ~KisToolCrop();
+
+ virtual void update(KisCanvasSubject *subject);
+
+ virtual TQWidget* createOptionWidget(TQWidget* tqparent);
+ virtual TQWidget* optionWidget();
+
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_TRANSFORM; }
+ virtual TQ_UINT32 priority() { return 1; }
+ virtual void paint(KisCanvasPainter& gc);
+ virtual void paint(KisCanvasPainter& gc, const TQRect& rc);
+ virtual void buttonPress(KisButtonPressEvent *e);
+ virtual void move(KisMoveEvent *e);
+ virtual void buttonRelease(KisButtonReleaseEvent *e);
+ virtual void doubleClick(KisDoubleClickEvent *);
+
+public slots:
+
+ virtual void activate();
+ virtual void deactivate();
+
+private:
+
+ void clearRect();
+ TQRegion handles(TQRect rect);
+ void paintOutlineWithHandles();
+ void paintOutlineWithHandles(KisCanvasPainter& gc, const TQRect& rc);
+ TQ_INT32 mouseOnHandle (const TQPoint currentViewPoint);
+ void setMoveResizeCursor (TQ_INT32 handle);
+ void validateSelection(bool updateratio = true);
+ void setOptionWidgetX(TQ_INT32 x);
+ void setOptionWidgetY(TQ_INT32 y);
+ void setOptionWidgetWidth(TQ_INT32 x);
+ void setOptionWidgetHeight(TQ_INT32 y);
+ void setOptionWidgetRatio(double ratio);
+
+private slots:
+
+ void crop();
+ void setCropX(int x);
+ void setCropY(int y);
+ void setCropWidth(int x);
+ void setCropHeight(int y);
+ void setRatio(double ratio);
+
+ inline TQRect realRectCrop() { TQRect r = m_rectCrop; r.setSize(r.size() - TQSize(1,1)); return r; }
+
+private:
+ void updateWidgetValues(bool updateratio = true);
+ KisCanvasSubject *m_subject;
+ TQRect m_rectCrop; // Is the coordinate of the outline rect and not of the region to crop (to get the region to crop you need to remove 1 to width and height
+// TQPoint m_startPos;
+// TQPoint m_endPos;
+ bool m_selecting;
+ TQPoint m_dragStart;
+ TQPoint m_dragStop;
+
+ WdgToolCrop* m_optWidget;
+
+ TQ_INT32 m_handleSize;
+ TQRegion m_handlesRegion;
+ bool m_haveCropSelection;
+ TQ_INT32 m_dx, m_dy;
+ TQ_INT32 m_mouseOnHandleType;
+ TQCursor m_cropCursor;
+
+ enum handleType
+ {
+ None = 0,
+ UpperLeft = 1,
+ UpperRight = 2,
+ LowerLeft = 3,
+ LowerRight = 4,
+ Upper = 5,
+ Lower = 6,
+ Left = 7,
+ Right = 8,
+ Inside = 9
+ };
+};
+
+class KisToolCropFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolCropFactory() : super() {};
+ virtual ~KisToolCropFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolCrop();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("crop", i18n("Crop Tool")); }
+};
+
+
+
+#endif // KIS_TOOL_CROP_H_
+
diff --git a/chalk/plugins/tools/tool_crop/tool_crop.cc b/chalk/plugins/tools/tool_crop/tool_crop.cc
new file mode 100644
index 00000000..599c7562
--- /dev/null
+++ b/chalk/plugins/tools/tool_crop/tool_crop.cc
@@ -0,0 +1,62 @@
+/*
+ * tool_crop.cc -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_tool_registry.h>
+
+#include "tool_crop.h"
+#include "kis_tool_crop.h"
+
+
+typedef KGenericFactory<ToolCrop> ToolCropFactory;
+K_EXPORT_COMPONENT_FACTORY( chalktoolcrop, ToolCropFactory( "chalk" ) )
+
+
+ToolCrop::ToolCrop(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ToolCropFactory::instance());
+
+ if ( tqparent->inherits("KisToolRegistry") )
+ {
+ KisToolRegistry * r = dynamic_cast<KisToolRegistry*>(tqparent);
+ r->add(new KisToolCropFactory());
+ }
+
+}
+
+ToolCrop::~ToolCrop()
+{
+}
+
+#include "tool_crop.moc"
diff --git a/chalk/plugins/tools/tool_crop/tool_crop.h b/chalk/plugins/tools/tool_crop/tool_crop.h
new file mode 100644
index 00000000..df5d7c28
--- /dev/null
+++ b/chalk/plugins/tools/tool_crop/tool_crop.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 TOOL_CROP_H_
+#define TOOL_CROP_H_
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+/**
+ * A module that provides a crop tool.
+ */
+class ToolCrop : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ ToolCrop(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ToolCrop();
+
+private:
+
+ KisView * m_view;
+
+};
+
+#endif // TOOL_CROP_H_
diff --git a/chalk/plugins/tools/tool_crop/tool_crop.png b/chalk/plugins/tools/tool_crop/tool_crop.png
new file mode 100644
index 00000000..ce53d708
--- /dev/null
+++ b/chalk/plugins/tools/tool_crop/tool_crop.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_crop/tool_crop_cursor.png b/chalk/plugins/tools/tool_crop/tool_crop_cursor.png
new file mode 100644
index 00000000..325461bb
--- /dev/null
+++ b/chalk/plugins/tools/tool_crop/tool_crop_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_crop/wdg_tool_crop.ui b/chalk/plugins/tools/tool_crop/wdg_tool_crop.ui
new file mode 100644
index 00000000..4f857cf9
--- /dev/null
+++ b/chalk/plugins/tools/tool_crop/wdg_tool_crop.ui
@@ -0,0 +1,216 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgToolCrop</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgToolCrop</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>346</width>
+ <height>123</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Crop</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout3</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>X:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>isbX</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="0" column="1">
+ <property name="name">
+ <cstring>intX</cstring>
+ </property>
+ <property name="maxValue">
+ <number>1000000000</number>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="1" column="3">
+ <property name="name">
+ <cstring>intHeight</cstring>
+ </property>
+ <property name="maxValue">
+ <number>1000000000</number>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="0" column="2">
+ <property name="name">
+ <cstring>boolWidth</cstring>
+ </property>
+ <property name="text">
+ <string>W&amp;idth:</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Will keep the width of the crop constant</string>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="0" column="3">
+ <property name="name">
+ <cstring>intWidth</cstring>
+ </property>
+ <property name="maxValue">
+ <number>1000000000</number>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox" row="1" column="1">
+ <property name="name">
+ <cstring>intY</cstring>
+ </property>
+ <property name="maxValue">
+ <number>1000000000</number>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="1" column="2">
+ <property name="name">
+ <cstring>boolHeight</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Height:</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Will keep the height of the crop constant</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Y:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>isbY</cstring>
+ </property>
+ </widget>
+ <widget class="KDoubleNumInput" row="2" column="3">
+ <property name="name">
+ <cstring>doubleRatio</cstring>
+ </property>
+ <property name="precision">
+ <number>2</number>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="2" column="2">
+ <property name="name">
+ <cstring>boolRatio</cstring>
+ </property>
+ <property name="text">
+ <string>R&amp;atio:</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Will keep the ratio constant</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout9</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="TQComboBox">
+ <item>
+ <property name="text">
+ <string>Layer</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Image</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>cmbType</cstring>
+ </property>
+ <property name="currentItem">
+ <number>1</number>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>bnCrop</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Crop</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>intX</tabstop>
+ <tabstop>intY</tabstop>
+ <tabstop>intWidth</tabstop>
+ <tabstop>intHeight</tabstop>
+ <tabstop>cmbType</tabstop>
+ <tabstop>bnCrop</tabstop>
+</tabstops>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/tools/tool_curves/Makefile.am b/chalk/plugins/tools/tool_curves/Makefile.am
new file mode 100644
index 00000000..5233106a
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/Makefile.am
@@ -0,0 +1,56 @@
+kde_services_DATA = chalktoolcurves.desktop
+
+# all_includes must remain last!
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalktoolcurves_la_SOURCES = \
+ kis_curve_framework.cc \
+ kis_tool_curve.cc \
+ tool_curves.cc \
+ wdg_tool_example.ui \
+ kis_tool_example.cc \
+ kis_tool_bezier.cc \
+ kis_tool_bezier_paint.cc \
+ kis_tool_bezier_select.cc \
+ kis_tool_moutline.cc
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = chalktoolcurves.la
+
+noinst_HEADERS = \
+ kis_curve_framework.h \
+ kis_tool_curve.h \
+ tool_curves.h \
+ kis_tool_example.h \
+ kis_tool_bezier.h \
+ kis_tool_bezier_paint.h \
+ kis_tool_bezier_select.h \
+ kis_tool_moutline.h
+
+chalktoolcurves_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalktoolcurves_la_LIBADD = ../../../libchalkcommon.la
+
+chalktoolcurves_la_METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
+
+chalkpics_DATA = \
+ tool_example.png \
+ tool_example_cursor.png \
+ tool_bezier_paint.png \
+ tool_bezier_select.png \
+ tool_bezier_cursor.png \
+ tool_moutline.png \
+ tool_moutline_cursor.png \
+ tool_curve_dragging.png \
+ tool_moutline_editing.png
+
+chalkpicsdir = $(kde_datadir)/chalk/pics
+
diff --git a/chalk/plugins/tools/tool_curves/chalktoolcurves.desktop b/chalk/plugins/tools/tool_curves/chalktoolcurves.desktop
new file mode 100644
index 00000000..1ab54038
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/chalktoolcurves.desktop
@@ -0,0 +1,36 @@
+[Desktop Entry]
+Name=Curves Tool
+Name[bg]=Инструмент криви
+Name[ca]=Eina de corbes
+Name[da]=Kurveværktøj
+Name[de]=Kurvenwerkzeug
+Name[el]=Εργαλείο καμπύλων
+Name[eo]=Kurvado-ilo
+Name[es]=Herramienta Curvas
+Name[et]=Kõverate tööriist
+Name[fa]=ابزار منحنیها
+Name[fy]=Krommings-ark
+Name[gl]=Ferramenta de Curvas
+Name[hu]=Görberajzoló
+Name[it]=Strumento curve
+Name[ja]=曲線ツール
+Name[km]=ឧបករណ៍​ខ្សែ​កោង
+Name[nb]=Kurveverktøy
+Name[nds]=Bagenwarktüüch
+Name[ne]=वक्र उपकरण
+Name[nl]=Krommen-gereedschap
+Name[pl]=Narzędzie krzywych
+Name[pt]=Ferramenta de Curvas
+Name[pt_BR]=Ferramenta de Curvas
+Name[ru]=Кривые
+Name[sk]=Krivky
+Name[sl]=Orodje za krivulje
+Name[sr]=Алат за криве
+Name[sr@Latn]=Alat za krive
+Name[sv]=Kurvverktyg
+Name[uk]=Криві
+Name[zh_TW]=曲線工具
+ServiceTypes=Chalk/Tool
+Type=Service
+X-KDE-Library=chalktoolcurves
+X-Chalk-Version=2
diff --git a/chalk/plugins/tools/tool_curves/kis_curve_framework.cc b/chalk/plugins/tools/tool_curves/kis_curve_framework.cc
new file mode 100644
index 00000000..416d3bfd
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/kis_curve_framework.cc
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2006 Emanuele Tamponi <emanuele@valinor.it>
+ *
+ * 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 <tqvaluelist.h>
+#include <tqrect.h>
+#include "kis_point.h"
+
+#include "kis_curve_framework.h"
+
+/* **************************** *
+ * KisCurve methods definitions *
+ * **************************** */
+
+KisCurve::iterator KisCurve::addPivot (KisCurve::iterator it, const KisPoint& point)
+{
+ return iterator(*this,m_curve.insert(it.position(), CurvePoint(point,true,false,NOHINTS)));
+}
+
+KisCurve::iterator KisCurve::pushPivot (const KisPoint& point)
+{
+ return selectPivot(iterator(*this,m_curve.append(CurvePoint(point,true,false,NOHINTS))), true);
+}
+
+KisCurve::iterator KisCurve::addPoint (KisCurve::iterator it, const KisPoint& point, bool pivot, bool selected, int hint)
+{
+ return iterator(*this,m_curve.insert(it.position(), CurvePoint(point,pivot,selected, hint)));
+}
+
+KisCurve::iterator KisCurve::addPoint (KisCurve::iterator it, const CurvePoint& point)
+{
+ return iterator(*this,m_curve.insert(it.position(), point));
+}
+
+KisCurve::iterator KisCurve::pushPoint (const KisPoint& point, bool pivot, bool selected,int hint)
+{
+ return iterator(*this,m_curve.append(CurvePoint(point,pivot,selected,hint)));
+}
+
+KisCurve::iterator KisCurve::pushPoint (const CurvePoint& point)
+{
+ return iterator(*this,m_curve.append(point));
+}
+
+KisCurve KisCurve::pivots()
+{
+ KisCurve temp;
+
+ for (iterator it = begin(); it != end(); it = it.nextPivot())
+ temp.pushPoint((*it));
+
+ return temp;
+}
+
+KisCurve KisCurve::selectedPivots(bool selected)
+{
+ KisCurve temp;
+
+ for (iterator it = begin(); it != end(); it = it.nextPivot())
+ if ((*it).isSelected() == selected)
+ temp.pushPoint((*it));
+
+ return temp;
+}
+
+KisCurve KisCurve::subCurve(const KisPoint& tend)
+{
+ return subCurve(tqfind(tend).previousPivot(),tqfind(tend));
+}
+
+KisCurve KisCurve::subCurve(const CurvePoint& tend)
+{
+ return subCurve(tqfind(tend).previousPivot(),tqfind(tend));
+}
+
+KisCurve KisCurve::subCurve(iterator tend)
+{
+ return subCurve(tend.previousPivot(),tend);
+}
+
+KisCurve KisCurve::subCurve(const KisPoint& tstart, const KisPoint& tend)
+{
+ return subCurve(tqfind(tstart),tqfind(tend));
+}
+
+KisCurve KisCurve::subCurve(const CurvePoint& tstart, const CurvePoint& tend)
+{
+ return subCurve(tqfind(tstart),tqfind(tend));
+}
+
+KisCurve KisCurve::subCurve(iterator tstart, iterator tend)
+{
+ KisCurve temp;
+
+ while (tstart != tend && tstart != m_curve.end())
+ temp.pushPoint((*++tstart));
+
+ return temp;
+}
+
+void KisCurve::deleteFirstPivot ()
+{
+ if (!m_curve.isEmpty()) {
+ m_curve.pop_front();
+ while (m_curve.count() > 1 && !first().isPivot())
+ m_curve.pop_front();
+ }
+}
+
+void KisCurve::deleteLastPivot ()
+{
+ if (!m_curve.isEmpty()) {
+ m_curve.pop_back();
+ while (m_curve.count() > 1 && !last().isPivot())
+ m_curve.pop_back();
+ }
+}
+
+KisCurve::iterator KisCurve::deleteCurve (const KisPoint& pos1, const KisPoint& pos2)
+{
+ return deleteCurve (CurvePoint(pos1),CurvePoint(pos2));
+}
+
+KisCurve::iterator KisCurve::deleteCurve (const CurvePoint& pos1, const CurvePoint& pos2)
+{
+ return deleteCurve (tqfind(pos1),tqfind(pos2));
+}
+
+KisCurve::iterator KisCurve::deleteCurve (KisCurve::iterator pos1, KisCurve::iterator pos2)
+{
+ if (pos1 == pos2)
+ return end();
+ iterator pos = pos1;
+ pos++;
+ while (pos != pos2 && pos != end()) {
+ pos = m_curve.erase(pos.position());
+ }
+ return pos;
+}
+
+KisCurve::iterator KisCurve::selectPivot(const KisPoint& pt, bool isSelected)
+{
+ return selectPivot(tqfind(CurvePoint(pt,true)),isSelected);
+}
+
+KisCurve::iterator KisCurve::selectPivot(const CurvePoint& pt, bool isSelected)
+{
+ return selectPivot(tqfind(pt),isSelected);
+}
+
+KisCurve::iterator KisCurve::selectPivot(KisCurve::iterator it, bool isSelected)
+{
+ bool sel = false;
+ if (m_standardkeepselected) {
+ if (m_actionOptions & KEEPSELECTEDOPTION)
+ sel = true;
+ }
+ KisCurve selected = pivots();
+ for (iterator i = selected.begin(); i != selected.end(); i++)
+ (*tqfind((*i))).setSelected(sel);
+ (*it).setSelected(isSelected);
+
+ return it;
+}
+
+KisCurve::iterator KisCurve::movePivot(const KisPoint& oldPt, const KisPoint& newPt)
+{
+ return movePivot(CurvePoint(oldPt,true), newPt);
+}
+
+KisCurve::iterator KisCurve::movePivot(const CurvePoint& oldPt, const KisPoint& newPt)
+{
+ return movePivot(tqfind(oldPt), newPt);
+}
+
+KisCurve::iterator KisCurve::movePivot(KisCurve::iterator it, const KisPoint& newPt)
+{
+ if (!(*it).isPivot())
+ return end();
+
+ (*it).setPoint(newPt);
+
+ if ((*it) != first()) {
+ deleteCurve (it.previousPivot(), it);
+ calculateCurve (it.previousPivot(), it, it);
+ }
+ if ((*it) != last()) {
+ deleteCurve (it, it.nextPivot());
+ calculateCurve (it, it.nextPivot(), it.nextPivot());
+ }
+
+ return it;
+}
+
+void KisCurve::deletePivot (const KisPoint& pt)
+{
+ deletePivot(CurvePoint(pt));
+}
+
+void KisCurve::deletePivot (const CurvePoint& pt)
+{
+ deletePivot(tqfind(pt));
+}
+
+void KisCurve::deletePivot (KisCurve::iterator it)
+{
+ if (!(*it).isPivot())
+ return;
+
+ iterator start = it.previousPivot();
+ iterator end = it.nextPivot();
+
+ if (end == m_curve.end())
+ deleteLastPivot();
+ else if (start == it)
+ deleteFirstPivot();
+ else {
+ deleteCurve(start,end);
+ calculateCurve(start,end,end);
+ }
+}
+
+// Probably it can be optimized - it is smooth though.
+void KisCurve::moveSelected (const KisPoint& trans)
+{
+ KisPoint p;
+ KisCurve sel = selectedPivots();
+
+ for (iterator it = sel.begin(); it != sel.end(); it++) {
+ p = (*it).point() + trans;
+ movePivot((*it),p);
+ }
+}
+
+void KisCurve::deleteSelected ()
+{
+ KisCurve sel = selectedPivots();
+ for (iterator it = sel.begin(); it != sel.end(); it++)
+ deletePivot((*it));
+}
+
+void KisCurve::selectAll(bool sel)
+{
+ for (iterator i = begin(); i != end(); i = i.nextPivot())
+ (*i).setSelected(sel);
+}
diff --git a/chalk/plugins/tools/tool_curves/kis_curve_framework.h b/chalk/plugins/tools/tool_curves/kis_curve_framework.h
new file mode 100644
index 00000000..c27369aa
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/kis_curve_framework.h
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2006 Emanuele Tamponi <emanuele@valinor.it>
+ *
+ * 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_CURVE_FRAMEWORK_H_
+#define KIS_CURVE_FRAMEWORK_H_
+
+#include "kis_point.h"
+
+const int NOHINTS = 0x0000;
+const int POINTHINT = 0x0001;
+const int LINEHINT = 0x0002;
+
+const int NOOPTIONS = 0x0000;
+const int SHIFTOPTION = 0x0001;
+const int CONTROLOPTION = 0x0002;
+const int ALTOPTION = 0x0004;
+
+const int KEEPSELECTEDOPTION = CONTROLOPTION;
+
+class CurvePoint {
+
+ KisPoint m_point;
+ bool m_pivot;
+ bool m_selected; // Only pivots can be selected
+
+ int m_hint;
+
+public:
+
+ /* Constructors and Destructor */
+
+ CurvePoint ();
+ CurvePoint (const KisPoint&, bool = false, bool = false, int = POINTHINT);
+ CurvePoint (double, double, bool = false, bool = false, int = POINTHINT);
+
+ ~CurvePoint () {}
+
+public:
+
+ /* Generic Functions */
+
+ bool operator!= (KisPoint p2) const { if (p2 != m_point) return true; else return false; }
+ bool operator!= (CurvePoint p2) const { if (p2.point() != m_point ||
+ p2.isPivot() != m_pivot ||
+ p2.hint() != m_hint) return true; else return false; }
+
+ bool operator== (KisPoint p2) const { if (p2 == m_point) return true; else return false; }
+ bool operator== (CurvePoint p2) const { if (p2.point() == m_point &&
+ p2.isPivot() == m_pivot &&
+ p2.hint() == m_hint) return true; else return false; }
+
+ KisPoint point() const {return m_point;}
+
+ void setPoint(const KisPoint&);
+ void setPoint(double, double);
+
+ bool isPivot() const {return m_pivot;}
+ bool isSelected() const {return m_selected;}
+ int hint() const {return m_hint;}
+
+ void setPivot(bool p) {m_pivot = p;}
+ void setSelected(bool s) {m_selected = ((m_pivot) ? s : false);} /* Only pivots can be selected */
+ void setHint(int h) {m_hint = h;}
+};
+
+typedef TQValueList<CurvePoint> PointList;
+typedef TQValueList<CurvePoint>::iterator BaseIterator;
+
+class CurveIterator;
+
+class KisCurve {
+
+public:
+
+ KisCurve () {m_actionOptions = NOOPTIONS; m_standardkeepselected = true;}
+ virtual ~KisCurve () {m_curve.clear();}
+
+ friend class CurveIterator;
+ typedef CurveIterator iterator;
+
+protected:
+ /* I need it to be mutable because my iterator needs to access
+ m_curve's end() and begin() functions using a const KisCurve
+ (see below in CurveIterator) */
+ mutable PointList m_curve;
+ int m_actionOptions;
+
+ bool m_standardkeepselected;
+
+ bool checkIterator (iterator checking) const;
+
+public:
+
+ void setActionOptions (int options) {m_actionOptions = options;}
+ void endActionOptions () {m_actionOptions = NOOPTIONS;}
+
+ CurvePoint& operator[](int i) {return m_curve[i];}
+
+ iterator addPoint(iterator, const CurvePoint&);
+ iterator addPoint(iterator, const KisPoint&, bool = false, bool = false, int = POINTHINT);
+
+ iterator pushPoint(const CurvePoint&);
+ iterator pushPoint(const KisPoint&, bool = false, bool = false, int = POINTHINT);
+
+ virtual iterator addPivot(iterator, const KisPoint&);
+ virtual iterator pushPivot(const KisPoint&);
+
+ int count() const {return m_curve.count();}
+ bool isEmpty() const {return m_curve.isEmpty();}
+ CurvePoint first() {return m_curve.front();}
+ CurvePoint last() {return m_curve.back();}
+ void clear() {m_curve.clear();}
+
+ /* These needs iterators so they are implemented inline after the definition of CurveIterator */
+ iterator begin() const;
+ iterator lastIterator() const;
+ iterator end() const;
+ iterator tqfind(const CurvePoint& pt);
+ iterator tqfind(const KisPoint& pt);
+ iterator tqfind(iterator it, const CurvePoint& pt);
+ iterator tqfind(iterator it, const KisPoint& pt);
+
+ KisCurve pivots();
+ KisCurve selectedPivots(bool = true);
+ KisCurve subCurve(const KisPoint&);
+ KisCurve subCurve(const CurvePoint&);
+ KisCurve subCurve(iterator);
+ KisCurve subCurve(const KisPoint&, const KisPoint&);
+ KisCurve subCurve(const CurvePoint&, const CurvePoint&);
+ KisCurve subCurve(iterator,iterator);
+
+ /* Core virtual functions */
+ virtual void deleteFirstPivot();
+ virtual void deleteLastPivot();
+
+ virtual iterator deleteCurve(const KisPoint&, const KisPoint&);
+ virtual iterator deleteCurve(const CurvePoint&, const CurvePoint&);
+ virtual iterator deleteCurve(iterator, iterator);
+
+ /* Core of the Core, calculateCurve is the only function that *needs* an implementation in the derived curves */
+ virtual void calculateCurve(const KisPoint&, const KisPoint&, iterator);
+ virtual void calculateCurve(const CurvePoint&, const CurvePoint&, iterator);
+ virtual void calculateCurve(iterator, iterator, iterator);
+ virtual void calculateCurve(iterator*);
+ virtual void calculateCurve();
+
+ virtual iterator selectPivot(const CurvePoint&, bool = true);
+ virtual iterator selectPivot(const KisPoint&, bool = true);
+ virtual iterator selectPivot(iterator, bool = true);
+
+ virtual iterator movePivot(const CurvePoint&, const KisPoint&);
+ virtual iterator movePivot(const KisPoint&, const KisPoint&);
+ virtual iterator movePivot(iterator, const KisPoint&);
+
+ virtual void deletePivot(const CurvePoint&);
+ virtual void deletePivot(const KisPoint&);
+ virtual void deletePivot(iterator);
+
+ virtual void moveSelected(const KisPoint&);
+ virtual void deleteSelected();
+ virtual void selectAll(bool = true);
+};
+
+class CurveIterator {
+
+ const KisCurve *m_target;
+
+ BaseIterator m_position;
+
+public:
+
+ CurveIterator () { m_target = 0; m_position = 0;}
+
+ CurveIterator (const KisCurve &target)
+ {m_target = &target;}
+
+ CurveIterator (const CurveIterator &it)
+ {m_position = it.position(); m_target = it.target();}
+
+ CurveIterator (const KisCurve &target, BaseIterator it)
+ {m_position = it; m_target = &target;}
+
+ ~CurveIterator () {}
+
+ bool operator==(BaseIterator it) {return m_position == it;}
+ bool operator==(CurveIterator it) {return m_position == it.position();}
+ bool operator!=(BaseIterator it) {return m_position != it;}
+ bool operator!=(CurveIterator it) {return m_position != it.position();}
+
+ CurveIterator operator++() {++m_position;return *this;}
+ CurveIterator operator++(int) {CurveIterator temp = *this; m_position++; return temp;}
+ CurveIterator operator--() {--m_position;return *this;}
+ CurveIterator operator--(int) {CurveIterator temp = *this; m_position--; return temp;}
+ CurveIterator operator+=(int i) {m_position+=i;return *this;}
+ CurveIterator operator-=(int i) {m_position-=i;return *this;}
+ CurveIterator operator=(const BaseIterator &it) {m_position=it; return *this;}
+ CurvePoint& operator*() {return (*m_position);}
+
+ const KisCurve* target() const {return m_target;}
+ BaseIterator position() const {return m_position;}
+
+ CurveIterator next()
+ {
+ CurveIterator it = *this;
+ return ++it;
+ }
+
+ CurveIterator previous()
+ {
+ CurveIterator it = *this;
+ return --it;
+ }
+
+ CurveIterator previousPivot()
+ {
+ CurveIterator it = *this;
+ while (it != m_target->m_curve.begin()) {
+ it-=1;
+ if ((*it).isPivot())
+ return it;
+ }
+
+ return it;
+ }
+
+ CurveIterator nextPivot()
+ {
+ CurveIterator it = *this;
+ while (it != m_target->m_curve.end()) {
+ it+=1;
+ if ((*it).isPivot())
+ return it;
+ }
+ return it;
+ }
+};
+
+/* ************************************* *
+ * CurvePoint inline methods definitions *
+ * ************************************* */
+
+inline CurvePoint::CurvePoint ()
+ : m_pivot(0), m_selected(0), m_hint(POINTHINT)
+{
+
+}
+
+inline CurvePoint::CurvePoint (const KisPoint& pt, bool p, bool s, int h)
+ : m_pivot(p), m_selected((p) ? s : false), m_hint(h)
+{
+ m_point = pt;
+}
+
+inline CurvePoint::CurvePoint (double x, double y, bool p, bool s, int h)
+ : m_pivot(p), m_selected((p) ? s : false), m_hint(h)
+{
+ KisPoint tmp(x,y);
+ m_point = tmp;
+}
+
+inline void CurvePoint::setPoint(const KisPoint& p)
+{
+ m_point = p;
+}
+
+inline void CurvePoint::setPoint(double x, double y)
+{
+ KisPoint tmp(x,y);
+ m_point = tmp;
+}
+
+
+/* *********************************** *
+ * KisCurve inline methods definitions *
+ * *********************************** */
+
+inline bool KisCurve::checkIterator (KisCurve::iterator checking) const
+{
+ if (checking.target() != this)
+ return false;
+ else
+ return true;
+}
+
+inline KisCurve::iterator KisCurve::begin() const
+{
+ return iterator(*this,m_curve.begin());
+}
+
+inline KisCurve::iterator KisCurve::lastIterator() const
+{
+ return (iterator(*this,--m_curve.end()));
+}
+
+inline KisCurve::iterator KisCurve::end() const
+{
+ return iterator(*this,m_curve.end());
+}
+
+inline KisCurve::iterator KisCurve::tqfind (const CurvePoint& pt)
+{
+ return iterator(*this,m_curve.tqfind(pt));
+}
+
+inline KisCurve::iterator KisCurve::tqfind (const KisPoint& pt)
+{
+ return iterator(*this,m_curve.tqfind(CurvePoint(pt)));
+}
+
+inline KisCurve::iterator KisCurve::tqfind (KisCurve::iterator it, const CurvePoint& pt)
+{
+ return iterator(*this,m_curve.tqfind(it.position(),pt));
+}
+
+inline KisCurve::iterator KisCurve::tqfind (iterator it, const KisPoint& pt)
+{
+ return iterator(*this,m_curve.tqfind(it.position(),CurvePoint(pt)));
+}
+
+inline void KisCurve::calculateCurve(const KisPoint& start, const KisPoint& end, KisCurve::iterator it)
+{
+ calculateCurve(tqfind(CurvePoint(start)),tqfind(CurvePoint(end)),it);
+}
+
+inline void KisCurve::calculateCurve(const CurvePoint& start, const CurvePoint& end, KisCurve::iterator it)
+{
+ calculateCurve(tqfind(start),tqfind(end),it);
+}
+
+inline void KisCurve::calculateCurve(KisCurve::iterator, KisCurve::iterator, KisCurve::iterator)
+{
+ return;
+}
+
+/* Really generic functions, provided if someone _really_ needs them: array of iterators and no iterators. */
+inline void KisCurve::calculateCurve(KisCurve::iterator*) {return;}
+inline void KisCurve::calculateCurve() {return;}
+
+#endif // KIS_CURVE_FRAMEWORK_H_
diff --git a/chalk/plugins/tools/tool_curves/kis_tool_bezier.cc b/chalk/plugins/tools/tool_curves/kis_tool_bezier.cc
new file mode 100644
index 00000000..e3baf49c
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/kis_tool_bezier.cc
@@ -0,0 +1,366 @@
+/*
+ * kis_tool_bezier.cc -- part of Chalk
+ *
+ * Copyright (c) 2006 Emanuele Tamponi <emanuele@valinor.it>
+ *
+ * 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 <math.h>
+
+#include <tqpainter.h>
+#include <tqlayout.h>
+#include <tqrect.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <knuminput.h>
+
+#include "kis_global.h"
+#include "kis_doc.h"
+#include "kis_painter.h"
+#include "kis_point.h"
+#include "kis_canvas_subject.h"
+#include "kis_canvas_controller.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+#include "kis_cursor.h"
+#include "kis_vec.h"
+
+#include "kis_curve_framework.h"
+#include "kis_tool_bezier.h"
+
+KisCurve::iterator KisCurveBezier::groupEndpoint (KisCurve::iterator it) const
+{
+ iterator temp = it;
+ if ((*it).hint() == BEZIERNEXTCONTROLHINT)
+ temp -= 1;
+ if ((*it).hint() == BEZIERPREVCONTROLHINT)
+ temp += 1;
+ return temp;
+}
+
+KisCurve::iterator KisCurveBezier::groupPrevControl (KisCurve::iterator it) const
+{
+ iterator temp = it;
+ if ((*it).hint() == BEZIERENDHINT)
+ temp -= 1;
+ if ((*it).hint() == BEZIERNEXTCONTROLHINT)
+ temp -= 2;
+ return temp;
+}
+
+KisCurve::iterator KisCurveBezier::groupNextControl (KisCurve::iterator it) const
+{
+ iterator temp = it;
+ if ((*it).hint() == BEZIERENDHINT)
+ temp += 1;
+ if ((*it).hint() == BEZIERPREVCONTROLHINT)
+ temp += 2;
+ return temp;
+}
+
+bool KisCurveBezier::groupSelected (KisCurve::iterator it) const
+{
+ if ((*groupPrevControl(it)).isSelected() || (*groupEndpoint(it)).isSelected() || (*groupNextControl(it)).isSelected())
+ return true;
+ return false;
+}
+
+KisCurve::iterator KisCurveBezier::nextGroupEndpoint (KisCurve::iterator it) const
+{
+ iterator temp = it;
+ if ((*it).hint() == BEZIERPREVCONTROLHINT) {
+ temp += 2;
+ temp = temp.nextPivot();
+ }
+ if ((*it).hint() == BEZIERENDHINT) {
+ temp += 1;
+ temp = temp.nextPivot();
+ }
+ if ((*it).hint() == BEZIERNEXTCONTROLHINT) {
+ temp = temp.nextPivot();
+ }
+ temp = temp.nextPivot();
+ return temp;
+}
+
+KisCurve::iterator KisCurveBezier::prevGroupEndpoint (KisCurve::iterator it) const
+{
+ iterator temp = it;
+ if ((*it).hint() == BEZIERNEXTCONTROLHINT) {
+ temp -= 1;
+ temp = temp.previousPivot().previousPivot();
+ }
+ if ((*it).hint() == BEZIERENDHINT) {
+ temp = temp.previousPivot().previousPivot();
+ }
+ if ((*it).hint() == BEZIERPREVCONTROLHINT) {
+ temp = temp.previousPivot();
+ }
+ temp = temp.previousPivot();
+ return temp;
+}
+
+KisPoint KisCurveBezier::midpoint (const KisPoint& P1, const KisPoint& P2)
+{
+ KisPoint temp;
+ temp.setX((P1.x()+P2.x())/2);
+ temp.setY((P1.y()+P2.y())/2);
+ return temp;
+}
+
+void KisCurveBezier::recursiveCurve (const KisPoint& P1, const KisPoint& P2, const KisPoint& P3,
+ const KisPoint& P4, int level, KisCurve::iterator it)
+{
+ if (level > m_maxLevel) {
+ addPoint(it,midpoint(P1,P4),false,false,LINEHINT);
+ return;
+ }
+
+ KisPoint L1, L2, L3, L4;
+ KisPoint H, R1, R2, R3, R4;
+
+ L1 = P1;
+ L2 = midpoint(P1, P2);
+ H = midpoint(P2, P3);
+ R3 = midpoint(P3, P4);
+ R4 = P4;
+ L3 = midpoint(L2, H);
+ R2 = midpoint(R3, H);
+ L4 = midpoint(L3, R2);
+ R1 = L4;
+ recursiveCurve(L1, L2, L3, L4, level + 1, it);
+ recursiveCurve(R1, R2, R3, R4, level + 1, it);
+}
+
+void KisCurveBezier::calculateCurve(KisCurve::iterator tstart, KisCurve::iterator tend, KisCurve::iterator)
+{
+ if (pivots().count() < 4)
+ return;
+
+ iterator origin, dest, control1, control2;
+
+ if ((*tstart).hint() == BEZIERENDHINT) {
+ origin = tstart;
+ control1 = tstart.nextPivot();
+ } else if ((*tstart).hint() == BEZIERNEXTCONTROLHINT) {
+ origin = tstart.previousPivot();
+ control1 = tstart;
+ } else if ((*tstart).hint() == BEZIERPREVCONTROLHINT) {
+ origin = tstart.nextPivot();
+ control1 = origin.nextPivot();
+ } else
+ return;
+
+ if ((*tend).hint() == BEZIERENDHINT) {
+ dest = tend;
+ control2 = tend.previousPivot();
+ } else if ((*tend).hint() == BEZIERPREVCONTROLHINT) {
+ dest = tend.nextPivot();
+ control2 = tend;
+ } else if ((*tend).hint() == BEZIERNEXTCONTROLHINT) {
+ dest = tend.previousPivot();
+ control2 = dest.previousPivot();
+ } else
+ return;
+
+ deleteCurve(control1,control2);
+ recursiveCurve((*origin).point(),(*control1).point(),(*control2).point(),(*dest).point(),1,control2);
+
+}
+
+KisCurve::iterator KisCurveBezier::pushPivot (const KisPoint& point)
+{
+ iterator it;
+
+ it = pushPoint(point,true,false,BEZIERENDHINT);
+ if (count() > 1)
+ addPoint(it,point,true,false,BEZIERPREVCONTROLHINT);
+
+ it = pushPoint(point,true,false,BEZIERNEXTCONTROLHINT);
+
+ return selectPivot(it);
+}
+
+KisCurve::iterator KisCurveBezier::movePivot(KisCurve::iterator it, const KisPoint& newPt)
+{
+ if (!(*it).isPivot())
+ return end();
+
+ int hint = (*it).hint();
+ iterator thisEnd, prevEnd, nextEnd;
+
+ thisEnd = groupEndpoint(it);
+ prevEnd = prevGroupEndpoint(it);
+ nextEnd = nextGroupEndpoint(it);
+
+ if (hint == BEZIERENDHINT) {
+ KisPoint trans = newPt - (*it).point();
+ (*thisEnd).setPoint((*thisEnd).point()+trans);
+ (*thisEnd.previous()).setPoint((*thisEnd.previous()).point()+trans);
+ (*thisEnd.next()).setPoint((*thisEnd.next()).point()+trans);
+ } else if (!(m_actionOptions & KEEPSELECTEDOPTION))
+ (*it).setPoint(newPt);
+ if (!(m_actionOptions & KEEPSELECTEDOPTION) && hint != BEZIERENDHINT) {
+ if (nextEnd == end() || (m_actionOptions & SYMMETRICALCONTROLSOPTION)) {
+ KisPoint trans = (*it).point() - (*thisEnd).point();
+ trans = KisPoint(-trans.x()*2,-trans.y()*2);
+ if (hint == BEZIERNEXTCONTROLHINT)
+ (*groupPrevControl(it)).setPoint(newPt+trans);
+ else
+ (*groupNextControl(it)).setPoint(newPt+trans);
+ }
+ }
+
+ if (nextEnd != end() && count() > 4)
+ calculateCurve (thisEnd,nextEnd,iterator());
+ if (prevEnd != thisEnd && count() > 4)
+ calculateCurve (prevEnd,thisEnd,iterator());
+
+ return it;
+}
+
+void KisCurveBezier::deletePivot (KisCurve::iterator it)
+{
+ if (!(*it).isPivot())
+ return;
+
+ iterator prevControl,thisEnd,nextControl;
+
+ prevControl = prevGroupEndpoint(it).nextPivot();
+ thisEnd = groupEndpoint(it);
+ nextControl = nextGroupEndpoint(it).previousPivot();
+
+ if ((*thisEnd) == first()) {
+ deleteFirstPivot();
+ deleteFirstPivot();
+ deleteFirstPivot();
+ } else if ((*thisEnd.next()) == last()) {
+ deleteLastPivot();
+ deleteLastPivot();
+ deleteLastPivot();
+ } else {
+ deleteCurve(prevControl,nextControl);
+ calculateCurve(prevControl,nextControl,iterator());
+ }
+}
+
+KisToolBezier::KisToolBezier(const TQString& UIName)
+ : super(UIName)
+{
+ m_derivated = new KisCurveBezier;
+ m_curve = m_derivated;
+
+ m_supportMinimalDraw = false;
+
+ m_transactionMessage = i18n("Bezier Curve");
+}
+
+KisToolBezier::~KisToolBezier()
+{
+
+}
+
+KisCurve::iterator KisToolBezier::handleUnderMouse(const TQPoint& pos)
+{
+ TQPoint qpos;
+ KisCurve pivs = m_curve->pivots(), inHandle;
+ KisCurve::iterator it;
+ int hint;
+ for (it = pivs.begin(); it != pivs.end(); it++) {
+ qpos = m_subject->canvasController()->windowToView((*it).point().toTQPoint());
+ hint = (*it).hint();
+ if (hint != BEZIERENDHINT && !m_derivated->groupSelected(it))
+ continue;
+ if (hint == BEZIERENDHINT && (m_actionOptions & SHIFTOPTION))
+ continue;
+ if (pivotRect(qpos).tqcontains(pos)) {
+ inHandle.pushPoint((*it));
+ if (hint == BEZIERENDHINT && !(m_actionOptions & SHIFTOPTION))
+ break;
+ if (hint != BEZIERENDHINT && (m_actionOptions & SHIFTOPTION))
+ break;
+ }
+ }
+ if (inHandle.isEmpty())
+ return m_curve->end();
+
+ return m_curve->tqfind(inHandle.last());
+}
+
+KisCurve::iterator KisToolBezier::drawPoint (KisCanvasPainter& gc, KisCurve::iterator point)
+{
+ if ((*point).hint() != BEZIERENDHINT)
+ return ++point;
+
+ KisCanvasController *controller = m_subject->canvasController();
+
+ // Now draw the bezier
+
+ KisCurve::iterator origin,control1,control2,destination;
+
+ origin = point;
+ control1 = origin.next();
+ control2 = control1.nextPivot();
+ destination = control2.next();
+
+ if (control2 != m_curve->end()) {
+ point = control2;
+ TQPointArray vec(4);
+ vec[0] = controller->windowToView((*origin).point().toTQPoint());
+ vec[1] = controller->windowToView((*control1).point().toTQPoint());
+ vec[2] = controller->windowToView((*control2).point().toTQPoint());
+ vec[3] = controller->windowToView((*destination).point().toTQPoint());
+ gc.drawCubicBezier(vec);
+ }
+
+ point += 1;
+
+ return point;
+}
+
+void KisToolBezier::drawPivotHandle (KisCanvasPainter& gc, KisCurve::iterator point)
+{
+ if ((*point).hint() != BEZIERENDHINT)
+ return;
+
+ KisCanvasController *controller = m_subject->canvasController();
+
+ TQPoint endpPos = controller->windowToView((*point).point().toTQPoint());
+
+ if (!m_derivated->groupSelected(point)) {
+ gc.setPen(m_pivotPen);
+ gc.drawRoundRect(pivotRect(endpPos),m_pivotRounding,m_pivotRounding);
+ } else {
+ TQPoint nextControlPos = controller->windowToView((*point.next()).point().toTQPoint());
+ TQPoint prevControlPos = controller->windowToView((*point.previousPivot()).point().toTQPoint());
+
+ gc.setPen(m_selectedPivotPen);
+ gc.drawRoundRect(selectedPivotRect(endpPos),m_selectedPivotRounding,m_selectedPivotRounding);
+ if ((prevControlPos != endpPos || nextControlPos != endpPos) && !(m_actionOptions & CONTROLOPTION)) {
+ gc.drawRoundRect(pivotRect(nextControlPos),m_pivotRounding,m_pivotRounding);
+ gc.drawLine(endpPos,nextControlPos);
+ gc.drawRoundRect(pivotRect(prevControlPos),m_pivotRounding,m_pivotRounding);
+ gc.drawLine(prevControlPos,endpPos);
+ }
+ }
+
+ gc.setPen(m_drawingPen);
+}
+
+#include "kis_tool_bezier.moc"
diff --git a/chalk/plugins/tools/tool_curves/kis_tool_bezier.h b/chalk/plugins/tools/tool_curves/kis_tool_bezier.h
new file mode 100644
index 00000000..e1e0521a
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/kis_tool_bezier.h
@@ -0,0 +1,98 @@
+/*
+ * kis_tool_bezier.h -- part of Chalk
+ *
+ * Copyright (c) 2006 Emanuele Tamponi <emanuele@valinor.it>
+ *
+ * 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_TOOL_BEZIER_H_
+#define KIS_TOOL_BEZIER_H_
+
+#include "kis_tool_factory.h"
+#include "kis_tool_curve.h"
+#include "kis_point.h"
+
+class CurvePoint;
+class KisPoint;
+class KisCanvas;
+class KisCurve;
+class KisPainter;
+class KisPoint;
+
+const int BEZIERENDHINT = 0x0010;
+const int BEZIERPREVCONTROLHINT = 0x0020;
+const int BEZIERNEXTCONTROLHINT = 0x0040;
+
+const int SYMMETRICALCONTROLSOPTION = ALTOPTION;
+const int PREFERCONTROLSOPTION = SHIFTOPTION;
+
+class KisCurveBezier : public KisCurve {
+
+ typedef KisCurve super;
+
+ void recursiveCurve (const KisPoint& P1, const KisPoint& P2, const KisPoint& P3,
+ const KisPoint& P4, int level, iterator it);
+ KisPoint midpoint (const KisPoint&, const KisPoint&);
+
+ int m_maxLevel;
+
+public:
+
+ KisCurveBezier() : super() {m_maxLevel = 5;}
+
+ ~KisCurveBezier() {}
+
+ virtual void calculateCurve(iterator, iterator, iterator);
+ virtual iterator pushPivot(const KisPoint&);
+ virtual iterator movePivot(iterator, const KisPoint&);
+ virtual void deletePivot(iterator);
+
+public:
+
+ iterator groupEndpoint (iterator) const;
+ iterator groupPrevControl (iterator) const;
+ iterator groupNextControl (iterator) const;
+
+ bool groupSelected (iterator) const;
+
+ iterator nextGroupEndpoint (iterator) const;
+ iterator prevGroupEndpoint (iterator) const;
+
+};
+
+class KisToolBezier : public KisToolCurve {
+
+ typedef KisToolCurve super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolBezier(const TQString&);
+ virtual ~KisToolBezier();
+
+protected:
+
+ virtual KisCurve::iterator handleUnderMouse(const TQPoint& pos);
+ virtual void drawPivotHandle(KisCanvasPainter& gc, KisCurve::iterator point);
+ virtual KisCurve::iterator drawPoint(KisCanvasPainter& gc, KisCurve::iterator point);
+
+protected:
+
+ KisCurveBezier *m_derivated;
+
+};
+
+#endif //__KIS_TOOL_BEZIER_H__
diff --git a/chalk/plugins/tools/tool_curves/kis_tool_bezier_paint.cc b/chalk/plugins/tools/tool_curves/kis_tool_bezier_paint.cc
new file mode 100644
index 00000000..663e1324
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/kis_tool_bezier_paint.cc
@@ -0,0 +1,115 @@
+/*
+ * kis_tool_curve.cc -- part of Chalk
+ *
+ * Copyright (c) 2006 Emanuele Tamponi <emanuele@valinor.it>
+ *
+ * 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 <tqpainter.h>
+#include <tqlayout.h>
+#include <tqrect.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqwhatsthis.h>
+#include <tqcheckbox.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kiconloader.h>
+
+#include "kis_cmb_composite.h"
+#include "kis_colorspace.h"
+#include "kis_config.h"
+#include "kis_cursor.h"
+#include "kis_doc.h"
+#include "kis_global.h"
+#include "kis_image.h"
+#include "kis_int_spinbox.h"
+#include "kis_paint_device.h"
+#include "kis_painter.h"
+#include "kis_paintop_registry.h"
+#include "kis_point.h"
+#include "kis_tool_controller.h"
+#include "kis_tool_paint.h"
+
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+#include "kis_canvas_subject.h"
+
+#include "kis_curve_framework.h"
+#include "kis_tool_bezier_paint.h"
+
+KisToolBezierPaint::KisToolBezierPaint()
+ : super(i18n("Bezier Painting Tool"))
+{
+ setName("tool_bezier_paint");
+ m_cursor = "tool_bezier_cursor.png";
+ setCursor(KisCursor::load(m_cursor, 6, 6));
+}
+
+KisToolBezierPaint::~KisToolBezierPaint()
+{
+
+}
+
+KisCurve::iterator KisToolBezierPaint::paintPoint (KisPainter& painter, KisCurve::iterator point)
+{
+ KisCurve::iterator origin,destination,control1,control2;
+ switch ((*point).hint()) {
+ case BEZIERENDHINT:
+ origin = point++;
+ control1 = point;
+ control2 = control1.nextPivot();
+ destination = control2.next();
+ if (m_curve->count() > 4 && (*point) != m_curve->last()) {
+ point = point.nextPivot().next();
+ painter.paintAt((*origin).point(),PRESSURE_DEFAULT,0,0);
+ painter.paintBezierCurve((*origin).point(),PRESSURE_DEFAULT,0,0,(*control1).point(),
+ (*control2).point(),(*destination).point(),PRESSURE_DEFAULT,0,0,0);
+ }
+ break;
+ default:
+ point = super::paintPoint(painter,point);
+ }
+
+ return point;
+}
+
+void KisToolBezierPaint::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ KShortcut shortcut(TQt::Key_Plus);
+ shortcut.append(KShortcut(TQt::Key_F9));
+ m_action = new KRadioAction(i18n("&Bezier"),
+ "tool_bezier_paint",
+ shortcut,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ Q_CHECK_PTR(m_action);
+
+ m_action->setToolTip(i18n("Draw cubic beziers. Keep Alt, Control or Shift pressed for options. Return or double-click to finish."));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+#include "kis_tool_bezier_paint.moc"
diff --git a/chalk/plugins/tools/tool_curves/kis_tool_bezier_paint.h b/chalk/plugins/tools/tool_curves/kis_tool_bezier_paint.h
new file mode 100644
index 00000000..c2a3715b
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/kis_tool_bezier_paint.h
@@ -0,0 +1,63 @@
+/*
+ * kis_tool_curve_paint.h -- part of Chalk
+ *
+ * Copyright (c) 2006 Emanuele Tamponi <emanuele@valinor.it>
+ *
+ * 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_TOOL_BEZIER_PAINT_H_
+#define KIS_TOOL_BEZIER_PAINT_H_
+
+#include "kis_tool_factory.h"
+#include "kis_tool_bezier.h"
+#include "kis_point.h"
+
+class KisToolBezierPaint : public KisToolBezier {
+
+ typedef KisToolBezier super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolBezierPaint();
+ virtual ~KisToolBezierPaint();
+
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_SHAPE; }
+ virtual TQ_UINT32 priority() { return 7; }
+
+protected:
+
+ virtual KisCurve::iterator paintPoint(KisPainter& painter, KisCurve::iterator point);
+
+};
+
+class KisToolBezierPaintFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolBezierPaintFactory() : super() {};
+ virtual ~KisToolBezierPaintFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolBezierPaint();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("beziertqshape", i18n("Bezier Painting Tool")); }
+};
+
+#endif //__KIS_TOOL_CURVE_PAINT_H_
diff --git a/chalk/plugins/tools/tool_curves/kis_tool_bezier_select.cc b/chalk/plugins/tools/tool_curves/kis_tool_bezier_select.cc
new file mode 100644
index 00000000..ed1200d4
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/kis_tool_bezier_select.cc
@@ -0,0 +1,104 @@
+/*
+ * kis_tool_curve.cc -- part of Chalk
+ *
+ * Copyright (c) 2006 Emanuele Tamponi <emanuele@valinor.it>
+ *
+ * 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 <tqpainter.h>
+#include <tqlayout.h>
+#include <tqrect.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqwhatsthis.h>
+#include <tqcheckbox.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kiconloader.h>
+
+#include "kis_cmb_composite.h"
+#include "kis_colorspace.h"
+#include "kis_config.h"
+#include "kis_cursor.h"
+#include "kis_doc.h"
+#include "kis_global.h"
+#include "kis_image.h"
+#include "kis_int_spinbox.h"
+#include "kis_paint_device.h"
+#include "kis_painter.h"
+#include "kis_paintop_registry.h"
+#include "kis_point.h"
+#include "kis_tool_controller.h"
+#include "kis_tool_paint.h"
+
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+#include "kis_canvas_subject.h"
+
+#include "kis_curve_framework.h"
+#include "kis_tool_bezier_select.h"
+
+KisToolBezierSelect::KisToolBezierSelect()
+ : super(i18n("Bezier Selection Tool"))
+{
+ setName("tool_bezier_select");
+ m_cursor = "tool_bezier_cursor.png";
+ setCursor(KisCursor::load(m_cursor, 6, 6));
+}
+
+KisToolBezierSelect::~KisToolBezierSelect()
+{
+
+}
+
+TQValueVector<KisPoint> KisToolBezierSelect::convertCurve()
+{
+ TQValueVector<KisPoint> points;
+
+ for (KisCurve::iterator i = m_curve->begin(); i != m_curve->end(); i++) {
+ if (((*i).hint() != BEZIERPREVCONTROLHINT) && ((*i).hint() != BEZIERNEXTCONTROLHINT))
+ points.append((*i).point());
+ }
+
+ return points;
+}
+
+void KisToolBezierSelect::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ KShortcut shortcut(TQt::Key_Plus);
+ shortcut.append(KShortcut(TQt::Key_F9));
+ m_action = new KRadioAction(i18n("&Bezier"),
+ "tool_bezier_select",
+ shortcut,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ Q_CHECK_PTR(m_action);
+
+ m_action->setToolTip(i18n("Select areas of the image with bezier paths."));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+#include "kis_tool_bezier_select.moc"
diff --git a/chalk/plugins/tools/tool_curves/kis_tool_bezier_select.h b/chalk/plugins/tools/tool_curves/kis_tool_bezier_select.h
new file mode 100644
index 00000000..07aecc3a
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/kis_tool_bezier_select.h
@@ -0,0 +1,63 @@
+/*
+ * kis_tool_curve_paint.h -- part of Chalk
+ *
+ * Copyright (c) 2006 Emanuele Tamponi <emanuele@valinor.it>
+ *
+ * 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_TOOL_BEZIER_SELECT_H_
+#define KIS_TOOL_BEZIER_SELECT_H_
+
+#include "kis_tool_factory.h"
+#include "kis_tool_bezier.h"
+#include "kis_point.h"
+
+class KisToolBezierSelect : public KisToolBezier {
+
+ typedef KisToolBezier super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolBezierSelect();
+ virtual ~KisToolBezierSelect();
+
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_SELECT; }
+ virtual TQ_UINT32 priority() { return 10; }
+
+protected:
+
+ virtual TQValueVector<KisPoint> convertCurve();
+
+};
+
+class KisToolBezierSelectFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolBezierSelectFactory() : super() {};
+ virtual ~KisToolBezierSelectFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolBezierSelect();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("bezierselection", i18n("Bezier Selection Tool")); }
+};
+
+#endif //__KIS_TOOL_CURVE_PAINT_H_
diff --git a/chalk/plugins/tools/tool_curves/kis_tool_curve.cc b/chalk/plugins/tools/tool_curves/kis_tool_curve.cc
new file mode 100644
index 00000000..f98d2c72
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/kis_tool_curve.cc
@@ -0,0 +1,593 @@
+/*
+ * kis_tool_curve.cc -- part of Chalk
+ *
+ * Copyright (c) 2006 Emanuele Tamponi <emanuele@valinor.it>
+ *
+ * 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 <math.h>
+#include <limits.h>
+
+#include <tqapplication.h>
+#include <tqpainter.h>
+#include <tqlayout.h>
+#include <tqrect.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "kis_global.h"
+#include "kis_doc.h"
+#include "kis_painter.h"
+#include "kis_point.h"
+#include "kis_canvas_subject.h"
+#include "kis_canvas_controller.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_move_event.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+#include "kis_cursor.h"
+#include "kis_tool_controller.h"
+#include "kis_vec.h"
+#include "kis_selection.h"
+#include "kis_selection_options.h"
+#include "kis_selected_transaction.h"
+#include "kis_paintop_registry.h"
+
+#include "kis_curve_framework.h"
+#include "kis_tool_curve.h"
+
+TQRect KisToolCurve::pivotRect (const TQPoint& pos)
+{
+ return TQRect (pos-TQPoint(4,4),pos+TQPoint(4,4));
+}
+
+TQRect KisToolCurve::selectedPivotRect (const TQPoint& pos)
+{
+ return TQRect (pos-TQPoint(5,5),pos+TQPoint(5,5));
+}
+
+KisToolCurve::KisToolCurve(const TQString& UIName)
+ : super(UIName)
+{
+ m_UIName = UIName;
+ m_currentImage = 0;
+ m_optWidget = 0;
+
+ m_curve = 0;
+
+ m_dragging = false;
+ m_draggingCursor = false;
+ m_drawPivots = true;
+ m_drawingPen = TQPen(TQt::white, 0, TQt::SolidLine);
+ m_pivotPen = TQPen(TQt::gray, 0, TQt::SolidLine);
+ m_selectedPivotPen = TQPen(TQt::yellow, 0, TQt::SolidLine);
+ m_pivotRounding = m_selectedPivotRounding = 55;
+
+ m_actionOptions = NOOPTIONS;
+ m_supportMinimalDraw = true;
+ m_selectAction = SELECTION_ADD;
+}
+
+KisToolCurve::~KisToolCurve()
+{
+
+}
+
+void KisToolCurve::update (KisCanvasSubject *subject)
+{
+ super::update(subject);
+ if (m_subject)
+ m_currentImage = m_subject->currentImg();
+}
+
+void KisToolCurve::deactivate()
+{
+ draw(false);
+ if (m_curve) {
+ m_curve->clear();
+ m_curve->endActionOptions();
+ }
+
+ m_actionOptions = NOOPTIONS;
+ m_dragging = false;
+ m_drawPivots = true;
+}
+
+void KisToolCurve::buttonPress(KisButtonPressEvent *event)
+{
+ updateOptions(event->state());
+ if (!m_currentImage)
+ return;
+ if (event->button() == Qt::LeftButton) {
+ m_dragging = true;
+ m_currentPoint = event->pos();
+ PointPair temp = pointUnderMouse (m_subject->canvasController()->windowToView(event->pos().toTQPoint()));
+ if (temp.first == m_curve->end() && !(m_actionOptions)) {
+ draw(true, true);
+ m_curve->selectAll(false);
+ draw(true, true);
+ draw(m_curve->end());
+ m_previous = m_curve->tqfind(m_curve->last());
+ m_current = m_curve->pushPivot(event->pos());
+ if (m_curve->pivots().count() > 1)
+ m_curve->calculateCurve(m_previous,m_current,m_current);
+ draw(m_current);
+ } else {
+ draw(true, true);
+ if (temp.second)
+ m_current = m_curve->selectPivot(temp.first);
+ else
+ m_current = selectByMouse(temp.first);
+
+ if (!(*m_current).isSelected())
+ m_dragging = false;
+ draw(true, true);
+ }
+ }
+}
+
+void KisToolCurve::keyPress(TQKeyEvent *event)
+{
+ if (event->key() == TQt::Key_Return) {
+ m_dragging = false;
+ commitCurve();
+ } else
+ if (event->key() == TQt::Key_Escape) {
+ m_dragging = false;
+ draw(false);
+ m_curve->clear();
+ } else
+ if (event->key() == TQt::Key_Delete) {
+ draw(false);
+ m_dragging = false;
+ m_curve->deleteSelected();
+ m_current = m_curve->tqfind(m_curve->last());
+ m_previous = m_curve->selectPivot(m_current);
+ draw(false);
+ }
+}
+
+void KisToolCurve::keyRelease(TQKeyEvent *)
+{
+
+}
+
+void KisToolCurve::buttonRelease(KisButtonReleaseEvent *event)
+{
+ updateOptions(event->state());
+ m_dragging = false;
+}
+
+void KisToolCurve::doubleClick(KisDoubleClickEvent *)
+{
+ commitCurve();
+}
+
+void KisToolCurve::move(KisMoveEvent *event)
+{
+ updateOptions(event->state());
+ PointPair temp = pointUnderMouse(m_subject->canvasController()->windowToView(event->pos().toTQPoint()));
+ if (temp.first == m_curve->end() && !m_dragging) {
+ if (m_draggingCursor) {
+ setCursor(KisCursor::load(m_cursor, 6, 6));
+ m_draggingCursor = false;
+ }
+ } else {
+ setCursor(KisCursor::load("tool_curve_dragging.png", 6, 6));
+ m_draggingCursor = true;
+ }
+ if (m_dragging) {
+ draw();
+ KisPoint trans = event->pos() - m_currentPoint;
+ m_curve->moveSelected(trans);
+ m_currentPoint = event->pos();
+ draw();
+ }
+}
+
+double pointToSegmentDistance(const KisPoint& p, const KisPoint& l0, const KisPoint& l1)
+{
+ double lineLength = sqrt((l1.x() - l0.x()) * (l1.x() - l0.x()) + (l1.y() - l0.y()) * (l1.y() - l0.y()));
+ double distance = 0;
+ KisVector2D v0(l0), v1(l1), v(p), seg(v0-v1), dist0(v0-p), dist1(v1-p);
+
+ if (seg.length() < dist0.length() ||
+ seg.length() < dist1.length()) // the point doesn't perpendicolarly intersecate the segment (or it's too far from the segment)
+ return (double)INT_MAX;
+
+ if (lineLength > DBL_EPSILON) {
+ distance = ((l0.y() - l1.y()) * p.x() + (l1.x() - l0.x()) * p.y() + l0.x() * l1.y() - l1.x() * l0.y()) / lineLength;
+ distance = fabs(distance);
+ }
+
+ return distance;
+}
+
+PointPair KisToolCurve::pointUnderMouse(const TQPoint& pos)
+{
+ KisCurve::iterator it, next;
+ TQPoint pos1, pos2;
+ it = handleUnderMouse(pos);
+ if (it != m_curve->end())
+ return PointPair(it,true);
+
+ for (it = m_curve->begin(); it != m_curve->end(); it++) {
+ next = it.next();
+ if (next == m_curve->end() || it == m_curve->end())
+ return PointPair(m_curve->end(),false);
+ if ((*it).hint() > LINEHINT || (*next).hint() > LINEHINT)
+ continue;
+ pos1 = m_subject->canvasController()->windowToView((*it).point().toTQPoint());
+ pos2 = m_subject->canvasController()->windowToView((*next).point().toTQPoint());
+ if (pos1 == pos2)
+ continue;
+ if (pointToSegmentDistance(pos,pos1,pos2) <= MAXDISTANCE)
+ break;
+ }
+
+ return PointPair(it,false);
+}
+
+KisCurve::iterator KisToolCurve::handleUnderMouse(const TQPoint& pos)
+{
+ KisCurve pivs = m_curve->pivots(), inHandle;
+ KisCurve::iterator it;
+ for (it = pivs.begin(); it != pivs.end(); it++) {
+ if (pivotRect(m_subject->canvasController()->windowToView((*it).point().toTQPoint())).tqcontains(pos))
+ inHandle.pushPoint((*it));
+ }
+ if (inHandle.isEmpty())
+ return m_curve->end();
+ return m_curve->tqfind(inHandle.last());
+}
+
+KisCurve::iterator KisToolCurve::selectByMouse(KisCurve::iterator it)
+{
+ KisCurve::iterator prevPivot, nextPivot;
+
+ if ((*it).isPivot())
+ prevPivot = it;
+ else
+ prevPivot = it.previousPivot();
+ nextPivot = it.nextPivot();
+
+ m_curve->selectPivot(prevPivot);
+ (*nextPivot).setSelected(true);
+
+ return prevPivot;
+}
+
+int KisToolCurve::updateOptions(int key)
+{
+ int options = 0x0000;
+
+ if (key & TQt::ControlButton)
+ options |= CONTROLOPTION;
+
+ if (key & TQt::ShiftButton)
+ options |= SHIFTOPTION;
+
+ if (key & TQt::AltButton)
+ options |= ALTOPTION;
+
+ if (options != m_actionOptions) {
+ draw(false);
+ m_actionOptions = options;
+ m_curve->setActionOptions(m_actionOptions);
+ draw(false);
+ }
+
+ return m_actionOptions;
+}
+
+void KisToolCurve::draw(bool m, bool o)
+{
+ draw(KisCurve::iterator(), o, m);
+}
+
+void KisToolCurve::draw(KisCurve::iterator inf, bool pivotonly, bool minimal)
+{
+ if (m_curve->isEmpty())
+ return;
+ KisCanvasPainter *gc;
+ KisCanvasController *controller;
+ KisCanvas *canvas;
+ if (m_subject && m_currentImage) {
+ controller = m_subject->canvasController();
+ canvas = controller->kiscanvas();
+ gc = new KisCanvasPainter(canvas);
+ } else
+ return;
+
+ gc->setPen(m_drawingPen);
+ gc->setRasterOp(TQt::XorROP);
+
+ KisCurve::iterator it, finish;
+
+ if (minimal && m_supportMinimalDraw) {
+ if (pivotonly) {
+ KisCurve p = m_curve->pivots();
+ for (KisCurve::iterator i = p.begin(); i != p.end(); i++)
+ drawPivotHandle (*gc, i);
+ delete gc;
+ return;
+ }
+ if (inf.target() != 0) {
+ if (inf != m_curve->end()) {
+ it = inf.previousPivot();
+ finish = inf.nextPivot();
+ } else {
+ it = --m_curve->end();
+ finish = m_curve->end();
+ }
+ } else {
+ KisCurve sel = m_curve->selectedPivots();
+ if (sel.isEmpty()) {
+ delete gc;
+ return;
+ }
+ for (KisCurve::iterator i = sel.begin(); i != sel.end(); i++) {
+ it = m_curve->tqfind(*i).previousPivot();
+ finish = m_curve->tqfind(*i).nextPivot();
+ if ((*finish).isSelected())
+ finish = finish.previousPivot();
+ while (it != finish) {
+ if ((*it).isPivot())
+ drawPivotHandle (*gc, it);
+ it = drawPoint (*gc, it);
+ }
+ }
+ delete gc;
+ return;
+ }
+ } else {
+ it = m_curve->begin();
+ finish = m_curve->end();
+ }
+ while (it != finish) {
+ if ((*it).isPivot())
+ drawPivotHandle (*gc, it);
+ it = drawPoint (*gc, it);
+ }
+
+ delete gc;
+}
+
+KisCurve::iterator KisToolCurve::drawPoint(KisCanvasPainter& gc, KisCurve::iterator point)
+{
+ KisCanvasController *controller = m_subject->canvasController();
+
+ TQPoint pos1, pos2;
+ pos1 = controller->windowToView((*point).point().toTQPoint());
+
+ switch ((*point).hint()) {
+ case POINTHINT:
+ gc.drawPoint(pos1);
+ point += 1;
+ break;
+ case LINEHINT:
+ gc.drawPoint(pos1);
+ if (++point != m_curve->end() && (*point).hint() <= LINEHINT) {
+ pos2 = controller->windowToView((*point).point().toTQPoint());
+ gc.drawLine(pos1,pos2);
+ }
+ break;
+ default:
+ point += 1;
+ }
+
+ return point;
+}
+
+void KisToolCurve::drawPivotHandle(KisCanvasPainter& gc, KisCurve::iterator point)
+{
+ KisCanvasController *controller = m_subject->canvasController();
+
+ if (m_drawPivots) {
+ TQPoint pos = controller->windowToView((*point).point().toTQPoint());
+ if ((*point).isSelected()) {
+ gc.setPen(m_selectedPivotPen);
+ gc.drawRoundRect(selectedPivotRect(pos),m_selectedPivotRounding,m_selectedPivotRounding);
+ } else {
+ gc.setPen(m_pivotPen);
+ gc.drawRoundRect(pivotRect(pos),m_pivotRounding,m_pivotRounding);
+ }
+ gc.setPen(m_drawingPen);
+ }
+}
+
+void KisToolCurve::paint(KisCanvasPainter&)
+{
+ draw(false);
+}
+
+void KisToolCurve::paint(KisCanvasPainter&, const TQRect&)
+{
+ draw(false);
+}
+
+void KisToolCurve::commitCurve()
+{
+ if (toolType() == TOOL_SHAPE || toolType() == TOOL_FREEHAND)
+ paintCurve();
+ else if (toolType() == TOOL_SELECT)
+ selectCurve();
+ else
+ kdDebug(0) << "NO SUPPORT FOR THIS TYPE OF TOOL" << endl;
+
+ m_curve->clear();
+ m_curve->endActionOptions();
+}
+
+void KisToolCurve::paintCurve()
+{
+ KisPaintDeviceSP device = m_currentImage->activeDevice ();
+ if (!device) return;
+
+ KisPainter painter (device);
+ if (m_currentImage->undo()) painter.beginTransaction (m_transactionMessage);
+
+ painter.setPaintColor(m_subject->fgColor());
+ painter.setBrush(m_subject->currentBrush());
+ painter.setOpacity(m_opacity);
+ painter.setCompositeOp(m_compositeOp);
+ KisPaintOp * op = KisPaintOpRegistry::instance()->paintOp(m_subject->currentPaintop(), m_subject->currentPaintopSettings(), &painter);
+ painter.setPaintOp(op); // Painter takes ownership
+
+// Call paintPoint
+ KisCurve::iterator it = m_curve->begin();
+ while (it != m_curve->end())
+ it = paintPoint(painter,it);
+// Finish
+
+ device->setDirty( painter.dirtyRect() );
+ notifyModified();
+
+ if (m_currentImage->undo()) {
+ m_currentImage->undoAdapter()->addCommand(painter.endTransaction());
+ }
+
+ draw(false);
+}
+
+KisCurve::iterator KisToolCurve::paintPoint (KisPainter& painter, KisCurve::iterator point)
+{
+ KisCurve::iterator next = point; next+=1;
+ switch ((*point).hint()) {
+ case POINTHINT:
+ painter.paintAt((*point++).point(), PRESSURE_DEFAULT, 0, 0);
+ break;
+ case LINEHINT:
+ if (next != m_curve->end() && (*next).hint() <= LINEHINT)
+ painter.paintLine((*point++).point(), PRESSURE_DEFAULT, 0, 0, (*next).point(), PRESSURE_DEFAULT, 0, 0);
+ else
+ painter.paintAt((*point++).point(), PRESSURE_DEFAULT, 0, 0);
+ break;
+ default:
+ point += 1;
+ }
+
+ return point;
+}
+
+TQValueVector<KisPoint> KisToolCurve::convertCurve()
+{
+ TQValueVector<KisPoint> points;
+
+ for (KisCurve::iterator i = m_curve->begin(); i != m_curve->end(); i++)
+ if ((*i).hint() != NOHINTS)
+ points.append((*i).point());
+
+ return points;
+}
+
+void KisToolCurve::selectCurve()
+{
+ TQApplication::setOverrideCursor(KisCursor::waitCursor());
+ KisPaintDeviceSP dev = m_currentImage->activeDevice();
+ bool hasSelection = dev->hasSelection();
+ KisSelectedTransaction *t = 0;
+ if (m_currentImage->undo()) t = new KisSelectedTransaction(m_transactionMessage, dev);
+ KisSelectionSP selection = dev->selection();
+
+ if (!hasSelection) {
+ selection->clear();
+ }
+
+ KisPainter painter(selection.data());
+
+ painter.setPaintColor(KisColor(TQt::black, selection->colorSpace()));
+ painter.setFillStyle(KisPainter::FillStyleForegroundColor);
+ painter.setStrokeStyle(KisPainter::StrokeStyleNone);
+ painter.setBrush(m_subject->currentBrush());
+ painter.setOpacity(OPACITY_OPAQUE);
+ KisPaintOp * op = KisPaintOpRegistry::instance()->paintOp("paintbrush", 0, &painter);
+ painter.setPaintOp(op); // And now the painter owns the op and will destroy it.
+
+ switch (m_selectAction) {
+ case SELECTION_ADD:
+ painter.setCompositeOp(COMPOSITE_OVER);
+ break;
+ case SELECTION_SUBTRACT:
+ painter.setCompositeOp(COMPOSITE_SUBTRACT);
+ break;
+ default:
+ break;
+ }
+
+ painter.paintPolygon(convertCurve());
+
+
+ if(hasSelection) {
+ TQRect dirty(painter.dirtyRect());
+ dev->setDirty(dirty);
+ dev->emitSelectionChanged(dirty);
+ } else {
+ dev->setDirty();
+ dev->emitSelectionChanged();
+ }
+
+ if (m_currentImage->undo())
+ m_currentImage->undoAdapter()->addCommand(t);
+
+ TQApplication::restoreOverrideCursor();
+
+ draw(false);
+}
+
+TQWidget* KisToolCurve::createOptionWidget(TQWidget* tqparent)
+{
+ if (toolType() == TOOL_SHAPE || toolType() == TOOL_FREEHAND)
+ return super::createOptionWidget(tqparent);
+ else if (toolType() == TOOL_SELECT)
+ return createSelectionOptionWidget(tqparent);
+ else
+ kdDebug(0) << "NO SUPPORT FOR THIS TOOL TYPE" << endl;
+ return 0;
+}
+
+void KisToolCurve::slotSetAction(int action) {
+ if (action >= SELECTION_ADD && action <= SELECTION_SUBTRACT)
+ m_selectAction =(enumSelectionMode)action;
+}
+
+TQWidget* KisToolCurve::createSelectionOptionWidget(TQWidget* tqparent)
+{
+ m_optWidget = new KisSelectionOptions(tqparent, m_subject);
+ Q_CHECK_PTR(m_optWidget);
+ m_optWidget->setCaption(m_UIName);
+
+ connect (m_optWidget, TQT_SIGNAL(actionChanged(int)), this, TQT_SLOT(slotSetAction(int)));
+
+ TQVBoxLayout * l = dynamic_cast<TQVBoxLayout*>(m_optWidget->tqlayout());
+ l->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding));
+
+ return m_optWidget;
+}
+
+TQWidget* KisToolCurve::optionWidget()
+{
+ if (toolType() == TOOL_SELECT)
+ return m_optWidget;
+ else
+ return super::optionWidget();
+}
+
+#include "kis_tool_curve.moc"
diff --git a/chalk/plugins/tools/tool_curves/kis_tool_curve.h b/chalk/plugins/tools/tool_curves/kis_tool_curve.h
new file mode 100644
index 00000000..74d1ccda
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/kis_tool_curve.h
@@ -0,0 +1,205 @@
+/*
+ * kis_tool_curve.h -- part of Chalk
+ *
+ * Copyright (c) 2006 Emanuele Tamponi <emanuele@valinor.it>
+ *
+ * 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_TOOL_CURVE_H_
+#define KIS_TOOL_CURVE_H_
+
+#include <tqpen.h>
+#include <tqcursor.h>
+
+#include "kis_selection.h"
+#include "kis_tool_paint.h"
+#include "kis_canvas_subject.h"
+#include "kis_point.h"
+
+#include "kis_curve_framework.h"
+
+class TQRect;
+class KisPainter;
+class KisSelectionOptions;
+
+typedef TQPair<KisCurve::iterator,bool> PointPair;
+
+const double MAXDISTANCE = 2.5;
+double pointToSegmentDistance(const KisPoint& p, const KisPoint& l0, const KisPoint& l1);
+
+class KisToolCurve : public KisToolPaint {
+
+ typedef KisToolPaint super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolCurve(const TQString& UIName);
+ virtual ~KisToolCurve();
+
+ virtual void update (KisCanvasSubject *subject);
+ virtual TQWidget* createOptionWidget(TQWidget* tqparent);
+
+ virtual void buttonPress(KisButtonPressEvent *event);
+ virtual void move(KisMoveEvent *event);
+ virtual void buttonRelease(KisButtonReleaseEvent *event);
+ virtual void doubleClick(KisDoubleClickEvent *event);
+ virtual void keyPress(TQKeyEvent *event);
+ virtual void keyRelease(TQKeyEvent *event);
+
+public slots:
+
+ virtual void deactivate();
+
+protected:
+
+ virtual void paint(KisCanvasPainter&);
+ virtual void paint(KisCanvasPainter&, const TQRect&);
+
+ /* ********************** *
+ * KisToolCurve interface *
+ * ********************** */
+
+ /*
+ * This keep in sync the options of the tool with the options of the curve
+ */
+ virtual int updateOptions(int);
+
+ virtual PointPair pointUnderMouse(const TQPoint& pos);
+ virtual KisCurve::iterator handleUnderMouse(const TQPoint& pos);
+
+ /*
+ * Select the needed points; called after pointUnderMouse
+ */
+ virtual KisCurve::iterator selectByMouse(KisCurve::iterator it);
+
+ /*
+ * draw() initializes the KisCanvasPainter and then loop on the points of the curve for drawing them.
+ */
+ virtual void draw(bool = true, bool = false);
+ virtual void draw(KisCurve::iterator inf, bool = false, bool = true);
+
+ /*
+ * Used by draw() to draw the current point of the curve. Can draw more than one point and then returns the last one
+ */
+ virtual KisCurve::iterator drawPoint(KisCanvasPainter& gc, KisCurve::iterator point);
+
+ /*
+ * Used by draw(), if a point is a pivot, this draw the handle around it (if m_drawPivots is set to true)
+ */
+ virtual void drawPivotHandle(KisCanvasPainter& gc, KisCurve::iterator point);
+
+ /*
+ * Methods for commiting the curve
+ */
+
+ /*
+ * Called by selectCurve(), this convert m_curve to a vector of KisPoint in order to be used by paintPolygon()
+ */
+ virtual TQValueVector<KisPoint> convertCurve();
+
+ /*
+ * Called by paintCurve(), it behaves essentially like drawPoint(), but this uses a KisPainter
+ */
+ virtual KisCurve::iterator paintPoint(KisPainter&, KisCurve::iterator);
+
+ /*
+ * Finish the curve: if the tool is a TOOL_SHAPE or TOOL_FREEHAND, calls paintCurve(), if it's a TOOL_SELECT, then selectCurve()
+ */
+ virtual void commitCurve();
+
+ /*
+ * Used by commitCurve() if the tool is a painting tool
+ */
+ virtual void paintCurve();
+
+ /*
+ * Used by commitCurve() if the tool is a selection tool
+ */
+ virtual void selectCurve();
+
+ /*
+ * Return the rect around a given point, assuming that that point is an unselected pivot
+ */
+ TQRect pivotRect (const TQPoint&);
+
+ /*
+ * Same as above for selected pivots
+ */
+ TQRect selectedPivotRect (const TQPoint&);
+
+protected:
+
+ KisImageSP m_currentImage;
+
+ KisCurve *m_curve;
+ KisCurve::iterator m_current;
+ KisCurve::iterator m_previous;
+ KisPoint m_currentPoint;
+
+ bool m_dragging;
+ bool m_drawPivots;
+ TQPen m_drawingPen;
+ TQPen m_pivotPen;
+ TQPen m_selectedPivotPen;
+ int m_pivotRounding;
+ int m_selectedPivotRounding;
+
+ int m_actionOptions;
+ bool m_supportMinimalDraw;
+ bool m_draggingCursor;
+
+ TQString m_transactionMessage;
+ TQString m_cursor;
+
+private:
+
+ TQString m_UIName;
+
+
+/* ********************************** *
+ * Selection Tools specific functions *
+ * ********************************** */
+
+public:
+
+ /*
+ * This initializes our Option Widget (called by createOptionWidget())
+ */
+ virtual TQWidget* createSelectionOptionWidget(TQWidget* tqparent);
+
+ /*
+ * This return our internal KisSelectionOptions if toolType() returns TOOL_SELECT
+ */
+ virtual TQWidget* optionWidget();
+
+public slots:
+
+ /*
+ * Slot for createSelectionOptionWidget()
+ */
+ virtual void slotSetAction(int);
+
+private:
+
+ /*
+ * Members used by slotSetAction() and selectCurve()
+ */
+ KisSelectionOptions* m_optWidget;
+ enumSelectionMode m_selectAction;
+};
+
+#endif //__KIS_TOOL_CURVE_H_
diff --git a/chalk/plugins/tools/tool_curves/kis_tool_example.cc b/chalk/plugins/tools/tool_curves/kis_tool_example.cc
new file mode 100644
index 00000000..e14abcb5
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/kis_tool_example.cc
@@ -0,0 +1,108 @@
+/*
+ * kis_tool_example.cc -- part of Chalk
+ *
+ * Copyright (c) 2006 Emanuele Tamponi <emanuele@valinor.it>
+ *
+ * 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 <tqpainter.h>
+#include <tqlayout.h>
+#include <tqrect.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <knuminput.h>
+
+#include "kis_global.h"
+#include "kis_doc.h"
+#include "kis_painter.h"
+#include "kis_point.h"
+#include "kis_canvas_subject.h"
+#include "kis_canvas_controller.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_move_event.h"
+#include "kis_paintop_registry.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+#include "kis_cursor.h"
+#include "kis_vec.h"
+
+#include "kis_curve_framework.h"
+
+#include "kis_tool_example.h"
+
+
+class KisCurveExample : public KisCurve {
+
+ typedef KisCurve super;
+
+public:
+
+ KisCurveExample() : super() {}
+
+ ~KisCurveExample() {}
+
+ virtual iterator pushPivot (const KisPoint&);
+
+};
+
+KisCurve::iterator KisCurveExample::pushPivot (const KisPoint& point)
+{
+ return selectPivot(iterator(*this,m_curve.append(CurvePoint(point,true,false,LINEHINT))), true);
+}
+
+KisToolExample::KisToolExample()
+ : super(i18n("Tool for Curves - Example"))
+{
+ setName("tool_example");
+ m_cursor = "tool_example_cursor.png";
+ setCursor(KisCursor::load(m_cursor, 6, 6));
+
+ m_curve = new KisCurveExample;
+}
+
+KisToolExample::~KisToolExample()
+{
+
+}
+
+void KisToolExample::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ KShortcut shortcut(TQt::Key_Plus);
+ shortcut.append(KShortcut(TQt::Key_F9));
+ m_action = new KRadioAction(i18n("&Example"),
+ "tool_example",
+ shortcut,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ Q_CHECK_PTR(m_action);
+
+ m_action->setToolTip(i18n("This is a test tool for the Curve Framework."));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+#include "kis_tool_example.moc"
diff --git a/chalk/plugins/tools/tool_curves/kis_tool_example.h b/chalk/plugins/tools/tool_curves/kis_tool_example.h
new file mode 100644
index 00000000..e7bfd89e
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/kis_tool_example.h
@@ -0,0 +1,67 @@
+/*
+ * kis_tool_example.h -- part of Chalk
+ *
+ * Copyright (c) 2006 Emanuele Tamponi <emanuele@valinor.it>
+ *
+ * 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_TOOL_EXAMPLE_H_
+#define KIS_TOOL_EXAMPLE_H_
+
+#include "kis_tool_factory.h"
+#include "kis_tool_curve.h"
+#include "kis_point.h"
+
+class CurvePoint;
+class KisPoint;
+class KisCanvas;
+class KisCurve;
+class KisPainter;
+class KisPoint;
+class WdgToolExample;
+
+class KisToolExample : public KisToolCurve {
+
+ typedef KisToolCurve super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolExample();
+ virtual ~KisToolExample();
+
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_SHAPE; }
+
+};
+
+class KisToolExampleFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolExampleFactory() : super() {};
+ virtual ~KisToolExampleFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolExample();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("exampletqshape", i18n("Example Tool")); }
+};
+
+
+#endif //__KIS_TOOL_EXAMPLE_H__
diff --git a/chalk/plugins/tools/tool_curves/kis_tool_moutline.cc b/chalk/plugins/tools/tool_curves/kis_tool_moutline.cc
new file mode 100644
index 00000000..4b7e51d4
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/kis_tool_moutline.cc
@@ -0,0 +1,809 @@
+/*
+ * kis_tool_moutline.cc -- part of Chalk
+ *
+ * Copyright (c) 2006 Emanuele Tamponi <emanuele@valinor.it>
+ *
+ * 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 <math.h>
+#include <set>
+
+#include <tqpainter.h>
+#include <tqlayout.h>
+#include <tqrect.h>
+#include <tqlabel.h>
+#include <tqpushbutton.h>
+#include <tqslider.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <knuminput.h>
+
+#include "kis_global.h"
+#include "kis_iterators_pixel.h"
+#include "kis_colorspace.h"
+#include "kis_channelinfo.h"
+#include "kis_doc.h"
+#include "kis_painter.h"
+#include "kis_point.h"
+#include "kis_canvas_subject.h"
+#include "kis_canvas_controller.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_move_event.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+#include "kis_cursor.h"
+#include "kis_tool_controller.h"
+#include "kis_vec.h"
+#include "kis_selection.h"
+#include "kis_selection_options.h"
+#include "kis_selected_transaction.h"
+#include "kis_paintop_registry.h"
+#include "kis_convolution_painter.h"
+
+#include "kis_tool_moutline.h"
+
+using namespace std;
+
+#define RMS(a, b) (sqrt ((a) * (a) + (b) * (b)))
+#define ROUND(x) ((int) ((x) + 0.5))
+
+const int NOEDGE = 0x0000;
+
+const int ORTHOGONAL_COST = 10; // 1*10
+const int DIAGONAL_COST = 14; // sqrt(2)*10
+const int MALUS = 20; // This applies to NOEDGE nodes
+
+const int DEFAULTDIST = 40; // Default distance between two automatic pivots
+const int MAXDIST = 55; // Max distance
+const int MINDIST = 15;
+const int PAGESTEP = 5;
+
+class Node {
+
+ TQPoint m_pos;
+ int m_gCost;
+ int m_hCost;
+ int m_tCost;
+ bool m_malus;
+ TQPoint m_parent;
+
+public:
+
+ Node()
+ {
+ m_pos = m_parent = TQPoint(-1,-1);
+ m_gCost = m_hCost = m_tCost = 0;
+ m_malus = false;
+ }
+
+ Node(const Node& node)
+ {
+ m_pos = node.pos();
+ m_gCost = node.gCost();
+ m_hCost = node.hCost();
+ m_tCost = node.tCost();
+ m_malus = node.malus();
+ m_parent = node.tqparent();
+ }
+
+ Node(const TQPoint& tqparent, const TQPoint& pos, int g, int h, bool malus)
+ : m_pos(pos), m_hCost(h), m_malus(malus)
+ {
+ setGCost(g);
+ m_parent = tqparent;
+ }
+ ~Node ()
+ {
+ }
+
+ int gCost () const {return m_gCost;}
+ int hCost () const {return m_hCost;}
+ int tCost () const {return m_tCost;}
+ bool malus () const {return m_malus;}
+ TQPoint pos () const {return m_pos;}
+ int col () const {return m_pos.x();}
+ int row () const {return m_pos.y();}
+ TQPoint tqparent () const {return m_parent;}
+
+ void setGCost (int g)
+ {
+ m_gCost = g+(m_malus?MALUS:0);
+ m_tCost = m_gCost+m_hCost;
+ }
+ void setHCost (int h)
+ {
+ m_hCost = h;
+ m_tCost = m_gCost+m_hCost;
+ }
+ void setPos (const TQPoint& pos)
+ {
+ m_pos = pos;
+ }
+ void setMalus (bool malus)
+ {
+ m_malus = malus;
+ }
+ void clear ()
+ {
+ m_pos = TQPoint(-1,-1);
+ }
+
+ bool operator== (const Node& n2) const
+ {
+ return m_pos == n2.pos();
+ }
+ bool operator!= (const Node& n2) const
+ {
+ return m_pos != n2.pos();
+ }
+ bool operator== (const TQPoint& n2) const
+ {
+ return m_pos == n2;
+ }
+ bool operator!= (const TQPoint& n2) const
+ {
+ return m_pos != n2;
+ }
+ bool operator< (const Node& n2) const
+ {
+ return m_tCost < n2.tCost();
+ }
+ bool operator> (const Node& n2) const
+ {
+ return m_tCost > n2.tCost();
+ }
+
+ TQValueList<Node> getNeighbor(const GrayMatrix& src, const Node& end)
+ {
+ TQPoint tmpdist;
+ TQValueList<Node> temp;
+ int dcol, drow;
+ int g, h;
+ bool malus;
+ int x[8] = { 1, 1, 0,-1,-1,-1, 0, 1},
+ y[8] = { 0,-1,-1,-1, 0, 1, 1, 1};
+
+ for (int i = 0; i < 8; i++) {
+ dcol = m_pos.x() + x[i];
+ drow = m_pos.y() + y[i];
+ tmpdist = TQPoint(dcol,drow) - end.pos();
+ // I use src[0] here because all cols have same number of rows
+ if (dcol == (int)src.count() || dcol < 0 ||
+ drow == (int)src[0].count() || drow < 0)
+ continue;
+ if (src[dcol][drow])
+ malus = false;
+ else
+ malus = true;
+ if (i%2)
+ g = m_gCost + DIAGONAL_COST;
+ else
+ g = m_gCost + ORTHOGONAL_COST;
+ h = ORTHOGONAL_COST * (abs(tmpdist.x()) + abs(tmpdist.y()));
+ temp.append(Node(m_pos,TQPoint(dcol,drow),g,h,malus));
+ }
+ return temp;
+ }
+
+};
+
+KisKernelSP createKernel( TQ_INT32 i0, TQ_INT32 i1, TQ_INT32 i2,
+ TQ_INT32 i3, TQ_INT32 i4, TQ_INT32 i5,
+ TQ_INT32 i6, TQ_INT32 i7, TQ_INT32 i8,
+ TQ_INT32 factor, TQ_INT32 offset )
+{
+ KisKernelSP kernel = new KisKernel();
+ kernel->width = 3;
+ kernel->height = 3;
+
+ kernel->factor = factor;
+ kernel->offset = offset;
+
+ kernel->data = new TQ_INT32[9];
+ kernel->data[0] = i0;
+ kernel->data[1] = i1;
+ kernel->data[2] = i2;
+ kernel->data[3] = i3;
+ kernel->data[4] = i4;
+ kernel->data[5] = i5;
+ kernel->data[6] = i6;
+ kernel->data[7] = i7;
+ kernel->data[8] = i8;
+
+ return kernel;
+}
+
+KisCurveMagnetic::KisCurveMagnetic (KisToolMagnetic *tqparent)
+ : m_parent(tqparent)
+{
+ m_standardkeepselected = false;
+}
+
+KisCurveMagnetic::~KisCurveMagnetic ()
+{
+
+}
+
+KisCurve::iterator KisCurveMagnetic::addPivot (KisCurve::iterator it, const KisPoint& point)
+{
+ return iterator(*this,m_curve.insert(it.position(), CurvePoint(point,true,false,LINEHINT)));
+}
+
+KisCurve::iterator KisCurveMagnetic::pushPivot (const KisPoint& point)
+{
+ iterator it;
+
+ it = pushPoint(point,true,false,LINEHINT);
+// if (count() == 1 && !m_parent->editingMode())
+// addPoint(it,point,true,false,LINEHINT);
+
+ return selectPivot(it);
+}
+
+void KisCurveMagnetic::calculateCurve (KisCurve::iterator p1, KisCurve::iterator p2, KisCurve::iterator it)
+{
+ if (p1 == m_curve.end() || p2 == m_curve.end()) // It happens sometimes, for example on the first click
+ return;
+ if (m_parent->editingMode())
+ return;
+ TQPoint start = (*p1).point().roundTQPoint();
+ TQPoint end = (*p2).point().roundTQPoint();
+ TQRect rc = TQRect(start,end).normalize();
+ rc.setTopLeft(rc.topLeft()+TQPoint(-8,-8)); // Enlarge the view, so problems with gaussian blur can be removed
+ rc.setBottomRight(rc.bottomRight()+TQPoint(8,8)); // and we are able to find paths that go beyond the rect.
+
+ KisPaintDeviceSP src = m_parent->m_currentImage->activeDevice();
+ GrayMatrix dst = GrayMatrix(rc.width(),GrayCol(rc.height()));
+
+ detectEdges (rc, src, dst);
+ reduceMatrix (rc, dst, 3, 3, 3, 3);
+
+ Node startNode, endNode;
+ multiset<Node> openSet;
+ NodeMatrix openMatrix = NodeMatrix(rc.width(),NodeCol(rc.height()));
+ NodeMatrix closedMatrix = NodeMatrix(rc.width(),NodeCol(rc.height()));
+
+ TQPoint tl(rc.topLeft().x(),rc.topLeft().y());
+ start -= tl; // Relative to the matrix
+ end -= tl; // Relative to the matrix
+
+ findEdge (start.x(), start.y(), dst, startNode);
+ openMatrix[startNode.col()][startNode.row()] = *openSet.insert(startNode);
+ endNode.setPos(end);
+
+ while (!openSet.empty()) {
+ Node current = *openSet.begin();
+
+ openSet.erase(openSet.begin());
+ openMatrix[current.col()][current.row()].clear();
+
+ TQValueList<Node> successors = current.getNeighbor(dst,endNode);
+ for (TQValueList<Node>::iterator i = successors.begin(); i != successors.end(); i++) {
+ int col = (*i).col();
+ int row = (*i).row();
+ if ((*i) == endNode) {
+ while (current.tqparent() != TQPoint(-1,-1)) {
+ it = addPoint(it,KisPoint(tl+current.pos()),false,false,LINEHINT);
+ current = closedMatrix[current.tqparent().x()][current.tqparent().y()];
+ }
+ return;
+ }
+ Node *openNode = &openMatrix[col][row];
+ if (*openNode != TQPoint(-1,-1)) {
+ if (*i > *openNode)
+ continue;
+ else {
+ openSet.erase(tqFind(openSet.begin(),openSet.end(),*openNode));
+ openNode->clear(); // Clear the Node
+ }
+ }
+ Node *closedNode = &closedMatrix[col][row];
+ if (*closedNode != TQPoint(-1,-1)) {
+ if ((*i) > (*closedNode))
+ continue;
+ else {
+ openMatrix[col][row] = *openSet.insert(*closedNode);
+ closedNode->clear(); // Clear the Node
+ continue;
+ }
+ }
+ openMatrix[col][row] = *openSet.insert(*i);
+ }
+ closedMatrix[current.col()][current.row()] = current;
+ }
+}
+
+void KisCurveMagnetic::findEdge (int col, int row, const GrayMatrix& src, Node& node)
+{
+ int x = -1;
+ int y = -1;
+
+ // tmpdist out of range
+ KisVector2D mindist(5.0,5.0), tmpdist(1000.0,1000.0);
+ for (int i = -5; i < 6; i++) {
+ for (int j = -5; j < 6; j++) {
+ if (src[col+i][row+j] != NOEDGE) {
+ tmpdist = KisVector2D(i,j);
+ if (tmpdist.length() < mindist.length())
+ mindist = tmpdist;
+ }
+ }
+ }
+ if (tmpdist.x() == 1000.0)
+ mindist = KisVector2D(0.0,0.0);
+
+ x = (int)(col + mindist.x());
+ y = (int)(row + mindist.y());
+
+ node.setPos(TQPoint(x,y));
+}
+
+void KisCurveMagnetic::reduceMatrix (TQRect& rc, GrayMatrix& m, int top, int right, int bottom, int left)
+{
+ TQPoint topleft(top, left);
+ TQPoint bottomright(bottom, right);
+
+ rc.setTopLeft(rc.topLeft()+topleft);
+ rc.setBottomRight(rc.bottomRight()-bottomright);
+
+ if (left)
+ m.erase(m.begin(),m.begin()+left);
+ if (right)
+ m.erase(m.end()-right,m.end());
+ if (top) {
+ for (uint i = 0; i < m.count(); i++)
+ m[i].erase(m[i].begin(),m[i].begin()+top);
+ }
+ if (bottom) {
+ for (uint i = 0; i < m.count(); i++)
+ m[i].erase(m[i].end()-bottom,m[i].end());
+ }
+}
+
+void KisCurveMagnetic::detectEdges (const TQRect & rect, KisPaintDeviceSP src, GrayMatrix& dst)
+{
+ GrayMatrix graysrc(rect.width(),GrayCol(rect.height()));
+ GrayMatrix xdeltas(rect.width(),GrayCol(rect.height()));
+ GrayMatrix ydeltas(rect.width(),GrayCol(rect.height()));
+ GrayMatrix magnitude(rect.width(),GrayCol(rect.height()));
+ KisPaintDeviceSP smooth = new KisPaintDevice(src->colorSpace());
+
+ gaussianBlur(rect, src, smooth);
+ toGrayScale(rect, smooth, graysrc);
+ getDeltas(graysrc, xdeltas, ydeltas);
+ getMagnitude(xdeltas, ydeltas, magnitude);
+ nonMaxSupp(magnitude, xdeltas, ydeltas, dst);
+}
+
+void KisCurveMagnetic::gaussianBlur (const TQRect& rect, KisPaintDeviceSP src, KisPaintDeviceSP dst)
+{
+ int grectx = rect.x();
+ int grecty = rect.y();
+ int grectw = rect.width();
+ int grecth = rect.height();
+ if (dst != src) {
+ KisPainter gc(dst);
+ gc.bitBlt(grectx, grecty, COMPOSITE_COPY, src, grectx, grecty, grectw, grecth);
+ gc.end();
+ }
+
+ KisConvolutionPainter painter( dst );
+ // FIXME createKernel could create dynamic gaussian kernels having sigma as argument
+ KisKernelSP kernel = createKernel( 1, 1, 1, 1, 24, 1, 1, 1, 1, 32, 0);
+ painter.applyMatrix(kernel, grectx, grecty, grectw, grecth, BORDER_AVOID);
+}
+
+void KisCurveMagnetic::toGrayScale (const TQRect& rect, KisPaintDeviceSP src, GrayMatrix& dst)
+{
+ int grectx = rect.x();
+ int grecty = rect.y();
+ int grectw = rect.width();
+ int grecth = rect.height();
+ TQColor c;
+ KisColorSpace *cs = src->colorSpace();
+
+ for (int row = 0; row < grecth; row++) {
+ KisHLineIteratorPixel srcIt = src->createHLineIterator(grectx, grecty+row, grectw, false);
+ for (int col = 0; col < grectw; col++) {
+ cs->toTQColor(srcIt.rawData(),&c);
+ dst[col][row] = tqGray(c.rgb());
+ ++srcIt;
+ }
+ }
+}
+
+void KisCurveMagnetic::getDeltas (const GrayMatrix& src, GrayMatrix& xdelta, GrayMatrix& ydelta)
+{
+ uint start = 1, xend = src[0].count()-1, yend = src.count()-1;
+ TQ_INT16 deri;
+ for (uint col = 0; col < src.count(); col++) {
+ for (uint row = 0; row < src[col].count(); row++) {
+ if (row >= start && row < xend) {
+ deri = src[col][row+1] - src[col][row-1];
+ xdelta[col][row] = deri;
+ } else
+ xdelta[col][row] = 0;
+ if (col >= start && col < yend) {
+ deri = src[col+1][row] - src[col-1][row];
+ ydelta[col][row] = deri;
+ } else
+ ydelta[col][row] = 0;
+ }
+ }
+}
+
+void KisCurveMagnetic::getMagnitude (const GrayMatrix& xdelta, const GrayMatrix& ydelta, GrayMatrix& gradient)
+{
+ for (uint col = 0; col < xdelta.count(); col++) {
+ for (uint row = 0; row < xdelta[col].count(); row++)
+ gradient[col][row] = (TQ_INT16)(ROUND(RMS(xdelta[col][row],ydelta[col][row])));
+ }
+}
+
+void KisCurveMagnetic::nonMaxSupp (const GrayMatrix& magnitude, const GrayMatrix& xdelta, const GrayMatrix& ydelta, GrayMatrix& nms)
+{
+ // Directions:
+ // 1: 0 - 22.5 degrees
+ // 2: 22.5 - 67.5 degrees
+ // 3: 67.5 - 90 degrees
+ // Second direction is relative to a quadrant. The quadrant is known by looking at x and y derivatives
+ // First quadrant: Gx < 0 & Gy >= 0
+ // Second quadrant: Gx < 0 & Gy < 0
+ // Third quadrant: Gx >= 0 & Gy < 0
+ // Fourth quadrant: Gx >= 0 & Gy >= 0
+ // For this reason: first direction is relative to Gy only and third direction to Gx only
+
+ double theta; // theta = invtan (|Gy| / |Gx|) This give the direction relative to a quadrant
+ TQ_INT16 mag; // Current magnitude
+ TQ_INT16 lmag; // Magnitude at the left (So this pixel is "more internal" than the current
+ TQ_INT16 rmag; // Magnitude at the right (So this pixel is "more external")
+ double xdel; // Current xdelta
+ double ydel; // Current ydelta
+ TQ_INT16 result;
+
+ for (uint col = 0; col < magnitude.count(); col++) {
+ for (uint row = 0; row < magnitude[col].count(); row++) {
+ mag = magnitude[col][row];
+ if (!mag || row == 0 || row == (magnitude[col].count()-1) ||
+ col == 0 || col == (magnitude.count()-1))
+ {
+ result = NOEDGE;
+ } else {
+ xdel = (double)xdelta[col][row];
+ ydel = (double)ydelta[col][row];
+ theta = atan(fabs(ydel)/fabs(xdel));
+ if (theta < 0)
+ theta = fabs(theta)+M_PI_2;
+ theta = (theta * 360.0) / (2.0*M_PI); // Radians -> degrees
+ if (theta >= 0 && theta < 22.5) { // .0 - .3926990816
+ if (ydel >= 0) {
+ lmag = magnitude[col][row-1];
+ rmag = magnitude[col][row+1];
+ } else {
+ lmag = magnitude[col][row+1];
+ rmag = magnitude[col][row-1];
+ }
+ }
+ if (theta >= 22.5 && theta < 67.5) { // .3926990816 - 1.1780972449
+ if (xdel >= 0) {
+ if (ydel >= 0) {
+ lmag = magnitude[col-1][row-1];
+ rmag = magnitude[col+1][row+1];
+ } else {
+ lmag = magnitude[col+1][row-1];
+ rmag = magnitude[col-1][row+1];
+ }
+ } else {
+ if (ydel >= 0) {
+ lmag = magnitude[col-1][row+1];
+ rmag = magnitude[col+1][row-1];
+ } else {
+ lmag = magnitude[col+1][row+1];
+ rmag = magnitude[col-1][row-1];
+ }
+ }
+ }
+ if (theta >= 67.5 && theta <= 90.0) { // 1.1780972449 - 1.5707963266
+ if (xdel >= 0) {
+ lmag = magnitude[col+1][row];
+ rmag = magnitude[col-1][row];
+ } else {
+ lmag = magnitude[col-1][row];
+ rmag = magnitude[col+1][row];
+ }
+ }
+
+ if ((mag < lmag) || (mag < rmag)) {
+ result = NOEDGE;
+ } else {
+ if (rmag == mag) // If the external magnitude is equal to the current, suppress current.
+ result = NOEDGE;
+ else
+ result = (mag > 255) ? 255 : mag;
+ }
+ }
+ nms[col][row] = result;
+ }
+ }
+}
+
+KisToolMagnetic::KisToolMagnetic ()
+ : super("Magnetic Outline Tool")
+{
+ setName("tool_moutline");
+ setCursor(KisCursor::load("tool_moutline_cursor.png", 6, 6));
+
+ m_editingMode = false;
+ m_editingCursor = m_draggingCursor = false;
+
+ m_mode = 0;
+ m_curve = m_derived = 0;
+ m_current = m_previous = 0;
+
+ m_distance = DEFAULTDIST;
+
+ m_transactionMessage = i18n("Magnetic Outline Selection");
+}
+
+KisToolMagnetic::~KisToolMagnetic ()
+{
+ m_curve = 0;
+ delete m_derived;
+}
+
+void KisToolMagnetic::update (KisCanvasSubject *subject)
+{
+ super::update(subject);
+}
+
+void KisToolMagnetic::activate ()
+{
+ super::activate();
+ if (!m_derived) {
+ m_derived = new KisCurveMagnetic(this);
+ m_curve = m_derived;
+ }
+}
+
+void KisToolMagnetic::deactivate ()
+{
+ m_curve->endActionOptions();
+ m_actionOptions = NOOPTIONS;
+ m_dragging = false;
+ m_drawPivots = true;
+}
+
+void KisToolMagnetic::keyPress(TQKeyEvent *event)
+{
+ if (event->key() == TQt::Key_Control) {
+ draw(false);
+ if (m_editingMode) {
+ m_editingMode = false;
+ if (m_current != 0)
+ m_curve->selectPivot(m_current,false);
+ m_mode->setText(i18n("Automatic Mode"));
+ } else {
+ m_editingMode = true;
+ m_mode->setText(i18n("Manual Mode"));
+ }
+ draw(false);
+ } else if (event->key() == TQt::Key_Delete && m_curve->count()) {
+ draw(false);
+ m_dragging = false;
+ if (m_curve->pivots().count() == 2)
+ m_curve->clear();
+ else {
+ if ((*m_current) == m_curve->last() && !(m_editingMode)) {
+ m_curve->deletePivot(m_current.previousPivot());
+ m_previous = m_current.previousPivot();
+ } else {
+ m_editingMode = false;
+ m_curve->deletePivot(m_current);
+ m_previous = m_current = m_curve->selectPivot(m_curve->lastIterator());
+ m_editingMode = true;
+ }
+ }
+ draw(false);
+ } else
+ super::keyPress(event);
+}
+
+void KisToolMagnetic::buttonRelease(KisButtonReleaseEvent *event)
+{
+ if (m_editingMode) {
+ draw(m_current);
+ m_editingMode = false;
+ if (!m_curve->isEmpty())
+ m_curve->movePivot(m_current, m_currentPoint);
+ m_editingMode = true;
+ draw(m_current);
+ }
+ super::buttonRelease(event);
+}
+
+void KisToolMagnetic::buttonPress(KisButtonPressEvent *event)
+{
+ updateOptions(event->state());
+ if (!m_currentImage)
+ return;
+ if (event->button() == Qt::LeftButton) {
+ m_dragging = true;
+ m_currentPoint = event->pos();
+ PointPair temp(m_curve->end(),false);
+ if (m_editingMode)
+ temp = pointUnderMouse (m_subject->canvasController()->windowToView(event->pos().toTQPoint()));
+ if (temp.first == m_curve->end() && !(m_actionOptions)) {
+ if (m_editingMode) {
+ draw(true, true);
+ m_curve->selectAll(false);
+ draw(true, true);
+ }
+ draw(m_curve->end());
+ if (!m_curve->isEmpty()) {
+ m_previous = m_current;
+ m_current = m_curve->pushPivot(event->pos());
+ } else {
+ m_previous = m_current = m_curve->pushPivot(event->pos());
+ }
+ if (m_curve->pivots().count() > 1)
+ m_curve->calculateCurve(m_previous,m_current,m_current);
+ if (m_editingMode)
+ draw();
+ else {
+ if ((*m_previous).point() == (*m_current).point())
+ draw(m_curve->end());
+ else
+ draw();
+ }
+ } else if (temp.first != m_curve->end() && m_editingMode) {
+ if (temp.second) {
+ draw(true, true);
+ m_current = m_curve->selectPivot(temp.first);
+ draw(true, true);
+ } else {
+ draw(false);
+ m_current = selectByMouse(temp.first);
+ draw(false);
+ }
+ if (!(*m_current).isSelected())
+ m_dragging = false;
+ }
+ }
+}
+
+void KisToolMagnetic::move(KisMoveEvent *event)
+{
+ updateOptions(event->state());
+ if (m_currentPoint == event->pos().floorTQPoint())
+ return;
+ if (m_editingMode) {
+ PointPair temp = pointUnderMouse(m_subject->canvasController()->windowToView(event->pos().toTQPoint()));
+ if (temp.first == m_curve->end() && !m_dragging) {
+ if (m_editingCursor || m_draggingCursor) {
+ setCursor(KisCursor::load("tool_moutline_cursor.png", 6, 6));
+ m_editingCursor = m_draggingCursor = false;
+ }
+ } else {
+ if (!m_draggingCursor && temp.second) {
+ setCursor(KisCursor::load("tool_moutline_dragging.png", 6, 6));
+ m_editingCursor = false;
+ m_draggingCursor = true;
+ }
+ if (!m_editingCursor && !temp.second) {
+ setCursor(KisCursor::load("tool_moutline_editing.png", 6, 6));
+ m_editingCursor = true;
+ m_draggingCursor = false;
+ }
+ }
+ if (!m_dragging)
+ return;
+ } else {
+ if (m_editingCursor || m_draggingCursor) {
+ setCursor(KisCursor::load("tool_moutline_cursor.png", 6, 6));
+ m_editingCursor = m_draggingCursor = false;
+ }
+ }
+ if (m_curve->selectedPivots().isEmpty())
+ return;
+
+ KisPoint trans = event->pos() - m_currentPoint;
+ KisPoint dist;
+ dist = (*m_current).point() - (*m_current.previousPivot()).point();
+ if ((m_distance >= MINDIST && (fabs(dist.x()) + fabs(dist.y())) > m_distance && !(m_editingMode))
+ || m_curve->pivots().count() == 1) {
+ draw(m_curve->end());
+ m_previous = m_current;
+ m_current = m_curve->pushPivot(event->pos());
+ } else if ((*m_previous).point() == (*m_current).point() && (*m_previous).point() == m_curve->last().point())
+ draw(m_curve->end());
+ else
+ draw(m_current);
+ m_curve->movePivot(m_current,event->pos());
+ m_currentPoint = event->pos().floorTQPoint();
+ draw(m_current);
+}
+
+KisCurve::iterator KisToolMagnetic::selectByMouse(KisCurve::iterator it)
+{
+ KisCurve::iterator currPivot = m_curve->selectPivot(m_curve->addPivot(it, KisPoint(0,0)));
+ m_curve->movePivot(currPivot,(*it).point());
+
+ return currPivot;
+}
+
+void KisToolMagnetic::slotCommitCurve ()
+{
+ if (!m_curve->isEmpty())
+ commitCurve();
+}
+
+void KisToolMagnetic::slotSetDistance (int dist)
+{
+ m_distance = dist;
+}
+
+TQWidget* KisToolMagnetic::createOptionWidget(TQWidget* tqparent)
+{
+ m_optWidget = super::createOptionWidget(tqparent);
+ TQVBoxLayout * l = dynamic_cast<TQVBoxLayout*>(m_optWidget->tqlayout());
+ TQGridLayout *box = new TQGridLayout(l, 2, 2, 3);
+ box->setColStretch(0, 1);
+ box->setColStretch(1, 1);
+ Q_CHECK_PTR(box);
+
+ m_mode = new TQLabel(i18n("Automatic mode"), m_optWidget);
+ m_lbDistance = new TQLabel(i18n("Distance: "), m_optWidget);
+ TQPushButton *finish = new TQPushButton(i18n("To Selection"), m_optWidget);
+ m_slDistance = new TQSlider(MINDIST, MAXDIST, PAGESTEP, m_distance, Qt::Horizontal, m_optWidget);
+
+ connect(m_slDistance, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotSetDistance(int)));
+ connect(finish, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotCommitCurve()));
+
+ box->addWidget(m_lbDistance, 0, 0);
+ box->addWidget(m_slDistance, 0, 1);
+ box->addWidget(m_mode, 1, 0);
+ box->addWidget(finish, 1, 1);
+
+ return m_optWidget;
+}
+
+void KisToolMagnetic::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ KShortcut shortcut(TQt::Key_Plus);
+ shortcut.append(KShortcut(TQt::Key_F9));
+ m_action = new KRadioAction(i18n("Magnetic Outline"),
+ "tool_moutline",
+ shortcut,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ Q_CHECK_PTR(m_action);
+
+ m_action->setToolTip(i18n("Magnetic Selection: move around an edge to select it. Hit Ctrl to enter/quit manual mode, and double click to finish."));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+#include "kis_tool_moutline.moc"
diff --git a/chalk/plugins/tools/tool_curves/kis_tool_moutline.h b/chalk/plugins/tools/tool_curves/kis_tool_moutline.h
new file mode 100644
index 00000000..ac7327fe
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/kis_tool_moutline.h
@@ -0,0 +1,132 @@
+/*
+ * kis_tool_moutline.h -- part of Chalk
+ *
+ * Copyright (c) 2006 Emanuele Tamponi <emanuele@valinor.it>
+ *
+ * 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_TOOL_MOUTLINE_H_
+#define KIS_TOOL_MOUTLINE_H_
+
+#include "kis_tool_factory.h"
+#include "kis_curve_framework.h"
+#include "kis_tool_curve.h"
+
+class TQSlider;
+class KisToolMagnetic;
+class KisVector2D;
+class Node;
+
+typedef TQValueVector<Node> NodeCol;
+typedef TQValueVector<NodeCol> NodeMatrix;
+typedef TQValueVector<TQ_INT16> GrayCol;
+typedef TQValueVector<GrayCol> GrayMatrix;
+
+class KisCurveMagnetic : public KisCurve {
+
+ typedef KisCurve super;
+
+ KisToolMagnetic *m_parent;
+
+ void reduceMatrix (TQRect&, GrayMatrix&, int, int, int, int);
+ void findEdge (int, int, const GrayMatrix&, Node&);
+ void detectEdges (const TQRect&, KisPaintDeviceSP, GrayMatrix&);
+
+ void gaussianBlur (const TQRect&, KisPaintDeviceSP, KisPaintDeviceSP);
+ void toGrayScale (const TQRect&, KisPaintDeviceSP, GrayMatrix&);
+ void getDeltas (const GrayMatrix&, GrayMatrix&, GrayMatrix&);
+ void getMagnitude (const GrayMatrix&, const GrayMatrix&, GrayMatrix&);
+ void nonMaxSupp (const GrayMatrix&, const GrayMatrix&, const GrayMatrix&, GrayMatrix&);
+
+public:
+
+ KisCurveMagnetic (KisToolMagnetic *tqparent);
+ ~KisCurveMagnetic ();
+
+ virtual KisCurve::iterator addPivot (iterator, const KisPoint&);
+ virtual KisCurve::iterator pushPivot (const KisPoint&);
+ virtual void calculateCurve (iterator, iterator, iterator);
+
+};
+
+class KisToolMagnetic : public KisToolCurve {
+
+ typedef KisToolCurve super;
+ Q_OBJECT
+ TQ_OBJECT
+
+ friend class KisCurveMagnetic;
+
+public:
+
+ KisToolMagnetic();
+ ~KisToolMagnetic();
+
+ virtual void update (KisCanvasSubject*);
+ virtual void setup (KActionCollection*);
+ virtual enumToolType toolType() { return TOOL_SELECT; }
+ virtual TQ_UINT32 priority() { return 9; }
+
+ virtual void keyPress(TQKeyEvent*);
+ virtual void buttonPress(KisButtonPressEvent*);
+ virtual void buttonRelease(KisButtonReleaseEvent*);
+ virtual void move(KisMoveEvent*);
+
+ virtual KisCurve::iterator selectByMouse(KisCurve::iterator it);
+
+ bool editingMode() {return m_editingMode;}
+ virtual TQWidget* createOptionWidget(TQWidget* tqparent);
+
+public slots:
+
+ virtual void activate ();
+ virtual void deactivate ();
+
+ void slotCommitCurve ();
+ void slotSetDistance (int);
+
+private:
+
+ KisCurveMagnetic *m_derived;
+ TQWidget* m_optWidget;
+ TQLabel* m_mode;
+ TQLabel* m_lbDistance;
+ TQSlider* m_slDistance;
+ bool m_editingMode;
+ bool m_editingCursor;
+ bool m_draggingCursor;
+ bool m_needNewPivot;
+
+ int m_distance;
+
+};
+
+class KisToolMagneticFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolMagneticFactory() : super() {};
+ virtual ~KisToolMagneticFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolMagnetic();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("magneticoutline", i18n("Magnetic Outline Selection Tool")); }
+};
+
+#endif // KIS_TOOL_MOUTLINE_H_
diff --git a/chalk/plugins/tools/tool_curves/tool_bezier_cursor.png b/chalk/plugins/tools/tool_curves/tool_bezier_cursor.png
new file mode 100644
index 00000000..d25a4ab1
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/tool_bezier_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_curves/tool_bezier_paint.png b/chalk/plugins/tools/tool_curves/tool_bezier_paint.png
new file mode 100644
index 00000000..290a1f02
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/tool_bezier_paint.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_curves/tool_bezier_select.png b/chalk/plugins/tools/tool_curves/tool_bezier_select.png
new file mode 100644
index 00000000..106c47ff
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/tool_bezier_select.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_curves/tool_curve_dragging.png b/chalk/plugins/tools/tool_curves/tool_curve_dragging.png
new file mode 100644
index 00000000..a7669ef1
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/tool_curve_dragging.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_curves/tool_curves.cc b/chalk/plugins/tools/tool_curves/tool_curves.cc
new file mode 100644
index 00000000..f9f5be33
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/tool_curves.cc
@@ -0,0 +1,67 @@
+/*
+ * tool_bezier.cc -- part of Chalk
+ *
+ * Copyright (c) 2006 Emanuele Tamponi <emanuele@valinor.it>
+ *
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_tool_registry.h>
+
+#include "tool_curves.h"
+#include "kis_tool_bezier_paint.h"
+#include "kis_tool_bezier_select.h"
+#include "kis_tool_moutline.h"
+
+
+typedef KGenericFactory<ToolCurves> ToolCurvesFactory;
+K_EXPORT_COMPONENT_FACTORY( chalktoolcurves, ToolCurvesFactory( "chalk" ) )
+
+
+ToolCurves::ToolCurves(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ToolCurvesFactory::instance());
+
+ if ( tqparent->inherits("KisToolRegistry") )
+ {
+ KisToolRegistry * r = dynamic_cast<KisToolRegistry*>( tqparent );
+ r->add(new KisToolBezierPaintFactory());
+ r->add(new KisToolBezierSelectFactory());
+ r->add(new KisToolMagneticFactory());
+ }
+
+}
+
+ToolCurves::~ToolCurves()
+{
+}
+
+#include "tool_curves.moc"
diff --git a/chalk/plugins/tools/tool_curves/tool_curves.h b/chalk/plugins/tools/tool_curves/tool_curves.h
new file mode 100644
index 00000000..82199e48
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/tool_curves.h
@@ -0,0 +1,36 @@
+/*
+ * tool_bezier.h -- part of Chalk
+ *
+ * Copyright (c) 2006 Emanuele Tamponi <emanuele@valinor.it>
+ *
+ * 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 TOOL_BEZIER_H_
+#define TOOL_BEZIER_H_
+
+#include <kparts/plugin.h>
+
+class ToolCurves : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ ToolCurves(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ToolCurves();
+
+};
+
+#endif // TOOL_BEZIER_H__
diff --git a/chalk/plugins/tools/tool_curves/tool_example.png b/chalk/plugins/tools/tool_curves/tool_example.png
new file mode 100644
index 00000000..893d2514
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/tool_example.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_curves/tool_example_cursor.png b/chalk/plugins/tools/tool_curves/tool_example_cursor.png
new file mode 100644
index 00000000..d25a4ab1
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/tool_example_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_curves/tool_moutline.png b/chalk/plugins/tools/tool_curves/tool_moutline.png
new file mode 100644
index 00000000..e2670292
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/tool_moutline.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_curves/tool_moutline_cursor.png b/chalk/plugins/tools/tool_curves/tool_moutline_cursor.png
new file mode 100644
index 00000000..283a86d1
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/tool_moutline_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_curves/tool_moutline_editing.png b/chalk/plugins/tools/tool_curves/tool_moutline_editing.png
new file mode 100644
index 00000000..3a308901
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/tool_moutline_editing.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_curves/wdg_tool_example.ui b/chalk/plugins/tools/tool_curves/wdg_tool_example.ui
new file mode 100644
index 00000000..eac06e2b
--- /dev/null
+++ b/chalk/plugins/tools/tool_curves/wdg_tool_example.ui
@@ -0,0 +1,128 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgToolExample</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgToolExample</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>280</width>
+ <height>50</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Example</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout8</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Vertices:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>isbX</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>verticesSpinBox</cstring>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="minValue">
+ <number>2</number>
+ </property>
+ <property name="value">
+ <number>5</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout7</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Ratio:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>isbWidth</cstring>
+ </property>
+ </widget>
+ <widget class="KisIntSpinbox">
+ <property name="name">
+ <cstring>ratioSpinBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </hbox>
+</widget>
+<tabstops>
+ <tabstop>verticesSpinBox</tabstop>
+ <tabstop>ratioSpinBox</tabstop>
+</tabstops>
+<customwidgets>
+<customwidget>
+ <class>KisIntSpinbox</class>
+ <header location="global">kis_int_spinbox.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image4</pixmap>
+</customwidget>
+</customwidgets>
+<images>
+ <image name="image4">
+ <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data>
+ </image>
+</images>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/tools/tool_filter/Makefile.am b/chalk/plugins/tools/tool_filter/Makefile.am
new file mode 100644
index 00000000..e1f6d5b4
--- /dev/null
+++ b/chalk/plugins/tools/tool_filter/Makefile.am
@@ -0,0 +1,38 @@
+kde_services_DATA = chalktoolfilter.desktop
+
+# all_includes must remain last!
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalktoolfilter_la_SOURCES = \
+ kis_filterop.cc \
+ kis_tool_filter.cc \
+ tool_filter.cc
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = chalktoolfilter.la
+
+noinst_HEADERS = \
+ kis_filterop.h \
+ kis_tool_filter.h \
+ tool_filter.h
+
+chalktoolfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalktoolfilter_la_LIBADD = ../../../libchalkcommon.la
+
+chalktoolfilter_la_METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
+
+chalkpics_DATA = \
+ tool_filter.png \
+ tool_filter_cursor.png
+
+chalkpicsdir = $(kde_datadir)/chalk/pics
+
diff --git a/chalk/plugins/tools/tool_filter/chalktoolfilter.desktop b/chalk/plugins/tools/tool_filter/chalktoolfilter.desktop
new file mode 100644
index 00000000..d22b19df
--- /dev/null
+++ b/chalk/plugins/tools/tool_filter/chalktoolfilter.desktop
@@ -0,0 +1,92 @@
+[Desktop Entry]
+Name=Filter Tool
+Name[bg]=Инструмент за филтриране
+Name[br]=Ostil ar sil
+Name[ca]=Eina de filtre
+Name[cy]=Erfyn Hidlen
+Name[da]=Filterværktøj
+Name[de]=Filterwerkzeug
+Name[el]=Εργαλείο φίλτρου
+Name[eo]=Filtrado-ilo
+Name[es]=Herramienta para filtrar
+Name[et]=Filtritööriist
+Name[eu]=Iragazkia tresna
+Name[fa]=ابزار پالایه
+Name[fi]=Suodintyökalu
+Name[fr]=Outil filtre
+Name[fy]=Filter-ark
+Name[ga]=Uirlis Scagaire
+Name[gl]=Ferramenta de Filtraxe
+Name[he]=כלי סינון
+Name[hu]=Szűrő eszköz
+Name[is]=Síutól
+Name[it]=Strumento di filtro
+Name[ja]=フィルタツール
+Name[km]=ឧបករណ៍​ត្រង
+Name[lv]=Filtru rīki
+Name[ms]=Alat Penapis
+Name[nb]=Filterverktøy
+Name[nds]=Filterwarktüüch
+Name[ne]=फिल्टर उपकरण
+Name[nl]=Filtergereedschap
+Name[nn]=Filterverktøy
+Name[pl]=Narzędzie filtru
+Name[pt]=Ferramenta de Filtragem
+Name[pt_BR]=Ferramenta de Filtragem
+Name[ru]=Фильтр
+Name[se]=Sillenreaidu
+Name[sk]=Filter
+Name[sl]=Orodje za filtriranje
+Name[sr]=Филтерски алат
+Name[sr@Latn]=Filterski alat
+Name[sv]=Filtreringsverktyg
+Name[uk]=Засіб фільтрування
+Name[uz]=Filter vositasi
+Name[uz@cyrillic]=Филтер воситаси
+Name[zh_CN]=过滤工具
+Name[zh_TW]=濾鏡工具
+Comment=Filter tool and paint operation
+Comment[bg]=Инструмент за филтриране и рисуване
+Comment[ca]=Operació d'eina de filtre i pintura
+Comment[cy]=Erfyn hidlen a gweithrediadau paent
+Comment[da]=Filterværktøj og maleoperation
+Comment[de]=Filterwerkzeug und Maloperation
+Comment[el]=Εργαλείο φίλτρου και λειτουργία ζωγραφικής
+Comment[eo]=Escepto ĉe kalkulado kun realaj nombroj.
+Comment[es]=Herramienta de filtrado y operaciones de pintado
+Comment[et]=Filtritööriist ja joonistamistoiming
+Comment[eu]=Iragazkia tresna eta margotze-eragiketa
+Comment[fa]=ابزار پالایه و عمل رنگ‌آمیزی
+Comment[fi]=Suodintyökalu ja väritystoimepinde
+Comment[fr]=Outil de filtrage et opération de dessin
+Comment[fy]=Filter-ark en skildersaksje
+Comment[gl]=Ferramenta de filtraxe e operación de pintura
+Comment[he]=כלי סינון ופעולת ציור
+Comment[hu]=Szűrő eszköz és festési művelet
+Comment[is]=Síutól og málunaraðgerðir
+Comment[it]=Strumento di filtro e operazione di disegno
+Comment[ja]=フィルタツールと画像操作
+Comment[km]=ដំណើរ​ការ​គូរ និង​ឧបករណ៍​តម្រង
+Comment[ms]=Alat penapis dan operasi warna
+Comment[nb]=Filterverktøy og maleteknikker
+Comment[nds]=Filterwarktüüch un Malen
+Comment[ne]=फिल्टर उपकरण र पेन्ट अपरेसन
+Comment[nl]=Filtergereedschap en schilderoperatie
+Comment[nn]=Filterverktøy og måleoperasjon
+Comment[pl]=Narzędzie filtrat oraz operacje malowania
+Comment[pt]=Ferramenta de filtragem e operação de pintura
+Comment[pt_BR]=Ferramenta de filtragem e operação de pintura
+Comment[ru]=Фильтр обработки изображения
+Comment[se]=Sillenreaidu ja málendoaibma
+Comment[sk]=Nástroj filter a operácie kreslenia
+Comment[sl]=Orodje za filtriranje in operacije za slikanje
+Comment[sr]=Филтерски алат и операција цртања
+Comment[sr@Latn]=Filterski alat i operacija crtanja
+Comment[sv]=Filtreringsverktyg och målningsåtgärd
+Comment[uk]=Засіб фільтрування та дій малювання
+Comment[zh_CN]=过滤器工具和绘图集成
+Comment[zh_TW]=濾鏡工具與繪圖操作
+ServiceTypes=Chalk/Tool
+Type=Service
+X-KDE-Library=chalktoolfilter
+X-Chalk-Version=2
diff --git a/chalk/plugins/tools/tool_filter/kis_filterop.cc b/chalk/plugins/tools/tool_filter/kis_filterop.cc
new file mode 100644
index 00000000..1f2200b3
--- /dev/null
+++ b/chalk/plugins/tools/tool_filter/kis_filterop.cc
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Clarence Dang <dang@kde.org>
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <tqrect.h>
+
+#include <kdebug.h>
+
+#include "kis_brush.h"
+#include "kis_global.h"
+#include "kis_paint_device.h"
+#include "kis_painter.h"
+#include "kis_types.h"
+#include "kis_iterators_pixel.h"
+#include "kis_paintop.h"
+#include "kis_colorspace.h"
+#include "kis_selection.h"
+#include "kis_filterop.h"
+
+
+KisPaintOp * KisFilterOpFactory::createOp(const KisPaintOpSettings */*settings*/, KisPainter * painter)
+{
+ KisPaintOp * op = new KisFilterOp(painter);
+ return op;
+}
+
+
+KisFilterOp::KisFilterOp(KisPainter * painter)
+ : super(painter)
+{
+ m_filterConfiguration = 0;
+}
+
+KisFilterOp::~KisFilterOp()
+{
+ delete m_filterConfiguration;
+}
+
+void KisFilterOp::paintAt(const KisPoint &pos, const KisPaintInformation& info)
+{
+ if (!m_painter) return;
+
+ KisFilterSP filter = m_painter->filter();
+ if (!filter) return;
+
+ if ( ! m_source ) return;
+
+ KisBrush * brush = m_painter->brush();
+ if (!brush) return;
+
+ KisColorSpace * colorSpace = m_source->colorSpace();
+
+ KisPoint hotSpot = brush->hotSpot(info);
+ KisPoint pt = pos - hotSpot;
+
+ // Split the coordinates into integer plus fractional parts. The integer
+ // is where the dab will be positioned and the fractional part determines
+ // the sub-pixel positioning.
+ TQ_INT32 x;
+ double xFraction;
+ TQ_INT32 y;
+ double yFraction;
+
+ splitCoordinate(pt.x(), &x, &xFraction);
+ splitCoordinate(pt.y(), &y, &yFraction);
+
+ // Filters always work with a tqmask, never with an image; that
+ // wouldn't be useful at all.
+ KisAlphaMaskSP tqmask = brush->tqmask(info, xFraction, yFraction);
+
+ m_painter->setPressure(info.pressure);
+
+ TQ_INT32 tqmaskWidth = tqmask->width();
+ TQ_INT32 tqmaskHeight = tqmask->height();
+
+ // Create a temporary paint device
+ KisPaintDeviceSP tmpDev = new KisPaintDevice(colorSpace, "filterop tmpdev");
+ Q_CHECK_PTR(tmpDev);
+
+ // Copy the layer data onto the new paint device
+
+ KisPainter p( tmpDev );
+ p.bitBlt( 0, 0, COMPOSITE_COPY, m_source, OPACITY_OPAQUE, x, y, tqmaskWidth, tqmaskHeight );
+
+ // Filter the paint device
+ filter->disableProgress();
+ filter->process( tmpDev, tmpDev, m_filterConfiguration, TQRect( 0, 0, tqmaskWidth, tqmaskHeight ));
+ filter->enableProgress();
+
+ // Apply the tqmask on the paint device (filter before tqmask because edge pixels may be important)
+ for (int y = 0; y < tqmaskHeight; y++)
+ {
+ KisHLineIterator hiter = tmpDev->createHLineIterator(0, y, tqmaskWidth, false);
+ int x=0;
+ while(! hiter.isDone())
+ {
+ TQ_UINT8 alpha = tqmask->alphaAt( x++, y );
+ colorSpace->setAlpha(hiter.rawData(), alpha, 1);
+
+ ++hiter;
+ }
+ }
+
+ // Blit the paint device onto the layer
+ TQRect dabRect = TQRect(0, 0, tqmaskWidth, tqmaskHeight);
+ TQRect dstRect = TQRect(x, y, dabRect.width(), dabRect.height());
+
+ KisImage * image = m_painter->device()->image();
+
+ if (image != 0) {
+ dstRect &= image->bounds();
+ }
+
+ if (dstRect.isNull() || dstRect.isEmpty() || !dstRect.isValid()) return;
+
+ TQ_INT32 sx = dstRect.x() - x;
+ TQ_INT32 sy = dstRect.y() - y;
+ TQ_INT32 sw = dstRect.width();
+ TQ_INT32 sh = dstRect.height();
+
+ if (m_source->hasSelection()) {
+ m_painter->bltSelection(dstRect.x(), dstRect.y(), m_painter->compositeOp(), tmpDev.data(),
+ m_source->selection(), m_painter->opacity(), sx, sy, sw, sh);
+ }
+ else {
+ m_painter->bitBlt(dstRect.x(), dstRect.y(), m_painter->compositeOp(), tmpDev.data(), m_painter->opacity(), sx, sy, sw, sh);
+ }
+
+ m_painter->addDirtyRect(dstRect);
+}
+
+void KisFilterOp::setFilterConfiguration(KisFilterConfiguration* filterConfiguration)
+{
+ delete m_filterConfiguration;
+ m_filterConfiguration = filterConfiguration;
+}
diff --git a/chalk/plugins/tools/tool_filter/kis_filterop.h b/chalk/plugins/tools/tool_filter/kis_filterop.h
new file mode 100644
index 00000000..06703b34
--- /dev/null
+++ b/chalk/plugins/tools/tool_filter/kis_filterop.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2004 Clarence Dang <dang@kde.org>
+ * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com>
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_FILTEROP_H_
+#define KIS_FILTEROP_H_
+
+#include "kis_paintop.h"
+#include <koffice_export.h>
+
+class KisPoint;
+class KisPainter;
+class KisFilterConfiguration;
+
+class KisFilterOpFactory : public KisPaintOpFactory {
+
+public:
+ KisFilterOpFactory() {}
+ virtual ~KisFilterOpFactory() {}
+
+ virtual KisPaintOp * createOp(const KisPaintOpSettings *settings, KisPainter * painter);
+ virtual KisID id() { return KisID(("filter"), i18n("Filter")); }
+ virtual bool userVisible(KisColorSpace * = 0) { return false; }
+};
+
+
+
+class KRITAPAINT_EXPORT KisFilterOp : public KisPaintOp {
+
+ typedef KisPaintOp super;
+
+public:
+
+ KisFilterOp(KisPainter * painter);
+ virtual ~KisFilterOp();
+
+ void paintAt(const KisPoint &pos, const KisPaintInformation& info);
+public:
+ void setFilterConfiguration(KisFilterConfiguration*);
+private:
+ KisFilterConfiguration* m_filterConfiguration;
+};
+
+
+#endif // KIS_FILTEROP_H_
diff --git a/chalk/plugins/tools/tool_filter/kis_tool_filter.cc b/chalk/plugins/tools/tool_filter/kis_tool_filter.cc
new file mode 100644
index 00000000..e9fdad9e
--- /dev/null
+++ b/chalk/plugins/tools/tool_filter/kis_tool_filter.cc
@@ -0,0 +1,154 @@
+/*
+ * kis_tool_filter.cc - part of Chalk
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <tqbitmap.h>
+#include <tqpainter.h>
+#include <tqcombobox.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <klocale.h>
+
+#include "kis_filter_config_widget.h"
+#include "kis_tool_filter.h"
+#include <kis_brush.h>
+#include <kis_button_press_event.h>
+#include <kis_button_release_event.h>
+#include <kis_canvas_subject.h>
+#include <kis_cmb_idlist.h>
+#include <kis_cursor.h>
+#include <kis_doc.h>
+#include <kis_filter.h>
+#include <kis_filterop.h>
+#include <kis_id.h>
+#include <kis_image.h>
+#include <kis_layer.h>
+#include <kis_move_event.h>
+#include <kis_painter.h>
+#include <kis_paintop.h>
+#include <kis_paintop_registry.h>
+#include <kis_vec.h>
+
+KisToolFilter::KisToolFilter()
+ : super(i18n("Filter Brush")), m_filterConfigurationWidget(0)
+{
+ setName("tool_filter");
+ m_subject = 0;
+ setCursor(KisCursor::load("tool_filter_cursor.png", 5, 5));
+}
+
+KisToolFilter::~KisToolFilter()
+{
+}
+
+void KisToolFilter::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Filter Brush"),
+ "tool_filter", 0, this,
+ TQT_SLOT(activate()), collection,
+ name());
+ Q_CHECK_PTR(m_action);
+ m_action->setToolTip(i18n("Paint with filters"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+void KisToolFilter::initPaint(KisEvent *e)
+{
+ // Some filters want to paint directly on the current state of
+ // the canvas, others cannot handle that and need a temporary layer
+ // so they can work on the old data before painting started.
+ m_paintIncremental = m_filter->supportsIncrementalPainting();
+
+ super::initPaint(e);
+ KisPaintOp * op = KisPaintOpRegistry::instance()->paintOp("filter", 0, painter());
+ op->setSource ( m_source );
+ painter()->setPaintOp(op); // And now the painter owns the op and will destroy it.
+ painter()->setFilter( m_filter );
+
+ // XXX: Isn't there a better way to set the config? The filter config widget needs to
+ // to go into the tool options widget, and just the data carried over to the filter.
+ // I've got a bit of a problem with core classes having too much GUI about them.
+ // BSAR.
+ dynamic_cast<KisFilterOp *>(op)->setFilterConfiguration( m_filter->configuration( m_filterConfigurationWidget) );
+}
+
+TQWidget* KisToolFilter::createOptionWidget(TQWidget* tqparent)
+{
+ TQWidget *widget = super::createOptionWidget(tqparent);
+
+ m_cbFilter = new KisCmbIDList(widget);
+ Q_CHECK_PTR(m_cbFilter);
+
+ TQLabel* lbFilter = new TQLabel(i18n("Filter:"), widget);
+ Q_CHECK_PTR(lbFilter);
+
+ // Check which filters support painting
+ KisIDList l = KisFilterRegistry::instance()->listKeys();
+ KisIDList l2;
+ KisIDList::iterator it;
+ for (it = l.begin(); it != l.end(); ++it) {
+ KisFilterSP f = KisFilterRegistry::instance()->get(*it);
+ if (f->supportsPainting()) {
+ l2.push_back(*it);
+ }
+ }
+ m_cbFilter ->setIDList( l2 );
+
+ addOptionWidgetOption(m_cbFilter, lbFilter);
+
+ m_optionLayout = new TQGridLayout(widget, 1, 1, 0, 6);
+ Q_CHECK_PTR(m_optionLayout);
+ super::addOptionWidgetLayout(m_optionLayout);
+
+ connect(m_cbFilter, TQT_SIGNAL(activated ( const KisID& )), this, TQT_SLOT( changeFilter( const KisID& ) ) );
+ changeFilter( m_cbFilter->currentItem () );
+
+ return widget;
+}
+
+void KisToolFilter::changeFilter( const KisID & id)
+{
+ m_filter = KisFilterRegistry::instance()->get( id );
+ Q_ASSERT(m_filter != 0);
+ if( m_filterConfigurationWidget != 0 )
+ {
+ m_optionLayout->remove ( m_filterConfigurationWidget );
+ delete m_filterConfigurationWidget;
+ }
+
+ m_source = m_currentImage->activeDevice();
+ if (!m_source) return;
+
+ m_filterConfigurationWidget = m_filter->createConfigurationWidget( optionWidget(), m_source );
+ if( m_filterConfigurationWidget != 0 )
+ {
+ m_optionLayout->addMultiCellWidget ( m_filterConfigurationWidget, 2, 2, 0, 1 );
+ m_filterConfigurationWidget->show();
+ }
+}
+
+#include "kis_tool_filter.moc"
diff --git a/chalk/plugins/tools/tool_filter/kis_tool_filter.h b/chalk/plugins/tools/tool_filter/kis_tool_filter.h
new file mode 100644
index 00000000..e8b5e86b
--- /dev/null
+++ b/chalk/plugins/tools/tool_filter/kis_tool_filter.h
@@ -0,0 +1,81 @@
+/*
+ * kis_tool_filter.h - part of Chalk
+ *
+ * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_TOOL_FILTER_H__
+#define __KIS_TOOL_FILTER_H__
+
+#include "kis_tool_freehand.h"
+#include "kis_tool_factory.h"
+
+class TQComboBox;
+class TQGridLayout;
+class KisEvent;
+class KisFilterConfigurationWidget;
+class KisButtonPressEvent;
+class KisView;
+class KisID;
+class KisCmbIDList;
+
+
+class KisToolFilter : public KisToolFreehand {
+ Q_OBJECT
+ TQ_OBJECT
+ typedef KisToolFreehand super;
+
+public:
+ KisToolFilter();
+ virtual ~KisToolFilter();
+
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_FREEHAND; }
+ virtual TQ_UINT32 priority() { return 1; }
+ virtual TQWidget* createOptionWidget(TQWidget* tqparent);
+
+public slots:
+ void changeFilter( const KisID & filter);
+
+protected:
+ virtual void initPaint(KisEvent *e);
+
+private:
+ KisFilterSP m_filter;
+ TQWidget* m_filterConfigurationWidget;
+ TQGridLayout* m_optionLayout;
+ KisCmbIDList * m_cbFilter;
+};
+
+
+class KisToolFilterFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolFilterFactory() : super() {};
+ virtual ~KisToolFilterFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolFilter();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("filter", i18n("Filter Tool")); }
+};
+
+#endif //__KIS_TOOL_FILTER_H__
+
diff --git a/chalk/plugins/tools/tool_filter/tool_filter.cc b/chalk/plugins/tools/tool_filter/tool_filter.cc
new file mode 100644
index 00000000..484ed39a
--- /dev/null
+++ b/chalk/plugins/tools/tool_filter/tool_filter.cc
@@ -0,0 +1,68 @@
+/*
+ * tool_filter.cc -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_debug_areas.h>
+#include <kis_types.h>
+#include <kis_tool_registry.h>
+#include <kis_paintop_registry.h>
+
+#include "tool_filter.h"
+#include "kis_filterop.h"
+#include "kis_tool_filter.h"
+
+
+typedef KGenericFactory<ToolFilter> ToolFilterFactory;
+K_EXPORT_COMPONENT_FACTORY( chalktoolfilter, ToolFilterFactory( "chalk" ) )
+
+
+ToolFilter::ToolFilter(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ToolFilterFactory::instance());
+
+ if ( tqparent->inherits("KisToolRegistry") )
+ {
+ KisToolRegistry * r = dynamic_cast<KisToolRegistry*>(tqparent);
+ r->add( new KisToolFilterFactory());
+
+ // XXX: Put this in a separate plugin?
+ KisPaintOpRegistry * pr = KisPaintOpRegistry::instance();
+ pr->add( new KisFilterOpFactory );
+
+ }
+}
+
+ToolFilter::~ToolFilter()
+{
+}
+
+#include "tool_filter.moc"
diff --git a/chalk/plugins/tools/tool_filter/tool_filter.h b/chalk/plugins/tools/tool_filter/tool_filter.h
new file mode 100644
index 00000000..7bf33dca
--- /dev/null
+++ b/chalk/plugins/tools/tool_filter/tool_filter.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 TOOL_FILTER_H_
+#define TOOL_FILTER_H_
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+/**
+ * A module that provides a filter tool.
+ */
+class ToolFilter : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ ToolFilter(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ToolFilter();
+
+private:
+
+ KisView * m_view;
+
+};
+
+#endif // TOOL_FILTER_H_
diff --git a/chalk/plugins/tools/tool_filter/tool_filter.png b/chalk/plugins/tools/tool_filter/tool_filter.png
new file mode 100644
index 00000000..6598d9fc
--- /dev/null
+++ b/chalk/plugins/tools/tool_filter/tool_filter.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_filter/tool_filter.svg b/chalk/plugins/tools/tool_filter/tool_filter.svg
new file mode 100644
index 00000000..eb808919
--- /dev/null
+++ b/chalk/plugins/tools/tool_filter/tool_filter.svg
@@ -0,0 +1,468 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="/home/cyrille/koffice/chalk/plugins/tools/tool_filter/tool_filter.png"
+ sodipodi:docname="tool_filter.svg"
+ sodipodi:docbase="/home/cyrille/src/koffice-svn/koffice/chalk/plugins/tools/tool_filter"
+ inkscape:version="0.43"
+ sodipodi:version="0.32"
+ id="svg1409"
+ height="22"
+ width="22"
+ version="1.0">
+ <defs
+ id="defs3">
+ <linearGradient
+ id="linearGradient3264">
+ <stop
+ style="stop-color:#787878;stop-opacity:1;"
+ offset="0"
+ id="stop3266" />
+ <stop
+ style="stop-color:#a0a0a0;stop-opacity:1;"
+ offset="1"
+ id="stop3268" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3256">
+ <stop
+ style="stop-color:#969696;stop-opacity:1;"
+ offset="0"
+ id="stop3258" />
+ <stop
+ style="stop-color:#969696;stop-opacity:0;"
+ offset="1"
+ id="stop3260" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3208">
+ <stop
+ style="stop-color:#313436;stop-opacity:1;"
+ offset="0"
+ id="stop3210" />
+ <stop
+ id="stop3216"
+ offset="0.76999998"
+ style="stop-color:#373a3c;stop-opacity:1;" />
+ <stop
+ style="stop-color:#313436;stop-opacity:1;"
+ offset="1"
+ id="stop3212" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3136">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.23958333;"
+ offset="0"
+ id="stop3138" />
+ <stop
+ style="stop-color:#ff0909;stop-opacity:0;"
+ offset="1"
+ id="stop3140" />
+ </linearGradient>
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.261963,0,0,1.01636,-7.978266,-0.517425)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1333"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.32525,0,0,1.003779,-5.702957,1.287849)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1331"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient9512"
+ gradientTransform="matrix(1.32525,0,0,1.003779,-5.702957,1.287849)"
+ x1="10.878086"
+ y1="4.5492039"
+ x2="39.857029"
+ y2="36.873619"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient10280"
+ gradientTransform="matrix(1.261963,0,0,1.01636,-7.978266,-0.517425)"
+ cx="48.488476"
+ cy="46.914463"
+ fx="48.488476"
+ fy="46.914463"
+ r="31.677956"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ id="light90to0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.90833336;"
+ offset="0.0000000"
+ id="stop1890" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="1.0000000"
+ id="stop1892" />
+ </linearGradient>
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.181248,0,0,0.943878,-80.46799,5.3461)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient2086"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.240487,0,0,0.932195,-78.33821,7.022631)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient2089"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.240487,0,0,0.932195,-78.33821,7.022631)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3732"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.181248,0,0,0.943878,-80.46799,5.3461)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3734"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.47229,0,0,1.176435,-85.47464,-0.281735)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3737"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.546124,0,0,1.161874,-42.82011,1.807868)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3740"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.546124,0,0,1.161874,-82.82011,1.807868)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3748"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.181248,0,0,0.943878,-86.67547,5.3461)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3888"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.240487,0,0,0.932195,-84.54569,7.022631)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3891"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.240487,0,0,0.932195,-84.54569,7.022631)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3899"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.181248,0,0,0.943878,-86.67547,5.3461)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3901"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.842551,0,0,1.472293,-26.91085,-7.897181)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3904"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.934954,0,0,1.454069,-43.58874,-5.282071)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3907"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.934954,0,0,1.454069,-23.58874,-5.282071)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3917"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(1.934954,0,0,1.454069,-23.58874,-5.282071)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3939"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(1.842551,0,0,1.472293,-26.91085,-7.897181)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3941"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="radialGradient3103"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.843411,0,0,1.546427,-39.13262,-18.20529)"
+ cx="48.488476"
+ cy="46.914463"
+ fx="48.488476"
+ fy="46.914463"
+ r="31.677956" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient3106"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.935858,0,0,1.527286,-33.53707,-3.676156)"
+ x1="10.878086"
+ y1="4.5492039"
+ x2="39.857029"
+ y2="36.873619" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3136"
+ id="radialGradient3142"
+ cx="25.014776"
+ cy="24.372894"
+ fx="25.014776"
+ fy="24.372894"
+ r="8.1216803"
+ gradientTransform="matrix(1,0,0,0.92,0,1.94983)"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3136"
+ id="radialGradient3198"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.92,0,1.94983)"
+ cx="25.014776"
+ cy="24.372894"
+ fx="25.014776"
+ fy="24.372894"
+ r="8.1216803" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3256"
+ id="linearGradient3262"
+ x1="42.718361"
+ y1="28.488203"
+ x2="57.968361"
+ y2="28.488203"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.379522,0,0,0.379522,-3.932923e-16,-3.72157e-3)" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3264"
+ id="linearGradient3270"
+ x1="2.2501231"
+ y1="12.139999"
+ x2="21.997738"
+ y2="12.139999"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(2.262e-3,-9.301e-3)" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3136"
+ id="radialGradient3292"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.92,0,1.94983)"
+ cx="25.014776"
+ cy="24.372894"
+ fx="25.014776"
+ fy="24.372894"
+ r="8.1216803" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3256"
+ id="linearGradient3301"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.379522,0,0,0.379522,11.99971,7.621365)"
+ x1="42.718361"
+ y1="28.488203"
+ x2="57.968361"
+ y2="28.488203" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3136"
+ id="radialGradient3303"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.92,0,1.94983)"
+ cx="25.014776"
+ cy="24.372894"
+ fx="25.014776"
+ fy="24.372894"
+ r="8.1216803" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:window-y="29"
+ inkscape:window-x="-6"
+ inkscape:window-height="865"
+ inkscape:window-width="1020"
+ inkscape:grid-bbox="true"
+ inkscape:document-units="px"
+ showgrid="true"
+ inkscape:current-layer="layer1"
+ inkscape:cy="10.948218"
+ inkscape:cx="11.00702"
+ inkscape:zoom="26.673274"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0000000"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <sodipodi:guide
+ orientation="horizontal"
+ position="32.270144"
+ id="guide3123" />
+ <sodipodi:guide
+ orientation="vertical"
+ position="27.830292"
+ id="guide3125" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:groupmode="layer"
+ inkscape:label="Layer 1"
+ id="layer1">
+ <path
+ style="fill:#bebebe;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 2.870858,16.882359 C 5.0598873,15.626359 5.4905158,16.595273 5.4905158,16.595273 L 6.2441162,18.281903 L 5.3828589,19.322589"
+ id="path3151"
+ sodipodi:nodetypes="cccc" />
+ <path
+ style="opacity:1;fill:url(#linearGradient3270);fill-opacity:1;stroke:none;stroke-width:5.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.98913042"
+ d="M 11.685746,2.2635359 C 6.4415012,2.4956003 2.2523851,6.8307301 2.2523851,12.131768 C 2.2523851,17.581319 6.6821924,22 12.131768,22 C 17.581343,22 22,17.581319 22,12.131768 C 21.999999,6.6822174 17.581343,2.2635359 12.131768,2.2635359 C 12.004043,2.2635359 11.879202,2.2587206 11.752649,2.2635359 C 11.732052,2.2643196 11.706312,2.2626259 11.685746,2.2635359 z M 11.797252,5.2853334 C 11.840148,5.2829026 11.876807,5.2869734 11.919908,5.2853334 C 12.008177,5.281975 12.098433,5.2853334 12.187521,5.2853334 C 15.988577,5.2853334 19.067407,8.364162 19.067407,12.16522 C 19.067407,14.065748 17.766075,15.397225 16.521235,16.642064 C 15.276395,17.886904 14.088049,19.045106 12.187521,19.045106 C 8.386464,19.045106 5.2964839,15.966276 5.2964835,12.16522 C 5.2964835,8.49675 8.179632,5.4903078 11.797252,5.2853334 z "
+ id="path3149"
+ sodipodi:nodetypes="csssssccssssssc" />
+ <path
+ style="fill:#6e6e6e;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 4.6829485,14.913971 C 4.3986517,12.248484 4.1732961,10.502726 5.6607092,8.0399772 C 7.9623626,4.2290697 12.792842,4.2762827 15.037384,4.9281667 C 16.297373,5.2941059 13.8014,2.0801252 13.685675,1.8486741 C 13.555694,1.5887131 10.790175,0.65325747 10.315629,0.69792667 C 9.0556677,0.81652736 6.1065158,1.8817743 4.8906765,2.6295384 C 4.1184435,3.1044764 1.5558033,6.5046123 1.2740418,7.0681355 C 1.0820562,7.4521065 0.62128553,11.654096 0.82196244,12.65748 C 0.88790126,12.987174 4.7238226,15.297195 4.6829485,14.913971 z "
+ id="path3130"
+ sodipodi:nodetypes="cssssssss" />
+ <path
+ style="fill:#ff0909;fill-opacity:0.45405406;stroke:none;stroke-width:5.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.98913042"
+ d="M 11.28125,3.46875 C 7.0156744,3.8021114 3.65625,7.4758848 3.65625,11.9375 C 3.65625,15.448279 5.7527084,18.462078 8.71875,19.75 C 8.5411163,19.572282 8.2707985,19.260891 8.15625,19.0625 C 8.1432138,19.038406 8.132279,18.989549 8.125,18.96875 C 8.1239941,18.964034 8.1255755,18.941957 8.125,18.9375 C 8.1248707,18.933315 8.1246675,18.910152 8.125,18.90625 C 8.1263033,18.90295 8.1231878,18.877981 8.125,18.875 C 8.1336316,18.868079 8.173723,18.847371 8.1875,18.84375 C 8.1926954,18.842933 8.2129358,18.844164 8.21875,18.84375 C 8.2254977,18.84375 8.2430579,18.844063 8.25,18.84375 C 8.2713908,18.841902 8.3207757,18.848147 8.34375,18.84375 C 8.3672153,18.838563 8.412672,18.819877 8.4375,18.8125 C 8.8330113,18.686414 9.4034506,18.311913 9.78125,18.21875 C 9.8048993,18.213564 9.8528577,18.190227 9.875,18.1875 C 9.8894021,18.186268 9.9238535,18.1875 9.9375,18.1875 C 10.280065,18.173019 12.681854,17.727974 12.96875,17.65625 C 13.197391,17.567298 15.774962,15.915357 16.0625,15.6875 C 16.064368,15.685632 16.091055,15.659527 16.09375,15.65625 C 16.310468,15.368508 18.03202,12.498462 18.125,12.3125 C 18.227335,12.057307 18.750238,9.5088168 18.90625,9.1875 C 18.908686,9.1833497 18.935279,9.1590607 18.9375,9.15625 C 18.950344,9.15625 19.655829,9.2469227 19.75,9.25 C 19.740635,9.2297736 19.745791,9.1655723 19.71875,9.125 C 19.529461,8.8409941 18.943665,8.1429826 18.875,8 C 18.914573,7.9010676 18.989778,7.8045847 19.0625,7.71875 C 19.07058,7.7092128 19.054085,7.6967151 19.0625,7.6875 C 19.059155,7.681599 19.097109,7.662142 19.09375,7.65625 C 17.659524,5.1403638 14.981334,3.46875 11.9375,3.46875 C 11.723647,3.46875 11.491032,3.4523552 11.28125,3.46875 z "
+ id="path3115" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#radialGradient3303);fill-opacity:1;stroke:none;stroke-width:5.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.98913042"
+ id="path3134"
+ sodipodi:cx="25.014776"
+ sodipodi:cy="24.372894"
+ sodipodi:rx="8.1216803"
+ sodipodi:ry="7.4719462"
+ d="M 33.136456 24.372894 A 8.1216803 7.4719462 0 1 1 16.893096,24.372894 A 8.1216803 7.4719462 0 1 1 33.136456 24.372894 z"
+ transform="matrix(0.607235,0,0,0.660038,-5.151071,-7.62158)" />
+ <path
+ style="opacity:1;fill:#4e4e4e;fill-opacity:1;stroke:none;stroke-width:5.625;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ d="M 9.433361,0.0021401333 C 4.189116,0.23420453 0,4.5693346 0,9.8703729 C 0,15.319923 4.429807,19.738605 9.879383,19.738605 C 15.328958,19.738605 19.747615,15.319923 19.747615,9.8703729 C 19.747614,4.4208218 15.328958,0.0021401333 9.879383,0.0021401333 C 9.751658,0.0021401333 9.626817,-0.0026751667 9.500264,0.0021401333 C 9.479667,0.0029239333 9.453927,0.0012301333 9.433361,0.0021401333 z M 9.544867,3.0239379 C 9.587763,3.0215073 9.624422,3.0255778 9.667523,3.0239379 C 9.755792,3.0205795 9.846048,3.0239379 9.935136,3.0239379 C 13.736192,3.0239379 16.815022,6.1027668 16.815022,9.9038239 C 16.815022,13.704881 13.736192,16.783711 9.935136,16.783711 C 6.134079,16.783711 3.044099,13.704881 3.044099,9.9038239 C 3.044099,6.2353545 5.927246,3.2289124 9.544867,3.0239379 z "
+ id="path1361" />
+ </g>
+</svg>
diff --git a/chalk/plugins/tools/tool_filter/tool_filter_cursor.png b/chalk/plugins/tools/tool_filter/tool_filter_cursor.png
new file mode 100644
index 00000000..d1e7f3d5
--- /dev/null
+++ b/chalk/plugins/tools/tool_filter/tool_filter_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_perspectivegrid/Makefile.am b/chalk/plugins/tools/tool_perspectivegrid/Makefile.am
new file mode 100644
index 00000000..b3b0f74f
--- /dev/null
+++ b/chalk/plugins/tools/tool_perspectivegrid/Makefile.am
@@ -0,0 +1,35 @@
+kde_services_DATA = chalktoolperspectivegrid.desktop
+
+# all_includes must remain last!
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalktoolperspectivegrid_la_SOURCES = \
+ tool_perspectivegrid.cc \
+ kis_tool_perspectivegrid.cc
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = chalktoolperspectivegrid.la
+
+noinst_HEADERS = \
+ tool_perspectivegrid.h \
+ kis_tool_perspectivegrid.h
+
+chalktoolperspectivegrid_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalktoolperspectivegrid_la_LIBADD = ../../../libchalkcommon.la
+
+METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
+
+chalkpics_DATA = \
+ tool_perspectivegrid.png
+
+chalkpicsdir = $(kde_datadir)/chalk/pics
+
diff --git a/chalk/plugins/tools/tool_perspectivegrid/chalktoolperspectivegrid.desktop b/chalk/plugins/tools/tool_perspectivegrid/chalktoolperspectivegrid.desktop
new file mode 100644
index 00000000..70001614
--- /dev/null
+++ b/chalk/plugins/tools/tool_perspectivegrid/chalktoolperspectivegrid.desktop
@@ -0,0 +1,35 @@
+[Desktop Entry]
+Name=Perspective Grid Tool
+Name[bg]=Инструмент мрежа
+Name[ca]=Eina de graella de perspectiva
+Name[da]=Perspektivgitterværktøj
+Name[de]=Perspektive-Raster-Werkzeug
+Name[el]=Εργαλείο προοπτικού πλέγματος
+Name[eo]=Perspektivkrado-ilo
+Name[es]=Herramienta Cuadrícula de perspectiva
+Name[et]=Perspektiivvõrgu tööriist
+Name[fa]=ابزار توری بُعدنما
+Name[fy]=Perspeksjeraster-ark
+Name[hu]=Perspektívarács
+Name[it]=Strumento di reticolo prospettico
+Name[ja]=遠近法グリッドツール
+Name[km]=ឧបករណ៍​ក្រឡា​ចត្រង្គ​យថាទស្សន៍
+Name[nb]=Perspektivnett-verktøy
+Name[nds]=Kiekwinkelgadder-Warktüüch
+Name[ne]=दृश्यात्मक ग्रीड उपकरण
+Name[nl]=Perspectiefraster-gereedschap
+Name[pl]=Narzędzie siatki perspektywy
+Name[pt]=Ferramenta de Grelha em Perspectiva
+Name[pt_BR]=Ferramenta de Grade em Perspectiva
+Name[ru]=Перспектива
+Name[sk]=Perspektívna mriežka
+Name[sl]=Orodja Mreža za perspektivo
+Name[sr]=Алат за мрежу у перспективи
+Name[sr@Latn]=Alat za mrežu u perspektivi
+Name[sv]=Perspektivrutnätsverktyg
+Name[uk]=Засіб ґратки перспективи
+Name[zh_TW]=透視格工具
+ServiceTypes=Chalk/Tool
+Type=Service
+X-KDE-Library=chalktoolperspectivegrid
+X-Chalk-Version=2
diff --git a/chalk/plugins/tools/tool_perspectivegrid/kis_tool_perspectivegrid.cc b/chalk/plugins/tools/tool_perspectivegrid/kis_tool_perspectivegrid.cc
new file mode 100644
index 00000000..3a21e72e
--- /dev/null
+++ b/chalk/plugins/tools/tool_perspectivegrid/kis_tool_perspectivegrid.cc
@@ -0,0 +1,499 @@
+/*
+ * kis_tool_perspectivegrid.cc - part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_tool_perspectivegrid.h>
+
+#include <tqapplication.h>
+#include <tqpainter.h>
+#include <tqregion.h>
+#include <tqwidget.h>
+#include <tqlayout.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <kcommand.h>
+#include <klocale.h>
+
+#include <kis_button_press_event.h>
+#include <kis_button_release_event.h>
+#include <kis_canvas_controller.h>
+#include <kis_canvas_painter.h>
+#include <kis_canvas_subject.h>
+#include <kis_cursor.h>
+#include <kis_image.h>
+#include <kis_move_event.h>
+#include <kis_perspective_grid_manager.h>
+#include <kis_selected_transaction.h>
+#include <kis_painter.h>
+#include <kis_paintop_registry.h>
+#include <kis_vec.h>
+
+#include <kis_canvas.h>
+
+KisToolPerspectiveGrid::KisToolPerspectiveGrid()
+ : super(i18n("Perspective Grid")), m_handleSize(13), m_handleHalfSize(6)
+
+{
+ setName("tool_perspectivegrid");
+
+ m_subject = 0;
+ m_dragging = false;
+}
+
+KisToolPerspectiveGrid::~KisToolPerspectiveGrid()
+{
+}
+
+void KisToolPerspectiveGrid::activate()
+{
+ m_subject->perspectiveGridManager()->startEdition();
+ if( ! m_subject->currentImg()->perspectiveGrid()->hasSubGrids() )
+ {
+ m_mode = MODE_CREATION;
+ m_points.clear();
+ } else {
+ m_mode = MODE_EDITING;
+ drawGrid();
+ }
+ super::activate();
+}
+
+void KisToolPerspectiveGrid::deactivate()
+{
+ m_subject->perspectiveGridManager()->stopEdition();
+ m_subject->perspectiveGridManager()->setGridVisible( true);
+ if( m_mode == MODE_CREATION )
+ {
+ drawGridCreation();
+ m_points.clear();
+ m_dragging = false;
+ } else {
+ drawGrid();
+ }
+}
+
+
+void KisToolPerspectiveGrid::update (KisCanvasSubject *subject)
+{
+ m_subject = subject;
+ super::update(m_subject);
+}
+
+bool KisToolPerspectiveGrid::mouseNear(const TQPoint& mousep, const TQPoint point)
+{
+ return (TQRect( (point.x() - m_handleHalfSize), (point.y() - m_handleHalfSize), m_handleSize, m_handleSize).tqcontains(mousep) );
+}
+
+void KisToolPerspectiveGrid::buttonPress(KisButtonPressEvent *event)
+{
+ KisPerspectiveGrid* pGrid = m_subject->currentImg()->perspectiveGrid();
+ if(!pGrid->hasSubGrids() && m_mode != MODE_CREATION)
+ { // it's possible that the perspectiv grid was cleared
+ m_mode = MODE_CREATION;
+ m_points.clear();
+ }
+ if( m_mode == MODE_CREATION && event->button() == Qt::LeftButton)
+ {
+ m_dragging = true;
+
+ if (m_points.isEmpty())
+ {
+ m_dragStart = event->pos();
+ m_dragEnd = event->pos();
+ m_points.append(m_dragStart);
+ } else {
+ m_dragStart = m_dragEnd;
+ m_dragEnd = event->pos();
+ drawGridCreation();
+ }
+ } else if(m_mode == MODE_EDITING && event->button() == Qt::LeftButton){
+ // Look for the handle which was pressed
+ if (!m_subject)
+ return;
+ KisCanvasController *controller = m_subject->canvasController();
+ Q_ASSERT(controller);
+ TQPoint mousep = controller->windowToView( event->pos().roundTQPoint() );
+
+ for( TQValueList<KisSubPerspectiveGrid*>::const_iterator it = pGrid->begin(); it != pGrid->end(); ++it)
+ {
+ KisSubPerspectiveGrid* grid = *it;
+ if( mouseNear( mousep, controller->windowToView(grid->topLeft()->roundTQPoint() ) ) )
+ {
+ kdDebug() << " PRESS TOPLEFT HANDLE " << endl;
+ m_mode = MODE_DRAGING_NODE;
+ m_selectedNode1 = grid->topLeft();
+ break;
+ }
+ else if( mouseNear( mousep, controller->windowToView(grid->topRight()->roundTQPoint() ) ) )
+ {
+ kdDebug() << " PRESS TOPRIGHT HANDLE " << endl;
+ m_mode = MODE_DRAGING_NODE;
+ m_selectedNode1 = grid->topRight();
+ break;
+ }
+ else if( mouseNear( mousep, controller->windowToView(grid->bottomLeft()->roundTQPoint() ) ) )
+ {
+ kdDebug() << " PRESS BOTTOMLEFT HANDLE " << endl;
+ m_mode = MODE_DRAGING_NODE;
+ m_selectedNode1 = grid->bottomLeft();
+ break;
+ }
+ else if( mouseNear( mousep, controller->windowToView(grid->bottomRight()->roundTQPoint() ) ) )
+ {
+ kdDebug() << " PRESS BOTTOMRIGHT HANDLE " << endl;
+ m_mode = MODE_DRAGING_NODE;
+ m_selectedNode1 = grid->bottomRight();
+ break;
+ }
+ else if( !grid->leftGrid() && mouseNear( mousep, controller->windowToView( ((*grid->topLeft() + *grid->bottomLeft() )*0.5) ).roundTQPoint() ) )
+ {
+ kdDebug() << " PRESS LEFT HANDLE " << endl;
+ m_mode = MODE_DRAGING_TRANSLATING_TWONODES;
+ drawGrid();
+ m_selectedNode1 = new KisPerspectiveGridNode( *grid->topLeft() );
+ m_selectedNode2 = new KisPerspectiveGridNode( *grid->bottomLeft() );
+ KisSubPerspectiveGrid* newsubgrid = new KisSubPerspectiveGrid( m_selectedNode1, grid->topLeft() , grid->bottomLeft(), m_selectedNode2);
+ m_dragEnd = event->pos();
+ newsubgrid->setRightGrid( grid);
+ grid->setLeftGrid( newsubgrid);
+ pGrid->addNewSubGrid( newsubgrid);
+ drawGrid();
+ break;
+ }
+ else if( !grid->rightGrid() && mouseNear( mousep, controller->windowToView( ((*grid->topRight() + *grid->bottomRight() )*0.5) ).roundTQPoint() ) )
+ {
+ kdDebug() << " PRESS RIGHT HANDLE " << endl;
+ m_mode = MODE_DRAGING_TRANSLATING_TWONODES;
+ drawGrid();
+ m_selectedNode1 = new KisPerspectiveGridNode( *grid->topRight() );
+ m_selectedNode2 = new KisPerspectiveGridNode( *grid->bottomRight() );
+ KisSubPerspectiveGrid* newsubgrid = new KisSubPerspectiveGrid( grid->topRight(), m_selectedNode1, m_selectedNode2, grid->bottomRight());
+ m_dragEnd = event->pos();
+ newsubgrid->setLeftGrid( grid);
+ grid->setRightGrid( newsubgrid);
+ pGrid->addNewSubGrid( newsubgrid);
+ drawGrid();
+ break;
+ }
+ else if( !grid->topGrid() && mouseNear( mousep, controller->windowToView( ((*grid->topLeft() + *grid->topRight() )*0.5) ).roundTQPoint() ) )
+ {
+ kdDebug() << " PRESS TOP HANDLE " << endl;
+ m_mode = MODE_DRAGING_TRANSLATING_TWONODES;
+ drawGrid();
+ m_selectedNode1 = new KisPerspectiveGridNode( *grid->topLeft() );
+ m_selectedNode2 = new KisPerspectiveGridNode( *grid->topRight() );
+ KisSubPerspectiveGrid* newsubgrid = new KisSubPerspectiveGrid( m_selectedNode1, m_selectedNode2, grid->topRight(), grid->topLeft() );
+ m_dragEnd = event->pos();
+ newsubgrid->setBottomGrid( grid);
+ grid->setTopGrid( newsubgrid);
+ pGrid->addNewSubGrid( newsubgrid);
+ drawGrid();
+ break;
+ }
+ else if( !grid->bottomGrid() && mouseNear( mousep, controller->windowToView( ((*grid->bottomLeft() + *grid->bottomRight() )*0.5) ).roundTQPoint() ) )
+ {
+ kdDebug() << " PRESS BOTTOM HANDLE " << endl;
+ m_mode = MODE_DRAGING_TRANSLATING_TWONODES;
+ drawGrid();
+ m_selectedNode1 = new KisPerspectiveGridNode( *grid->bottomLeft() );
+ m_selectedNode2 = new KisPerspectiveGridNode( *grid->bottomRight() );
+ KisSubPerspectiveGrid* newsubgrid = new KisSubPerspectiveGrid( grid->bottomLeft(), grid->bottomRight(), m_selectedNode2, m_selectedNode1);
+ m_dragEnd = event->pos();
+ newsubgrid->setTopGrid( grid);
+ grid->setBottomGrid( newsubgrid);
+ pGrid->addNewSubGrid( newsubgrid);
+ drawGrid();
+ break;
+ }
+ }
+ }
+}
+
+
+void KisToolPerspectiveGrid::move(KisMoveEvent *event)
+{
+ if( m_mode == MODE_CREATION )
+ {
+ if (m_dragging) {
+ // erase old lines on canvas
+ drawGridCreation();
+ // get current mouse position
+ m_dragEnd = event->pos();
+ // draw new lines on canvas
+ drawGridCreation();
+ }
+ } else {
+ if( m_mode == MODE_DRAGING_NODE)
+ {
+ drawGrid();
+ m_selectedNode1->setX( event->pos().x() );
+ m_selectedNode1->setY( event->pos().y() );
+ drawGrid();
+ }
+ if( m_mode == MODE_DRAGING_TRANSLATING_TWONODES)
+ {
+ drawGrid();
+ KisPoint translate = event->pos() - m_dragEnd;
+ m_dragEnd = event->pos();
+ *m_selectedNode1 += translate;;
+ *m_selectedNode2 += translate;;
+ drawGrid();
+ }
+ }
+}
+
+void KisToolPerspectiveGrid::buttonRelease(KisButtonReleaseEvent *event)
+{
+ if (!m_subject)
+ return;
+
+ if( m_mode == MODE_CREATION )
+ {
+ if (m_dragging && event->button() == Qt::LeftButton) {
+ m_dragging = false;
+ m_points.append (m_dragEnd);
+ if( m_points.size() == 4)
+ { // wow we have a grid, isn't that cool ?
+ drawGridCreation(); // Clean
+ m_subject->currentImg()->perspectiveGrid()->addNewSubGrid( new KisSubPerspectiveGrid( new KisPerspectiveGridNode(m_points[0]), new KisPerspectiveGridNode(m_points[1]), new KisPerspectiveGridNode(m_points[2]), new KisPerspectiveGridNode(m_points[3]) ) );
+ drawGrid();
+ m_mode = MODE_EDITING;
+ }
+ }
+ } else {
+ m_mode = MODE_EDITING;
+ m_selectedNode1 = 0;
+ m_selectedNode2 = 0;
+ }
+
+/* if (m_dragging && event->button() == RightButton) {
+
+ }*/
+}
+
+void KisToolPerspectiveGrid::paint(KisCanvasPainter& gc)
+{
+ if( m_mode == MODE_CREATION )
+ {
+ drawGridCreation(gc);
+ } else {
+ drawGrid(gc);
+ }
+}
+
+void KisToolPerspectiveGrid::paint(KisCanvasPainter& gc, const TQRect&)
+{
+ if( m_mode == MODE_CREATION )
+ {
+ drawGridCreation(gc);
+ } else {
+ drawGrid(gc);
+ }
+}
+
+void KisToolPerspectiveGrid::drawGridCreation()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter gc(canvas);
+
+ drawGridCreation(gc);
+ }
+}
+
+
+void KisToolPerspectiveGrid::drawGridCreation(KisCanvasPainter& gc)
+{
+ if (!m_subject)
+ return;
+
+ TQPen pen(TQt::white);
+
+ gc.setPen(pen);
+ gc.setRasterOp(TQt::XorROP);
+
+ KisCanvasController *controller = m_subject->canvasController();
+ KisPoint start, end;
+ TQPoint startPos;
+ TQPoint endPos;
+
+ if (m_dragging) {
+ startPos = controller->windowToView(m_dragStart.floorTQPoint());
+ endPos = controller->windowToView(m_dragEnd.floorTQPoint());
+ gc.drawLine(startPos, endPos);
+ } else {
+ for (KisPointVector::iterator it = m_points.begin(); it != m_points.end(); ++it) {
+
+ if (it == m_points.begin())
+ {
+ start = (*it);
+ } else {
+ end = (*it);
+
+ startPos = controller->windowToView(start.floorTQPoint());
+ endPos = controller->windowToView(end.floorTQPoint());
+
+ gc.drawLine(startPos, endPos);
+
+ start = end;
+ }
+ }
+ }
+}
+
+void KisToolPerspectiveGrid::drawSmallRectangle(KisCanvasPainter& gc, TQPoint p)
+{
+ gc.drawRect( p.x() - m_handleHalfSize - 1, p.y() - m_handleHalfSize - 1, m_handleSize, m_handleSize);
+}
+
+void KisToolPerspectiveGrid::drawGrid(KisCanvasPainter& gc)
+{
+
+ if (!m_subject)
+ return;
+
+ KisCanvasController *controller = m_subject->canvasController();
+
+ TQPen pen(TQt::white);
+ TQPoint startPos;
+ TQPoint endPos;
+
+ gc.setPen(pen);
+ gc.setRasterOp(TQt::XorROP);
+ KisPerspectiveGrid* pGrid = m_subject->currentImg()->perspectiveGrid();
+
+ for( TQValueList<KisSubPerspectiveGrid*>::const_iterator it = pGrid->begin(); it != pGrid->end(); ++it)
+ {
+ KisSubPerspectiveGrid* grid = *it;
+ int index = grid->index();
+ bool drawLeft = !(grid->leftGrid() && (index > grid->leftGrid()->index() ) );
+ bool drawRight = !(grid->rightGrid() && (index > grid->rightGrid()->index() ) );
+ bool drawTop = !(grid->topGrid() && (index > grid->topGrid()->index() ) );
+ bool drawBottom = !(grid->bottomGrid() && (index > grid->bottomGrid()->index() ) );
+ if(drawTop) {
+ startPos = controller->windowToView(grid->topLeft()->roundTQPoint());
+ endPos = controller->windowToView(grid->topRight()->roundTQPoint());
+ gc.drawLine( startPos, endPos );
+ if( !grid->topGrid() )
+ {
+ drawSmallRectangle(gc, (endPos + startPos) / 2);
+ }
+ if(drawLeft) {
+ drawSmallRectangle(gc, startPos);
+ }
+ if(drawRight) {
+ drawSmallRectangle(gc, endPos);
+ }
+ }
+ if(drawRight) {
+ startPos = controller->windowToView(grid->topRight()->roundTQPoint());
+ endPos = controller->windowToView(grid->bottomRight()->roundTQPoint());
+ gc.drawLine( startPos, endPos );
+ if( !grid->rightGrid() )
+ {
+ drawSmallRectangle(gc, (endPos + startPos) / 2);
+ }
+ }
+ if(drawBottom) {
+ startPos = controller->windowToView(grid->bottomRight()->roundTQPoint());
+ endPos = controller->windowToView(grid->bottomLeft()->roundTQPoint());
+ gc.drawLine( startPos, endPos );
+ if( !grid->bottomGrid() )
+ {
+ drawSmallRectangle(gc, (endPos + startPos) / 2);
+ }
+ if(drawLeft) {
+ drawSmallRectangle(gc, endPos);
+ }
+ if(drawRight) {
+ drawSmallRectangle(gc, startPos);
+ }
+ }
+ if(drawLeft) {
+ startPos = controller->windowToView(grid->bottomLeft()->roundTQPoint());
+ endPos = controller->windowToView(grid->topLeft()->roundTQPoint());
+ gc.drawLine( startPos, endPos );
+ if( !grid->leftGrid() )
+ {
+ drawSmallRectangle(gc, (endPos + startPos) / 2);
+ }
+ }
+ KisPoint tbVpf = grid->topBottomVanishingPoint();
+ if( fabs(tbVpf.x()) < 30000000. && fabs(tbVpf.y()) < 30000000.)
+ {
+ TQPoint tbVp = controller->windowToView(tbVpf.roundTQPoint());
+ gc.drawLine( tbVp.x() - m_handleHalfSize, tbVp.y() - m_handleHalfSize, tbVp.x() + m_handleHalfSize, tbVp.y() + m_handleHalfSize);
+ gc.drawLine( tbVp.x() - m_handleHalfSize, tbVp.y() + m_handleHalfSize, tbVp.x() + m_handleHalfSize, tbVp.y() - m_handleHalfSize);
+ }
+ KisPoint lrVpf = grid->leftRightVanishingPoint();
+ if( fabs(lrVpf.x()) < 30000000. && fabs(lrVpf.y()) < 30000000.)
+ { // Don't display it, if it is too far, or you get funny results
+ TQPoint lrVp = controller->windowToView(lrVpf.roundTQPoint());
+ gc.drawLine( lrVp.x() - m_handleHalfSize, lrVp.y() - m_handleHalfSize, lrVp.x() + m_handleHalfSize, lrVp.y() + m_handleHalfSize);
+ gc.drawLine( lrVp.x() - m_handleHalfSize, lrVp.y() + m_handleHalfSize, lrVp.x() + m_handleHalfSize, lrVp.y() - m_handleHalfSize);
+ }
+ }
+}
+
+void KisToolPerspectiveGrid::drawGrid()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter gc(canvas);
+
+ drawGrid(gc);
+ }
+
+}
+
+
+void KisToolPerspectiveGrid::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Perspective Grid"),
+ "tool_perspectivegrid" ,
+ 0,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ Q_CHECK_PTR(m_action);
+ m_action->setExclusiveGroup("tools");
+ m_action->setToolTip(i18n("Edit the perspective grid"));
+ m_ownAction = true;
+ }
+}
+
+
+// TQWidget* KisToolPerspectiveGrid::createOptionWidget(TQWidget* tqparent)
+// {
+// return 0;
+// }
+//
+// TQWidget* KisToolPerspectiveGrid::optionWidget()
+// {
+// return 0;
+// }
+
+
+#include "kis_tool_perspectivegrid.moc"
diff --git a/chalk/plugins/tools/tool_perspectivegrid/kis_tool_perspectivegrid.h b/chalk/plugins/tools/tool_perspectivegrid/kis_tool_perspectivegrid.h
new file mode 100644
index 00000000..69f6407a
--- /dev/null
+++ b/chalk/plugins/tools/tool_perspectivegrid/kis_tool_perspectivegrid.h
@@ -0,0 +1,111 @@
+/*
+ * kis_tool_perspectivegrid.h - part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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_TOOL_PERSPECTIVE_GRID_H_
+#define _KIS_TOOL_PERSPECTIVE_GRID_H_
+
+#include <kis_perspective_grid.h>
+#include <kis_point.h>
+#include <kis_tool_non_paint.h>
+#include <kis_tool_factory.h>
+
+class KisToolPerspectiveGrid : public KisToolNonPaint {
+ Q_OBJECT
+ TQ_OBJECT
+ enum PerspectiveGridEditionMode {
+ MODE_CREATION, // This is the mode when there is not yet a perspective grid
+ MODE_EDITING, // This is the mode when the grid has been created, and we are waiting for the user to click on a control box
+ MODE_DRAGING_NODE, // In this mode one node is translated
+ MODE_DRAGING_TRANSLATING_TWONODES // This mode is used when creating a new sub perspective grid
+ };
+ typedef KisToolNonPaint super;
+public:
+ KisToolPerspectiveGrid();
+ virtual ~KisToolPerspectiveGrid();
+ //
+ // KisCanvasObserver interface
+ //
+
+ virtual void update (KisCanvasSubject *subject);
+
+ //
+ // KisToolPaint interface
+ //
+
+ virtual void setup(KActionCollection *collection);
+ virtual TQ_UINT32 priority() { return 3; }
+ virtual enumToolType toolType() { return TOOL_VIEW; }
+ virtual void buttonPress(KisButtonPressEvent *event);
+ virtual void move(KisMoveEvent *event);
+ virtual void buttonRelease(KisButtonReleaseEvent *event);
+
+// TQWidget* createOptionWidget(TQWidget* tqparent);
+// virtual TQWidget* optionWidget();
+
+public slots:
+ virtual void activate();
+ void deactivate();
+
+protected:
+ virtual void paint(KisCanvasPainter& gc);
+ virtual void paint(KisCanvasPainter& gc, const TQRect& rc);
+ void drawGridCreation(KisCanvasPainter& gc);
+ void drawGridCreation();
+ void drawGrid(KisCanvasPainter& gc);
+ void drawGrid();
+
+private:
+ void drawSmallRectangle(KisCanvasPainter& gc, TQPoint p);
+ bool mouseNear(const TQPoint& mousep, const TQPoint point);
+
+protected:
+ KisPoint m_dragStart;
+ KisPoint m_dragEnd;
+
+ bool m_dragging;
+private:
+ typedef TQValueVector<KisPoint> KisPointVector;
+ KisCanvasSubject *m_subject;
+ KisPointVector m_points;
+ PerspectiveGridEditionMode m_mode;
+ TQ_INT32 m_handleSize, m_handleHalfSize;
+ KisPerspectiveGridNodeSP m_selectedNode1, m_selectedNode2;
+
+};
+
+
+class KisToolPerspectiveGridFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolPerspectiveGridFactory() : super() {};
+ virtual ~KisToolPerspectiveGridFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolPerspectiveGrid();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("perspectivegridtool", i18n("Perspective Grid Tool")); }
+};
+
+
+#endif
+
diff --git a/chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.cc b/chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.cc
new file mode 100644
index 00000000..69158e21
--- /dev/null
+++ b/chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.cc
@@ -0,0 +1,62 @@
+/*
+ * tool_perspectivegrid.cc -- Part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_tool_registry.h>
+
+#include "tool_perspectivegrid.h"
+#include "kis_tool_perspectivegrid.h"
+
+
+typedef KGenericFactory<ToolPerspectiveGrid> ToolPerspectiveGridFactory;
+K_EXPORT_COMPONENT_FACTORY( chalktoolperspectivegrid, ToolPerspectiveGridFactory( "chalk" ) )
+
+
+ToolPerspectiveGrid::ToolPerspectiveGrid(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ToolPerspectiveGridFactory::instance());
+
+ if ( tqparent->inherits("KisToolRegistry") )
+ {
+ KisToolRegistry * r = dynamic_cast<KisToolRegistry*>(tqparent);
+ r->add(new KisToolPerspectiveGridFactory());
+ }
+
+}
+
+ToolPerspectiveGrid::~ToolPerspectiveGrid()
+{
+}
+
+#include "tool_perspectivegrid.moc"
diff --git a/chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.h b/chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.h
new file mode 100644
index 00000000..aed4a60c
--- /dev/null
+++ b/chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 TOOL_PERSPECTIVE_GRID_H_
+#define TOOL_PERSPECTIVE_GRID_H_
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+/**
+ * A module that provides a tool for editing the perspective grid.
+ */
+class ToolPerspectiveGrid : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ ToolPerspectiveGrid(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ToolPerspectiveGrid();
+
+private:
+
+ KisView * m_view;
+
+};
+
+#endif // TOOL_PERSPECTIVE_GRID_H_
diff --git a/chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.png b/chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.png
new file mode 100644
index 00000000..ac4efbfa
--- /dev/null
+++ b/chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.svg b/chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.svg
new file mode 100644
index 00000000..3dd79413
--- /dev/null
+++ b/chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.svg
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="22"
+ height="22"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.43"
+ version="1.0"
+ sodipodi:docbase="/home/cyrille/koffice-1.6/chalk/plugins/tools/tool_perspectivegrid"
+ sodipodi:docname="tool_perspectivegrid.svg"
+ inkscape:export-filename="/home/cyrille/koffice-1.6/chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="9.8597476"
+ inkscape:cx="12.855376"
+ inkscape:cy="7.6671075"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="749"
+ inkscape:window-height="540"
+ inkscape:window-x="424"
+ inkscape:window-y="433" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 4.8682788,20.580085 C 6.5924609,1.3098151 6.7953058,1.5126601 6.7953058,1.5126601 L 6.7953058,1.5126601 L 6.7953058,1.5126601"
+ id="path2183" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 11.359317,18.551636 C 10.446515,2.3240399 10.446515,2.3240399 10.446515,2.3240399 L 10.446515,2.3240399 L 10.446515,2.3240399"
+ id="path2185" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 17.444666,17.131721 C 13.894879,3.1354197 13.894879,3.1354197 13.894879,3.1354197"
+ id="path2187" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 2.7384068,4.7581793 C 17.647511,6.5837838 17.546088,6.5837838 17.546088,6.5837838"
+ id="path2191" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 2.0284495,10.742105 C 18.256045,9.7278805 18.86458,9.1193456 18.86458,9.1193456"
+ id="path2193"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 1.0142247,17.131721 C 20.08165,12.56771 20.08165,12.364865 20.08165,12.364865"
+ id="path2195"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 3.1440967,0.59985768 L 16.531864,3.6425319 L 21.70441,15.813228 L 0.50711235,21.594309 L 3.1440967,0.59985768 z "
+ id="rect1307"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+</svg>
diff --git a/chalk/plugins/tools/tool_perspectivetransform/Makefile.am b/chalk/plugins/tools/tool_perspectivetransform/Makefile.am
new file mode 100644
index 00000000..416bdcc3
--- /dev/null
+++ b/chalk/plugins/tools/tool_perspectivetransform/Makefile.am
@@ -0,0 +1,35 @@
+kde_services_DATA = chalktoolperspectivetransform.desktop
+
+# all_includes must remain last!
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalktoolperspectivetransform_la_SOURCES = \
+ tool_perspectivetransform.cc \
+ kis_tool_perspectivetransform.cc
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = chalktoolperspectivetransform.la
+
+noinst_HEADERS = \
+ tool_perspectivetransform.h \
+ kis_tool_perspectivetransform.h
+
+chalktoolperspectivetransform_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalktoolperspectivetransform_la_LIBADD = ../../../libchalkcommon.la
+
+chalktoolperspectivetransform_la_METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
+
+chalkpics_DATA = \
+ tool_perspectivetransform.png
+
+chalkpicsdir = $(kde_datadir)/chalk/pics
+
diff --git a/chalk/plugins/tools/tool_perspectivetransform/chalktoolperspectivetransform.desktop b/chalk/plugins/tools/tool_perspectivetransform/chalktoolperspectivetransform.desktop
new file mode 100644
index 00000000..860efc69
--- /dev/null
+++ b/chalk/plugins/tools/tool_perspectivetransform/chalktoolperspectivetransform.desktop
@@ -0,0 +1,37 @@
+[Desktop Entry]
+Icon=
+Name=Perspective transform Tool
+Name[bg]=Инструмент трансформиране
+Name[ca]=Eina de transformació de perspectiva
+Name[da]=Perspectivetransformeringsværktøj
+Name[de]=Perspektive-Transformationswerkzeug
+Name[el]=Εργαλείο προοπτικού μετασχηματισμού
+Name[eo]=Perspektivŝanĝo-ilo
+Name[es]=Herramienta Transformar perspectiva
+Name[et]=Perspektiivteisenduse tööriist
+Name[fa]=ابزار تبدیل بُعدنما
+Name[fr]=Outils de transformation de perspective
+Name[fy]=Perspeksje oerset ark
+Name[hu]=Perspektívaátalakító eszköz
+Name[it]=Strumento di trasformazione della prospettiva
+Name[ja]=視点変更ツール
+Name[km]=ឧបករណ៍​ប្លែង​យថាទស្សន៍
+Name[nb]=Verktøy for perspektivtransformasjon
+Name[nds]=Warktüüch för't Kiekwinkeltopassen
+Name[ne]=दृश्यात्मक रूपान्तरण उपकरण
+Name[nl]=Perspectiefrooster-gereedschap
+Name[pl]=Narzędzie zmiany perspektywy
+Name[pt]=Ferramenta de Transformação em Perspectiva
+Name[pt_BR]=Ferramentas de Transformação em Perspectiva
+Name[ru]=Перспектива
+Name[sk]=Perspektívna transformácia
+Name[sl]=Orodje za transformacijo perspektive
+Name[sr]=Алати за трансформацију перспективе
+Name[sr@Latn]=Alati za transformaciju perspektive
+Name[sv]=Perspektivtransformverktyg
+Name[uk]=Засіб перспективи
+Name[zh_TW]=透視轉換工具
+ServiceTypes=Chalk/Tool
+Type=Service
+X-KDE-Library=chalktoolperspectivetransform
+X-Chalk-Version=2
diff --git a/chalk/plugins/tools/tool_perspectivetransform/kis_tool_perspectivetransform.cc b/chalk/plugins/tools/tool_perspectivetransform/kis_tool_perspectivetransform.cc
new file mode 100644
index 00000000..809d1a7d
--- /dev/null
+++ b/chalk/plugins/tools/tool_perspectivetransform/kis_tool_perspectivetransform.cc
@@ -0,0 +1,742 @@
+/*
+ * kis_tool_transform.cc -- part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * Based on the transform tool from :
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2005 Casper Boemann <cbr@boemann.dk>
+ *
+ * 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; version 2 of the License.
+ *
+ * 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_tool_perspectivetransform.h"
+
+
+#include <tqpainter.h>
+#include <tqpen.h>
+#include <tqpushbutton.h>
+#include <tqobject.h>
+#include <tqlabel.h>
+#include <tqcombobox.h>
+#include <tqapplication.h>
+
+#include <kdebug.h>
+#include <kaction.h>
+#include <kcommand.h>
+#include <klocale.h>
+#include <knuminput.h>
+
+#include <kis_global.h>
+#include <kis_painter.h>
+#include <kis_canvas_controller.h>
+#include <kis_canvas_subject.h>
+#include <kis_cursor.h>
+#include <kis_image.h>
+#include <kis_undo_adapter.h>
+#include <kis_selected_transaction.h>
+#include <kis_button_press_event.h>
+#include <kis_button_release_event.h>
+#include <kis_move_event.h>
+#include <kis_selection.h>
+#include <kis_filter_strategy.h>
+#include <kis_cmb_idlist.h>
+#include <kis_id.h>
+#include <kis_tool_controller.h>
+#include <kis_perspectivetransform_worker.h>
+
+//#include "wdg_tool_transform.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+
+namespace {
+ class PerspectiveTransformCmd : public KisSelectedTransaction {
+ typedef KisSelectedTransaction super;
+
+ public:
+ PerspectiveTransformCmd(KisToolPerspectiveTransform *tool, KisPaintDeviceSP device, KisPaintDeviceSP origDevice, KisPoint topleft, KisPoint topright, KisPoint bottomleft, KisPoint bottomright, KisSelectionSP origSel, TQRect initialRect);
+ virtual ~PerspectiveTransformCmd();
+
+ public:
+ virtual void execute();
+ virtual void unexecute();
+ void transformArgs(KisPoint &topleft, KisPoint &topright, KisPoint &bottomleft, KisPoint& bottomright) const;
+ KisSelectionSP origSelection(TQRect& initialRect) const;
+ KisPaintDeviceSP theDevice();
+ KisPaintDeviceSP origDevice();
+
+ private:
+ TQRect m_initialRect;
+ KisPoint m_topleft, m_topright, m_bottomleft, m_bottomright;
+ KisToolPerspectiveTransform *m_tool;
+ KisSelectionSP m_origSelection;
+ KisPaintDeviceSP m_device;
+ KisPaintDeviceSP m_origDevice;
+ };
+
+ PerspectiveTransformCmd::PerspectiveTransformCmd(KisToolPerspectiveTransform *tool, KisPaintDeviceSP device, KisPaintDeviceSP origDevice, KisPoint topleft, KisPoint topright, KisPoint bottomleft, KisPoint bottomright, KisSelectionSP origSel, TQRect initialRect) :
+ super(i18n("Perspective Transform"), device), m_initialRect(initialRect)
+ , m_topleft(topleft), m_topright(topright), m_bottomleft(bottomleft), m_bottomright(bottomright)
+ , m_tool(tool), m_origSelection(origSel), m_device(device), m_origDevice(origDevice)
+ {
+ }
+
+ PerspectiveTransformCmd::~PerspectiveTransformCmd()
+ {
+ }
+
+ void PerspectiveTransformCmd::transformArgs(KisPoint &topleft, KisPoint &topright, KisPoint &bottomleft, KisPoint& bottomright) const
+ {
+ topleft = m_topleft;
+ topright = m_topright;
+ bottomleft = m_bottomleft;
+ bottomright = m_bottomright;
+ }
+
+ KisSelectionSP PerspectiveTransformCmd::origSelection(TQRect& initialRect) const
+ {
+ initialRect = m_initialRect;
+ return m_origSelection;
+ }
+
+ void PerspectiveTransformCmd::execute()
+ {
+ super::execute();
+ }
+
+ void PerspectiveTransformCmd::unexecute()
+ {
+ super::unexecute();
+ }
+
+ KisPaintDeviceSP PerspectiveTransformCmd::theDevice()
+ {
+ return m_device;
+ }
+
+ KisPaintDeviceSP PerspectiveTransformCmd::origDevice()
+ {
+ return m_origDevice;
+ }
+}
+
+KisToolPerspectiveTransform::KisToolPerspectiveTransform()
+ : super(i18n("Perspective Transform"))
+{
+ setName("tool_perspectivetransform");
+ setCursor(KisCursor::selectCursor());
+ m_subject = 0;
+ m_origDevice = 0;
+ m_origSelection = 0;
+ m_handleHalfSize = 8;
+ m_handleSize = 2 * m_handleHalfSize;
+ m_handleSelected = NOHANDLE;
+}
+
+KisToolPerspectiveTransform::~KisToolPerspectiveTransform()
+{
+}
+
+void KisToolPerspectiveTransform::deactivate()
+{
+ if (m_subject && m_subject->undoAdapter()) m_subject->undoAdapter()->removeCommandHistoryListener( this );
+
+ KisImageSP img = m_subject->currentImg();
+ if (!img) return;
+
+ paintOutline();
+
+ disconnect(m_subject->currentImg().data(), TQT_SIGNAL(sigLayerActivated(KisLayerSP)), this, TQT_SLOT(slotLayerActivated(KisLayerSP)));
+}
+
+void KisToolPerspectiveTransform::activate()
+{
+ super::activate();
+ m_currentSelectedPoint = 0;
+ if(m_subject && m_subject->currentImg() && m_subject->currentImg()->activeDevice())
+ {
+ //connect(m_subject, commandExecuted(KCommand *c), this, notifyCommandAdded( KCommand * c));
+ m_subject->undoAdapter()->setCommandHistoryListener( this );
+
+// KisToolControllerInterface *controller = m_subject->toolController();
+// if (controller)
+// controller->setCurrentTool(this);
+
+ PerspectiveTransformCmd * cmd=0;
+
+ if(m_subject->currentImg()->undoAdapter()->presentCommand())
+ cmd = dynamic_cast<PerspectiveTransformCmd*>(m_subject->currentImg()->undoAdapter()->presentCommand());
+
+ // One of our commands is on top
+ if(cmd &&cmd->theDevice() == m_subject->currentImg()->activeDevice())
+ {
+ m_interractionMode = EDITRECTINTERRACTION;
+ // and it even has the same device
+ // We should ask for tool args and orig selection
+ m_origDevice = cmd->origDevice();
+ cmd->transformArgs(m_topleft, m_topright, m_bottomleft, m_bottomright);
+ m_origSelection = cmd->origSelection(m_initialRect);
+ paintOutline();
+ }
+ else
+ {
+ m_interractionMode = DRAWRECTINTERRACTION;
+ m_points.clear();
+ initHandles();
+ }
+ }
+ connect(m_subject->currentImg(), TQT_SIGNAL(sigLayerActivated(KisLayerSP)), this, TQT_SLOT(slotLayerActivated(KisLayerSP)));
+}
+
+void KisToolPerspectiveTransform::initHandles()
+{
+// TQ_INT32 x,y,w,h;
+ KisImageSP img = m_subject->currentImg();
+
+ KisPaintDeviceSP dev = img->activeDevice();
+ if (!dev ) return;
+
+ // Create a lazy copy of the current state
+ m_origDevice = new KisPaintDevice(*dev.data());
+ Q_ASSERT(m_origDevice);
+
+ if(dev->hasSelection())
+ {
+ KisSelectionSP sel = dev->selection();
+ m_origSelection = new KisSelection(*sel.data());
+ m_initialRect = sel->selectedExactRect();
+ }
+ else {
+ m_initialRect = dev->exactBounds();
+ }
+ m_topleft = KisPoint(m_initialRect.topLeft());
+ m_topright = KisPoint(m_initialRect.topRight());
+ m_bottomleft = KisPoint(m_initialRect.bottomLeft());
+ m_bottomright = KisPoint(m_initialRect.bottomRight());
+
+ m_subject->canvasController() ->updateCanvas();
+}
+
+void KisToolPerspectiveTransform::paint(KisCanvasPainter& gc)
+{
+ paintOutline(gc, TQRect());
+}
+
+void KisToolPerspectiveTransform::paint(KisCanvasPainter& gc, const TQRect& rc)
+{
+ paintOutline(gc, rc);
+}
+
+bool KisToolPerspectiveTransform::mouseNear(const TQPoint& mousep, const TQPoint point)
+{
+ return (TQRect( (point.x() - m_handleHalfSize), (point.y() - m_handleHalfSize), m_handleSize, m_handleSize).tqcontains(mousep) );
+}
+
+void KisToolPerspectiveTransform::buttonPress(KisButtonPressEvent *event)
+{
+ if (m_subject) {
+ switch(m_interractionMode)
+ {
+ case DRAWRECTINTERRACTION:
+ {
+ if (m_points.isEmpty())
+ {
+ m_dragging = false;
+ m_dragStart = event->pos();
+ m_dragEnd = event->pos();
+ m_points.append(m_dragStart);
+ paintOutline();
+ } else {
+ m_dragging = true;
+ m_dragStart = m_dragEnd;
+ m_dragEnd = event->pos();
+ paintOutline();
+ }
+ }
+ case EDITRECTINTERRACTION:
+ {
+ KisImageSP img = m_subject->currentImg();
+
+ if (img && img->activeDevice() && event->button() == Qt::LeftButton) {
+ m_actualyMoveWhileSelected = false;
+ m_dragEnd = event->pos();
+ KisCanvasController *controller = m_subject->canvasController();
+ TQPoint mousep = controller->windowToView( event->pos().roundTQPoint() );
+ if( mouseNear( mousep, controller->windowToView(m_topleft.roundTQPoint() ) ) )
+ {
+ kdDebug() << " PRESS TOPLEFT HANDLE " << endl;
+ m_currentSelectedPoint = &m_topleft;
+ }
+ else if( mouseNear( mousep, controller->windowToView(m_topright.roundTQPoint() ) ) )
+ {
+ kdDebug() << " PRESS TOPRIGHT HANDLE " << endl;
+ m_currentSelectedPoint = &m_topright;
+ }
+ else if( mouseNear( mousep, controller->windowToView(m_bottomleft.roundTQPoint() ) ) )
+ {
+ kdDebug() << " PRESS BOTTOMLEFT HANDLE " << endl;
+ m_currentSelectedPoint = &m_bottomleft;
+ }
+ else if( mouseNear( mousep, controller->windowToView(m_bottomright.roundTQPoint() ) ) )
+ {
+ kdDebug() << " PRESS BOTTOMRIGHT HANDLE " << endl;
+ m_currentSelectedPoint = &m_bottomright;
+ } else if( mouseNear( mousep, controller->windowToView(KisPoint((m_topleft+m_topright)*0.5).roundTQPoint() ) ) )
+ {
+ kdDebug() << " PRESS TOP HANDLE " << endl;
+ m_handleSelected = TOPHANDLE;
+ }else if( mouseNear( mousep, controller->windowToView(KisPoint((m_topleft+m_bottomleft)*0.5).roundTQPoint() ) ) )
+ {
+ kdDebug() << " PRESS LEFT HANDLE " << endl;
+ m_handleSelected = LEFTHANDLE;
+ }else if( mouseNear( mousep, controller->windowToView(KisPoint((m_bottomleft+m_bottomright)*0.5).roundTQPoint() ) ) )
+ {
+ kdDebug() << " PRESS BOTTOM HANDLE " << endl;
+ m_handleSelected = BOTTOMHANDLE;
+ }else if( mouseNear( mousep, controller->windowToView(KisPoint((m_bottomright+m_topright)*0.5).roundTQPoint() ) ) )
+ {
+ kdDebug() << " PRESS RIGHT HANDLE " << endl;
+ m_handleSelected = RIGHTHANDLE;
+ }else if( mouseNear( mousep, controller->windowToView(KisPoint((m_topleft+m_bottomleft + m_bottomright+m_topright)*0.25).roundTQPoint() ) ) )
+ {
+ kdDebug() << " PRESS MIDDLE HANDLE " << endl;
+ m_handleSelected = MIDDLEHANDLE;
+ }
+ }
+ }
+ }
+ }
+}
+
+void KisToolPerspectiveTransform::move(KisMoveEvent *event)
+{
+ switch(m_interractionMode)
+ {
+ case DRAWRECTINTERRACTION:
+ {
+ if (m_dragging) {
+ // erase old lines on canvas
+ paintOutline();
+ // get current mouse position
+ m_dragEnd = event->pos();
+ // draw new lines on canvas
+ paintOutline();
+ }
+ }
+
+ case EDITRECTINTERRACTION:
+ {
+ if(m_currentSelectedPoint)
+ {
+ paintOutline();
+ KisPoint translate = event->pos() - m_dragEnd;
+ m_dragEnd = event->pos();
+ *m_currentSelectedPoint += translate;;
+ paintOutline();
+ m_actualyMoveWhileSelected = true;
+ }
+ else if(m_handleSelected == TOPHANDLE || m_handleSelected == LEFTHANDLE || m_handleSelected == BOTTOMHANDLE || m_handleSelected == RIGHTHANDLE)
+ {
+ paintOutline();
+
+ KisPoint translate = event->pos() - m_dragEnd;
+ m_dragEnd = event->pos();
+
+ double matrixFrom[3][3];
+ double* b = KisPerspectiveMath::computeMatrixTransfoToPerspective(m_topleft, m_topright, m_bottomleft, m_bottomright, m_initialRect);
+ for(int i = 0; i < 3; i++)
+ {
+ for(int j = 0; j < 3; j++)
+ {
+ matrixFrom[i][j] = b[3*i+j];
+ }
+ }
+ delete b;
+
+ KisPoint topLeft = KisPerspectiveMath::matProd(matrixFrom, KisPoint(m_initialRect.topLeft()) );
+ KisPoint topRight = KisPerspectiveMath::matProd(matrixFrom, KisPoint(m_initialRect.topRight()) );
+ KisPoint bottomLeft = KisPerspectiveMath::matProd(matrixFrom, KisPoint(m_initialRect.bottomLeft()) );
+ KisPoint bottomRight = KisPerspectiveMath::matProd(matrixFrom, KisPoint(m_initialRect.bottomRight()) );
+ TQRect dstRect = m_initialRect;
+ switch(m_handleSelected)
+ {
+ case TOPHANDLE:
+ dstRect.setTop( static_cast<int>( dstRect.top() + translate.y() ) ) ;
+ break;
+ case LEFTHANDLE:
+ dstRect.setLeft( static_cast<int>( dstRect.left() + translate.x() ) );
+ break;
+ case BOTTOMHANDLE:
+ dstRect.setBottom( static_cast<int>( dstRect.bottom() + translate.y() ) );
+ break;
+ case RIGHTHANDLE:
+ dstRect.setRight( static_cast<int>( dstRect.right() + translate.x() ) );
+ break;
+ case MIDDLEHANDLE:
+ case NOHANDLE:
+ kdDebug() << "Should NOT happen" << endl;
+ }
+ double matrixTo[3][3];
+ b = KisPerspectiveMath::computeMatrixTransfoToPerspective(topLeft, topRight, bottomLeft, bottomRight, dstRect );
+ for(int i = 0; i < 3; i++)
+ {
+ for(int j = 0; j < 3; j++)
+ {
+ matrixTo[i][j] = b[3*i+j];
+ }
+ }
+ delete b;
+ m_topleft = KisPerspectiveMath::matProd(matrixTo, KisPoint(m_initialRect.topLeft()));
+ m_topright = KisPerspectiveMath::matProd(matrixTo, KisPoint(m_initialRect.topRight()));
+ m_bottomleft = KisPerspectiveMath::matProd(matrixTo, KisPoint(m_initialRect.bottomLeft()));
+ m_bottomright = KisPerspectiveMath::matProd(matrixTo, KisPoint(m_initialRect.bottomRight()));
+
+ paintOutline();
+ m_actualyMoveWhileSelected = true;
+ } else if (m_handleSelected == MIDDLEHANDLE) {
+ paintOutline();
+ KisPoint translate = event->pos() - m_dragEnd;
+ m_dragEnd = event->pos();
+ m_topleft += translate;
+ m_topright += translate;
+ m_bottomleft += translate;
+ m_bottomright += translate;
+ paintOutline();
+ m_actualyMoveWhileSelected = true;
+ }
+ }
+ };
+}
+
+void KisToolPerspectiveTransform::buttonRelease(KisButtonReleaseEvent * event)
+{
+ KisImageSP img = m_subject->currentImg();
+
+ if (!img)
+ return;
+ if( event->button() == Qt::LeftButton)
+ {
+ switch(m_interractionMode)
+ {
+ case DRAWRECTINTERRACTION:
+ {
+ if (m_dragging && event->button() == Qt::LeftButton) {
+ paintOutline();
+ m_dragging = false;
+ m_points.append (m_dragEnd);
+ if( m_points.size() == 4)
+ {
+ // from the points, select which is topleft ? topright ? bottomright ? and bottomleft ?
+ m_topleft = m_points[0];
+ m_topright = m_points[1];
+ m_bottomleft = m_points[3];
+ m_bottomright = m_points[2];
+ double matrix[3][3];
+ double* b = KisPerspectiveMath::computeMatrixTransfoToPerspective(m_topleft, m_topright, m_bottomleft, m_bottomright, m_initialRect );
+ for(int i = 0; i < 3; i++)
+ {
+ for(int j = 0; j < 3; j++)
+ {
+ kdDebug() << "sol[" << 3*i+j << "]=" << b[3*i+j] << endl;
+ matrix[i][j] = b[3*i+j];
+ }
+ }
+ m_topleft = KisPerspectiveMath::matProd(matrix, KisPoint(m_initialRect.topLeft()));
+ m_topright = KisPerspectiveMath::matProd(matrix, KisPoint(m_initialRect.topRight()));
+ m_bottomleft = KisPerspectiveMath::matProd(matrix, KisPoint(m_initialRect.bottomLeft()));
+ m_bottomright = KisPerspectiveMath::matProd(matrix, KisPoint(m_initialRect.bottomRight()));
+ m_interractionMode = EDITRECTINTERRACTION;
+ paintOutline();
+ TQApplication::setOverrideCursor(KisCursor::waitCursor());
+ transform();
+ TQApplication::restoreOverrideCursor();
+ } else {
+ paintOutline();
+ }
+ }
+ }
+ break;
+ case EDITRECTINTERRACTION:
+ {
+ if(m_currentSelectedPoint )
+ {
+ m_currentSelectedPoint = 0;
+ if(m_actualyMoveWhileSelected)
+ {
+ paintOutline();
+ TQApplication::setOverrideCursor(KisCursor::waitCursor());
+ transform();
+ TQApplication::restoreOverrideCursor();
+ }
+ }
+ if(m_handleSelected != NOHANDLE)
+ {
+ m_handleSelected = NOHANDLE;
+ if(m_actualyMoveWhileSelected)
+ {
+// paintOutline();
+ TQApplication::setOverrideCursor(KisCursor::waitCursor());
+ transform();
+ TQApplication::restoreOverrideCursor();
+ }
+ }
+ }
+ break;
+ }
+ }
+}
+
+void KisToolPerspectiveTransform::paintOutline()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter gc(canvas);
+ TQRect rc;
+
+ paintOutline(gc, rc);
+ }
+}
+
+void KisToolPerspectiveTransform::paintOutline(KisCanvasPainter& gc, const TQRect&)
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ RasterOp op = gc.rasterOp();
+ TQPen old = gc.pen();
+ TQPen pen(TQt::SolidLine);
+ pen.setWidth(1);
+ Q_ASSERT(controller);
+
+ switch(m_interractionMode)
+ {
+ case DRAWRECTINTERRACTION:
+ {
+ kdDebug() << "DRAWRECTINTERRACTION paintOutline " << m_points.size() << endl;
+ KisPoint start, end;
+ TQPoint startPos;
+ TQPoint endPos;
+ for (KisPointVector::iterator it = m_points.begin(); it != m_points.end(); ++it) {
+
+ if (it == m_points.begin())
+ {
+ start = (*it);
+ } else {
+ end = (*it);
+
+ startPos = controller->windowToView(start.floorTQPoint());
+ endPos = controller->windowToView(end.floorTQPoint());
+
+ gc.drawLine(startPos, endPos);
+
+ start = end;
+ }
+ }
+ }
+ break;
+ case EDITRECTINTERRACTION:
+ {
+ TQPoint topleft = controller->windowToView(m_topleft ).roundTQPoint();
+ TQPoint topright = controller->windowToView(m_topright).roundTQPoint();
+ TQPoint bottomleft = controller->windowToView(m_bottomleft).roundTQPoint();
+ TQPoint bottomright = controller->windowToView(m_bottomright).roundTQPoint();
+
+ gc.setRasterOp(TQt::NotROP);
+ gc.setPen(pen);
+ gc.drawRect(topleft.x()-4, topleft.y()-4, 8, 8);
+ gc.drawLine(topleft.x(), topleft.y(), (topleft.x()+topright.x())/2, (topleft.y()+topright.y())/2);
+ gc.drawRect((topleft.x()+topright.x())/2-4, (topleft.y()+topright.y())/2-4, 8, 8);
+ gc.drawLine((topleft.x()+topright.x())/2, (topleft.y()+topright.y())/2, topright.x(), topright.y());
+ gc.drawRect(topright.x()-4, topright.y()-4, 8, 8);
+ gc.drawLine(topright.x(), topright.y(), (topright.x()+bottomright.x())/2, (topright.y()+bottomright.y())/2);
+ gc.drawRect((topright.x()+bottomright.x())/2-4, (topright.y()+bottomright.y())/2-4, 8, 8);
+ gc.drawLine((topright.x()+bottomright.x())/2, (topright.y()+bottomright.y())/2,bottomright.x(), bottomright.y());
+ gc.drawRect(bottomright.x()-4, bottomright.y()-4, 8, 8);
+ gc.drawLine(bottomright.x(), bottomright.y(), (bottomleft.x()+bottomright.x())/2, (bottomleft.y()+bottomright.y())/2);
+ gc.drawRect((bottomleft.x()+bottomright.x())/2-4, (bottomleft.y()+bottomright.y())/2-4, 8, 8);
+ gc.drawLine((bottomleft.x()+bottomright.x())/2, (bottomleft.y()+bottomright.y())/2, bottomleft.x(), bottomleft.y());
+ gc.drawRect(bottomleft.x()-4, bottomleft.y()-4, 8, 8);
+ gc.drawLine(bottomleft.x(), bottomleft.y(), (topleft.x()+bottomleft.x())/2, (topleft.y()+bottomleft.y())/2);
+ gc.drawRect((topleft.x()+bottomleft.x())/2-4, (topleft.y()+bottomleft.y())/2-4, 8, 8);
+ gc.drawLine((topleft.x()+bottomleft.x())/2, (topleft.y()+bottomleft.y())/2, topleft.x(), topleft.y());
+ gc.drawRect((bottomleft.x()+bottomright.x()+topleft.x()+topright.x())/4-4, (bottomleft.y()+bottomright.y()+topleft.y()+topright.y())/4-4, 8, 8);
+ }
+ break;
+ }
+ gc.setRasterOp(op);
+ gc.setPen(old);
+ }
+}
+
+void KisToolPerspectiveTransform::transform()
+{
+ KisImageSP img = m_subject->currentImg();
+
+ if (!img || !img->activeDevice())
+ return;
+
+ KisProgressDisplayInterface *progress = m_subject->progressDisplay();
+
+ // This mementoes the current state of the active device.
+ PerspectiveTransformCmd * transaction = new PerspectiveTransformCmd(this, img->activeDevice(), m_origDevice,
+ m_topleft, m_topright, m_bottomleft, m_bottomright, m_origSelection, m_initialRect);
+
+ // Copy the original state back.
+ TQRect rc = m_origDevice->extent();
+ rc = rc.normalize();
+ img->activeDevice()->clear();
+ KisPainter gc(img->activeDevice());
+ gc.bitBlt(rc.x(), rc.y(), COMPOSITE_COPY, m_origDevice, rc.x(), rc.y(), rc.width(), rc.height());
+ gc.end();
+
+ // Also restore the original selection.
+ if(m_origSelection)
+ {
+ TQRect rc = m_origSelection->selectedRect();
+ rc = rc.normalize();
+ img->activeDevice()->selection()->clear();
+ KisPainter sgc(img->activeDevice()->selection().data());
+ sgc.bitBlt(rc.x(), rc.y(), COMPOSITE_COPY, m_origSelection.data(), rc.x(), rc.y(), rc.width(), rc.height());
+ sgc.end();
+ }
+ else
+ if(img->activeDevice()->hasSelection())
+ img->activeDevice()->selection()->clear();
+
+ // Perform the transform. Since we copied the original state back, this doesn't degrade
+ // after many tweaks. Since we started the transaction before the copy back, the memento
+ // has the previous state.
+ KisPerspectiveTransformWorker t(img->activeDevice(),m_topleft, m_topright, m_bottomleft, m_bottomright, progress);
+ t.run();
+
+ // If canceled, go back to the memento
+ if(t.isCanceled())
+ {
+ transaction->unexecute();
+ delete transaction;
+ return;
+ }
+
+ img->activeDevice()->setDirty(rc); // XXX: This is not enough - should union with new extent
+
+ // Else add the command -- this will have the memento from the previous state,
+ // and the transformed state from the original device we cached in our activated()
+ // method.
+ if (transaction) {
+ if (img->undo())
+ img->undoAdapter()->addCommand(transaction);
+ else
+ delete transaction;
+ }
+}
+
+void KisToolPerspectiveTransform::notifyCommandAdded( KCommand * command)
+{
+ PerspectiveTransformCmd * cmd = dynamic_cast<PerspectiveTransformCmd*>(command);
+ if (cmd == 0) {
+ // The last added command wasn't one of ours;
+ // we should reset to the new state of the canvas.
+ // In effect we should treat this as if the tool has been just activated
+ initHandles();
+ }
+}
+
+void KisToolPerspectiveTransform::notifyCommandExecuted( KCommand * command)
+{
+ Q_UNUSED(command);
+ PerspectiveTransformCmd * cmd=0;
+ if(m_subject->currentImg()->undoAdapter()->presentCommand())
+ cmd = dynamic_cast<PerspectiveTransformCmd*>(m_subject->currentImg()->undoAdapter()->presentCommand());
+
+ if (cmd == 0) {
+ // The command now on the top of the stack isn't one of ours
+ // We should treat this as if the tool has been just activated
+ initHandles();
+ }
+ else
+ {
+ // One of our commands is now on top
+ // We should ask for tool args and orig selection
+ m_origDevice = cmd->origDevice();
+ cmd->transformArgs(m_topleft, m_topright, m_bottomleft, m_bottomright);
+ m_origSelection = cmd->origSelection(m_initialRect);
+ m_subject->canvasController() ->updateCanvas();
+ }
+}
+
+void KisToolPerspectiveTransform::slotLayerActivated(KisLayerSP)
+{
+ activate();
+}
+
+
+TQWidget* KisToolPerspectiveTransform::createOptionWidget(TQWidget* /*tqparent*/)
+{
+#if 0
+ m_optWidget = new WdgToolPerspectiveTransform(tqparent);
+ Q_CHECK_PTR(m_optWidget);
+
+ m_optWidget->cmbFilter->clear();
+ m_optWidget->cmbFilter->setIDList(KisFilterStrategyRegistry::instance()->listKeys());
+
+ m_optWidget->cmbFilter->setCurrentText("Mitchell");
+ connect(m_optWidget->cmbFilter, TQT_SIGNAL(activated(const KisID &)),
+ this, TQT_SLOT(slotSetFilter(const KisID &)));
+
+ KisID filterID = m_optWidget->cmbFilter->currentItem();
+ m_filter = KisFilterStrategyRegistry::instance()->get(filterID);
+
+/*
+ connect(m_optWidget->intStartX, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(setStartX(int)));
+ connect(m_optWidget->intStartY, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(setStartY(int)));
+ connect(m_optWidget->intEndX, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(setEndX(int)));
+ connect(m_optWidget->intEndY, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(setEndY(int)));
+*/
+ m_optWidget->intStartX->hide();
+ m_optWidget->intStartY->hide();
+ m_optWidget->intEndX->hide();
+ m_optWidget->intEndY->hide();
+ m_optWidget->textLabel1->hide();
+ m_optWidget->textLabel2->hide();
+ m_optWidget->textLabel3->hide();
+ m_optWidget->textLabel4->hide();
+#endif
+ return 0;
+}
+
+TQWidget* KisToolPerspectiveTransform::optionWidget()
+{
+ return 0;
+}
+
+void KisToolPerspectiveTransform::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Perspective Transform"),
+ "tool_perspectivetransform",
+ 0,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ Q_CHECK_PTR(m_action);
+ m_action->setToolTip(i18n("Perspective transform a layer or a selection"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+#include "kis_tool_perspectivetransform.moc"
diff --git a/chalk/plugins/tools/tool_perspectivetransform/kis_tool_perspectivetransform.h b/chalk/plugins/tools/tool_perspectivetransform/kis_tool_perspectivetransform.h
new file mode 100644
index 00000000..5d637ae5
--- /dev/null
+++ b/chalk/plugins/tools/tool_perspectivetransform/kis_tool_perspectivetransform.h
@@ -0,0 +1,131 @@
+/*
+ * kis_tool_transform.h - part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * Based on the transform tool from :
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2005 Casper Boemann <cbr@boemann.dk>
+ *
+ * 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; version 2 of the License.
+ *
+ * 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_TOOL_PERSPECTIVETRANSFORM_H_
+#define KIS_TOOL_PERSPECTIVETRANSFORM_H_
+
+#include <tqpoint.h>
+
+#include <kis_layer.h>
+#include <kis_point.h>
+#include <kis_tool_non_paint.h>
+#include <kis_tool_factory.h>
+#include <kis_undo_adapter.h>
+#include <kis_perspective_math.h>
+
+class KisTransaction;
+class WdgToolPerspectiveTransform;
+class KisID;
+class KisFilterStrategy;
+
+/**
+ * PerspectiveTransform tool
+ *
+ */
+class KisToolPerspectiveTransform : public KisToolNonPaint, KisCommandHistoryListener {
+
+ typedef KisToolNonPaint super;
+ Q_OBJECT
+ TQ_OBJECT
+ enum InterractionMode { DRAWRECTINTERRACTION, EDITRECTINTERRACTION };
+ enum HandleSelected { NOHANDLE, TOPHANDLE, BOTTOMHANDLE, RIGHTHANDLE, LEFTHANDLE, MIDDLEHANDLE };
+public:
+ KisToolPerspectiveTransform();
+ virtual ~KisToolPerspectiveTransform();
+
+ virtual TQWidget* createOptionWidget(TQWidget* tqparent);
+ virtual TQWidget* optionWidget();
+
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_TRANSFORM; }
+ virtual TQ_UINT32 priority() { return 4; }
+ virtual void paint(KisCanvasPainter& gc);
+ virtual void paint(KisCanvasPainter& gc, const TQRect& rc);
+ virtual void buttonPress(KisButtonPressEvent *e);
+ virtual void move(KisMoveEvent *e);
+ virtual void buttonRelease(KisButtonReleaseEvent *e);
+ void paintOutline();
+
+public:
+
+ void notifyCommandAdded(KCommand *);
+ void notifyCommandExecuted(KCommand *);
+
+public:
+ virtual void deactivate();
+
+private:
+
+ bool mouseNear(const TQPoint& mousep, const TQPoint point);
+ void paintOutline(KisCanvasPainter& gc, const TQRect& rc);
+ void transform();
+ void initHandles();
+
+private slots:
+ void slotLayerActivated(KisLayerSP);
+
+protected slots:
+ virtual void activate();
+
+private:
+ bool m_dragging;
+ InterractionMode m_interractionMode;
+ TQRect m_initialRect;
+ KisPoint m_dragStart, m_dragEnd;
+ KisPoint m_topleft, m_topright, m_bottomleft, m_bottomright;
+ KisPoint* m_currentSelectedPoint;
+ bool m_actualyMoveWhileSelected;
+
+ WdgToolPerspectiveTransform *m_optWidget;
+
+ KisPaintDeviceSP m_origDevice;
+ KisSelectionSP m_origSelection;
+ int m_handleHalfSize, m_handleSize;
+
+ // The following variables are used in during the draw rect interraction mode
+ typedef TQValueVector<KisPoint> KisPointVector;
+ KisPointVector m_points;
+ // The following variables are used when moving a middle handle
+ HandleSelected m_handleSelected;
+
+};
+
+class KisToolPerspectiveTransformFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+
+public:
+ KisToolPerspectiveTransformFactory() : super() {};
+ virtual ~KisToolPerspectiveTransformFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolPerspectiveTransform();
+ Q_CHECK_PTR(t);
+ t->setup(ac); return t;
+ }
+ virtual KisID id() { return KisID("perspective transform", i18n("Perspective transform Tool")); }
+};
+
+
+
+#endif // KIS_TOOL_TRANSFORM_H_
+
diff --git a/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.cc b/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.cc
new file mode 100644
index 00000000..2c3c85d4
--- /dev/null
+++ b/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.cc
@@ -0,0 +1,63 @@
+/*
+ * tool_perspectivetransform.cc -- Part of Chalk
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_tool_registry.h>
+
+#include "tool_perspectivetransform.h"
+#include "kis_tool_perspectivetransform.h"
+
+
+typedef KGenericFactory<ToolPerspectiveTransform> ToolPerspectiveTransformFactory;
+K_EXPORT_COMPONENT_FACTORY( chalktoolperspectivetransform, ToolPerspectiveTransformFactory( "chalk" ) )
+
+
+ToolPerspectiveTransform::ToolPerspectiveTransform(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ToolPerspectiveTransformFactory::instance());
+
+ if ( tqparent->inherits("KisToolRegistry") )
+ {
+ kdDebug() << " add perspective transform tool to the registry" << endl;
+ KisToolRegistry * r = dynamic_cast<KisToolRegistry*>(tqparent);
+ r->add(new KisToolPerspectiveTransformFactory());
+ }
+
+}
+
+ToolPerspectiveTransform::~ToolPerspectiveTransform()
+{
+}
+
+#include "tool_perspectivetransform.moc"
diff --git a/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.h b/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.h
new file mode 100644
index 00000000..1cbeadee
--- /dev/null
+++ b/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 TOOL_PERSPECTIVE_TRANSFORM_H_
+#define TOOL_PERSPECTIVE_TRANSFORM_H_
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+/**
+ * A module that provides a tool for doinge perspective transformation.
+ */
+class ToolPerspectiveTransform : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ ToolPerspectiveTransform(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ToolPerspectiveTransform();
+
+private:
+
+ KisView * m_view;
+
+};
+
+#endif // TOOL_PERSPECTIVE_TRANSFORM_H_
diff --git a/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.png b/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.png
new file mode 100644
index 00000000..c64d09eb
--- /dev/null
+++ b/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.svg b/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.svg
new file mode 100644
index 00000000..3dd79413
--- /dev/null
+++ b/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.svg
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="22"
+ height="22"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.43"
+ version="1.0"
+ sodipodi:docbase="/home/cyrille/koffice-1.6/chalk/plugins/tools/tool_perspectivegrid"
+ sodipodi:docname="tool_perspectivegrid.svg"
+ inkscape:export-filename="/home/cyrille/koffice-1.6/chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="9.8597476"
+ inkscape:cx="12.855376"
+ inkscape:cy="7.6671075"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="749"
+ inkscape:window-height="540"
+ inkscape:window-x="424"
+ inkscape:window-y="433" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 4.8682788,20.580085 C 6.5924609,1.3098151 6.7953058,1.5126601 6.7953058,1.5126601 L 6.7953058,1.5126601 L 6.7953058,1.5126601"
+ id="path2183" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 11.359317,18.551636 C 10.446515,2.3240399 10.446515,2.3240399 10.446515,2.3240399 L 10.446515,2.3240399 L 10.446515,2.3240399"
+ id="path2185" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 17.444666,17.131721 C 13.894879,3.1354197 13.894879,3.1354197 13.894879,3.1354197"
+ id="path2187" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 2.7384068,4.7581793 C 17.647511,6.5837838 17.546088,6.5837838 17.546088,6.5837838"
+ id="path2191" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 2.0284495,10.742105 C 18.256045,9.7278805 18.86458,9.1193456 18.86458,9.1193456"
+ id="path2193"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 1.0142247,17.131721 C 20.08165,12.56771 20.08165,12.364865 20.08165,12.364865"
+ id="path2195"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 3.1440967,0.59985768 L 16.531864,3.6425319 L 21.70441,15.813228 L 0.50711235,21.594309 L 3.1440967,0.59985768 z "
+ id="rect1307"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+</svg>
diff --git a/chalk/plugins/tools/tool_polygon/Makefile.am b/chalk/plugins/tools/tool_polygon/Makefile.am
new file mode 100644
index 00000000..66f4d403
--- /dev/null
+++ b/chalk/plugins/tools/tool_polygon/Makefile.am
@@ -0,0 +1,36 @@
+kde_services_DATA = chalktoolpolygon.desktop
+
+# all_includes must remain last!
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalktoolpolygon_la_SOURCES = \
+ tool_polygon.cc \
+ kis_tool_polygon.cc
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = chalktoolpolygon.la
+
+noinst_HEADERS = \
+ tool_polygon.h \
+ kis_tool_polygon.h
+
+chalktoolpolygon_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalktoolpolygon_la_LIBADD = ../../../libchalkcommon.la
+
+chalktoolpolygon_la_METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
+
+chalkpics_DATA = \
+ tool_polygon_cursor.png \
+ tool_polygon.png
+
+chalkpicsdir = $(kde_datadir)/chalk/pics
+
diff --git a/chalk/plugins/tools/tool_polygon/chalktoolpolygon.desktop b/chalk/plugins/tools/tool_polygon/chalktoolpolygon.desktop
new file mode 100644
index 00000000..2b981e8f
--- /dev/null
+++ b/chalk/plugins/tools/tool_polygon/chalktoolpolygon.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Name=Polygon Tool
+Name[bg]=Инструмент многоъгълник
+Name[br]=Ostilh liestueg
+Name[ca]=Eina de polígon
+Name[cy]=Erfyn Polygon
+Name[da]=Polygonværktøj
+Name[de]=Vieleck-Werkzeug
+Name[el]=Εργαλείο πολυγώνου
+Name[eo]=Poligon-ilo
+Name[es]=Herramienta Polígono
+Name[et]=Hulknurga tööriist
+Name[eu]=Poligonoa tresna
+Name[fa]=ابزار چندضلعی
+Name[fi]=Monikulmiotyökalu
+Name[fr]=Outil polygone
+Name[fy]=Meardere-hoek-ark
+Name[ga]=Uirlis Pholagáin
+Name[gl]=Ferramenta de Polígonos
+Name[he]=כלי מצולע
+Name[hu]=Sokszög eszköz
+Name[is]=Marghyrnitól
+Name[it]=Strumento poligono
+Name[ja]=多角形ツール
+Name[km]=ឧបករណ៍​រាង​ពហុកោណ
+Name[lt]=Daugiakampio įrankis
+Name[lv]=Poligonu rīks
+Name[ms]=Alat Poligon
+Name[nb]=Verktøy for mangekanter
+Name[nds]=Veeleck-Warktüüch
+Name[ne]=बहुभुज उपकरण
+Name[nl]=Veelhoeksgereedschap
+Name[nn]=Verktøy for mangekant
+Name[pl]=Narzędzie do rysowania wielokątów
+Name[pt]=Ferramenta de Polígonos
+Name[pt_BR]=Ferramenta Polígono
+Name[ru]=Многоугольник
+Name[se]=Moanáčiegareaidu
+Name[sk]=Mnohouholník
+Name[sl]=Orodje za poligon
+Name[sr]=Алат за полигоне
+Name[sr@Latn]=Alat za poligone
+Name[sv]=Polygonverktyg
+Name[uk]=Засіб багатокутника
+Name[uz]=Pligon vositasi
+Name[uz@cyrillic]=Плигон воситаси
+Name[zh_CN]=多边形工具
+Name[zh_TW]=多邊形工具
+ServiceTypes=Chalk/Tool
+Type=Service
+X-KDE-Library=chalktoolpolygon
+X-Chalk-Version=2
diff --git a/chalk/plugins/tools/tool_polygon/kis_tool_polygon.cc b/chalk/plugins/tools/tool_polygon/kis_tool_polygon.cc
new file mode 100644
index 00000000..dba84042
--- /dev/null
+++ b/chalk/plugins/tools/tool_polygon/kis_tool_polygon.cc
@@ -0,0 +1,252 @@
+/*
+ * kis_tool_polygon.cc -- part of Chalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <math.h>
+
+#include <tqpainter.h>
+#include <tqspinbox.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <knuminput.h>
+
+#include "kis_doc.h"
+#include "kis_view.h"
+#include "kis_painter.h"
+#include "kis_canvas_subject.h"
+#include "kis_canvas_controller.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_move_event.h"
+#include "kis_paintop_registry.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+#include "kis_cursor.h"
+
+#include "kis_tool_polygon.h"
+
+KisToolPolygon::KisToolPolygon()
+ : super(i18n ("Polygon")),
+ m_dragging (false),
+ m_currentImage (0)
+{
+ setName("tool_polygon");
+ setCursor(KisCursor::load("tool_polygon_cursor.png", 6, 6));
+}
+
+KisToolPolygon::~KisToolPolygon()
+{
+}
+
+void KisToolPolygon::update (KisCanvasSubject *subject)
+{
+ super::update (subject);
+ if (m_subject)
+ m_currentImage = m_subject->currentImg ();
+}
+
+void KisToolPolygon::buttonPress(KisButtonPressEvent *event)
+{
+ if (m_currentImage) {
+ if (event->button() == Qt::LeftButton && event->state() != ShiftButton) {
+
+ m_dragging = true;
+
+ if (m_points.isEmpty())
+ {
+ m_dragStart = event->pos();
+ m_dragEnd = event->pos();
+ m_points.append(m_dragStart);
+ } else {
+ m_dragStart = m_dragEnd;
+ m_dragEnd = event->pos();
+ draw();
+ }
+ } else if (event->button() == Qt::LeftButton && event->state() == ShiftButton) {
+ finish();
+ }
+ }
+}
+
+void KisToolPolygon::finish()
+{
+ // erase old lines on canvas
+ draw();
+ m_dragging = false;
+
+ KisPaintDeviceSP device = m_currentImage->activeDevice ();
+ if (!device) return;
+
+ KisPainter painter (device);
+ if (m_currentImage->undo()) painter.beginTransaction (i18n ("Polygon"));
+
+ painter.setPaintColor(m_subject->fgColor());
+ painter.setBackgroundColor(m_subject->bgColor());
+ painter.setFillStyle(fillStyle());
+ painter.setBrush(m_subject->currentBrush());
+ painter.setPattern(m_subject->currentPattern());
+ painter.setOpacity(m_opacity);
+ painter.setCompositeOp(m_compositeOp);
+ KisPaintOp * op = KisPaintOpRegistry::instance()->paintOp(m_subject->currentPaintop(), m_subject->currentPaintopSettings(), &painter);
+ painter.setPaintOp(op); // Painter takes ownership
+
+ painter.paintPolygon(m_points);
+
+ m_points.clear();
+
+ device->setDirty( painter.dirtyRect() );
+ notifyModified();
+
+ if (m_currentImage->undo()) {
+ m_currentImage->undoAdapter()->addCommand(painter.endTransaction());
+ }
+}
+
+void KisToolPolygon::doubleClick( KisDoubleClickEvent * )
+{
+ finish();
+}
+
+void KisToolPolygon::move(KisMoveEvent *event)
+{
+ if (m_dragging) {
+ // erase old lines on canvas
+ draw();
+ // get current mouse position
+ m_dragEnd = event->pos();
+ // draw new lines on canvas
+ draw();
+ }
+}
+
+void KisToolPolygon::buttonRelease(KisButtonReleaseEvent *event)
+{
+ if (!m_subject || !m_currentImage)
+ return;
+
+ if (m_dragging && event->button() == Qt::LeftButton) {
+ m_dragging = false;
+ m_points.append (m_dragEnd);
+ }
+
+ if (m_dragging && event->button() == Qt::RightButton) {
+
+ }
+}
+
+void KisToolPolygon::paint(KisCanvasPainter& gc)
+{
+ draw(gc);
+}
+
+void KisToolPolygon::paint(KisCanvasPainter& gc, const TQRect&)
+{
+ draw(gc);
+}
+
+void KisToolPolygon::draw()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter gc(canvas);
+
+ draw(gc);
+ }
+}
+
+void KisToolPolygon::draw(KisCanvasPainter& gc)
+{
+ if (!m_subject || !m_currentImage)
+ return;
+
+ TQPen pen(TQt::white, 0, TQt::SolidLine);
+
+ gc.setPen(pen);
+ gc.setRasterOp(TQt::XorROP);
+
+ KisCanvasController *controller = m_subject->canvasController();
+ KisPoint start, end;
+ TQPoint startPos;
+ TQPoint endPos;
+
+ if (m_dragging) {
+ startPos = controller->windowToView(m_dragStart.floorTQPoint());
+ endPos = controller->windowToView(m_dragEnd.floorTQPoint());
+ gc.drawLine(startPos, endPos);
+ } else {
+ for (KisPointVector::iterator it = m_points.begin(); it != m_points.end(); ++it) {
+
+ if (it == m_points.begin())
+ {
+ start = (*it);
+ } else {
+ end = (*it);
+
+ startPos = controller->windowToView(start.floorTQPoint());
+ endPos = controller->windowToView(end.floorTQPoint());
+
+ gc.drawLine(startPos, endPos);
+
+ start = end;
+ }
+ }
+ }
+}
+
+
+
+void KisToolPolygon::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ KShortcut shortcut(TQt::Key_Plus);
+ shortcut.append(KShortcut(TQt::Key_F9));
+ m_action = new KRadioAction(i18n("&Polygon"),
+ "tool_polygon",
+ shortcut,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ Q_CHECK_PTR(m_action);
+
+ m_action->setToolTip(i18n("Draw a polygon. Shift-mouseclick ends the polygon."));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+void KisToolPolygon::keyPress(TQKeyEvent *e)
+{
+ if (e->key()==TQt::Key_Escape) {
+ // erase old lines on canvas
+ draw();
+ m_dragging = false;
+ m_points.clear();
+ }
+}
+
+
+#include "kis_tool_polygon.moc"
diff --git a/chalk/plugins/tools/tool_polygon/kis_tool_polygon.h b/chalk/plugins/tools/tool_polygon/kis_tool_polygon.h
new file mode 100644
index 00000000..9be3f324
--- /dev/null
+++ b/chalk/plugins/tools/tool_polygon/kis_tool_polygon.h
@@ -0,0 +1,102 @@
+/*
+ * kis_tool_polygon.h - part of Chalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael Thaler@physik.tu-muenchen.de>
+ *
+ * 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_TOOL_POLYGON_H_
+#define KIS_TOOL_POLYGON_H_
+
+#include <tqvaluevector.h>
+
+#include "kis_tool_shape.h"
+
+class KisCanvas;
+class KisDoc;
+class KisPainter;
+class KisView;
+class KisRect;
+
+class KisToolPolygon : public KisToolShape {
+
+ typedef KisToolShape super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolPolygon();
+ virtual ~KisToolPolygon();
+
+ //
+ // KisCanvasObserver interface
+ //
+
+ virtual void update (KisCanvasSubject *subject);
+
+ //
+ // KisToolPaint interface
+ //
+
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_SHAPE; }
+ virtual TQ_UINT32 priority() { return 4; }
+ virtual void buttonPress(KisButtonPressEvent *event);
+ virtual void move(KisMoveEvent *event);
+ virtual void buttonRelease(KisButtonReleaseEvent *event);
+ virtual TQString quickHelp() const {
+ return i18n("Shift-click will end the polygon.");
+ }
+ virtual void doubleClick(KisDoubleClickEvent * event);
+
+protected:
+ virtual void paint(KisCanvasPainter& gc);
+ virtual void paint(KisCanvasPainter& gc, const TQRect& rc);
+ void draw(KisCanvasPainter& gc);
+ void draw();
+ void finish();
+ virtual void keyPress(TQKeyEvent *e);
+protected:
+ KisPoint m_dragStart;
+ KisPoint m_dragEnd;
+
+ bool m_dragging;
+ KisImageSP m_currentImage;
+private:
+ typedef TQValueVector<KisPoint> KisPointVector;
+ KisPointVector m_points;
+};
+
+
+#include "kis_tool_factory.h"
+
+class KisToolPolygonFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolPolygonFactory() : super() {};
+ virtual ~KisToolPolygonFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolPolygon();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("polygon", i18n("Polygon Tool")); }
+};
+
+
+#endif //__KIS_TOOL_POLYGON_H__
diff --git a/chalk/plugins/tools/tool_polygon/tool_polygon.cc b/chalk/plugins/tools/tool_polygon/tool_polygon.cc
new file mode 100644
index 00000000..3dbd15d6
--- /dev/null
+++ b/chalk/plugins/tools/tool_polygon/tool_polygon.cc
@@ -0,0 +1,62 @@
+/*
+ * tool_polygon.cc -- Part of Chalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_tool_registry.h>
+#include "tool_polygon.h"
+#include "tool_polygon.moc"
+#include "kis_tool_polygon.h"
+
+
+typedef KGenericFactory<ToolPolygon> ToolPolygonFactory;
+K_EXPORT_COMPONENT_FACTORY( chalktoolpolygon, ToolPolygonFactory( "chalk" ) )
+
+
+ToolPolygon::ToolPolygon(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ToolPolygonFactory::instance());
+
+ if ( tqparent->inherits("KisToolRegistry") )
+ {
+ KisToolRegistry * r = dynamic_cast<KisToolRegistry*>( tqparent );
+ r->add(new KisToolPolygonFactory());
+ }
+
+}
+
+ToolPolygon::~ToolPolygon()
+{
+}
+
+//#include "tool_polygon.moc"
diff --git a/chalk/plugins/tools/tool_polygon/tool_polygon.h b/chalk/plugins/tools/tool_polygon/tool_polygon.h
new file mode 100644
index 00000000..ec816736
--- /dev/null
+++ b/chalk/plugins/tools/tool_polygon/tool_polygon.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 TOOL_POLYGON_H_
+#define TOOL_POLYGON_H_
+
+#include <kparts/plugin.h>
+
+/**
+ * A module that provides a polygon tool.
+ */
+class ToolPolygon : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ ToolPolygon(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ToolPolygon();
+
+};
+
+#endif // TOOL_POLYGON_H_
diff --git a/chalk/plugins/tools/tool_polygon/tool_polygon.png b/chalk/plugins/tools/tool_polygon/tool_polygon.png
new file mode 100644
index 00000000..654083c6
--- /dev/null
+++ b/chalk/plugins/tools/tool_polygon/tool_polygon.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_polygon/tool_polygon_cursor.png b/chalk/plugins/tools/tool_polygon/tool_polygon_cursor.png
new file mode 100644
index 00000000..bca4bffd
--- /dev/null
+++ b/chalk/plugins/tools/tool_polygon/tool_polygon_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_polyline/Makefile.am b/chalk/plugins/tools/tool_polyline/Makefile.am
new file mode 100644
index 00000000..39b9ebf6
--- /dev/null
+++ b/chalk/plugins/tools/tool_polyline/Makefile.am
@@ -0,0 +1,36 @@
+kde_services_DATA = chalktoolpolyline.desktop
+
+# all_includes must remain last!
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalktoolpolyline_la_SOURCES = \
+ tool_polyline.cc \
+ kis_tool_polyline.cc
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = chalktoolpolyline.la
+
+noinst_HEADERS = \
+ tool_polyline.h \
+ kis_tool_polyline.h
+
+chalktoolpolyline_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalktoolpolyline_la_LIBADD = ../../../libchalkcommon.la
+
+chalktoolpolyline_la_METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
+
+chalkpics_DATA = \
+ tool_polyline_cursor.png \
+ polyline.png
+
+chalkpicsdir = $(kde_datadir)/chalk/pics
+
diff --git a/chalk/plugins/tools/tool_polyline/chalktoolpolyline.desktop b/chalk/plugins/tools/tool_polyline/chalktoolpolyline.desktop
new file mode 100644
index 00000000..0c9c2be1
--- /dev/null
+++ b/chalk/plugins/tools/tool_polyline/chalktoolpolyline.desktop
@@ -0,0 +1,49 @@
+[Desktop Entry]
+Name=Polyline Tool
+Name[bg]=Инструмент съставна линия
+Name[br]=Ostilh lieslinenn
+Name[ca]=Eina de polilínia
+Name[cy]=Erfyn Polylinell
+Name[da]=Flerlinjeværktøj
+Name[de]=Linienketten-Werkzeug
+Name[el]=Εργαλείο συνεχούς γραμμής
+Name[eo]=Plurlinio-ilo
+Name[es]=Herramienta Polilínea
+Name[et]=Kompleksjoone tööriist
+Name[eu]=Polilerroa tresna
+Name[fa]=ابزار چندخطی
+Name[fr]=Outil lignes multiples
+Name[fy]=Brútsen-streek-ark
+Name[ga]=Uirlis Il-líne
+Name[gl]=Ferramenta de Liñas Poligonais
+Name[he]=כלי קו שבור
+Name[hu]=Sokszögvonal eszköz
+Name[is]=Fjöllínutól
+Name[it]=Strumento polilinea
+Name[ja]=ポリラインツール
+Name[km]=ឧបករណ៍​ពហុបន្ទាត់
+Name[ms]=Alat Poligaris
+Name[nb]=Verktøy for flerstrekslinje
+Name[nds]=Lienenkeden-Warktüüch (Polygon-Tog)
+Name[ne]=बहुरेखा उपकरण
+Name[nl]=Gebroken-lijngereedschap
+Name[nn]=Verktøy for fleirstrekslinje
+Name[pl]=Narzędzie do rysowania łamanej
+Name[pt]=Ferramenta de Linhas Poligonais
+Name[pt_BR]=Ferramenta Poli-linha
+Name[ru]=Ломаная
+Name[se]=Moanálinnjáreaidu
+Name[sk]=Lomená čiara
+Name[sl]=Orodje za lomljeno črto
+Name[sr]=Алат за полилиније
+Name[sr@Latn]=Alat za polilinije
+Name[sv]=Flerlinjesverktyg
+Name[uk]=Засіб ламаної лінії
+Name[uz]=Koʻpburchak asbobi
+Name[uz@cyrillic]=Кўпбурчак асбоби
+Name[zh_CN]=折线工具
+Name[zh_TW]=任意線工具
+ServiceTypes=Chalk/Tool
+Type=Service
+X-KDE-Library=chalktoolpolyline
+X-Chalk-Version=2
diff --git a/chalk/plugins/tools/tool_polyline/kis_tool_polyline.cc b/chalk/plugins/tools/tool_polyline/kis_tool_polyline.cc
new file mode 100644
index 00000000..4fab06e7
--- /dev/null
+++ b/chalk/plugins/tools/tool_polyline/kis_tool_polyline.cc
@@ -0,0 +1,271 @@
+/*
+ * kis_tool_polyline.cc -- part of Chalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <math.h>
+
+#include <tqpainter.h>
+#include <tqspinbox.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <knuminput.h>
+
+#include "kis_doc.h"
+#include "kis_view.h"
+#include "kis_painter.h"
+#include "kis_canvas_subject.h"
+#include "kis_canvas_controller.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_move_event.h"
+#include "kis_paintop_registry.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+#include "kis_cursor.h"
+
+#include "kis_tool_polyline.h"
+
+KisToolPolyline::KisToolPolyline()
+ : super(i18n ("Polyline")),
+ m_dragging (false),
+ m_currentImage (0)
+{
+ setName("tool_polyline");
+ setCursor(KisCursor::load("tool_polyline_cursor.png", 6, 6));
+}
+
+KisToolPolyline::~KisToolPolyline()
+{
+}
+
+void KisToolPolyline::update (KisCanvasSubject *subject)
+{
+ super::update (subject);
+ if (m_subject)
+ m_currentImage = m_subject->currentImg ();
+}
+
+void KisToolPolyline::buttonPress(KisButtonPressEvent *event)
+{
+ if (m_currentImage) {
+ if (event->button() == Qt::LeftButton && event->state() != TQt::ShiftButton ) {
+
+ m_dragging = true;
+
+ if (m_points.isEmpty())
+ {
+ m_dragStart = event->pos();
+ m_dragEnd = event->pos();
+ m_points.append(m_dragStart);
+ } else {
+ m_dragStart = m_dragEnd;
+ m_dragEnd = event->pos();
+ draw();
+ }
+ } else if (event->button() == Qt::LeftButton && event->state() == TQt::ShiftButton ) {
+ finish();
+ }
+ }
+}
+
+void KisToolPolyline::deactivate()
+{
+ draw();
+ m_points.clear();
+ m_dragging = false;
+}
+
+void KisToolPolyline::finish()
+{
+ // erase old lines on canvas
+ draw();
+ m_dragging = false;
+
+ KisPaintDeviceSP device = m_currentImage->activeDevice ();
+ if (!device) return;
+
+ KisPainter painter (device);
+ if (m_currentImage->undo()) painter.beginTransaction (i18n ("Polyline"));
+
+ painter.setPaintColor(m_subject->fgColor());
+ painter.setBrush(m_subject->currentBrush());
+ painter.setOpacity(m_opacity);
+ painter.setCompositeOp(m_compositeOp);
+ KisPaintOp * op = KisPaintOpRegistry::instance()->paintOp(m_subject->currentPaintop(), m_subject->currentPaintopSettings(), &painter);
+ painter.setPaintOp(op); // Painter takes ownership
+
+ KisPoint start,end;
+ KisPointVector::iterator it;
+ for( it = m_points.begin(); it != m_points.end(); ++it )
+ {
+ if( it == m_points.begin() )
+ {
+ start = (*it);
+ } else {
+ end = (*it);
+ painter.paintLine(start, PRESSURE_DEFAULT, 0, 0, end, PRESSURE_DEFAULT, 0, 0);
+ start = end;
+ }
+ }
+ m_points.clear();
+
+ device->setDirty( painter.dirtyRect() );
+ notifyModified();
+
+ if (m_currentImage->undo()) {
+ m_currentImage->undoAdapter()->addCommand(painter.endTransaction());
+ }
+
+}
+void KisToolPolyline::move(KisMoveEvent *event)
+{
+ if (m_dragging) {
+ // erase old lines on canvas
+ draw();
+ // get current mouse position
+ m_dragEnd = event->pos();
+ // draw new lines on canvas
+ draw();
+ }
+}
+
+void KisToolPolyline::buttonRelease(KisButtonReleaseEvent *event)
+{
+ if (!m_subject || !m_currentImage)
+ return;
+
+ if (m_dragging && event->button() == Qt::LeftButton) {
+ m_dragging = false;
+ m_points.append (m_dragEnd);
+ }
+
+ if (m_dragging && event->button() == Qt::RightButton) {
+
+ }
+}
+
+
+void KisToolPolyline::doubleClick(KisDoubleClickEvent *)
+{
+ finish();
+}
+
+
+void KisToolPolyline::paint(KisCanvasPainter& gc)
+{
+ draw(gc);
+}
+
+void KisToolPolyline::paint(KisCanvasPainter& gc, const TQRect&)
+{
+ draw(gc);
+}
+
+void KisToolPolyline::draw()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter gc(canvas);
+
+ draw(gc);
+ }
+}
+
+void KisToolPolyline::draw(KisCanvasPainter& gc)
+{
+ if (!m_subject || !m_currentImage)
+ return;
+
+ TQPen pen(TQt::white, 0, TQt::SolidLine);
+
+ gc.setPen(pen);
+ gc.setRasterOp(TQt::XorROP);
+
+ KisCanvasController *controller = m_subject->canvasController();
+ KisPoint start, end;
+ TQPoint startPos;
+ TQPoint endPos;
+
+ if (m_dragging) {
+ startPos = controller->windowToView(m_dragStart.floorTQPoint());
+ endPos = controller->windowToView(m_dragEnd.floorTQPoint());
+ gc.drawLine(startPos, endPos);
+ } else {
+ for (KisPointVector::iterator it = m_points.begin(); it != m_points.end(); ++it) {
+
+ if (it == m_points.begin())
+ {
+ start = (*it);
+ } else {
+ end = (*it);
+
+ startPos = controller->windowToView(start.floorTQPoint());
+ endPos = controller->windowToView(end.floorTQPoint());
+
+ gc.drawLine(startPos, endPos);
+
+ start = end;
+ }
+ }
+ }
+}
+
+void KisToolPolyline::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ KShortcut shortcut(TQt::Key_Plus);
+ shortcut.append(KShortcut(TQt::Key_F9));
+ m_action = new KRadioAction(i18n("&Polyline"),
+ "polyline",
+ shortcut,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ Q_CHECK_PTR(m_action);
+
+ m_action->setToolTip(i18n("Draw a polyline. Shift-mouseclick ends the polyline."));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+TQString KisToolPolyline::quickHelp() const
+{
+ return i18n("Press shift-mouseclick to end the polyline.");
+}
+
+void KisToolPolyline::keyPress(TQKeyEvent *e)
+{
+ if (e->key()==TQt::Key_Escape) {
+ // erase old lines on canvas
+ draw();
+ m_dragging = false;
+ m_points.clear();
+ }
+}
+
+#include "kis_tool_polyline.moc"
diff --git a/chalk/plugins/tools/tool_polyline/kis_tool_polyline.h b/chalk/plugins/tools/tool_polyline/kis_tool_polyline.h
new file mode 100644
index 00000000..a7cee195
--- /dev/null
+++ b/chalk/plugins/tools/tool_polyline/kis_tool_polyline.h
@@ -0,0 +1,109 @@
+/*
+ * kis_tool_polyline.h - part of Chalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael Thaler@physik.tu-muenchen.de>
+ *
+ * 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_TOOL_POLYLINE_H_
+#define KIS_TOOL_POLYLINE_H_
+
+#include <tqvaluevector.h>
+#include <tqstring.h>
+
+#include "kis_tool_paint.h"
+#include "kis_point.h"
+
+class KisCanvas;
+class KisDoc;
+class KisPainter;
+class KisView;
+class KisRect;
+
+
+class KisToolPolyline : public KisToolPaint {
+
+ typedef KisToolPaint super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolPolyline();
+ virtual ~KisToolPolyline();
+
+ //
+ // KisCanvasObserver interface
+ //
+
+ virtual void update (KisCanvasSubject *subject);
+
+ //
+ // KisToolPaint interface
+ //
+
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_SHAPE; }
+ virtual TQ_UINT32 priority() { return 5; }
+
+ virtual void buttonPress(KisButtonPressEvent *event);
+ virtual void doubleClick(KisDoubleClickEvent *e);
+ virtual void move(KisMoveEvent *event);
+ virtual void buttonRelease(KisButtonReleaseEvent *event);
+ virtual TQString quickHelp() const;
+ void finish();
+ virtual void keyPress(TQKeyEvent *e);
+
+public slots:
+
+ void deactivate();
+
+protected:
+ virtual void paint(KisCanvasPainter& gc);
+ virtual void paint(KisCanvasPainter& gc, const TQRect& rc);
+ void draw(KisCanvasPainter& gc);
+ void draw();
+
+protected:
+ KisPoint m_dragStart;
+ KisPoint m_dragEnd;
+
+ bool m_dragging;
+ KisImageSP m_currentImage;
+private:
+ typedef TQValueVector<KisPoint> KisPointVector;
+ KisPointVector m_points;
+};
+
+
+#include "kis_tool_factory.h"
+
+class KisToolPolylineFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolPolylineFactory() : super() {};
+ virtual ~KisToolPolylineFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolPolyline();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("polyline", i18n("Polyline Tool")); }
+};
+
+
+#endif //__KIS_TOOL_POLYLINE_H__
diff --git a/chalk/plugins/tools/tool_polyline/polyline.png b/chalk/plugins/tools/tool_polyline/polyline.png
new file mode 100644
index 00000000..df36313e
--- /dev/null
+++ b/chalk/plugins/tools/tool_polyline/polyline.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_polyline/tool_polyline.cc b/chalk/plugins/tools/tool_polyline/tool_polyline.cc
new file mode 100644
index 00000000..369169c9
--- /dev/null
+++ b/chalk/plugins/tools/tool_polyline/tool_polyline.cc
@@ -0,0 +1,64 @@
+/*
+ * tool_polyline.cc -- Part of Chalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_tool_registry.h>
+#include <kis_view.h>
+
+#include "tool_polyline.h"
+#include "kis_tool_polyline.h"
+
+
+typedef KGenericFactory<ToolPolyline> ToolPolylineFactory;
+K_EXPORT_COMPONENT_FACTORY( chalktoolpolyline, ToolPolylineFactory( "chalk" ) )
+
+
+ToolPolyline::ToolPolyline(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ToolPolylineFactory::instance());
+
+ if ( tqparent->inherits("KisToolRegistry") )
+ {
+ KisToolRegistry * r = dynamic_cast<KisToolRegistry*>(tqparent);
+
+ r->add(new KisToolPolylineFactory());
+ }
+
+}
+
+ToolPolyline::~ToolPolyline()
+{
+}
+
+#include "tool_polyline.moc"
diff --git a/chalk/plugins/tools/tool_polyline/tool_polyline.h b/chalk/plugins/tools/tool_polyline/tool_polyline.h
new file mode 100644
index 00000000..9f483363
--- /dev/null
+++ b/chalk/plugins/tools/tool_polyline/tool_polyline.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 TOOL_POLYLINE_H_
+#define TOOL_POLYLINE_H_
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+/**
+ * A module that provides a polyline tool.
+ */
+class ToolPolyline : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ ToolPolyline(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ToolPolyline();
+
+private:
+
+ KisView * m_view;
+
+};
+
+#endif // TOOL_POLYLINE_H_
diff --git a/chalk/plugins/tools/tool_polyline/tool_polyline_cursor.png b/chalk/plugins/tools/tool_polyline/tool_polyline_cursor.png
new file mode 100644
index 00000000..b60c2db0
--- /dev/null
+++ b/chalk/plugins/tools/tool_polyline/tool_polyline_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_selectsimilar/Makefile.am b/chalk/plugins/tools/tool_selectsimilar/Makefile.am
new file mode 100644
index 00000000..f57296ba
--- /dev/null
+++ b/chalk/plugins/tools/tool_selectsimilar/Makefile.am
@@ -0,0 +1,32 @@
+kde_services_DATA = chalktoolselectsimilar.desktop
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+
+chalktoolselectsimilar_la_SOURCES = selectsimilar.cc kis_tool_selectsimilar.cc
+noinst_HEADERS = selectsimilar.h kis_tool_selectsimilar.h
+
+kde_module_LTLIBRARIES = chalktoolselectsimilar.la
+
+chalktoolselectsimilar_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalktoolselectsimilar_la_LIBADD = ../../../libchalkcommon.la
+
+chalktoolselectsimilar_la_METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
+
+# directory for pixmaps
+chalkpics_DATA = \
+ tool_similar_selection.png \
+ tool_similar_selection_plus_cursor.png \
+ tool_similar_selection_minus_cursor.png
+
+chalkpicsdir = $(kde_datadir)/chalk/pics
+
diff --git a/chalk/plugins/tools/tool_selectsimilar/chalktoolselectsimilar.desktop b/chalk/plugins/tools/tool_selectsimilar/chalktoolselectsimilar.desktop
new file mode 100644
index 00000000..408d1c5a
--- /dev/null
+++ b/chalk/plugins/tools/tool_selectsimilar/chalktoolselectsimilar.desktop
@@ -0,0 +1,43 @@
+[Desktop Entry]
+Name=Select Similar Colors Tool
+Name[bg]=Инструмент за маркиране на подобни цветове
+Name[ca]=Selecciona eines de colors similars
+Name[cy]=Offer Detholi Lliwiau Tebyg
+Name[da]=Vælg lignende farve-værktøjer
+Name[de]="Auswahl nach ähnlichen Farben"-Werkzeug
+Name[el]=Εργαλείο επιλογής παρόμοιων χρωμάτων
+Name[en_GB]=Select Similar Colours Tool
+Name[eo]=Similkolorelekto-ilo
+Name[es]=Herramienta de selección de colores similares
+Name[et]=Sarnase värvi valimise tööriist
+Name[fa]=برگزیدن ابزار رنگهای مشابه
+Name[fr]=Outils de sélection des couleurs similaires
+Name[fy]=Lykense kleur seleksje ark
+Name[gl]=Ferramenta de Selección de Cores Semellantes
+Name[he]=בחירת כלי צבעים דומים
+Name[hu]=Hasonló színeket kiválasztó eszköz
+Name[is]=Velja svipaða liti tól
+Name[it]=Strumento per la selezione dei colori simili
+Name[ja]=類似色選択ツール
+Name[km]=ឧបករណ៍​ជ្រើស​ពណ៌​ស្រដៀង​គ្នា
+Name[nb]=Verktøy som velger liknende farger
+Name[nds]=Warktüüch för de Utwahl vun lieke Klören
+Name[ne]=समान रङ उपकरणहरू चयन गर्नुहोस्
+Name[nl]=Gereedschap voor soortgelijke kleuren
+Name[pl]=Narzędzie wyboru podobnych kolorów
+Name[pt]=Ferramenta de Selecção de Cores Semelhantes
+Name[pt_BR]=Ferramenta de Seleção de Cores Semelhantes
+Name[ru]=Выделение по цвету
+Name[se]=Reaidu mii vállje sullosaš ivnniid
+Name[sk]=Výber podobných farieb
+Name[sl]=Orodje za izbiro podobnih barv
+Name[sr]=Алат за избор сличних боја
+Name[sr@Latn]=Alat za izbor sličnih boja
+Name[sv]=Välj liknande färg-verktyg
+Name[uk]=Засіб вибору подібних кольорів
+Name[zh_CN]=选择相似颜色工具
+Name[zh_TW]=選取近似色彩工具
+ServiceTypes=Chalk/Tool
+Type=Service
+X-KDE-Library=chalktoolselectsimilar
+X-Chalk-Version=2
diff --git a/chalk/plugins/tools/tool_selectsimilar/kis_tool_selectsimilar.cc b/chalk/plugins/tools/tool_selectsimilar/kis_tool_selectsimilar.cc
new file mode 100644
index 00000000..2dfe40f1
--- /dev/null
+++ b/chalk/plugins/tools/tool_selectsimilar/kis_tool_selectsimilar.cc
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 1999 Matthias Elter <me@kde.org>
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <tqpoint.h>
+#include <tqlayout.h>
+#include <tqcheckbox.h>
+#include <tqlabel.h>
+#include <tqcombobox.h>
+#include <tqtimer.h>
+
+#include <kapplication.h>
+#include <kaction.h>
+#include <klocale.h>
+#include <knuminput.h>
+
+#include <kis_cursor.h>
+#include <kis_selection_manager.h>
+#include <kis_canvas_subject.h>
+#include <kis_image.h>
+#include <kis_layer.h>
+#include <kis_paint_device.h>
+#include <kis_button_press_event.h>
+#include <kis_canvas_subject.h>
+#include <kis_selection_options.h>
+#include <kis_selection.h>
+#include <kis_paint_device.h>
+#include <kis_iterators_pixel.h>
+#include <kis_selected_transaction.h>
+#include <kis_undo_adapter.h>
+
+#include "kis_tool_selectsimilar.h"
+
+void selectByColor(KisPaintDeviceSP dev, KisSelectionSP selection, const TQ_UINT8 * c, int fuzziness, enumSelectionMode mode)
+{
+ // XXX: Multithread this!
+ TQ_INT32 x, y, w, h;
+
+ dev->exactBounds(x, y, w, h);
+
+ KisColorSpace * cs = dev->colorSpace();
+
+ for (int y2 = y; y2 < y + h; ++y2) {
+ KisHLineIterator hiter = dev->createHLineIterator(x, y2, w, false);
+ KisHLineIterator selIter = selection->createHLineIterator(x, y2, w, true);
+ while (!hiter.isDone()) {
+ //if (dev->colorSpace()->hasAlpha())
+ // opacity = dev->colorSpace()->getAlpha(hiter.rawData());
+
+ TQ_UINT8 match = cs->difference(c, hiter.rawData());
+
+ if (mode == SELECTION_ADD) {
+ if (match <= fuzziness) {
+ *(selIter.rawData()) = MAX_SELECTED;
+ }
+ }
+ else if (mode == SELECTION_SUBTRACT) {
+ if (match <= fuzziness) {
+ *(selIter.rawData()) = MIN_SELECTED;
+ }
+ }
+ ++hiter;
+ ++selIter;
+ }
+ }
+
+}
+
+
+
+KisToolSelectSimilar::KisToolSelectSimilar()
+ : super(i18n("Select Similar Colors"))
+{
+ setName("tool_select_similar");
+ m_addCursor = KisCursor::load("tool_similar_selection_plus_cursor.png", 1, 21);
+ m_subtractCursor = KisCursor::load("tool_similar_selection_minus_cursor.png", 1, 21);
+ setCursor(m_addCursor);
+ m_subject = 0;
+ m_optWidget = 0;
+ m_selectionOptionsWidget = 0;
+ m_fuzziness = 20;
+ m_currentSelectAction = m_defaultSelectAction = SELECTION_ADD;
+ m_timer = new TQTimer(this);
+ connect(m_timer, TQT_SIGNAL(timeout()), TQT_SLOT(slotTimer()) );
+}
+
+KisToolSelectSimilar::~KisToolSelectSimilar()
+{
+}
+
+void KisToolSelectSimilar::activate()
+{
+ KisToolNonPaint::activate();
+ m_timer->start(50);
+ setPickerCursor(m_currentSelectAction);
+
+ if (m_selectionOptionsWidget) {
+ m_selectionOptionsWidget->slotActivated();
+ }
+}
+
+void KisToolSelectSimilar::deactivate()
+{
+ m_timer->stop();
+}
+
+void KisToolSelectSimilar::buttonPress(KisButtonPressEvent *e)
+{
+
+ if (m_subject) {
+ TQApplication::setOverrideCursor(KisCursor::waitCursor());
+ KisImageSP img;
+ KisPaintDeviceSP dev;
+ TQPoint pos;
+ TQ_UINT8 opacity = OPACITY_OPAQUE;
+
+ if (e->button() != Qt::LeftButton && e->button() != Qt::RightButton)
+ return;
+
+ if (!(img = m_subject->currentImg()))
+ return;
+
+ dev = img->activeDevice();
+
+ if (!dev || !img->activeLayer()->visible())
+ return;
+
+ pos = TQPoint(e->pos().floorX(), e->pos().floorY());
+ KisSelectedTransaction *t = 0;
+ if (img->undo()) t = new KisSelectedTransaction(i18n("Similar Selection"),dev);
+
+ KisColor c = dev->colorAt(pos.x(), pos.y());
+ opacity = dev->colorSpace()->getAlpha(c.data());
+
+ // XXX we should make this configurable: "allow to select transparent"
+ // if (opacity > OPACITY_TRANSPARENT)
+ selectByColor(dev, dev->selection(), c.data(), m_fuzziness, m_currentSelectAction);
+
+ dev->setDirty();
+ dev->emitSelectionChanged();
+
+ if(img->undo())
+ img->undoAdapter()->addCommand(t);
+ m_subject->canvasController()->updateCanvas();
+
+ TQApplication::restoreOverrideCursor();
+ }
+}
+
+void KisToolSelectSimilar::slotTimer()
+{
+#if KDE_IS_VERSION(3,4,0)
+ int state = kapp->keyboardMouseState() & (TQt::ShiftButton|TQt::ControlButton|TQt::AltButton);
+#else
+ int state = kapp->keyboardModifiers() & (KApplication::ShiftModifier
+ |KApplication::ControlModifier|KApplication::Modifier1);
+#endif
+ enumSelectionMode action;
+
+ if (state == TQt::ShiftButton)
+ action = SELECTION_ADD;
+ else if (state == TQt::ControlButton)
+ action = SELECTION_SUBTRACT;
+ else
+ action = m_defaultSelectAction;
+
+ if (action != m_currentSelectAction) {
+ m_currentSelectAction = action;
+ setPickerCursor(action);
+ }
+}
+
+void KisToolSelectSimilar::setPickerCursor(enumSelectionMode action)
+{
+ switch (action) {
+ case SELECTION_ADD:
+ m_subject->canvasController()->setCanvasCursor(m_addCursor);
+ break;
+ case SELECTION_SUBTRACT:
+ m_subject->canvasController()->setCanvasCursor(m_subtractCursor);
+ }
+}
+
+void KisToolSelectSimilar::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Similar Selection"), "tool_similar_selection", "Ctrl+E", this, TQT_SLOT(activate()), collection, name());
+ Q_CHECK_PTR(m_action);
+ m_action->setToolTip(i18n("Select similar colors"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+void KisToolSelectSimilar::update(KisCanvasSubject *subject)
+{
+ super::update(subject);
+ m_subject = subject;
+}
+
+void KisToolSelectSimilar::slotSetFuzziness(int fuzziness)
+{
+ m_fuzziness = fuzziness;
+}
+
+void KisToolSelectSimilar::slotSetAction(int action)
+{
+ m_defaultSelectAction = (enumSelectionMode)action;
+}
+
+TQWidget* KisToolSelectSimilar::createOptionWidget(TQWidget* tqparent)
+{
+ m_optWidget = new TQWidget(tqparent);
+ Q_CHECK_PTR(m_optWidget);
+
+ m_optWidget->setCaption(i18n("Similar Selection"));
+
+ TQVBoxLayout * l = new TQVBoxLayout(m_optWidget, 0, 6);
+ Q_CHECK_PTR(l);
+
+ m_selectionOptionsWidget = new KisSelectionOptions(m_optWidget, m_subject);
+ Q_CHECK_PTR(m_selectionOptionsWidget);
+
+ l->addWidget(m_selectionOptionsWidget);
+ connect (m_selectionOptionsWidget, TQT_SIGNAL(actionChanged(int)), this, TQT_SLOT(slotSetAction(int)));
+
+ TQHBoxLayout * hbox = new TQHBoxLayout(l);
+ Q_CHECK_PTR(hbox);
+
+ TQLabel * lbl = new TQLabel(i18n("Fuzziness: "), m_optWidget);
+ Q_CHECK_PTR(lbl);
+
+ hbox->addWidget(lbl);
+
+ KIntNumInput * input = new KIntNumInput(m_optWidget, "fuzziness");
+ Q_CHECK_PTR(input);
+
+ input->setRange(0, 200, 10, true);
+ input->setValue(20);
+ hbox->addWidget(input);
+ connect(input, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slotSetFuzziness(int)));
+
+ l->addItem(new TQSpacerItem(1, 1, TQSizePolicy::Fixed, TQSizePolicy::Expanding));
+
+ return m_optWidget;
+}
+
+TQWidget* KisToolSelectSimilar::optionWidget()
+{
+ return m_optWidget;
+}
+
+#include "kis_tool_selectsimilar.moc"
diff --git a/chalk/plugins/tools/tool_selectsimilar/kis_tool_selectsimilar.h b/chalk/plugins/tools/tool_selectsimilar/kis_tool_selectsimilar.h
new file mode 100644
index 00000000..d98659d0
--- /dev/null
+++ b/chalk/plugins/tools/tool_selectsimilar/kis_tool_selectsimilar.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1999 Matthias Elter
+ * Copyright (c) 2002 Patrick Julien
+ * 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_TOOL_SELECT_PICKER_H_
+#define KIS_TOOL_SELECT_PICKER_H_
+
+#include <kis_tool_non_paint.h>
+#include <kis_tool_factory.h>
+#include <kis_selection.h>
+
+class KisCanvasSubject;
+class TQWidget;
+class TQVBoxLayout;
+class TQCheckBox;
+class KisIntSpinbox;
+
+/**
+ * Tool to select colours by pointing at a color on the image.
+ * TODO:
+ * Implement shift/shift-ctrl keyboard shortcuts for
+ * temporary add/subtract selection mode.
+ */
+
+class KisSelectionOptions;
+
+class KisToolSelectSimilar : public KisToolNonPaint {
+
+ Q_OBJECT
+ TQ_OBJECT
+ typedef KisToolNonPaint super;
+
+public:
+ KisToolSelectSimilar();
+ virtual ~KisToolSelectSimilar();
+
+ virtual void update(KisCanvasSubject *subject);
+ virtual void setup(KActionCollection *collection);
+ virtual TQ_UINT32 priority() { return 8; }
+ virtual enumToolType toolType() { return TOOL_SELECT; }
+
+public slots:
+
+ void activate();
+ void deactivate();
+
+ virtual void slotSetFuzziness(int);
+ virtual void slotSetAction(int);
+
+private:
+ virtual TQWidget* createOptionWidget(TQWidget* tqparent);
+ virtual TQWidget* optionWidget();
+
+ virtual void buttonPress(KisButtonPressEvent *e);
+ void setPickerCursor(enumSelectionMode);
+
+ KisCanvasSubject *m_subject;
+ TQWidget *m_optWidget;
+ KisSelectionOptions *m_selectionOptionsWidget;
+
+ int m_fuzziness;
+ enumSelectionMode m_defaultSelectAction;
+ enumSelectionMode m_currentSelectAction;
+ TQTimer *m_timer;
+ TQCursor m_addCursor;
+ TQCursor m_subtractCursor;
+
+private slots:
+ void slotTimer();
+};
+
+class KisToolSelectSimilarFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolSelectSimilarFactory() : super() {};
+ virtual ~KisToolSelectSimilarFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolSelectSimilar();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("selectsimilar", i18n("Select Similar")); }
+};
+
+
+#endif // KIS_TOOL_SELECT_PICKER_H_
+
diff --git a/chalk/plugins/tools/tool_selectsimilar/selectsimilar.cc b/chalk/plugins/tools/tool_selectsimilar/selectsimilar.cc
new file mode 100644
index 00000000..539f534a
--- /dev/null
+++ b/chalk/plugins/tools/tool_selectsimilar/selectsimilar.cc
@@ -0,0 +1,61 @@
+/*
+ * selectsimilar.h -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 <math.h>
+
+#include <stdlib.h>
+
+#include <tqslider.h>
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_tool_registry.h>
+
+#include "selectsimilar.h"
+#include "kis_tool_selectsimilar.h"
+
+typedef KGenericFactory<SelectSimilar> SelectSimilarFactory;
+K_EXPORT_COMPONENT_FACTORY( chalktoolselectsimilar, SelectSimilarFactory( "chalk" ) )
+
+SelectSimilar::SelectSimilar(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(SelectSimilarFactory::instance());
+
+ if ( tqparent->inherits("KisToolRegistry") )
+ {
+ KisToolRegistry * r = dynamic_cast<KisToolRegistry*>(tqparent);
+ r->add(new KisToolSelectSimilarFactory());
+ }
+}
+
+SelectSimilar::~SelectSimilar()
+{
+}
+
+#include "selectsimilar.moc"
+
diff --git a/chalk/plugins/tools/tool_selectsimilar/selectsimilar.h b/chalk/plugins/tools/tool_selectsimilar/selectsimilar.h
new file mode 100644
index 00000000..a0588bfb
--- /dev/null
+++ b/chalk/plugins/tools/tool_selectsimilar/selectsimilar.h
@@ -0,0 +1,35 @@
+/*
+ * selectsimilar.h -- Part of Chalk
+ *
+ * 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 SELECTSIMILAR_H
+#define SELECTSIMILAR_H
+
+#include <kparts/plugin.h>
+
+class SelectSimilar : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+ public:
+ SelectSimilar(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~SelectSimilar();
+
+
+};
+
+#endif // SELECTSIMILAR_H
diff --git a/chalk/plugins/tools/tool_selectsimilar/tool_similar_selection.png b/chalk/plugins/tools/tool_selectsimilar/tool_similar_selection.png
new file mode 100644
index 00000000..3025b100
--- /dev/null
+++ b/chalk/plugins/tools/tool_selectsimilar/tool_similar_selection.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_selectsimilar/tool_similar_selection.svg b/chalk/plugins/tools/tool_selectsimilar/tool_similar_selection.svg
new file mode 100644
index 00000000..f1e881bc
--- /dev/null
+++ b/chalk/plugins/tools/tool_selectsimilar/tool_similar_selection.svg
@@ -0,0 +1,2118 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:export-ydpi="33.000000"
+ inkscape:export-xdpi="33.000000"
+ inkscape:export-filename="/home/danny/work/kde/koffice/chalk/chalk/new/tool_picker_selection.png"
+ width="48.000000pt"
+ height="48.000000pt"
+ id="svg17707"
+ sodipodi:version="0.32"
+ inkscape:version="0.41"
+ sodipodi:docbase="/home/danny"
+ sodipodi:docname="co.svg">
+ <defs
+ id="defs3">
+ <linearGradient
+ y2="-88.103630"
+ x2="-2035.2124"
+ y1="-86.329994"
+ x1="-2105.8408"
+ gradientTransform="matrix(0.275772,6.677168e-2,-1.785205,1.778283,15.77866,-194.5809)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13777"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="406.47195"
+ x2="-420.16779"
+ y1="405.99652"
+ x1="-432.85263"
+ gradientTransform="matrix(1.161617,-4.739154e-2,2.691281e-2,0.545879,5.167330,-400.1846)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13775"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="405.64288"
+ x2="-419.48849"
+ y1="403.28021"
+ x1="-435.29645"
+ gradientTransform="matrix(1.161617,-4.739154e-2,2.691281e-2,0.545879,5.167330,-400.1846)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13773"
+ xlink:href="#sadow75to0w"
+ inkscape:collect="always" />
+ <radialGradient
+ r="14.292608"
+ fy="224.71202"
+ fx="-36.269680"
+ cy="224.72163"
+ cx="-36.280697"
+ spreadMethod="reflect"
+ gradientTransform="matrix(1.289960,-2.934787,-1.254670,-0.687701,-135.1226,-352.8727)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient13771"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ id="light100to75to0">
+ <stop
+ id="stop2779"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+ <stop
+ id="stop2782"
+ offset="0.50000000"
+ style="stop-color:#ffffff;stop-opacity:0.77499998;" />
+ <stop
+ id="stop2780"
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <radialGradient
+ r="20.501772"
+ fy="-238.20859"
+ fx="-580.40790"
+ cy="-238.20859"
+ cx="-580.40790"
+ spreadMethod="pad"
+ gradientTransform="matrix(0.777876,3.246476e-2,2.423728e-2,0.784691,13.97124,-196.1555)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient13769"
+ xlink:href="#light100to75to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="14.292608"
+ fy="224.71202"
+ fx="-36.269680"
+ cy="224.72163"
+ cx="-36.280697"
+ spreadMethod="reflect"
+ gradientTransform="matrix(1.458853,-2.843975,1.264624,0.666794,-721.3474,-644.7191)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient13767"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="235.01132"
+ x2="135.19012"
+ y1="198.13455"
+ x1="111.31033"
+ gradientTransform="matrix(2.980933,-1.623511,0.421337,1.602678,-832.2722,-621.5866)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13765"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="203.17725"
+ x2="159.03880"
+ y1="169.79622"
+ x1="139.84422"
+ spreadMethod="reflect"
+ gradientTransform="matrix(2.501016,-1.261406,3.268214e-2,1.810490,-830.4708,-1463.906)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13763"
+ xlink:href="#greylighttograyw"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="438.93094"
+ x2="236.60674"
+ y1="441.75595"
+ x1="238.34102"
+ gradientTransform="matrix(-8.083600e-2,-0.768518,-1.314142,-0.122986,-4.770628e-13,8.999746e-14)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13761"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="-295.75092"
+ x2="-417.17459"
+ y1="-417.90485"
+ x1="-492.07742"
+ gradientTransform="matrix(4.666024e-2,4.366770e-3,7.470758e-3,7.102536e-2,-570.7207,-206.9104)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13759"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="123.06261"
+ x2="187.18298"
+ y1="227.44664"
+ x1="184.86623"
+ gradientTransform="matrix(7.470016e-2,6.828522e-2,-2.777414e-2,3.139757e-2,-606.6362,-251.3928)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13757"
+ xlink:href="#greandarktobgrean"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="-428.42480"
+ x2="-613.35199"
+ y1="-430.20041"
+ x1="-614.11633"
+ gradientTransform="matrix(1.048782,-0.305752,-0.108731,0.985186,-4.770628e-13,8.999746e-14)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13755"
+ xlink:href="#greandraktoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="-429.79779"
+ x2="-601.16077"
+ y1="-436.17172"
+ x1="-607.02917"
+ spreadMethod="reflect"
+ gradientTransform="matrix(1.063407,-0.310015,-0.107235,0.971636,-4.770628e-13,8.999746e-14)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13753"
+ xlink:href="#greandarktobgrean"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="118.38348"
+ x2="219.65416"
+ y1="150.76836"
+ x1="239.13113"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.165829,-5.173052e-2,-1.826319e-2,0.197436,-628.6676,-249.7811)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13751"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="118.38348"
+ x2="219.65416"
+ y1="150.76836"
+ x1="239.13113"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.165829,-5.173052e-2,-1.826319e-2,0.197436,-628.6676,-249.7811)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13749"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="118.38348"
+ x2="219.65416"
+ y1="150.76836"
+ x1="239.13113"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.165829,-5.173052e-2,-1.826319e-2,0.197436,-628.6676,-249.7811)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13747"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="163.71248"
+ x2="166.34229"
+ y1="140.82243"
+ x1="165.24026"
+ gradientTransform="matrix(0.224936,-7.016936e-2,-1.346405e-2,0.145555,-629.0715,-249.6400)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13745"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="118.38348"
+ x2="219.65416"
+ y1="150.76836"
+ x1="239.13113"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.165829,-5.173052e-2,-1.826319e-2,0.197436,-628.6676,-249.7811)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13743"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="101.48473"
+ x2="186.14693"
+ y1="208.29716"
+ x1="211.31139"
+ gradientTransform="matrix(0.163150,-4.324279e-2,-1.925222e-2,0.147313,-623.7133,-249.0598)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13741"
+ xlink:href="#greandraktoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ id="greandarktobgrean">
+ <stop
+ id="stop4492"
+ offset="0.0000000"
+ style="stop-color:#00ad01;stop-opacity:1.0000000;" />
+ <stop
+ id="stop4493"
+ offset="1.0000000"
+ style="stop-color:#15720f;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ y2="227.49260"
+ x2="198.67084"
+ y1="100.63807"
+ x1="139.79741"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.165426,-4.384578e-2,-1.898738e-2,0.145287,-614.6689,-246.6268)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13739"
+ xlink:href="#greandarktobgrean"
+ inkscape:collect="always" />
+ <linearGradient
+ id="greandraktoblack">
+ <stop
+ id="stop7328"
+ offset="0.0000000"
+ style="stop-color:#007c00;stop-opacity:1.0000000;" />
+ <stop
+ id="stop7329"
+ offset="1.0000000"
+ style="stop-color:#025a00;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ y2="-643.52313"
+ x2="-303.30316"
+ y1="-852.35785"
+ x1="-406.36154"
+ spreadMethod="reflect"
+ gradientTransform="matrix(1.085489,-0.277106,-0.134433,0.955562,-6.884770e-13,-5.417332e-13)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13737"
+ xlink:href="#greandraktoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="-351.53336"
+ x2="-279.99734"
+ y1="-529.27637"
+ x1="-426.86380"
+ gradientTransform="scale(1.014829,0.985388)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13735"
+ xlink:href="#graytoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="linearGradient17705"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.889037,1.124812)"
+ spreadMethod="reflect"
+ x1="239.13113"
+ y1="150.76836"
+ x2="219.65416"
+ y2="118.38348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="linearGradient17703"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.889037,1.124812)"
+ spreadMethod="reflect"
+ x1="239.13113"
+ y1="150.76836"
+ x2="219.65416"
+ y2="118.38348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="linearGradient17701"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.889037,1.124812)"
+ spreadMethod="reflect"
+ x1="239.13113"
+ y1="150.76836"
+ x2="219.65416"
+ y2="118.38348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light100to0"
+ id="linearGradient17699"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.205925,0.829239)"
+ x1="165.24026"
+ y1="140.82243"
+ x2="166.34229"
+ y2="163.71248" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="linearGradient17697"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.889037,1.124812)"
+ spreadMethod="reflect"
+ x1="239.13113"
+ y1="150.76836"
+ x2="219.65416"
+ y2="118.38348" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="radialGradient17695"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.917031,-0.155019,0.179218,1.060181,-23.61859,31.63539)"
+ cx="130.43364"
+ cy="187.24419"
+ fx="130.40277"
+ fy="187.29732"
+ r="13.523715" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="radialGradient17693"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.917031,-0.155019,0.179218,1.060181,-23.61859,31.63539)"
+ cx="130.43364"
+ cy="187.24419"
+ fx="130.40277"
+ fy="187.29732"
+ r="13.523715" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="radialGradient17691"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.917031,-0.155019,0.179218,1.060181,-23.61859,31.63539)"
+ cx="130.43364"
+ cy="187.24419"
+ fx="130.40277"
+ fy="187.29732"
+ r="13.523715" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="radialGradient17689"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.917031,-0.155019,0.179218,1.060181,-23.61859,31.63539)"
+ cx="130.43364"
+ cy="187.24419"
+ fx="130.40277"
+ fy="187.29732"
+ r="13.523715" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="radialGradient17687"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.917031,-0.155019,0.179218,1.060181,-23.61859,31.63539)"
+ cx="130.43364"
+ cy="187.24419"
+ fx="130.40277"
+ fy="187.29732"
+ r="13.523715" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="linearGradient17685"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.919303,-4.587116e-16,-9.003051e-17,1.087781,-31.65752,40.91072)"
+ x1="132.47713"
+ y1="128.17326"
+ x2="138.51009"
+ y2="135.55878" />
+ <linearGradient
+ id="sadow75to0w">
+ <stop
+ style="stop-color:#000000;stop-opacity:0.72941178;"
+ offset="0.0000000"
+ id="stop3429" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="1.0000000"
+ id="stop3430" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#sadow75to0w"
+ id="linearGradient17683"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.919303,-4.587116e-16,-9.003051e-17,1.087781,-31.65752,40.91072)"
+ spreadMethod="reflect"
+ x1="131.99300"
+ y1="129.27406"
+ x2="134.97223"
+ y2="132.72443" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="radialGradient17681"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.277707,-1.314622,0.656307,0.494064,-23.61859,31.63539)"
+ spreadMethod="reflect"
+ cx="-36.280697"
+ cy="224.72163"
+ fx="-36.269680"
+ fy="224.71202"
+ r="14.292608" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="radialGradient17679"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.917031,-0.155019,0.179218,1.060181,-23.61859,31.63539)"
+ cx="130.43364"
+ cy="187.24419"
+ fx="130.40277"
+ fy="187.29732"
+ r="13.523715" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light100to0"
+ id="radialGradient17677"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.952120,-0.160951,0.172613,1.021109,-23.57515,31.60495)"
+ cx="124.97867"
+ cy="166.89621"
+ fx="124.97867"
+ fy="166.89621"
+ r="4.5374427" />
+ <linearGradient
+ id="light100to0">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop2764" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="1.0000000"
+ id="stop2765" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light100to0"
+ id="radialGradient17675"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.952120,-0.160951,0.172613,1.021109,-23.61859,31.63539)"
+ cx="140.60791"
+ cy="183.52762"
+ fx="140.60791"
+ fy="183.52762"
+ r="8.2203732" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="linearGradient17673"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.068635,-0.180647,0.153793,0.909776,-2.125903e-15,-5.608359e-15)"
+ x1="111.31033"
+ y1="198.13455"
+ x2="135.19012"
+ y2="235.01132" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="linearGradient17671"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.068635,-0.180647,0.153793,0.909776,-23.61859,31.63539)"
+ x1="121.55471"
+ y1="169.77112"
+ x2="130.17465"
+ y2="182.88293" />
+ <linearGradient
+ id="zerotowhitetozero">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.0000000"
+ id="stop3155" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.33462518"
+ id="stop3156" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1.0000000;"
+ offset="0.55554277"
+ id="stop3157" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="0.74528182"
+ id="stop3158" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0.0000000;"
+ offset="1.0000000"
+ id="stop3159" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="linearGradient17669"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.918796,-4.448298e-7,2.186431e-9,1.088383,-31.71369,41.04076)"
+ x1="130.94159"
+ y1="136.24300"
+ x2="141.97820"
+ y2="119.97503" />
+ <linearGradient
+ id="orangetoblackorange">
+ <stop
+ style="stop-color:#ff8b00;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop4207" />
+ <stop
+ style="stop-color:#4d0200;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop4209" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#orangetoblackorange"
+ id="linearGradient17667"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.994153,1.005881)"
+ x1="211.31139"
+ y1="208.29716"
+ x2="186.14693"
+ y2="101.48473" />
+ <linearGradient
+ id="orangelesstoyelow">
+ <stop
+ style="stop-color:#ff0d00;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop2689" />
+ <stop
+ style="stop-color:#ff3900;stop-opacity:1.0000000;"
+ offset="0.25358382"
+ id="stop2690" />
+ <stop
+ style="stop-color:#d05521;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop2691" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#orangelesstoyelow"
+ id="linearGradient17665"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.008016,-3.457641e-17,-7.028912e-17,0.992047,59.09612,34.16495)"
+ spreadMethod="reflect"
+ x1="139.79741"
+ y1="100.63807"
+ x2="198.67084"
+ y2="227.49260" />
+ <linearGradient
+ id="greylighttograyw">
+ <stop
+ style="stop-color:#b5b5b8;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop575" />
+ <stop
+ style="stop-color:#ebebee;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop576" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#greylighttograyw"
+ id="linearGradient17663"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.068635,-0.180647,0.153793,0.909776,-23.61859,31.63539)"
+ spreadMethod="reflect"
+ x1="139.84422"
+ y1="169.79622"
+ x2="159.03880"
+ y2="203.17725" />
+ <radialGradient
+ r="5.8189325"
+ fy="9.5002232"
+ fx="8.0907059"
+ cy="9.5002232"
+ cx="8.0907059"
+ gradientTransform="matrix(0.542260,0.000000,0.000000,1.241312,-0.785301,11.64914)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient20026"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="41.545322"
+ x2="22.396454"
+ y1="35.206337"
+ x1="22.425571"
+ gradientTransform="matrix(2.038890,0.000000,0.000000,0.330138,-12.72324,1.327640)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient20022"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="14.270030"
+ fy="51.904903"
+ fx="25.923746"
+ cy="52.497688"
+ cx="25.952410"
+ gradientTransform="matrix(2.144567,0.000000,0.000000,0.313870,-12.72324,1.327640)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient20019"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="9.9914455"
+ fy="55.457653"
+ fx="92.643608"
+ cy="55.457653"
+ cx="92.643608"
+ gradientTransform="matrix(0.715419,0.000000,0.000000,0.940867,-15.98071,11.24691)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient20008"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="85.112236"
+ x2="-21.621279"
+ y1="81.885979"
+ x1="-16.569721"
+ gradientTransform="matrix(0.000000,-2.069389,0.325272,0.000000,20.75234,15.09638)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient20005"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="41.545322"
+ x2="22.396454"
+ y1="35.206337"
+ x1="22.425571"
+ gradientTransform="matrix(2.038890,0.000000,0.000000,0.330138,-31.37563,1.327640)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient20001"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="14.270030"
+ fy="51.904903"
+ fx="25.923746"
+ cy="52.497688"
+ cx="25.952410"
+ gradientTransform="matrix(2.144567,0.000000,0.000000,0.313870,-31.37563,1.327640)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient19998"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="41.545322"
+ x2="22.396454"
+ y1="35.206337"
+ x1="22.425571"
+ gradientTransform="matrix(2.038890,0.000000,0.000000,0.330138,-20.05593,48.23092)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient19994"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="14.270030"
+ fy="51.904903"
+ fx="25.923746"
+ cy="52.497688"
+ cx="25.952410"
+ gradientTransform="matrix(2.144567,0.000000,0.000000,0.313870,-20.05593,48.23092)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient19991"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="41.545322"
+ x2="22.396454"
+ y1="35.206337"
+ x1="22.425571"
+ gradientTransform="matrix(2.038890,0.000000,0.000000,0.330138,-38.78637,48.23092)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient19987"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="14.270030"
+ fy="51.904903"
+ fx="25.923746"
+ cy="52.497688"
+ cx="25.952410"
+ gradientTransform="matrix(2.144567,0.000000,0.000000,0.313870,-38.78637,48.23092)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient19984"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="85.112236"
+ x2="-21.621279"
+ y1="81.885979"
+ x1="-16.569721"
+ gradientTransform="matrix(0.000000,-2.069389,0.325272,0.000000,20.66765,1.378444)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient19980"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="8.5514765"
+ fy="95.221397"
+ fx="-23.859682"
+ cy="95.221397"
+ cx="-23.859682"
+ gradientTransform="matrix(0.000000,-2.142981,0.309244,0.000000,20.66765,1.878457)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient19977"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="85.112236"
+ x2="-21.621279"
+ y1="81.885979"
+ x1="-16.569721"
+ gradientTransform="matrix(0.000000,-2.069389,0.325272,0.000000,-25.58840,-6.393896)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient19973"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="8.5514765"
+ fy="95.221397"
+ fx="-23.859682"
+ cy="95.221397"
+ cx="-23.859682"
+ gradientTransform="matrix(0.000000,-2.142981,0.309244,0.000000,-25.58840,-5.893883)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient19970"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="85.112236"
+ x2="-21.621279"
+ y1="81.885979"
+ x1="-16.569721"
+ gradientTransform="matrix(0.000000,-2.069389,0.325272,0.000000,-25.58840,10.88376)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient19966"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="8.5514765"
+ fy="95.221397"
+ fx="-23.859682"
+ cy="95.221397"
+ cx="-23.859682"
+ gradientTransform="matrix(0.000000,-2.142981,0.309244,0.000000,-25.58840,11.38378)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient19963"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="218.74910"
+ x2="198.28532"
+ y1="264.70230"
+ x1="145.42192"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient19163"
+ xlink:href="#graytoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="210.46336"
+ x2="84.003502"
+ y1="279.47504"
+ x1="132.72992"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient18401"
+ xlink:href="#graytoblack"
+ inkscape:collect="always" />
+ <radialGradient
+ r="83.259750"
+ fy="332.37268"
+ fx="86.514435"
+ cy="332.37268"
+ cx="86.514435"
+ gradientTransform="matrix(0.281643,-1.886110e-2,0.000000,0.179517,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient16881"
+ xlink:href="#graytoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="216.48166"
+ x2="144.13652"
+ y1="120.63583"
+ x1="149.74805"
+ gradientTransform="matrix(0.331788,0.000000,0.000000,0.171926,-4.383100,-17.56719)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13087"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="172.01805"
+ x2="88.821419"
+ y1="215.05040"
+ x1="42.080868"
+ gradientTransform="matrix(0.182201,0.000000,0.000000,0.313078,-4.383100,-17.56719)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13085"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="213.05858"
+ x2="189.53893"
+ y1="213.05858"
+ x1="24.253796"
+ gradientTransform="matrix(0.331788,0.000000,0.000000,0.171926,-4.383100,-17.56719)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13083"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="229.92639"
+ x2="120.08266"
+ y1="203.68118"
+ x1="203.79491"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.250582,0.000000,0.000000,0.227641,-4.383105,-17.56717)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13081"
+ xlink:href="#orangetoblackorange"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="189.54620"
+ x2="129.06503"
+ y1="179.83293"
+ x1="119.80309"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.302207,-2.036411e-2,1.731823e-2,0.187588,4.903646,-12.38550)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13079"
+ xlink:href="#orangetoblackorange"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="189.54620"
+ x2="129.06503"
+ y1="179.83293"
+ x1="119.80309"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.302207,-2.036411e-2,1.731823e-2,0.187588,-0.406378,-15.67507)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13077"
+ xlink:href="#orangetoblackorange"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="189.54620"
+ x2="129.06503"
+ y1="179.83293"
+ x1="119.80309"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.302207,-2.036411e-2,1.731823e-2,0.187588,-5.784573,-19.06245)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13075"
+ xlink:href="#orangetoblackorange"
+ inkscape:collect="always" />
+ <radialGradient
+ r="24.113470"
+ fy="265.90030"
+ fx="145.82777"
+ cy="265.90030"
+ cx="145.82777"
+ gradientTransform="matrix(0.282097,-1.889158e-2,0.000000,0.179229,-4.383100,-12.51208)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient13073"
+ xlink:href="#light50to25to7"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="301.15750"
+ x2="137.31036"
+ y1="301.15747"
+ x1="163.74318"
+ gradientTransform="matrix(0.273027,-1.828417e-2,0.000000,0.185183,-4.383100,-12.51208)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13071"
+ xlink:href="#shadow100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="224.95407"
+ x2="99.415497"
+ y1="199.20517"
+ x1="124.51332"
+ gradientTransform="matrix(0.273027,-1.828417e-2,0.000000,0.185183,-4.383100,-12.51208)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13069"
+ xlink:href="#shadow100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="224.95407"
+ x2="99.415497"
+ y1="199.20517"
+ x1="124.51332"
+ gradientTransform="matrix(0.273027,-1.828417e-2,0.000000,0.185183,-4.383100,-12.51208)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13067"
+ xlink:href="#shadow100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="574.66980"
+ x2="90.955330"
+ y1="221.05045"
+ x1="138.68466"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.262073,-1.755056e-2,0.000000,0.217660,-4.383105,-17.56717)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13065"
+ xlink:href="#graytoblack"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="220.31316"
+ x2="269.30646"
+ y1="173.35371"
+ x1="188.09673"
+ gradientTransform="matrix(0.218024,-1.460066e-2,0.000000,0.231901,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13063"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="18.127838"
+ x2="40.120766"
+ y1="43.692036"
+ x1="77.830383"
+ gradientTransform="matrix(0.870407,-5.828951e-2,0.000000,1.148888,-2.107689e-16,7.113450e-16)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13061"
+ xlink:href="#orangemoretoyelow"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="189.89319"
+ x2="126.82574"
+ y1="300.55457"
+ x1="134.59328"
+ gradientTransform="matrix(0.286285,-1.917198e-2,0.000000,0.176607,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13059"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="47.244961"
+ x2="28.653791"
+ y1="4.8842254"
+ x1="36.606781"
+ gradientTransform="matrix(1.273196,-8.526361e-2,0.000000,0.785425,-2.107689e-16,7.113450e-16)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13057"
+ xlink:href="#orangemoretoyelow"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="234.35374"
+ x2="184.11906"
+ y1="219.68500"
+ x1="159.18221"
+ gradientTransform="matrix(0.180988,-1.212046e-2,0.000000,0.279356,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13055"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="218.74910"
+ x2="198.28532"
+ y1="264.70230"
+ x1="145.42192"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13053"
+ xlink:href="#wihitetolightgray"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="250.54321"
+ x2="54.607849"
+ y1="213.43617"
+ x1="136.55682"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13051"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="210.46336"
+ x2="84.003502"
+ y1="279.47504"
+ x1="132.72992"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13049"
+ xlink:href="#wihitetolightgray"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="247.07323"
+ x2="73.286217"
+ y1="335.76117"
+ x1="86.514435"
+ gradientTransform="matrix(0.281643,-1.886110e-2,0.000000,0.179517,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient13047"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="83.259750"
+ fy="332.37268"
+ fx="86.514435"
+ cy="332.37268"
+ cx="86.514435"
+ gradientTransform="matrix(0.281643,-1.886110e-2,0.000000,0.179517,-4.383105,-16.75305)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient13045"
+ xlink:href="#wihitetolightgray"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient18012">
+ <stop
+ id="stop18014"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+ <stop
+ id="stop18016"
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient18006">
+ <stop
+ id="stop18008"
+ offset="0.0000000"
+ style="stop-color:#ff8b00;stop-opacity:1.0000000;" />
+ <stop
+ id="stop18010"
+ offset="1.0000000"
+ style="stop-color:#4d0200;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="light50to25to7">
+ <stop
+ id="stop2791"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.47450981;" />
+ <stop
+ id="stop2795"
+ offset="0.50000000"
+ style="stop-color:#ffffff;stop-opacity:0.25833333;" />
+ <stop
+ id="stop2793"
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.10833333;" />
+ </linearGradient>
+ <linearGradient
+ id="shadow100to0">
+ <stop
+ id="stop3425"
+ offset="0.0000000"
+ style="stop-color:#000000;stop-opacity:1.0000000;" />
+ <stop
+ id="stop3426"
+ offset="1.0000000"
+ style="stop-color:#000000;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="graytoblack">
+ <stop
+ id="stop5097"
+ offset="0.0000000"
+ style="stop-color:#7d7d7d;stop-opacity:1.0000000;" />
+ <stop
+ id="stop5098"
+ offset="1.0000000"
+ style="stop-color:#000000;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="orangemoretoyelow">
+ <stop
+ id="stop2671"
+ offset="0.0000000"
+ style="stop-color:#ff7d00;stop-opacity:1.0000000;" />
+ <stop
+ id="stop2679"
+ offset="0.74641621"
+ style="stop-color:#ffbe00;stop-opacity:1.0000000;" />
+ <stop
+ id="stop2672"
+ offset="1.0000000"
+ style="stop-color:#ffff00;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="wihitetolightgray">
+ <stop
+ id="stop1885"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+ <stop
+ id="stop1886"
+ offset="1.0000000"
+ style="stop-color:#d5d4d4;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ y2="13.431447"
+ x2="14.101834"
+ y1="6.5494914"
+ x1="4.4536543"
+ gradientTransform="matrix(0.791643,0.000000,0.000000,1.263196,-1.626700,-5.630763)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient7931"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ id="light90to0">
+ <stop
+ id="stop1890"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.90833336;" />
+ <stop
+ id="stop1892"
+ offset="1.0000000"
+ style="stop-color:#ffffff;stop-opacity:0.0000000;" />
+ </linearGradient>
+ <radialGradient
+ r="5.8189325"
+ fy="9.5002232"
+ fx="8.0907059"
+ cy="9.5002232"
+ cx="8.0907059"
+ gradientTransform="scale(0.665867,1.501801)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient7933"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="41.545322"
+ x2="22.396454"
+ y1="35.206337"
+ x1="22.425571"
+ gradientTransform="matrix(2.503650,0.000000,0.000000,0.399417,-16.65916,-12.48664)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient7935"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="14.270030"
+ fy="51.904903"
+ fx="25.923746"
+ cy="52.497688"
+ cx="25.952410"
+ gradientTransform="matrix(2.633416,0.000000,0.000000,0.379735,-16.65916,-12.48664)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient7937"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="85.112236"
+ x2="-21.621279"
+ y1="81.885979"
+ x1="-16.569721"
+ gradientTransform="matrix(0.000000,-2.503650,0.399417,0.000000,26.44710,-31.82936)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient7939"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="8.5514765"
+ fy="95.221397"
+ fx="-23.859682"
+ cy="95.221397"
+ cx="-23.859682"
+ gradientTransform="matrix(0.000000,-2.592685,0.379735,0.000000,26.44710,-31.22442)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient7941"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="9.9914455"
+ fy="55.457653"
+ fx="92.643608"
+ cy="55.457653"
+ cx="92.643608"
+ gradientTransform="matrix(0.878497,0.000000,0.000000,1.138308,-18.65916,-0.486640)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient7943"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="85.112236"
+ x2="-21.621279"
+ y1="81.885979"
+ x1="-16.569721"
+ gradientTransform="matrix(0.000000,-2.503650,0.399417,0.000000,26.44710,4.170640)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient7945"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="41.545322"
+ x2="22.396454"
+ y1="35.206337"
+ x1="22.425571"
+ gradientTransform="matrix(2.503650,0.000000,0.000000,0.399417,-38.65916,-12.48664)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient7947"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="14.270030"
+ fy="51.904903"
+ fx="25.923746"
+ cy="52.497688"
+ cx="25.952410"
+ gradientTransform="matrix(2.633416,0.000000,0.000000,0.379735,-38.65916,-12.48664)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient7949"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="41.545322"
+ x2="22.396454"
+ y1="35.206337"
+ x1="22.425571"
+ gradientTransform="matrix(2.503650,0.000000,0.000000,0.399417,-22.86332,44.21180)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient7951"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="14.270030"
+ fy="51.904903"
+ fx="25.923746"
+ cy="52.497688"
+ cx="25.952410"
+ gradientTransform="matrix(2.633416,0.000000,0.000000,0.379735,-22.86332,44.21180)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient7953"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="41.545322"
+ x2="22.396454"
+ y1="35.206337"
+ x1="22.425571"
+ gradientTransform="matrix(2.503650,0.000000,0.000000,0.399417,-44.86332,44.21180)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient7955"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="14.270030"
+ fy="51.904903"
+ fx="25.923746"
+ cy="52.497688"
+ cx="25.952410"
+ gradientTransform="matrix(2.633416,0.000000,0.000000,0.379735,-44.86332,44.21180)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient7957"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="85.112236"
+ x2="-21.621279"
+ y1="81.885979"
+ x1="-16.569721"
+ gradientTransform="matrix(0.000000,-2.503650,0.399417,0.000000,26.44710,-11.82936)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient7959"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="8.5514765"
+ fy="95.221397"
+ fx="-23.859682"
+ cy="95.221397"
+ cx="-23.859682"
+ gradientTransform="matrix(0.000000,-2.592685,0.379735,0.000000,26.44710,-11.22442)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient7961"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="85.112236"
+ x2="-21.621279"
+ y1="81.885979"
+ x1="-16.569721"
+ gradientTransform="matrix(0.000000,-2.503650,0.399417,0.000000,-30.45690,-21.82936)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient7963"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="8.5514765"
+ fy="95.221397"
+ fx="-23.859682"
+ cy="95.221397"
+ cx="-23.859682"
+ gradientTransform="matrix(0.000000,-2.592685,0.379735,0.000000,-30.45690,-21.22442)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient7965"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="85.112236"
+ x2="-21.621279"
+ y1="81.885979"
+ x1="-16.569721"
+ gradientTransform="matrix(0.000000,-2.503650,0.399417,0.000000,-30.45690,-1.829360)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient7967"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="8.5514765"
+ fy="95.221397"
+ fx="-23.859682"
+ cy="95.221397"
+ cx="-23.859682"
+ gradientTransform="matrix(0.000000,-2.592685,0.379735,0.000000,-30.45690,-1.224420)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient7969"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <radialGradient
+ gradientUnits="userSpaceOnUse"
+ r="31.677956"
+ fy="46.914463"
+ fx="48.488476"
+ cy="46.914463"
+ cx="48.488476"
+ gradientTransform="matrix(0.983903,0.000000,0.000000,1.016360,-33.35882,-2.298655)"
+ id="radialGradient10280"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ gradientUnits="userSpaceOnUse"
+ y2="36.873619"
+ x2="39.857029"
+ y1="4.5492039"
+ x1="10.878086"
+ gradientTransform="matrix(0.996235,0.000000,0.000000,1.003779,-32.74998,-1.298655)"
+ id="linearGradient9512"
+ xlink:href="#light90to0"
+ inkscape:collect="always" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light100to0"
+ id="linearGradient18107"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.281643,-1.886110e-2,0.000000,0.179517,-4.383105,-16.75305)"
+ x1="86.514435"
+ y1="335.76117"
+ x2="73.286217"
+ y2="247.07323" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light100to0"
+ id="linearGradient18109"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.195716,-1.310673e-2,0.000000,0.258334,-4.383105,-16.75305)"
+ x1="136.55682"
+ y1="213.43617"
+ x2="54.607849"
+ y2="250.54321" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light100to0"
+ id="linearGradient18111"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.180988,-1.212046e-2,0.000000,0.279356,-4.383105,-16.75305)"
+ x1="159.18221"
+ y1="219.68500"
+ x2="184.11906"
+ y2="234.35374" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient1589"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.996235,0.000000,0.000000,1.003779,-32.74998,-1.298655)"
+ x1="10.878086"
+ y1="4.5492039"
+ x2="39.857029"
+ y2="36.873619" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#greylighttograyw"
+ id="linearGradient1591"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.068635,-0.180647,0.153793,0.909776,-23.61859,31.63539)"
+ spreadMethod="reflect"
+ x1="139.84422"
+ y1="169.79622"
+ x2="159.03880"
+ y2="203.17725" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#orangelesstoyelow"
+ id="linearGradient1593"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.008016,-3.957640e-17,-8.345152e-17,0.992047,59.09612,34.16495)"
+ spreadMethod="reflect"
+ x1="139.79741"
+ y1="100.63807"
+ x2="198.67084"
+ y2="227.49260" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#orangetoblackorange"
+ id="linearGradient1595"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.994153,1.005881)"
+ x1="211.31139"
+ y1="208.29716"
+ x2="186.14693"
+ y2="101.48473" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="linearGradient1597"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.918796,-4.448298e-7,2.186431e-9,1.088383,-31.71369,41.04076)"
+ x1="130.94159"
+ y1="136.24300"
+ x2="141.97820"
+ y2="119.97503" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="linearGradient1599"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.068635,-0.180647,0.153793,0.909776,-23.61859,31.63539)"
+ x1="121.55471"
+ y1="169.77112"
+ x2="130.17465"
+ y2="182.88293" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="linearGradient1601"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.068635,-0.180647,0.153793,0.909776,-5.706373e-15,-6.128776e-15)"
+ x1="111.31033"
+ y1="198.13455"
+ x2="135.19012"
+ y2="235.01132" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light100to0"
+ id="radialGradient1603"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.952120,-0.160951,0.172613,1.021109,-23.61859,31.63539)"
+ cx="140.60791"
+ cy="183.52762"
+ fx="140.60791"
+ fy="183.52762"
+ r="8.2203732" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#light100to0"
+ id="radialGradient1605"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.952120,-0.160951,0.172613,1.021109,-23.57515,31.60495)"
+ cx="124.97867"
+ cy="166.89621"
+ fx="124.97867"
+ fy="166.89621"
+ r="4.5374427" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="radialGradient1607"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.917031,-0.155019,0.179218,1.060181,-23.61859,31.63539)"
+ cx="130.43364"
+ cy="187.24419"
+ fx="130.40277"
+ fy="187.29732"
+ r="13.523715" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="radialGradient1609"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.277707,-1.314622,0.656307,0.494064,-23.61859,31.63539)"
+ spreadMethod="reflect"
+ cx="-36.280697"
+ cy="224.72163"
+ fx="-36.269680"
+ fy="224.71202"
+ r="14.292608" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#sadow75to0w"
+ id="linearGradient1611"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.919303,-5.848951e-16,-9.825667e-17,1.087781,-31.65752,40.91072)"
+ spreadMethod="reflect"
+ x1="131.99300"
+ y1="129.27406"
+ x2="134.97223"
+ y2="132.72443" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="linearGradient1613"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.919303,-5.848951e-16,-9.825667e-17,1.087781,-31.65752,40.91072)"
+ x1="132.47713"
+ y1="128.17326"
+ x2="138.51009"
+ y2="135.55878" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="radialGradient1615"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.917031,-0.155019,0.179218,1.060181,-23.61859,31.63539)"
+ cx="130.43364"
+ cy="187.24419"
+ fx="130.40277"
+ fy="187.29732"
+ r="13.523715" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="radialGradient1617"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.917031,-0.155019,0.179218,1.060181,-23.61859,31.63539)"
+ cx="130.43364"
+ cy="187.24419"
+ fx="130.40277"
+ fy="187.29732"
+ r="13.523715" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="radialGradient1619"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.917031,-0.155019,0.179218,1.060181,-23.61859,31.63539)"
+ cx="130.43364"
+ cy="187.24419"
+ fx="130.40277"
+ fy="187.29732"
+ r="13.523715" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="radialGradient1621"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.917031,-0.155019,0.179218,1.060181,-23.61859,31.63539)"
+ cx="130.43364"
+ cy="187.24419"
+ fx="130.40277"
+ fy="187.29732"
+ r="13.523715" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="radialGradient1623"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.917031,-0.155019,0.179218,1.060181,-23.61859,31.63539)"
+ cx="130.43364"
+ cy="187.24419"
+ fx="130.40277"
+ fy="187.29732"
+ r="13.523715" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="linearGradient1625"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.889037,1.124812)"
+ spreadMethod="reflect"
+ x1="239.13113"
+ y1="150.76836"
+ x2="219.65416"
+ y2="118.38348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light100to0"
+ id="linearGradient1627"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(1.205925,0.829239)"
+ x1="165.24026"
+ y1="140.82243"
+ x2="166.34229"
+ y2="163.71248" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="linearGradient1629"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.889037,1.124812)"
+ spreadMethod="reflect"
+ x1="239.13113"
+ y1="150.76836"
+ x2="219.65416"
+ y2="118.38348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="linearGradient1631"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.889037,1.124812)"
+ spreadMethod="reflect"
+ x1="239.13113"
+ y1="150.76836"
+ x2="219.65416"
+ y2="118.38348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#zerotowhitetozero"
+ id="linearGradient1633"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="scale(0.889037,1.124812)"
+ spreadMethod="reflect"
+ x1="239.13113"
+ y1="150.76836"
+ x2="219.65416"
+ y2="118.38348" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#light90to0"
+ id="linearGradient1683"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.996235,0.000000,0.000000,1.003779,-32.74998,-1.298655)"
+ x1="10.878086"
+ y1="4.5492039"
+ x2="39.857029"
+ y2="36.873619" />
+ <linearGradient
+ y2="118.38348"
+ x2="219.65416"
+ y1="150.76836"
+ x1="239.13113"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.319331,-7.293299e-2,9.428053e-2,0.413393,-13.56014,-24.84285)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1521"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="118.38348"
+ x2="219.65416"
+ y1="150.76836"
+ x1="239.13113"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.319331,-7.293299e-2,9.428053e-2,0.413393,-13.56014,-24.84285)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1524"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="118.38348"
+ x2="219.65416"
+ y1="150.76836"
+ x1="239.13113"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.319331,-7.293299e-2,9.428053e-2,0.413393,-13.56014,-24.84285)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1527"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="163.71248"
+ x2="166.34229"
+ y1="140.82243"
+ x1="165.24026"
+ gradientTransform="matrix(0.433153,-9.892919e-2,6.950592e-2,0.304764,-13.56014,-24.84285)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1530"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="118.38348"
+ x2="219.65416"
+ y1="150.76836"
+ x1="239.13113"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.319331,-7.293299e-2,9.428053e-2,0.413393,-13.56014,-24.84285)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1533"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <radialGradient
+ r="13.523715"
+ fy="187.29732"
+ fx="130.40277"
+ cy="187.24419"
+ cx="130.43364"
+ gradientTransform="matrix(0.316392,-0.132202,0.153236,0.374938,-39.39199,-11.27857)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1538"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <radialGradient
+ r="13.523715"
+ fy="187.29732"
+ fx="130.40277"
+ cy="187.24419"
+ cx="130.43364"
+ gradientTransform="matrix(0.316392,-0.132202,0.153236,0.374938,-39.39199,-11.27857)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1541"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <radialGradient
+ r="13.523715"
+ fy="187.29732"
+ fx="130.40277"
+ cy="187.24419"
+ cx="130.43364"
+ gradientTransform="matrix(0.316392,-0.132202,0.153236,0.374938,-39.39199,-11.27857)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1544"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <radialGradient
+ r="13.523715"
+ fy="187.29732"
+ fx="130.40277"
+ cy="187.24419"
+ cx="130.43364"
+ gradientTransform="matrix(0.316392,-0.132202,0.153236,0.374938,-39.39199,-11.27857)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1547"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <radialGradient
+ r="13.523715"
+ fy="187.29732"
+ fx="130.40277"
+ cy="187.24419"
+ cx="130.43364"
+ gradientTransform="matrix(0.316392,-0.132202,0.153236,0.374938,-39.39199,-11.27857)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1550"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="135.55878"
+ x2="138.51009"
+ y1="128.17326"
+ x1="132.47713"
+ gradientTransform="matrix(0.339274,-2.885214e-16,-7.500068e-18,0.409774,-35.72368,-9.866746)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1553"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="132.72443"
+ x2="134.97223"
+ y1="129.27406"
+ x1="131.99300"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.339274,-2.885214e-16,-7.500068e-18,0.409774,-35.72368,-9.866746)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1556"
+ xlink:href="#sadow75to0w"
+ inkscape:collect="always" />
+ <radialGradient
+ r="14.292608"
+ fy="224.71202"
+ fx="-36.269680"
+ cy="224.72163"
+ cx="-36.280697"
+ spreadMethod="reflect"
+ gradientTransform="matrix(-1.044145e-2,-0.505934,0.277149,0.127739,-39.39199,-11.27857)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1559"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <radialGradient
+ r="13.523715"
+ fy="187.29732"
+ fx="130.40277"
+ cy="187.24419"
+ cx="130.43364"
+ gradientTransform="matrix(0.316392,-0.132202,0.153236,0.374938,-39.39199,-11.27857)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1562"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <radialGradient
+ r="4.5374427"
+ fy="166.89621"
+ fx="124.97867"
+ cy="166.89621"
+ cx="124.97867"
+ gradientTransform="matrix(0.328498,-0.137261,0.147589,0.361120,-39.37893,-11.29333)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1565"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <radialGradient
+ r="8.2203732"
+ fy="183.52762"
+ fx="140.60791"
+ cy="183.52762"
+ cx="140.60791"
+ gradientTransform="matrix(0.328498,-0.137261,0.147589,0.361120,-39.39199,-11.27857)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient1568"
+ xlink:href="#light100to0"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="235.01132"
+ x2="135.19012"
+ y1="198.13455"
+ x1="111.31033"
+ gradientTransform="matrix(0.368698,-0.154058,0.131497,0.321746,-33.56014,-24.84285)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1571"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="182.88293"
+ x2="130.17465"
+ y1="169.77112"
+ x1="121.55471"
+ gradientTransform="matrix(0.368698,-0.154058,0.131497,0.321746,-39.39199,-11.27857)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1574"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="119.97503"
+ x2="141.97820"
+ y1="136.24300"
+ x1="130.94159"
+ gradientTransform="matrix(0.339102,-1.675700e-7,8.069510e-10,0.410000,-35.78877,-9.716957)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1577"
+ xlink:href="#zerotowhitetozero"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="227.49260"
+ x2="198.67084"
+ y1="100.63807"
+ x1="139.79741"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.362066,-8.269354e-2,8.315231e-2,0.364599,-9.469913,-17.13449)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1581"
+ xlink:href="#orangelesstoyelow"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="101.48473"
+ x2="186.14693"
+ y1="208.29716"
+ x1="211.31139"
+ gradientTransform="matrix(0.357087,-8.155628e-2,8.431186e-2,0.369683,-33.56014,-24.84285)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1583"
+ xlink:href="#orangetoblackorange"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="203.17725"
+ x2="159.03880"
+ y1="169.79622"
+ x1="139.84422"
+ spreadMethod="reflect"
+ gradientTransform="matrix(0.368698,-0.154058,0.131497,0.321746,-39.39199,-11.27857)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient1587"
+ xlink:href="#greylighttograyw"
+ inkscape:collect="always" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="5.6562500"
+ inkscape:cx="32.000000"
+ inkscape:cy="28.069417"
+ inkscape:current-layer="svg17707"
+ showgrid="false"
+ inkscape:document-units="px"
+ inkscape:grid-bbox="true"
+ inkscape:window-width="1020"
+ inkscape:window-height="691"
+ inkscape:window-x="0"
+ inkscape:window-y="0" />
+ <metadata
+ id="metadata4">
+ <rdf:RDF
+ id="RDF5">
+ <cc:Work
+ rdf:about=""
+ id="Work6">
+ <dc:format
+ id="format7">image/svg+xml</dc:format>
+ <dc:type
+ id="type9"
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="g1508"
+ transform="matrix(0.941176,0.000000,0.000000,0.928006,27.63182,14.26213)">
+ <path
+ id="rect7971"
+ d="M -22.672010,-0.29866329 L 15.954371,-0.29866329 C 17.996863,-0.29866329 19.641180,1.8444887 19.641180,4.5066107 L 19.641180,42.413492 C 19.641180,45.075614 17.996863,47.218766 15.954371,47.218766 L -22.672010,47.218766 C -24.714502,47.218766 -26.358819,45.075614 -26.358819,42.413492 L -26.358819,4.5066107 C -26.358819,1.8444887 -24.714502,-0.29866329 -22.672010,-0.29866329 z "
+ style="opacity:0.79446638;fill:#0028c6;fill-opacity:0.18099548;stroke:#000000;stroke-width:0.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.035294119" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path8746"
+ d="M -22.063169,0.70133671 L 16.563212,0.70133671 C 18.221266,26.074276 -6.9124940,11.860590 -25.749978,43.413492 L -25.749978,5.5066107 C -25.749978,2.8444887 -24.105661,0.70133671 -22.063169,0.70133671 z "
+ style="opacity:0.79446638;fill:url(#linearGradient1683);fill-opacity:1.0000000;stroke:#000000;stroke-width:0.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:0.035294119" />
+ <path
+ id="path7697"
+ d="M -27.017489,-2.3989893 C -27.634507,-2.4157123 -28.231851,-2.1778653 -28.673074,-1.7397773 C -29.114296,-1.3016903 -29.361708,-0.70078429 -29.358794,-0.074320286 L -29.358794,7.2871317 C -29.358794,8.5710117 -28.333344,9.6118007 -27.068387,9.6118007 C -25.803430,9.6118007 -24.777980,8.5710117 -24.777980,7.2871317 L -24.777980,2.2761787 L -23.047450,2.3020077 C -22.210634,2.3584147 -21.410841,1.9440847 -20.964931,1.2231677 C -20.519022,0.50225171 -20.498961,-0.40890429 -20.912697,-1.1493183 C -21.326432,-1.8897313 -22.107191,-2.3399103 -22.945654,-2.3215003 L -27.017489,-2.3989893 z "
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path7695"
+ d="M 4.7173740,-2.3996693 C 3.4524170,-2.4139343 2.4155730,-1.3847093 2.4015180,-0.10083029 C 2.3874630,1.1830497 3.4015190,2.2354037 4.6664760,2.2496687 L 14.362533,2.3788167 C 15.201936,2.4293217 16.000613,2.0068887 16.440691,1.2796477 C 16.880768,0.55240471 16.890831,-0.36162729 16.466873,-1.0986683 C 16.042914,-1.8357073 15.253736,-2.2761473 14.413431,-2.2446913 L 4.7173740,-2.3996693 z "
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccccc"
+ id="path1937"
+ d="M 19.325083,2.8678727 C 18.716776,2.8719947 18.135305,3.1226217 17.709963,3.5640277 C 17.284621,4.0054337 17.050668,4.6010267 17.060125,5.2183717 L 17.060125,15.059471 C 17.060125,16.343351 18.085575,17.384140 19.350532,17.384140 C 20.615489,17.384140 21.640939,16.343351 21.640939,15.059471 L 21.640939,5.2183717 C 21.650596,4.5920277 21.409706,3.9884577 20.973288,3.5455107 C 20.536870,3.1025647 19.942196,2.8580717 19.325083,2.8678727 L 19.325083,2.8678727 z "
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path4304"
+ d="M 17.469045,15.629181 C 18.413100,15.815021 18.857757,12.747829 18.787749,8.0727497 C 18.730382,4.3058467 20.289306,5.8257017 20.406837,3.7850817 C 20.424951,3.4705687 20.006991,3.3070317 19.501480,3.3228087 C 18.995969,3.3385857 18.402909,3.5336767 18.070823,3.9364157 C 17.881055,4.0953987 17.733643,4.3228087 17.633611,4.5892757 C 17.533580,4.8557427 17.480928,5.1612677 17.480686,5.4764867 C 17.480443,5.7917047 17.470985,13.110517 17.469045,15.629181 z "
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path4306"
+ d="M 18.559674,14.805816 C 18.551108,15.772956 19.169111,16.565687 19.940024,16.576434 C 20.710936,16.587180 21.342828,15.811869 21.351393,14.844730 L 21.428941,5.1347497 C 21.459268,4.4929737 21.205614,3.8823327 20.768938,3.5458657 C 20.332262,3.2094007 19.783427,3.2017067 19.340866,3.5258487 C 18.898307,3.8499917 18.633842,4.4533697 18.652730,5.0958337 L 18.559674,14.805816 z "
+ style="opacity:0.79446638;fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path7691"
+ d="M 19.325083,37.172044 C 18.716776,37.176166 18.135305,37.426793 17.709963,37.868200 C 17.284621,38.309605 17.050668,38.905198 17.060125,39.522543 L 17.060125,44.636815 L 15.278697,44.636815 C 14.013740,44.636815 12.988290,45.677605 12.988290,46.961484 C 12.988290,48.245364 14.013740,49.286153 15.278697,49.286153 L 19.350532,49.286153 C 19.958797,49.288854 20.542918,49.044801 20.973031,48.608254 C 21.403144,48.171707 21.643600,47.578848 21.640939,46.961484 L 21.640939,39.522543 C 21.650596,38.896199 21.409706,38.292629 20.973288,37.849682 C 20.536870,37.406736 19.942196,37.162243 19.325083,37.172044 z "
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path7751"
+ d="M -20.276241,44.557850 C -21.426599,44.557629 -22.359001,45.598301 -22.358820,46.882257 C -22.358640,48.166214 -21.425944,49.207246 -20.275587,49.207467 L -11.457752,49.228967 C -10.693981,49.270151 -9.9720160,48.838877 -9.5791980,48.106796 C -9.1863820,47.374712 -9.1864600,46.460625 -9.5794010,45.728336 C -9.9723420,44.996049 -10.694380,44.564397 -11.458145,44.605179 L -20.276241,44.557850 z "
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccccc"
+ id="path7775"
+ d="M -27.015658,12.745151 C -27.623965,12.748858 -28.205436,12.974268 -28.630778,13.371262 C -29.056120,13.768256 -29.290073,14.303923 -29.280616,14.859155 L -29.280616,23.710092 C -29.280616,24.864795 -28.255166,25.800865 -26.990209,25.800865 C -25.725252,25.800865 -24.699802,24.864795 -24.699802,23.710092 L -24.699802,14.859155 C -24.690145,14.295830 -24.931035,13.752988 -25.367452,13.354609 C -25.803871,12.956229 -26.398545,12.736336 -27.015658,12.745151 L -27.015658,12.745151 z "
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccccc"
+ id="path7781"
+ d="M -27.015658,30.753110 C -27.623965,30.756942 -28.205436,30.989917 -28.630778,31.400235 C -29.056120,31.810552 -29.290073,32.364197 -29.280616,32.938062 L -29.280616,42.086048 C -29.280616,43.279504 -28.255166,44.246990 -26.990209,44.246990 C -25.725252,44.246990 -24.699802,43.279504 -24.699802,42.086048 L -24.699802,32.938062 C -24.690145,32.355832 -24.931035,31.794772 -25.367452,31.383022 C -25.803871,30.971273 -26.398545,30.743999 -27.015658,30.753110 L -27.015658,30.753110 z "
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccccc"
+ id="path20031"
+ d="M 19.186414,18.552305 C 18.578107,18.556137 17.996636,18.789112 17.571294,19.199430 C 17.145953,19.609747 16.912000,20.163392 16.921456,20.737257 L 16.921456,29.885243 C 16.921456,31.078699 17.946906,32.046185 19.211863,32.046185 C 20.476820,32.046185 21.502270,31.078699 21.502270,29.885243 L 21.502270,20.737257 C 21.511927,20.155027 21.271037,19.593967 20.834620,19.182217 C 20.398201,18.770468 19.803527,18.543194 19.186414,18.552305 L 19.186414,18.552305 z "
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path20029"
+ d="M -2.2762410,44.557850 C -3.4265990,44.557629 -4.3590010,45.598301 -4.3588200,46.882257 C -4.3586390,48.166214 -3.4259440,49.207246 -2.2755870,49.207467 L 6.5422480,49.228967 C 7.3060190,49.270151 8.0279840,48.838877 8.4208020,48.106796 C 8.8136180,47.374712 8.8135400,46.460625 8.4205990,45.728336 C 8.0276580,44.996049 7.3056200,44.564397 6.5418550,44.605179 L -2.2762410,44.557850 z "
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path20033"
+ d="M -14.276241,-2.4376393 C -15.426599,-2.4378603 -16.359001,-1.3971883 -16.358820,-0.11323229 C -16.358639,1.1707247 -15.425944,2.2117567 -14.275587,2.2119777 L -5.4577520,2.2334777 C -4.6939810,2.2746617 -3.9720160,1.8433877 -3.5791980,1.1113067 C -3.1863820,0.37922271 -3.1864600,-0.53486429 -3.5794010,-1.2671533 C -3.9723420,-1.9994403 -4.6943800,-2.4310923 -5.4581450,-2.3903103 L -14.276241,-2.4376393 z "
+ style="fill:#343435;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:5.5999999;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ </g>
+ <g
+ transform="matrix(0.138177,0.000000,0.000000,0.138257,87.66417,90.01531)"
+ id="g13710">
+ <path
+ id="path11931"
+ d="M -339.87500,-562.53125 C -348.58569,-560.19181 -352.59558,-550.93590 -359.43799,-545.70947 C -400.13675,-505.05011 -440.77483,-464.31985 -480.90625,-423.12500 C -488.18544,-410.84910 -488.57103,-394.62620 -500.21875,-385.09375 C -512.57969,-368.83179 -493.71621,-341.25818 -474.03125,-348.46875 C -462.87531,-352.89885 -454.65140,-363.31654 -442.27737,-364.87405 C -422.26991,-370.77618 -410.50805,-389.32181 -395.67326,-402.58313 C -357.90771,-440.29554 -320.13784,-478.00363 -282.37500,-515.71875 C -304.24739,-521.94254 -323.63528,-537.78263 -331.84375,-559.21875 C -333.74226,-561.73503 -336.74020,-563.06552 -339.87500,-562.53125 z "
+ style="fill:url(#linearGradient13735);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.12500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path9921"
+ d="M -248.21875,-651.00000 C -272.98861,-648.93037 -291.28010,-629.68275 -305.01089,-610.67441 C -309.74512,-604.20687 -315.77838,-598.30024 -323.87075,-596.72703 C -333.71425,-591.10503 -341.85744,-582.42201 -348.40590,-573.28134 C -356.94664,-559.26149 -347.65041,-543.09265 -338.40023,-532.09521 C -325.64008,-517.98152 -310.00267,-502.74422 -289.90668,-501.76041 C -276.01725,-502.20182 -266.41769,-514.40996 -257.37500,-523.56250 C -253.67156,-531.93631 -250.48772,-541.23540 -242.11203,-546.09451 C -225.14025,-560.83248 -205.84726,-576.48649 -201.47173,-599.85041 C -196.42613,-618.96398 -206.88605,-640.92302 -225.80992,-647.67024 C -232.89201,-650.60139 -240.61145,-651.32708 -248.21875,-651.00000 z "
+ style="fill:url(#linearGradient13737);fill-opacity:1.0000000;stroke:none;stroke-width:0.85625488;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" />
+ <g
+ transform="matrix(12.73027,0.137313,-0.136532,12.81415,7258.558,2532.625)"
+ id="g9797">
+ <path
+ sodipodi:nodetypes="csccccsss"
+ id="path1748"
+ d="M -592.17375,-241.34258 C -593.22346,-241.27560 -593.89434,-240.80940 -594.54434,-240.26028 C -596.02721,-239.00754 -596.59699,-237.07947 -597.79980,-237.13371 C -598.41374,-236.45764 -598.16875,-235.86990 -597.94968,-235.36640 C -597.14476,-234.02668 -596.25974,-233.23302 -595.17964,-232.76588 C -594.79886,-232.65612 -593.80858,-232.70213 -593.38704,-233.02313 C -593.17176,-234.17444 -592.02724,-234.45349 -590.47137,-236.07679 C -589.39077,-237.20372 -589.00732,-238.90820 -589.39094,-239.80855 C -589.72572,-240.59428 -590.59454,-241.44334 -592.17375,-241.34258 z "
+ style="fill:url(#linearGradient13739);fill-opacity:1.0000000;stroke:url(#linearGradient13741);stroke-width:0.033576056;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path1750"
+ d="M -595.92745,-235.45451 C -594.37002,-236.99404 -592.53504,-238.28074 -590.97762,-239.82027 C -589.95578,-239.82640 -589.36868,-238.72428 -589.80124,-237.37356 C -591.48098,-235.57587 -593.09300,-233.31300 -594.77274,-231.51531 C -594.17986,-233.13605 -595.03454,-235.13095 -595.92745,-235.45451 z "
+ style="opacity:0.41897234;fill:url(#linearGradient13743);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="czzzzzz"
+ id="path1752"
+ d="M -592.10692,-241.16843 C -591.40492,-241.26355 -591.32655,-241.23523 -591.06938,-241.09419 C -590.81221,-240.95314 -591.11699,-240.25114 -591.90772,-239.88474 C -592.67827,-239.52769 -593.36149,-237.64481 -594.74329,-237.47336 C -596.11739,-237.30286 -595.89714,-238.63489 -595.53650,-239.03881 C -595.18712,-239.43012 -594.27429,-240.23331 -593.84394,-240.47127 C -593.41931,-240.70606 -592.82833,-241.07069 -592.10692,-241.16843 z "
+ style="fill:url(#linearGradient13745);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path1754"
+ d="M -595.92745,-235.45451 C -594.37002,-236.99404 -593.56775,-237.21078 -592.01032,-238.75031 C -590.98849,-238.75644 -590.40138,-237.65432 -590.83394,-236.30360 C -592.51368,-234.50591 -593.09300,-233.31300 -594.77274,-231.51531 C -594.17986,-233.13605 -595.03454,-235.13095 -595.92745,-235.45451 z "
+ style="opacity:0.41897234;fill:url(#linearGradient13747);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path1756"
+ d="M -595.92745,-235.45451 C -594.37002,-236.99404 -594.90821,-235.82047 -593.35079,-237.35999 C -592.32895,-237.36613 -591.74185,-236.26401 -592.17441,-234.91328 C -593.85415,-233.11560 -593.09300,-233.31300 -594.77274,-231.51531 C -594.17986,-233.13605 -595.03454,-235.13095 -595.92745,-235.45451 z "
+ style="opacity:0.41897234;fill:url(#linearGradient13749);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path1758"
+ d="M -595.92745,-235.45451 C -594.37002,-236.99404 -595.54420,-235.17339 -593.98678,-236.71291 C -592.96494,-236.71905 -592.37784,-235.61693 -592.81040,-234.26620 C -594.49013,-232.46852 -593.09300,-233.31300 -594.77274,-231.51531 C -594.17986,-233.13605 -595.03454,-235.13095 -595.92745,-235.45451 z "
+ style="opacity:0.41897234;fill:url(#linearGradient13751);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="ccccccs"
+ id="path6419"
+ d="M -598.04283,-237.04726 C -599.64965,-235.44966 -598.06711,-237.06765 -599.21142,-235.88808 C -599.90549,-235.07201 -599.58991,-234.87256 -599.32823,-234.27747 C -598.37632,-232.69822 -597.34248,-231.77031 -596.09022,-231.23464 C -595.64978,-231.11115 -595.36127,-230.95227 -594.88202,-231.34218 C -594.29993,-231.75702 -593.40557,-232.48954 -593.34014,-232.94032 C -593.48708,-235.38350 -597.20306,-237.88220 -598.04283,-237.04726 z "
+ style="fill:url(#linearGradient13753);fill-opacity:1.0000000;stroke:url(#linearGradient13755);stroke-width:0.28321710;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path5651"
+ d="M -594.83596,-231.32818 C -595.31283,-230.78909 -596.74079,-231.30312 -598.02337,-232.47555 C -599.30595,-233.64799 -599.95985,-235.03705 -599.48298,-235.57614 C -599.00611,-236.11522 -597.57815,-235.60120 -596.29557,-234.42876 C -595.02037,-233.26307 -594.36566,-231.88358 -594.82825,-231.33709"
+ style="fill:url(#linearGradient13757);fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path6517"
+ d="M -594.66112,-235.43807 L -595.92818,-234.21440 C -594.94605,-233.30894 -594.45796,-232.19443 -594.62336,-231.63361 C -594.12081,-232.00805 -593.47462,-232.56507 -593.42247,-232.92577 C -593.47512,-233.79970 -593.95290,-234.74821 -594.66112,-235.43807 z "
+ style="opacity:0.73015875;fill:url(#linearGradient13759);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.98446530;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="ccccc"
+ id="path7315"
+ d="M -595.46050,-236.18333 L -596.78454,-234.92355 C -597.77066,-235.58294 -598.53599,-235.94106 -599.09873,-235.79328 C -598.72302,-236.24221 -597.91973,-237.05870 -597.55778,-237.10530 C -596.68084,-237.05831 -596.19549,-236.74487 -595.46050,-236.18333 z "
+ style="opacity:0.73015875;fill:url(#linearGradient13761);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.98446530;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" />
+ </g>
+ <path
+ id="path1764"
+ d="M -339.32166,-551.95970 C -382.78973,-508.61018 -426.81257,-464.54870 -470.28066,-421.19906 C -470.43182,-421.04413 -473.78890,-417.69517 -476.55621,-410.43436 C -479.32350,-403.17344 -479.02460,-390.86160 -490.01618,-382.02809 C -497.33019,-374.47909 -495.26066,-368.35934 -491.76389,-363.58610 C -491.36478,-363.04133 -490.65745,-362.46620 -489.99979,-361.88702 C -489.43559,-361.23028 -488.87612,-360.52324 -488.34384,-360.12322 C -483.62117,-356.57401 -477.54940,-354.45043 -469.99067,-361.75167 C -461.12879,-372.74156 -448.88647,-372.35503 -441.64599,-375.08672 C -434.40563,-377.81843 -431.05157,-381.17043 -430.89644,-381.32134 C -387.48067,-424.72396 -343.35307,-468.67938 -299.93744,-512.08199 C -307.05399,-513.84754 -315.89647,-520.64189 -323.38771,-528.24674 C -330.90736,-535.83660 -337.61384,-544.78511 -339.32166,-551.95970 z "
+ style="fill:url(#linearGradient13763);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.12500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="csccscc"
+ id="path1766"
+ d="M -495.37743,-406.53835 C -481.21007,-420.86199 -464.97412,-419.04773 -452.14935,-409.73688 C -441.34327,-401.89166 -430.14316,-385.12729 -443.54787,-372.03886 C -395.77769,-419.56762 -347.79937,-467.20985 -300.02932,-514.73862 C -286.38154,-526.57788 -300.98631,-543.98334 -311.74429,-552.47020 C -324.11576,-562.23008 -342.60016,-558.10199 -355.83435,-545.79655 C -403.15898,-498.53499 -448.05305,-453.79991 -495.37743,-406.53835 z "
+ style="fill:url(#linearGradient13765);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cscsssc"
+ id="path1768"
+ d="M -493.10005,-374.87492 C -493.57266,-372.95073 -493.09468,-366.78198 -491.01745,-366.84264 C -489.43933,-366.88872 -479.82570,-377.34365 -477.84450,-379.61428 C -469.44438,-392.18875 -469.36414,-391.96639 -468.53678,-393.70297 C -464.68311,-401.79166 -468.20899,-419.41442 -469.92379,-418.19158 C -476.03754,-413.83136 -477.10397,-398.38072 -480.10969,-392.79552 C -485.20251,-383.33248 -491.06725,-380.00026 -493.10005,-374.87492 z "
+ style="fill:url(#radialGradient13767);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.12500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cccccccccc"
+ id="path7323"
+ d="M -475.55038,-416.99830 C -477.17707,-414.90674 -476.79082,-415.97951 -477.47661,-412.69167 C -481.95615,-403.22812 -479.93980,-393.13162 -490.93140,-384.29811 C -498.24541,-376.74909 -496.16644,-370.64003 -492.66976,-365.86679 C -489.69675,-361.80861 -480.25137,-355.90923 -475.00373,-360.94411 C -465.14299,-370.02706 -456.51435,-370.70143 -448.09371,-373.67453 C -444.36401,-374.55474 -440.66645,-376.12426 -437.27104,-378.75434 C -436.90023,-379.12276 -436.48786,-379.53630 -436.11640,-379.90549 C -437.60471,-399.57405 -447.70609,-413.03581 -471.63246,-419.51857 L -475.55038,-416.99830 z "
+ style="opacity:0.82010579;fill:url(#radialGradient13769);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.12500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="cscsssc"
+ id="path7348"
+ d="M -474.83322,-388.39078 C -476.01087,-386.84563 -480.96758,-383.59885 -482.15275,-385.41357 C -483.05322,-386.79221 -480.83030,-401.22078 -480.28436,-404.26295 C -475.73657,-418.90872 -475.95245,-418.84558 -475.12727,-420.58325 C -471.28320,-428.67721 -455.84248,-436.10260 -455.75271,-433.90950 C -455.43244,-426.09005 -466.50583,-416.01969 -468.95565,-410.13553 C -473.10646,-400.16598 -472.15504,-393.16913 -474.83322,-388.39078 z "
+ style="fill:url(#radialGradient13771);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:0.12500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+ <g
+ transform="matrix(0.640718,0.741394,-0.737351,0.644231,-294.5805,92.05109)"
+ id="g11960">
+ <path
+ id="path8110"
+ d="M -471.76248,-159.41569 C -471.64802,-157.09303 -475.56651,-155.04421 -480.50909,-154.84260 C -485.45184,-154.64099 -489.55616,-156.36237 -489.67069,-158.68512 C -489.78530,-161.00777 -485.86674,-163.05651 -480.92408,-163.25821 C -476.00985,-163.45872 -471.92297,-161.76114 -471.76473,-159.45371"
+ style="fill:url(#linearGradient13773);fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" />
+ <path
+ id="path8872"
+ d="M -471.76248,-159.41569 C -471.64802,-157.09303 -475.56651,-155.04421 -480.50909,-154.84260 C -485.45184,-154.64099 -489.55616,-156.36237 -489.67069,-158.68512 C -489.78530,-161.00777 -485.86674,-163.05651 -480.92408,-163.25821 C -476.00985,-163.45872 -471.92297,-161.76114 -471.76473,-159.45371"
+ style="opacity:0.82539684;fill:url(#linearGradient13775);fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccccccc"
+ id="rect8885"
+ d="M -314.54660,-554.44188 L -450.62838,-418.21806 C -451.87637,-416.97490 -454.02554,-416.25114 -455.44711,-416.59531 L -471.72399,-420.53638 C -473.14554,-420.88055 -473.28516,-422.15854 -472.03718,-423.40168 L -337.95342,-556.96545 C -333.51612,-561.13237 -324.94522,-561.52186 -314.54660,-554.44188 z "
+ style="fill:url(#linearGradient13777);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" />
+ <path
+ sodipodi:nodetypes="ccccccccccccccccczc"
+ id="path1776"
+ d="M -329.21748,-562.35117 C -330.45222,-561.11966 -340.77595,-550.82916 -342.01159,-549.59663 C -342.14833,-549.47457 -342.30382,-549.39708 -342.43874,-549.27187 C -385.90684,-505.92222 -427.38447,-464.78249 -470.85256,-421.43284 C -470.04383,-422.23842 -469.17510,-422.77969 -468.34027,-423.45742 C -468.64503,-423.15343 -468.95453,-422.84526 -469.25928,-422.54127 C -469.41035,-422.38623 -472.76550,-419.00078 -475.53281,-411.73997 C -478.30010,-404.47915 -480.44060,-391.72189 -488.98829,-383.37089 C -496.30242,-375.82187 -494.22344,-369.71279 -490.72665,-364.93958 C -487.75378,-360.88139 -478.30838,-354.98201 -473.06074,-360.01701 C -463.19987,-369.09987 -454.57054,-369.74971 -446.15001,-372.72280 C -442.92489,-373.48392 -439.76128,-374.92319 -436.75859,-376.95683 C -437.22252,-376.44748 -437.59897,-375.88088 -438.09508,-375.39712 C -437.44655,-376.04153 -436.78692,-376.67809 -436.13839,-377.32249 C -435.87291,-377.51305 -435.58993,-377.62424 -435.32806,-377.82712 C -418.96187,-394.08837 -401.64184,-411.45948 -384.43034,-428.69342 C -358.40110,-454.53113 -292.29459,-520.42324 -293.00855,-520.58372 C -289.12326,-530.07515 -297.52097,-542.53858 -302.91252,-547.54876 C -308.41419,-552.66131 -319.61856,-562.78363 -329.21748,-562.35117 z "
+ style="opacity:0.079051383;fill:#000000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000" />
+ </g>
+</svg>
diff --git a/chalk/plugins/tools/tool_selectsimilar/tool_similar_selection_minus_cursor.png b/chalk/plugins/tools/tool_selectsimilar/tool_similar_selection_minus_cursor.png
new file mode 100644
index 00000000..e6b2da50
--- /dev/null
+++ b/chalk/plugins/tools/tool_selectsimilar/tool_similar_selection_minus_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_selectsimilar/tool_similar_selection_plus_cursor.png b/chalk/plugins/tools/tool_selectsimilar/tool_similar_selection_plus_cursor.png
new file mode 100644
index 00000000..d5a5e726
--- /dev/null
+++ b/chalk/plugins/tools/tool_selectsimilar/tool_similar_selection_plus_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_star/Makefile.am b/chalk/plugins/tools/tool_star/Makefile.am
new file mode 100644
index 00000000..11cab8a3
--- /dev/null
+++ b/chalk/plugins/tools/tool_star/Makefile.am
@@ -0,0 +1,37 @@
+kde_services_DATA = chalktoolstar.desktop
+
+# all_includes must remain last!
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalktoolstar_la_SOURCES = \
+ wdg_tool_star.ui \
+ tool_star.cc \
+ kis_tool_star.cc
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = chalktoolstar.la
+
+noinst_HEADERS = \
+ tool_star.h \
+ kis_tool_star.h
+
+chalktoolstar_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalktoolstar_la_LIBADD = ../../../libchalkcommon.la
+
+chalktoolstar_la_METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
+
+chalkpics_DATA = \
+ tool_star.png \
+ tool_star_cursor.png
+
+chalkpicsdir = $(kde_datadir)/chalk/pics
+
diff --git a/chalk/plugins/tools/tool_star/chalktoolstar.desktop b/chalk/plugins/tools/tool_star/chalktoolstar.desktop
new file mode 100644
index 00000000..546c0d97
--- /dev/null
+++ b/chalk/plugins/tools/tool_star/chalktoolstar.desktop
@@ -0,0 +1,52 @@
+[Desktop Entry]
+Name=Star Tool
+Name[bg]=Инструмент звезда
+Name[br]=Ostilh steredenn
+Name[ca]=Eina d'estrella
+Name[cy]=Erfyn Seren
+Name[da]=Stjerneværktøj
+Name[de]=Stern-Werkzeug
+Name[el]=Εργαλείο αστεριού
+Name[eo]=Stelo-ilo
+Name[es]=Herramienta Estrella
+Name[et]=Tähe tööriist
+Name[eu]=Izarra tresna
+Name[fa]=ابزار ستاره
+Name[fi]=Tähtityökalu
+Name[fr]=Outil étoile
+Name[fy]=Sjer-ark
+Name[ga]=Uirlis Réiltín
+Name[gl]=Ferramenta de Estrelas
+Name[he]=כלי כוכב
+Name[hu]=Csillag eszköz
+Name[is]=Stjörnutól
+Name[it]=Strumento stella
+Name[ja]=星型ツール
+Name[km]=ឧបករណ៍​រាង​ផ្កាយ
+Name[lt]=Žvaigždės įrankis
+Name[lv]=Zvaigznes rīks
+Name[ms]=Alat Bintang
+Name[nb]=Stjerneverktøy
+Name[nds]=Steern-Warktüüch
+Name[ne]=तारा उपकरण
+Name[nl]=Stergereedschap
+Name[nn]=Stjerneverktøy
+Name[pl]=Narzędzie do rysowania gwiazdki
+Name[pt]=Ferramenta de Estrelas
+Name[pt_BR]=Ferramenta Estrela
+Name[ru]=Звезда
+Name[se]=Nástereaidu
+Name[sk]=Hviezda
+Name[sl]=Zvezdno orodje
+Name[sr]=Алат за звезде
+Name[sr@Latn]=Alat za zvezde
+Name[sv]=Stjärnverktyg
+Name[uk]=Інструмент зірки
+Name[uz]=Yulduz vositasi
+Name[uz@cyrillic]=Юлдуз воситаси
+Name[zh_CN]=星形工具
+Name[zh_TW]=星形工具
+ServiceTypes=Chalk/Tool
+Type=Service
+X-KDE-Library=chalktoolstar
+X-Chalk-Version=2
diff --git a/chalk/plugins/tools/tool_star/kis_tool_star.cc b/chalk/plugins/tools/tool_star/kis_tool_star.cc
new file mode 100644
index 00000000..3a804f89
--- /dev/null
+++ b/chalk/plugins/tools/tool_star/kis_tool_star.cc
@@ -0,0 +1,245 @@
+/*
+ * kis_tool_star.cc -- part of Chalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <math.h>
+
+#include <tqpainter.h>
+#include <tqspinbox.h>
+#include <tqlayout.h>
+
+#include <kaction.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <knuminput.h>
+
+#include "kis_doc.h"
+#include "kis_view.h"
+#include "kis_painter.h"
+#include "kis_int_spinbox.h"
+#include "kis_canvas_subject.h"
+#include "kis_canvas_controller.h"
+#include "kis_button_press_event.h"
+#include "kis_button_release_event.h"
+#include "kis_move_event.h"
+#include "kis_paintop_registry.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+#include "kis_cursor.h"
+#include "kis_int_spinbox.h"
+
+#include "kis_tool_star.h"
+#include "wdg_tool_star.h"
+
+KisToolStar::KisToolStar()
+ : super(i18n("Star")),
+ m_dragging (false),
+ m_currentImage (0)
+{
+ setName("tool_star");
+ setCursor(KisCursor::load("tool_star_cursor.png", 6, 6));
+ m_innerOuterRatio=40;
+ m_vertices=5;
+}
+
+KisToolStar::~KisToolStar()
+{
+}
+
+void KisToolStar::update (KisCanvasSubject *subject)
+{
+ super::update (subject);
+ if (m_subject)
+ m_currentImage = m_subject->currentImg ();
+}
+
+void KisToolStar::buttonPress(KisButtonPressEvent *event)
+{
+ if (m_currentImage && event->button() == Qt::LeftButton) {
+ m_dragging = true;
+ m_dragStart = event->pos();
+ m_dragEnd = event->pos();
+ m_vertices = m_optWidget->verticesSpinBox->value();
+ m_innerOuterRatio = m_optWidget->ratioSpinBox->value();
+ }
+}
+
+void KisToolStar::move(KisMoveEvent *event)
+{
+ if (m_dragging) {
+ // erase old lines on canvas
+ draw(m_dragStart, m_dragEnd);
+ // move (alt) or resize star
+ if (event->state() & TQt::AltButton) {
+ KisPoint trans = event->pos() - m_dragEnd;
+ m_dragStart += trans;
+ m_dragEnd += trans;
+ } else {
+ m_dragEnd = event->pos();
+ }
+ // draw new lines on canvas
+ draw(m_dragStart, m_dragEnd);
+ }
+}
+
+void KisToolStar::buttonRelease(KisButtonReleaseEvent *event)
+{
+ if (!m_subject || !m_currentImage)
+ return;
+
+ if (m_dragging && event->button() == Qt::LeftButton) {
+ // erase old lines on canvas
+ draw(m_dragStart, m_dragEnd);
+ m_dragging = false;
+
+ if (m_dragStart == m_dragEnd)
+ return;
+
+ if (!m_currentImage)
+ return;
+
+ if (!m_currentImage->activeDevice())
+ return;
+
+ KisPaintDeviceSP device = m_currentImage->activeDevice ();;
+ KisPainter painter (device);
+ if (m_currentImage->undo()) painter.beginTransaction (i18n("Star"));
+
+ painter.setPaintColor(m_subject->fgColor());
+ painter.setBackgroundColor(m_subject->bgColor());
+ painter.setFillStyle(fillStyle());
+ painter.setBrush(m_subject->currentBrush());
+ painter.setPattern(m_subject->currentPattern());
+ painter.setOpacity(m_opacity);
+ painter.setCompositeOp(m_compositeOp);
+ KisPaintOp * op = KisPaintOpRegistry::instance()->paintOp(m_subject->currentPaintop(), m_subject->currentPaintopSettings(), &painter);
+ painter.setPaintOp(op); // Painter takes ownership
+
+ vKisPoint coord = starCoordinates(m_vertices, m_dragStart.x(), m_dragStart.y(), m_dragEnd.x(), m_dragEnd.y());
+
+ painter.paintPolygon(coord);
+
+ device->setDirty( painter.dirtyRect() );
+ notifyModified();
+
+ if (m_currentImage->undo()) {
+ m_currentImage->undoAdapter()->addCommand(painter.endTransaction());
+ }
+ }
+}
+
+void KisToolStar::draw(const KisPoint& start, const KisPoint& end )
+{
+ if (!m_subject || !m_currentImage)
+ return;
+
+ KisCanvasController *controller = m_subject->canvasController();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter p (canvas);
+ TQPen pen(TQt::SolidLine);
+
+ KisPoint startPos;
+ KisPoint endPos;
+ startPos = controller->windowToView(start);
+ endPos = controller->windowToView(end);
+
+ p.setRasterOp(TQt::NotROP);
+
+ vKisPoint points = starCoordinates(m_vertices, startPos.x(), startPos.y(), endPos.x(), endPos.y());
+
+ for (uint i = 0; i < points.count() - 1; i++) {
+ p.drawLine(points[i].floorTQPoint(), points[i + 1].floorTQPoint());
+ }
+ p.drawLine(points[points.count() - 1].floorTQPoint(), points[0].floorTQPoint());
+
+ p.end ();
+}
+
+void KisToolStar::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ KShortcut shortcut(TQt::Key_Plus);
+ shortcut.append(KShortcut(TQt::Key_F9));
+ m_action = new KRadioAction(i18n("&Star"),
+ "tool_star",
+ shortcut,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ Q_CHECK_PTR(m_action);
+
+ m_action->setToolTip(i18n("Draw a star"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+vKisPoint KisToolStar::starCoordinates(int N, double mx, double my, double x, double y)
+{
+ double R=0, r=0;
+ TQ_INT32 n=0;
+ double angle;
+
+ vKisPoint starCoordinatesArray(2*N);
+
+ // the radius of the outer edges
+ R=sqrt((x-mx)*(x-mx)+(y-my)*(y-my));
+
+ // the radius of the inner edges
+ r=R*m_innerOuterRatio/100.0;
+
+ // the angle
+ angle=-atan2((x-mx),(y-my));
+
+ //set outer edges
+ for(n=0;n<N;n++){
+ starCoordinatesArray[2*n] = KisPoint(mx+R*cos(n * 2.0 * M_PI / N + angle),my+R*sin(n *2.0 * M_PI / N+angle));
+ }
+
+ //set inner edges
+ for(n=0;n<N;n++){
+ starCoordinatesArray[2*n+1] = KisPoint(mx+r*cos((n + 0.5) * 2.0 * M_PI / N + angle),my+r*sin((n +0.5) * 2.0 * M_PI / N + angle));
+ }
+
+ return starCoordinatesArray;
+}
+
+TQWidget* KisToolStar::createOptionWidget(TQWidget* tqparent)
+{
+ TQWidget *widget = super::createOptionWidget(tqparent);
+
+ m_optWidget = new WdgToolStar(widget);
+ Q_CHECK_PTR(m_optWidget);
+
+ m_optWidget->ratioSpinBox->setValue(m_innerOuterRatio);
+
+ TQGridLayout *optionLayout = new TQGridLayout(widget, 1, 1);
+ super::addOptionWidgetLayout(optionLayout);
+
+ optionLayout->addWidget(m_optWidget, 0, 0);
+
+ return widget;
+}
+
+#include "kis_tool_star.moc"
diff --git a/chalk/plugins/tools/tool_star/kis_tool_star.h b/chalk/plugins/tools/tool_star/kis_tool_star.h
new file mode 100644
index 00000000..3bd8df2b
--- /dev/null
+++ b/chalk/plugins/tools/tool_star/kis_tool_star.h
@@ -0,0 +1,101 @@
+/*
+ * kis_tool_star.h - part of Chalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael Thaler@physik.tu-muenchen.de>
+ *
+ * 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_TOOL_STAR_H_
+#define KIS_TOOL_STAR_H_
+
+#include "kis_tool_shape.h"
+
+class KisCanvas;
+class KisDoc;
+class KisPainter;
+class KisView;
+class KisRect;
+class WdgToolStar;
+
+class KisToolStar : public KisToolShape {
+
+ typedef KisToolShape super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolStar();
+ virtual ~KisToolStar();
+
+ //
+ // KisCanvasObserver interface
+ //
+
+ virtual void update (KisCanvasSubject *subject);
+
+ virtual TQWidget* createOptionWidget(TQWidget* tqparent);
+
+ //
+ // KisToolPaint interface
+ //
+
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_SHAPE; }
+ virtual TQ_UINT32 priority() { return 6; }
+ virtual void buttonPress(KisButtonPressEvent *event);
+ virtual void move(KisMoveEvent *event);
+ virtual void buttonRelease(KisButtonReleaseEvent *event);
+
+protected:
+ virtual void draw(const KisPoint& start, const KisPoint& stop);
+ //virtual void draw(KisPainter *gc, const TQRect& rc);
+
+protected:
+ int m_lineThickness;
+
+ KisPoint m_dragStart;
+ KisPoint m_dragEnd;
+ TQRect m_final_lines;
+
+ bool m_dragging;
+ KisImageSP m_currentImage;
+private:
+ vKisPoint starCoordinates(int N, double mx, double my, double x, double y);
+ TQ_INT32 m_innerOuterRatio;
+ TQ_INT32 m_vertices;
+ WdgToolStar* m_optWidget;
+};
+
+
+#include "kis_tool_factory.h"
+
+class KisToolStarFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+public:
+ KisToolStarFactory() : super() {};
+ virtual ~KisToolStarFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolStar();
+ Q_CHECK_PTR(t);
+ t->setup(ac);
+ return t;
+ }
+ virtual KisID id() { return KisID("startqshape", i18n("Star Tool")); }
+};
+
+
+#endif //__KIS_TOOL_STAR_H__
diff --git a/chalk/plugins/tools/tool_star/tool_star.cc b/chalk/plugins/tools/tool_star/tool_star.cc
new file mode 100644
index 00000000..e399fafa
--- /dev/null
+++ b/chalk/plugins/tools/tool_star/tool_star.cc
@@ -0,0 +1,62 @@
+/*
+ * tool_star.cc -- Part of Chalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_tool_registry.h>
+
+#include "tool_star.h"
+#include "kis_tool_star.h"
+
+
+typedef KGenericFactory<ToolStar> ToolStarFactory;
+K_EXPORT_COMPONENT_FACTORY( chalktoolstar, ToolStarFactory( "chalk" ) )
+
+
+ToolStar::ToolStar(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ToolStarFactory::instance());
+
+ if ( tqparent->inherits("KisToolRegistry") )
+ {
+ KisToolRegistry * r = dynamic_cast<KisToolRegistry*>( tqparent );
+ r->add(new KisToolStarFactory());
+ }
+
+}
+
+ToolStar::~ToolStar()
+{
+}
+
+#include "tool_star.moc"
diff --git a/chalk/plugins/tools/tool_star/tool_star.h b/chalk/plugins/tools/tool_star/tool_star.h
new file mode 100644
index 00000000..36172dd6
--- /dev/null
+++ b/chalk/plugins/tools/tool_star/tool_star.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 TOOL_STAR_H_
+#define TOOL_STAR_H_
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+/**
+ * A module that provides a star tool.
+ */
+class ToolStar : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ ToolStar(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ToolStar();
+
+private:
+
+ KisView * m_view;
+
+};
+
+#endif // TOOL_STAR_H_
diff --git a/chalk/plugins/tools/tool_star/tool_star.png b/chalk/plugins/tools/tool_star/tool_star.png
new file mode 100644
index 00000000..c7627866
--- /dev/null
+++ b/chalk/plugins/tools/tool_star/tool_star.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_star/tool_star_cursor.png b/chalk/plugins/tools/tool_star/tool_star_cursor.png
new file mode 100644
index 00000000..d3cef598
--- /dev/null
+++ b/chalk/plugins/tools/tool_star/tool_star_cursor.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_star/wdg_tool_star.ui b/chalk/plugins/tools/tool_star/wdg_tool_star.ui
new file mode 100644
index 00000000..b342a927
--- /dev/null
+++ b/chalk/plugins/tools/tool_star/wdg_tool_star.ui
@@ -0,0 +1,128 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgToolStar</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgToolStar</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>280</width>
+ <height>50</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Star</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout8</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Vertices:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>isbX</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>verticesSpinBox</cstring>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="minValue">
+ <number>2</number>
+ </property>
+ <property name="value">
+ <number>5</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout7</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Ratio:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>isbWidth</cstring>
+ </property>
+ </widget>
+ <widget class="KisIntSpinbox">
+ <property name="name">
+ <cstring>ratioSpinBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </hbox>
+</widget>
+<tabstops>
+ <tabstop>verticesSpinBox</tabstop>
+ <tabstop>ratioSpinBox</tabstop>
+</tabstops>
+<customwidgets>
+<customwidget>
+ <class>KisIntSpinbox</class>
+ <header location="global">kis_int_spinbox.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image4</pixmap>
+</customwidget>
+</customwidgets>
+<images>
+ <image name="image4">
+ <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data>
+ </image>
+</images>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/tools/tool_transform/Makefile.am b/chalk/plugins/tools/tool_transform/Makefile.am
new file mode 100644
index 00000000..7b088383
--- /dev/null
+++ b/chalk/plugins/tools/tool_transform/Makefile.am
@@ -0,0 +1,37 @@
+kde_services_DATA = chalktooltransform.desktop
+
+# all_includes must remain last!
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalktooltransform_la_SOURCES = \
+ wdg_tool_transform.ui \
+ tool_transform.cc \
+ kis_tool_transform.cc
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = chalktooltransform.la
+
+noinst_HEADERS = \
+ tool_transform.h \
+ kis_tool_transform.h
+
+chalktooltransform_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui
+chalktooltransform_la_LIBADD = ../../../libchalkcommon.la
+
+chalktooltransform_la_METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
+
+chalkpics_DATA = \
+ rotate_cursor.xpm \
+ tool_transform.png
+
+chalkpicsdir = $(kde_datadir)/chalk/pics
+
diff --git a/chalk/plugins/tools/tool_transform/chalktooltransform.desktop b/chalk/plugins/tools/tool_transform/chalktooltransform.desktop
new file mode 100644
index 00000000..4ea3db98
--- /dev/null
+++ b/chalk/plugins/tools/tool_transform/chalktooltransform.desktop
@@ -0,0 +1,46 @@
+[Desktop Entry]
+Name=Transform Tool
+Name[bg]=Инструмент за трансформиране
+Name[br]=Ostilh treuzfurmiñ
+Name[ca]=Eina de transformació
+Name[cy]=Erfyn Trawsffurfio
+Name[da]=Transformeringsværktøj
+Name[de]=Transformation-Werkzeug
+Name[el]=Εργαλείο μετασχηματισμού
+Name[eo]=Transform-ilo
+Name[es]=Herramienta para transformar
+Name[et]=Transformeermistööriist
+Name[fa]=ابزار تبدیل
+Name[fr]=Outil transformation
+Name[fy]=ferfoarmingsark
+Name[ga]=Uirlis Trasfhoirmithe
+Name[gl]=Ferramenta de Transformación
+Name[hu]=Átalakító eszköz
+Name[is]=Ummyndunartól
+Name[it]=Strumento di trasformazione
+Name[ja]=変換ツール
+Name[km]=ឧបករណ៍​ប្លែង
+Name[lt]=Transformavimo įrankis
+Name[lv]=Transformāciju rīks
+Name[nb]=Transformeringsverktøy
+Name[nds]=Ümwanneln-Warktüüch
+Name[ne]=रूपान्तरण उपकरण
+Name[nl]=Vervormgereedschap
+Name[pl]=Narzędzie przekształcania
+Name[pt]=Ferramenta de Transformação
+Name[pt_BR]=Ferramenta de Transformação
+Name[ru]=Преобразование
+Name[sk]=Transformácia
+Name[sl]=Orodje za pretvorbo
+Name[sr]=Алат за трансформацију
+Name[sr@Latn]=Alat za transformaciju
+Name[sv]=Transformeringsverktyg
+Name[uk]=Засіб перетворення
+Name[uz]=Aylantirish asbobi
+Name[uz@cyrillic]=Айлантириш асбоби
+Name[zh_CN]=变形工具
+Name[zh_TW]=變形工具
+ServiceTypes=Chalk/Tool
+Type=Service
+X-KDE-Library=chalktooltransform
+X-Chalk-Version=2
diff --git a/chalk/plugins/tools/tool_transform/kis_tool_transform.cc b/chalk/plugins/tools/tool_transform/kis_tool_transform.cc
new file mode 100644
index 00000000..5b828122
--- /dev/null
+++ b/chalk/plugins/tools/tool_transform/kis_tool_transform.cc
@@ -0,0 +1,916 @@
+/*
+ * kis_tool_transform.cc -- part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2005 Casper Boemann <cbr@boemann.dk>
+ *
+ * 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 <tqpainter.h>
+#include <tqpen.h>
+#include <tqpushbutton.h>
+#include <tqobject.h>
+#include <tqlabel.h>
+#include <tqcombobox.h>
+#include <tqapplication.h>
+
+#include <kdebug.h>
+#include <kaction.h>
+#include <kcommand.h>
+#include <klocale.h>
+#include <knuminput.h>
+
+#include <kis_global.h>
+#include <kis_painter.h>
+#include <kis_canvas_controller.h>
+#include <kis_canvas_subject.h>
+#include <kis_cursor.h>
+#include <kis_image.h>
+#include <kis_undo_adapter.h>
+#include <kis_selected_transaction.h>
+#include <kis_button_press_event.h>
+#include <kis_button_release_event.h>
+#include <kis_move_event.h>
+#include <kis_selection.h>
+#include <kis_filter_strategy.h>
+#include <kis_cmb_idlist.h>
+#include <kis_id.h>
+#include <kis_tool_controller.h>
+#include <kis_transform_worker.h>
+
+#include "kis_tool_transform.h"
+#include "wdg_tool_transform.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+
+namespace {
+ class TransformCmd : public KisSelectedTransaction {
+ typedef KisSelectedTransaction super;
+
+ public:
+ TransformCmd(KisToolTransform *tool, KisPaintDeviceSP device, KisPaintDeviceSP origDevice, double scaleX, double scaleY, double tX, double tY, double a, KisSelectionSP origSel, TQPoint startPos, TQPoint endPos);
+ virtual ~TransformCmd();
+
+ public:
+ virtual void execute();
+ virtual void unexecute();
+ void transformArgs(double &sx, double &sy, double &tx, double &ty, double &a);
+ KisSelectionSP origSelection(TQPoint &startPos, TQPoint &endPos);
+ KisPaintDeviceSP theDevice();
+ KisPaintDeviceSP origDevice();
+
+ private:
+ double m_scaleX;
+ double m_scaleY;
+ double m_translateX;
+ double m_translateY;
+ double m_a;
+ KisToolTransform *m_tool;
+ KisSelectionSP m_origSelection;
+ TQPoint m_startPos;
+ TQPoint m_endPos;
+ KisPaintDeviceSP m_device;
+ KisPaintDeviceSP m_origDevice;
+ };
+
+ TransformCmd::TransformCmd(KisToolTransform *tool, KisPaintDeviceSP device, KisPaintDeviceSP origDevice, double scaleX, double scaleY, double tX, double tY, double a, KisSelectionSP origSel, TQPoint startPos, TQPoint endPos) :
+ super(i18n("Transform"), device)
+ , m_scaleX(scaleX)
+ , m_scaleY(scaleY)
+ , m_translateX(tX)
+ , m_translateY(tY)
+ , m_a(a)
+ , m_tool(tool)
+ , m_origSelection(origSel)
+ , m_startPos(startPos)
+ , m_endPos(endPos)
+ , m_device(device)
+ , m_origDevice(origDevice)
+ {
+ }
+
+ TransformCmd::~TransformCmd()
+ {
+ }
+
+ void TransformCmd::transformArgs(double &sx, double &sy, double &tx, double &ty, double &a)
+ {
+ sx = m_scaleX;
+ sy = m_scaleY;
+ tx= m_translateX;
+ ty = m_translateY;
+ a = m_a;
+ }
+
+ KisSelectionSP TransformCmd::origSelection(TQPoint &startPos, TQPoint &endPos)
+ {
+ startPos = m_startPos;
+ endPos = m_endPos;
+ return m_origSelection;
+ }
+
+ void TransformCmd::execute()
+ {
+ super::execute();
+ }
+
+ void TransformCmd::unexecute()
+ {
+ super::unexecute();
+ }
+
+ KisPaintDeviceSP TransformCmd::theDevice()
+ {
+ return m_device;
+ }
+
+ KisPaintDeviceSP TransformCmd::origDevice()
+ {
+ return m_origDevice;
+ }
+}
+
+KisToolTransform::KisToolTransform()
+ : super(i18n("Transform"))
+ , m_wasPressed( false )
+{
+ setName("tool_transform");
+ setCursor(KisCursor::selectCursor());
+ m_subject = 0;
+ m_selecting = false;
+ m_startPos = TQPoint(0, 0);
+ m_endPos = TQPoint(0, 0);
+ m_optWidget = 0;
+ m_sizeCursors[0] = KisCursor::sizeVerCursor();
+ m_sizeCursors[1] = KisCursor::sizeBDiagCursor();
+ m_sizeCursors[2] = KisCursor::sizeHorCursor();
+ m_sizeCursors[3] = KisCursor::sizeFDiagCursor();
+ m_sizeCursors[4] = KisCursor::sizeVerCursor();
+ m_sizeCursors[5] = KisCursor::sizeBDiagCursor();
+ m_sizeCursors[6] = KisCursor::sizeHorCursor();
+ m_sizeCursors[7] = KisCursor::sizeFDiagCursor();
+ m_origDevice = 0;
+ m_origSelection = 0;
+
+}
+
+KisToolTransform::~KisToolTransform()
+{
+}
+
+void KisToolTransform::deactivate()
+{
+ if (m_subject && m_subject->undoAdapter()) m_subject->undoAdapter()->removeCommandHistoryListener( this );
+
+ KisImageSP img = m_subject->currentImg();
+ if (!img) return;
+
+ paintOutline();
+
+ disconnect(m_subject->currentImg().data(), TQT_SIGNAL(sigLayerActivated(KisLayerSP)), this, TQT_SLOT(slotLayerActivated(KisLayerSP)));
+}
+
+void KisToolTransform::activate()
+{
+ if(m_subject && m_subject->currentImg() && m_subject->currentImg()->activeDevice())
+ {
+ //connect(m_subject, commandExecuted(KCommand *c), this, notifyCommandAdded( KCommand * c));
+ m_subject->undoAdapter()->setCommandHistoryListener( this );
+
+ KisToolControllerInterface *controller = m_subject->toolController();
+
+ if (controller)
+ controller->setCurrentTool(this);
+
+ TransformCmd * cmd=0;
+
+ if(m_subject->currentImg()->undoAdapter()->presentCommand())
+ cmd = dynamic_cast<TransformCmd*>(m_subject->currentImg()->undoAdapter()->presentCommand());
+
+ if (cmd == 0) {
+ initHandles();
+ }
+ else
+ {
+ // One of our commands is on top
+ if(cmd->theDevice() == m_subject->currentImg()->activeDevice())
+ {
+ // and it even has the same device
+ // We should ask for tool args and orig selection
+ m_origDevice = cmd->origDevice();
+ cmd->transformArgs(m_scaleX, m_scaleY, m_translateX, m_translateY, m_a);
+ m_origSelection = cmd->origSelection(m_startPos, m_endPos);
+ m_org_cenX = (m_startPos.x() + m_endPos.x()) / 2.0;
+ m_org_cenY = (m_startPos.y() + m_endPos.y()) / 2.0;
+ paintOutline();
+ }
+ else
+ initHandles();
+ }
+ }
+ connect(m_subject->currentImg(), TQT_SIGNAL(sigLayerActivated(KisLayerSP)), this, TQT_SLOT(slotLayerActivated(KisLayerSP)));
+}
+
+void KisToolTransform::initHandles()
+{
+ TQ_INT32 x,y,w,h;
+ KisImageSP img = m_subject->currentImg();
+
+ KisPaintDeviceSP dev = img->activeDevice();
+ if (!dev ) return;
+
+ // Create a lazy copy of the current state
+ m_origDevice = new KisPaintDevice(*dev.data());
+ Q_ASSERT(m_origDevice);
+
+ if(dev->hasSelection())
+ {
+ KisSelectionSP sel = dev->selection();
+ m_origSelection = new KisSelection(*sel.data());
+ TQRect r = sel->selectedExactRect();
+ r.rect(&x, &y, &w, &h);
+ }
+ else {
+ dev->exactBounds(x,y,w,h);
+ m_origSelection = 0;
+ }
+ m_startPos = TQPoint(x, y);
+ m_endPos = TQPoint(x+w-1, y+h-1);
+ m_org_cenX = (m_startPos.x() + m_endPos.x()) / 2.0;
+ m_org_cenY = (m_startPos.y() + m_endPos.y()) / 2.0;
+
+ m_a = 0.0;
+ m_scaleX = 1.0;
+ m_scaleY = 1.0;
+ m_translateX = m_org_cenX;
+ m_translateY = m_org_cenY;
+
+ m_subject->canvasController() ->updateCanvas();
+}
+
+void KisToolTransform::paint(KisCanvasPainter& gc)
+{
+ paintOutline(gc, TQRect());
+}
+
+void KisToolTransform::paint(KisCanvasPainter& gc, const TQRect& rc)
+{
+ paintOutline(gc, rc);
+}
+
+
+void KisToolTransform::buttonPress(KisButtonPressEvent *e)
+{
+ if (m_subject && e->button() == Qt::LeftButton) {
+ m_wasPressed = true;
+ }
+
+ if (m_subject) {
+ KisImageSP img = m_subject->currentImg();
+
+ if (img && img->activeDevice() && e->button() == Qt::LeftButton) {
+ switch(m_function)
+ {
+ case ROTATE:
+ m_clickoffset = e->pos().floorTQPoint()
+ - TQPoint(static_cast<int>(m_translateX),static_cast<int>(m_translateY));
+ m_clickangle = -m_a - atan2(m_clickoffset.x(),m_clickoffset.y());
+ m_clickoffset = TQPoint(0, 0);
+ break;
+ case MOVE:
+ m_clickoffset = e->pos().floorTQPoint()
+ - TQPoint(static_cast<int>(m_translateX),static_cast<int>(m_translateY));
+ break;
+ case TOPSCALE:
+ m_clickoffset = e->pos().floorTQPoint()
+ - TQPoint((m_topleft + m_topright)/2);
+ break;
+ case TOPRIGHTSCALE:
+ m_clickoffset = e->pos().floorTQPoint() - m_topright;
+ break;
+ case RIGHTSCALE:
+ m_clickoffset = e->pos().floorTQPoint()
+ - TQPoint((m_topright + m_bottomright)/2);
+ break;
+ case BOTTOMRIGHTSCALE:
+ m_clickoffset = e->pos().floorTQPoint() - m_bottomright;
+ break;
+ case BOTTOMSCALE:
+ m_clickoffset = e->pos().floorTQPoint()
+ - TQPoint((m_bottomleft + m_bottomright)/2);
+ break;
+ case BOTTOMLEFTSCALE:
+ m_clickoffset = e->pos().floorTQPoint() - m_bottomleft;
+ break;
+ case LEFTSCALE:
+ m_clickoffset = e->pos().floorTQPoint()
+ - TQPoint((m_topleft + m_bottomleft)/2);
+ break;
+ case TOPLEFTSCALE:
+ m_clickoffset = e->pos().floorTQPoint() - m_topleft;
+ break;
+ }
+ m_selecting = true;
+ m_actualyMoveWhileSelected = false;
+ }
+ }
+}
+
+int KisToolTransform::det(TQPoint v,TQPoint w)
+{
+ return v.x()*w.y()-v.y()*w.x();
+}
+int KisToolTransform::distsq(TQPoint v,TQPoint w)
+{
+ v -= w;
+ return v.x()*v.x() + v.y()*v.y();
+}
+
+void KisToolTransform::setFunctionalCursor()
+{
+ int rotOctant = 8 + int(8.5 + m_a* 4 / M_PI);
+
+ int s;
+ if(m_scaleX*m_scaleY<0)
+ s = -1;
+ else
+ s=1;
+
+ switch(m_function)
+ {
+ case MOVE:
+ setCursor(KisCursor::moveCursor());
+ break;
+ case ROTATE:
+ setCursor(KisCursor::rotateCursor());
+ break;
+ case TOPSCALE:
+ setCursor(m_sizeCursors[(0*s +rotOctant)%8]);
+ break;
+ case TOPRIGHTSCALE:
+ setCursor(m_sizeCursors[(1*s +rotOctant)%8]);
+ break;
+ case RIGHTSCALE:
+ setCursor(m_sizeCursors[(2*s +rotOctant)%8]);
+ break;
+ case BOTTOMRIGHTSCALE:
+ setCursor(m_sizeCursors[(3*s +rotOctant)%8]);
+ break;
+ case BOTTOMSCALE:
+ setCursor(m_sizeCursors[(4*s +rotOctant)%8]);
+ break;
+ case BOTTOMLEFTSCALE:
+ setCursor(m_sizeCursors[(5*s +rotOctant)%8]);
+ break;
+ case LEFTSCALE:
+ setCursor(m_sizeCursors[(6*s +rotOctant)%8]);
+ break;
+ case TOPLEFTSCALE:
+ setCursor(m_sizeCursors[(7*s +rotOctant)%8]);
+ break;
+ }
+}
+
+void KisToolTransform::move(KisMoveEvent *e)
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+
+ Q_ASSERT(controller);
+ TQPoint topleft = m_topleft;
+ TQPoint topright = m_topright;
+ TQPoint bottomleft = m_bottomleft;
+ TQPoint bottomright = m_bottomright;
+
+ TQPoint mousePos = e->pos().floorTQPoint();
+
+ if (m_subject && m_selecting) {
+ paintOutline();
+ m_actualyMoveWhileSelected = true;
+ mousePos -= m_clickoffset;
+
+ // transform mousePos coords, so it seems like it isn't rotated and centered at 0,0
+ double newX = invrotX(mousePos.x() - m_translateX, mousePos.y() - m_translateY);
+ double newY = invrotY(mousePos.x() - m_translateX, mousePos.y() - m_translateY);
+ double dx=0, dy=0;
+ double oldScaleX = m_scaleX;
+ double oldScaleY = m_scaleY;
+
+ if(m_function == MOVE)
+ {
+ m_translateX += mousePos.x() - m_translateX;
+ m_translateY += mousePos.y() - m_translateY;
+ }
+
+ if(m_function == ROTATE)
+ {
+ m_a = -atan2(mousePos.x() - m_translateX, mousePos.y() - m_translateY)
+ - m_clickangle;
+ }
+
+ if(m_function == TOPSCALE)
+ {
+ dy = (newY - m_scaleY * (m_startPos.y() - m_org_cenY)) / 2;
+ m_scaleY = (newY - dy) / (m_startPos.y() - m_org_cenY);
+
+ // enforce same acpect if shift button is pressed
+ if(e->state() & TQt::ShiftButton)
+ {
+ if(m_scaleX>0) // handle the mirrored cases
+ m_scaleX = fabs(m_scaleY);
+ else
+ m_scaleX = -fabs(m_scaleY);
+ }
+ }
+
+ if(m_function == TOPRIGHTSCALE)
+ {
+ dx = (newX - m_scaleX * (m_endPos.x() - m_org_cenX)) / 2;
+ m_scaleX = (newX - dx) / (m_endPos.x() - m_org_cenX);
+
+ dy = (newY - m_scaleY * (m_startPos.y() - m_org_cenY)) / 2;
+ m_scaleY = (newY - dy) / (m_startPos.y() - m_org_cenY);
+
+ // enforce same aspect if shift button is pressed
+ if(e->state() & TQt::ShiftButton)
+ {
+ if(m_scaleX < m_scaleY)
+ {
+ if(m_scaleX>0) // handle the mirrored cases
+ m_scaleX = fabs(m_scaleY);
+ else
+ m_scaleX = -fabs(m_scaleY);
+ dx = (m_scaleX - oldScaleX) * (m_endPos.x() - m_org_cenX);
+ }
+ else
+ {
+ if(m_scaleY>0) // handle the mirrored cases
+ m_scaleY = fabs(m_scaleX);
+ else
+ m_scaleY = -fabs(m_scaleX);
+ dy = (m_scaleY - oldScaleY) * (m_startPos.y() - m_org_cenY);
+ }
+ }
+ }
+
+ if(m_function == RIGHTSCALE)
+ {
+ dx = (newX - m_scaleX * (m_endPos.x() - m_org_cenX)) / 2;
+ m_scaleX = (newX - dx) / (m_endPos.x() - m_org_cenX);
+
+ // enforce same acpect if shift button is pressed
+ if(e->state() & TQt::ShiftButton)
+ {
+ if(m_scaleY>0) // handle the mirrored cases
+ m_scaleY = fabs(m_scaleX);
+ else
+ m_scaleY = -fabs(m_scaleX);
+ }
+ }
+
+ if(m_function == BOTTOMRIGHTSCALE)
+ {
+ dx = (newX - m_scaleX * (m_endPos.x() - m_org_cenX)) / 2;
+ m_scaleX = (newX - dx) / (m_endPos.x() - m_org_cenX);
+
+ dy = (newY - m_scaleY * (m_endPos.y() - m_org_cenY)) / 2;
+ m_scaleY = (newY - dy) / (m_endPos.y() - m_org_cenY);
+
+ // enforce same acpect if shift button is pressed
+ if(e->state() & TQt::ShiftButton)
+ {
+ if(m_scaleX < m_scaleY)
+ {
+ if(m_scaleX>0) // handle the mirrored cases
+ m_scaleX = fabs(m_scaleY);
+ else
+ m_scaleX = -fabs(m_scaleY);
+ dx = (m_scaleX - oldScaleX) * (m_endPos.x() - m_org_cenX);
+ }
+ else
+ {
+ if(m_scaleY>0) // handle the mirrored cases
+ m_scaleY = fabs(m_scaleX);
+ else
+ m_scaleY = -fabs(m_scaleX);
+ dy = (m_scaleY - oldScaleY) * (m_endPos.y() - m_org_cenY);
+ }
+ }
+ }
+
+ if(m_function == BOTTOMSCALE)
+ {
+ dy = (newY - m_scaleY * (m_endPos.y() - m_org_cenY)) / 2;
+ m_scaleY = (newY - dy) / (m_endPos.y() - m_org_cenY);
+
+ // enforce same acpect if shift button is pressed
+ if(e->state() & TQt::ShiftButton)
+ {
+ if(m_scaleX>0) // handle the mirrored cases
+ m_scaleX = fabs(m_scaleY);
+ else
+ m_scaleX = -fabs(m_scaleY);
+ }
+ }
+
+ if(m_function == BOTTOMLEFTSCALE)
+ {
+ dx = (newX - m_scaleX * (m_startPos.x() - m_org_cenX)) / 2;
+ m_scaleX = (newX - dx) / (m_startPos.x() - m_org_cenX);
+
+ dy = (newY - m_scaleY * (m_endPos.y() - m_org_cenY)) / 2;
+ m_scaleY = (newY - dy) / (m_endPos.y() - m_org_cenY);
+
+ // enforce same acpect if shift button is pressed
+ if(e->state() & TQt::ShiftButton)
+ {
+ if(m_scaleX < m_scaleY)
+ {
+ if(m_scaleX>0) // handle the mirrored cases
+ m_scaleX = fabs(m_scaleY);
+ else
+ m_scaleX = -fabs(m_scaleY);
+ dx = (m_scaleX - oldScaleX) * (m_startPos.x() - m_org_cenX);
+ }
+ else
+ {
+ if(m_scaleY>0) // handle the mirrored cases
+ m_scaleY = fabs(m_scaleX);
+ else
+ m_scaleY = -fabs(m_scaleX);
+ dy = (m_scaleY - oldScaleY) * (m_endPos.y() - m_org_cenY);
+ }
+ }
+ }
+
+ if(m_function == LEFTSCALE)
+ {
+ dx = (newX - m_scaleX * (m_startPos.x() - m_org_cenX)) / 2;
+ m_scaleX = (newX - dx) / (m_startPos.x() - m_org_cenX);
+
+ // enforce same acpect if shift button is pressed
+ if(e->state() & TQt::ShiftButton)
+ {
+ if(m_scaleY>0) // handle the mirrored cases
+ m_scaleY = fabs(m_scaleX);
+ else
+ m_scaleY = -fabs(m_scaleX);
+ }
+ }
+
+ if(m_function == TOPLEFTSCALE)
+ {
+ dx = (newX - m_scaleX * (m_startPos.x() - m_org_cenX)) / 2;
+ m_scaleX = (newX - dx) / (m_startPos.x() - m_org_cenX);
+
+ dy = (newY - m_scaleY * (m_startPos.y() - m_org_cenY)) / 2;
+ m_scaleY = (newY - dy) / (m_startPos.y() - m_org_cenY);
+
+ // enforce same acpect if shift button is pressed
+ if(e->state() & TQt::ShiftButton)
+ {
+ if(m_scaleX < m_scaleY)
+ {
+ if(m_scaleX>0) // handle the mirrored cases
+ m_scaleX = fabs(m_scaleY);
+ else
+ m_scaleX = -fabs(m_scaleY);
+ dx = (m_scaleX - oldScaleX) * (m_startPos.x() - m_org_cenX);
+ }
+ else
+ {
+ if(m_scaleY>0) // handle the mirrored cases
+ m_scaleY = fabs(m_scaleX);
+ else
+ m_scaleY = -fabs(m_scaleX);
+ dy = (m_scaleY - oldScaleY) * (m_startPos.y() - m_org_cenY);
+ }
+ }
+ }
+
+ m_translateX += rotX(dx, dy);
+ m_translateY += rotY(dx, dy);
+
+ paintOutline();
+ }
+ else
+ {
+ if(det(mousePos - topleft, topright - topleft)>0)
+ m_function = ROTATE;
+ else if(det(mousePos - topright, bottomright - topright)>0)
+ m_function = ROTATE;
+ else if(det(mousePos - bottomright, bottomleft - bottomright)>0)
+ m_function = ROTATE;
+ else if(det(mousePos - bottomleft, topleft - bottomleft)>0)
+ m_function = ROTATE;
+ else
+ m_function = MOVE;
+
+ int handleradius = int( 25 / (m_subject->zoomFactor() * m_subject->zoomFactor()) );
+
+ if(distsq(mousePos, (m_topleft + m_topright)/2)<=handleradius)
+ m_function = TOPSCALE;
+ if(distsq(mousePos, m_topright)<=handleradius)
+ m_function = TOPRIGHTSCALE;
+ if(distsq(mousePos, (m_topright + m_bottomright)/2)<=handleradius)
+ m_function = RIGHTSCALE;
+ if(distsq(mousePos, m_bottomright)<=handleradius)
+ m_function = BOTTOMRIGHTSCALE;
+ if(distsq(mousePos, (m_bottomleft + m_bottomright)/2)<=handleradius)
+ m_function = BOTTOMSCALE;
+ if(distsq(mousePos, m_bottomleft)<=handleradius)
+ m_function = BOTTOMLEFTSCALE;
+ if(distsq(mousePos, (m_topleft + m_bottomleft)/2)<=handleradius)
+ m_function = LEFTSCALE;
+ if(distsq(mousePos, m_topleft)<=handleradius)
+ m_function = TOPLEFTSCALE;
+
+ setFunctionalCursor();
+ }
+ }
+}
+
+void KisToolTransform::buttonRelease(KisButtonReleaseEvent *e)
+{
+ if (m_subject && e->button() == Qt::LeftButton) {
+ if(!m_wasPressed) return;
+ m_wasPressed = false;
+
+ KisImageSP img = m_subject->currentImg();
+
+ if (!img)
+ return;
+
+ m_selecting = false;
+
+ if(m_actualyMoveWhileSelected)
+ {
+ paintOutline();
+ TQApplication::setOverrideCursor(KisCursor::waitCursor());
+ transform();
+ TQApplication::restoreOverrideCursor();
+ }
+ }
+}
+
+void KisToolTransform::paintOutline()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter gc(canvas);
+ TQRect rc;
+
+ paintOutline(gc, rc);
+ }
+}
+
+void KisToolTransform::recalcOutline()
+{
+ double x,y;
+
+ m_sina = sin(m_a);
+ m_cosa = cos(m_a);
+
+ x = (m_startPos.x() - m_org_cenX) * m_scaleX;
+ y = (m_startPos.y() - m_org_cenY) * m_scaleY;
+ m_topleft = TQPoint(int(rotX(x,y) + m_translateX+0.5), int(rotY(x,y) + m_translateY+0.5));
+
+ x = (m_endPos.x() - m_org_cenX) * m_scaleX;
+ y = (m_startPos.y() - m_org_cenY) * m_scaleY;
+ m_topright = TQPoint(int(rotX(x,y) + m_translateX+0.5), int(rotY(x,y) + m_translateY+0.5));
+
+ x = (m_startPos.x() - m_org_cenX) * m_scaleX;
+ y = (m_endPos.y() - m_org_cenY) * m_scaleY;
+ m_bottomleft = TQPoint(int(rotX(x,y) + m_translateX+0.5), int(rotY(x,y) + m_translateY+0.5));
+
+ x = (m_endPos.x() - m_org_cenX) * m_scaleX;
+ y = (m_endPos.y() - m_org_cenY) * m_scaleY;
+ m_bottomright = TQPoint(int(rotX(x,y) + m_translateX+0.5), int(rotY(x,y) + m_translateY+0.5));
+}
+
+void KisToolTransform::paintOutline(KisCanvasPainter& gc, const TQRect&)
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ RasterOp op = gc.rasterOp();
+ TQPen old = gc.pen();
+ TQPen pen(TQt::SolidLine);
+ pen.setWidth(1);
+ Q_ASSERT(controller);
+
+ recalcOutline();
+ TQPoint topleft = controller->windowToView(m_topleft);
+ TQPoint topright = controller->windowToView(m_topright);
+ TQPoint bottomleft = controller->windowToView(m_bottomleft);
+ TQPoint bottomright = controller->windowToView(m_bottomright);
+
+ gc.setRasterOp(TQt::NotROP);
+ gc.setPen(pen);
+ gc.drawRect(topleft.x()-4, topleft.y()-4, 8, 8);
+ gc.drawLine(topleft.x(), topleft.y(), (topleft.x()+topright.x())/2, (topleft.y()+topright.y())/2);
+ gc.drawRect((topleft.x()+topright.x())/2-4, (topleft.y()+topright.y())/2-4, 8, 8);
+ gc.drawLine((topleft.x()+topright.x())/2, (topleft.y()+topright.y())/2, topright.x(), topright.y());
+ gc.drawRect(topright.x()-4, topright.y()-4, 8, 8);
+ gc.drawLine(topright.x(), topright.y(), (topright.x()+bottomright.x())/2, (topright.y()+bottomright.y())/2);
+ gc.drawRect((topright.x()+bottomright.x())/2-4, (topright.y()+bottomright.y())/2-4, 8, 8);
+ gc.drawLine((topright.x()+bottomright.x())/2, (topright.y()+bottomright.y())/2,bottomright.x(), bottomright.y());
+ gc.drawRect(bottomright.x()-4, bottomright.y()-4, 8, 8);
+ gc.drawLine(bottomright.x(), bottomright.y(), (bottomleft.x()+bottomright.x())/2, (bottomleft.y()+bottomright.y())/2);
+ gc.drawRect((bottomleft.x()+bottomright.x())/2-4, (bottomleft.y()+bottomright.y())/2-4, 8, 8);
+ gc.drawLine((bottomleft.x()+bottomright.x())/2, (bottomleft.y()+bottomright.y())/2, bottomleft.x(), bottomleft.y());
+ gc.drawRect(bottomleft.x()-4, bottomleft.y()-4, 8, 8);
+ gc.drawLine(bottomleft.x(), bottomleft.y(), (topleft.x()+bottomleft.x())/2, (topleft.y()+bottomleft.y())/2);
+ gc.drawRect((topleft.x()+bottomleft.x())/2-4, (topleft.y()+bottomleft.y())/2-4, 8, 8);
+ gc.drawLine((topleft.x()+bottomleft.x())/2, (topleft.y()+bottomleft.y())/2, topleft.x(), topleft.y());
+ gc.setRasterOp(op);
+ gc.setPen(old);
+ }
+}
+
+void KisToolTransform::transform()
+{
+
+ KisImageSP img = m_subject->currentImg();
+
+ if (!img || !img->activeDevice())
+ return;
+
+ double tx = m_translateX - rotX(m_org_cenX * m_scaleX, m_org_cenY * m_scaleY);
+ double ty = m_translateY - rotY(m_org_cenX * m_scaleX, m_org_cenY * m_scaleY);
+ KisProgressDisplayInterface *progress = m_subject->progressDisplay();
+
+ // This mementoes the current state of the active device.
+ TransformCmd * transaction = new TransformCmd(this, img->activeDevice(), m_origDevice,
+ m_scaleX, m_scaleY, m_translateX, m_translateY, m_a, m_origSelection, m_startPos, m_endPos);
+
+ // Copy the original state back.
+ TQRect rc = m_origDevice->extent();
+ rc = rc.normalize();
+ img->activeDevice()->clear();
+ KisPainter gc(img->activeDevice());
+ gc.bitBlt(rc.x(), rc.y(), COMPOSITE_COPY, m_origDevice, rc.x(), rc.y(), rc.width(), rc.height());
+ gc.end();
+
+ // Also restore the original selection.
+ if(m_origSelection)
+ {
+ //TQRect rc = m_origSelection->extent();
+ TQRect rc = m_origSelection->selectedRect();
+ rc = rc.normalize();
+ img->activeDevice()->selection()->clear();
+ KisPainter sgc(img->activeDevice()->selection().data());
+ sgc.bitBlt(rc.x(), rc.y(), COMPOSITE_COPY, m_origSelection.data(), rc.x(), rc.y(), rc.width(), rc.height());
+ sgc.end();
+ }
+ else
+ if(img->activeDevice()->hasSelection())
+ img->activeDevice()->selection()->clear();
+
+ // Perform the transform. Since we copied the original state back, this doesn't degrade
+ // after many tweaks. Since we started the transaction before the copy back, the memento
+ // has the previous state.
+ KisTransformWorker t(img->activeDevice(), m_scaleX, m_scaleY, 0, 0, m_a, int(tx), int(ty), progress, m_filter);
+ t.run();
+
+ // If canceled, go back to the memento
+ if(t.isCanceled())
+ {
+ transaction->unexecute();
+ delete transaction;
+ return;
+ }
+
+ img->activeDevice()->setDirty(rc); // XXX: This is not enough - should union with new extent
+
+ // Else add the command -- this will have the memento from the previous state,
+ // and the transformed state from the original device we cached in our activated()
+ // method.
+ if (transaction) {
+ if (img->undo())
+ img->undoAdapter()->addCommand(transaction);
+ else
+ delete transaction;
+ }
+}
+
+void KisToolTransform::notifyCommandAdded( KCommand * command)
+{
+ TransformCmd * cmd = dynamic_cast<TransformCmd*>(command);
+ if (cmd == 0) {
+ // The last added command wasn't one of ours;
+ // we should reset to the new state of the canvas.
+ // In effect we should treat this as if the tool has been just activated
+ initHandles();
+ }
+}
+
+void KisToolTransform::notifyCommandExecuted( KCommand * command)
+{
+ Q_UNUSED(command);
+ TransformCmd * cmd=0;
+
+ if(m_subject->currentImg()->undoAdapter()->presentCommand())
+ cmd = dynamic_cast<TransformCmd*>(m_subject->currentImg()->undoAdapter()->presentCommand());
+
+ if (cmd == 0) {
+ // The command now on the top of the stack isn't one of ours
+ // We should treat this as if the tool has been just activated
+ initHandles();
+ }
+ else
+ {
+ // One of our commands is now on top
+ // We should ask for tool args and orig selection
+ cmd->transformArgs(m_scaleX, m_scaleY, m_translateX, m_translateY, m_a);
+ m_origSelection = cmd->origSelection(m_startPos, m_endPos);
+ m_origDevice = cmd->origDevice();
+ m_org_cenX = (m_startPos.x() + m_endPos.x()) / 2.0;
+ m_org_cenY = (m_startPos.y() + m_endPos.y()) / 2.0;
+ m_subject->canvasController() ->updateCanvas();
+ }
+}
+
+void KisToolTransform::slotSetFilter(const KisID &filterID)
+{
+ m_filter = KisFilterStrategyRegistry::instance()->get(filterID);
+}
+
+void KisToolTransform::slotLayerActivated(KisLayerSP)
+{
+ activate();
+}
+
+
+TQWidget* KisToolTransform::createOptionWidget(TQWidget* tqparent)
+{
+
+ m_optWidget = new WdgToolTransform(tqparent);
+ Q_CHECK_PTR(m_optWidget);
+
+ m_optWidget->cmbFilter->clear();
+ m_optWidget->cmbFilter->setIDList(KisFilterStrategyRegistry::instance()->listKeys());
+
+ m_optWidget->cmbFilter->setCurrentText("Mitchell");
+ connect(m_optWidget->cmbFilter, TQT_SIGNAL(activated(const KisID &)),
+ this, TQT_SLOT(slotSetFilter(const KisID &)));
+
+ KisID filterID = m_optWidget->cmbFilter->currentItem();
+ m_filter = KisFilterStrategyRegistry::instance()->get(filterID);
+
+/*
+ connect(m_optWidget->intStartX, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(setStartX(int)));
+ connect(m_optWidget->intStartY, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(setStartY(int)));
+ connect(m_optWidget->intEndX, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(setEndX(int)));
+ connect(m_optWidget->intEndY, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(setEndY(int)));
+*/
+ m_optWidget->intStartX->hide();
+ m_optWidget->intStartY->hide();
+ m_optWidget->intEndX->hide();
+ m_optWidget->intEndY->hide();
+ m_optWidget->textLabel1->hide();
+ m_optWidget->textLabel2->hide();
+ m_optWidget->textLabel3->hide();
+ m_optWidget->textLabel4->hide();
+ return m_optWidget;
+}
+
+TQWidget* KisToolTransform::optionWidget()
+{
+ return m_optWidget;
+}
+
+void KisToolTransform::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Transform"),
+ "tool_transform",
+ 0,
+ this,
+ TQT_SLOT(activate()),
+ collection,
+ name());
+ Q_CHECK_PTR(m_action);
+ m_action->setToolTip(i18n("Transform a layer or a selection"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+#include "kis_tool_transform.moc"
diff --git a/chalk/plugins/tools/tool_transform/kis_tool_transform.h b/chalk/plugins/tools/tool_transform/kis_tool_transform.h
new file mode 100644
index 00000000..a98cd4f7
--- /dev/null
+++ b/chalk/plugins/tools/tool_transform/kis_tool_transform.h
@@ -0,0 +1,155 @@
+/*
+ * kis_tool_transform.h - part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2005 Casper Boemann <cbr@boemann.dk>
+ *
+ * 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_TOOL_TRANSFORM_H_
+#define KIS_TOOL_TRANSFORM_H_
+
+#include <tqpoint.h>
+
+#include <kis_tool_non_paint.h>
+#include <kis_tool_factory.h>
+#include <kis_undo_adapter.h>
+#include <kis_layer.h>
+
+class KisTransaction;
+class WdgToolTransform;
+class KisID;
+class KisFilterStrategy;
+
+/**
+ * Transform tool
+ *
+ */
+class KisToolTransform : public KisToolNonPaint, KisCommandHistoryListener {
+
+ typedef KisToolNonPaint super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisToolTransform();
+ virtual ~KisToolTransform();
+
+ virtual TQWidget* createOptionWidget(TQWidget* tqparent);
+ virtual TQWidget* optionWidget();
+
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_TRANSFORM; }
+ virtual TQ_UINT32 priority() { return 3; }
+ virtual void paint(KisCanvasPainter& gc);
+ virtual void paint(KisCanvasPainter& gc, const TQRect& rc);
+ virtual void buttonPress(KisButtonPressEvent *e);
+ virtual void move(KisMoveEvent *e);
+ virtual void buttonRelease(KisButtonReleaseEvent *e);
+ void setScaleX(double sx) { m_scaleX = sx; }
+ void setScaleY(double sy) { m_scaleY = sy; }
+ void setTranslateX(double tx) { m_translateX = tx; }
+ void setTranslateY(double ty) { m_translateY = ty; }
+ void setAngle(double a) { m_a = a; }
+ void paintOutline();
+
+public:
+
+ void notifyCommandAdded(KCommand *);
+ void notifyCommandExecuted(KCommand *);
+
+public:
+ virtual void deactivate();
+
+private:
+
+ void paintOutline(KisCanvasPainter& gc, const TQRect& rc);
+ void transform();
+ void recalcOutline();
+ double rotX(double x, double y) { return m_cosa*x - m_sina*y;};
+ double rotY(double x, double y) { return m_sina*x + m_cosa*y;};
+ double invrotX(double x, double y) { return m_cosa*x + m_sina*y;};
+ double invrotY(double x, double y) { return -m_sina*x + m_cosa*y;};
+ int det(TQPoint v,TQPoint w);
+ int distsq(TQPoint v,TQPoint w);
+ void setFunctionalCursor();
+ void initHandles();
+
+private slots:
+
+ void slotLayerActivated(KisLayerSP);
+ void slotSetFilter(const KisID &);
+ void setStartX(int x) { m_startPos.setX(x); }
+ void setStartY(int y) { m_startPos.setY(y); }
+ void setEndX(int x) { m_endPos.setX(x); }
+ void setEndY(int y) { m_endPos.setY(y); }
+
+protected slots:
+ virtual void activate();
+
+private:
+ enum function {ROTATE,MOVE,TOPLEFTSCALE,TOPSCALE,TOPRIGHTSCALE,RIGHTSCALE,
+ BOTTOMRIGHTSCALE, BOTTOMSCALE,BOTTOMLEFTSCALE, LEFTSCALE};
+ TQCursor m_sizeCursors[8];
+ function m_function;
+ TQPoint m_startPos;
+ TQPoint m_endPos;
+ bool m_selecting;
+ bool m_actualyMoveWhileSelected;
+ TQPoint m_topleft;
+ TQPoint m_topright;
+ TQPoint m_bottomleft;
+ TQPoint m_bottomright;
+ double m_scaleX;
+ double m_scaleY;
+ double m_translateX;
+ double m_translateY;
+ TQPoint m_clickoffset;
+ double m_org_cenX;
+ double m_org_cenY;
+ double m_cosa;
+ double m_sina;
+ double m_a;
+ double m_clickangle;
+ KisFilterStrategy *m_filter;
+
+ WdgToolTransform *m_optWidget;
+
+ KisPaintDeviceSP m_origDevice;
+ KisSelectionSP m_origSelection;
+
+ bool m_wasPressed;
+};
+
+class KisToolTransformFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+
+public:
+ KisToolTransformFactory() : super() {};
+ virtual ~KisToolTransformFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolTransform();
+ Q_CHECK_PTR(t);
+ t->setup(ac); return t;
+ }
+ virtual KisID id() { return KisID("transform", i18n("Transform Tool")); }
+};
+
+
+
+#endif // KIS_TOOL_TRANSFORM_H_
+
diff --git a/chalk/plugins/tools/tool_transform/rotate_cursor.xpm b/chalk/plugins/tools/tool_transform/rotate_cursor.xpm
new file mode 100644
index 00000000..f3860232
--- /dev/null
+++ b/chalk/plugins/tools/tool_transform/rotate_cursor.xpm
@@ -0,0 +1,29 @@
+/* XPM */
+static char *rotate_cursor[]={
+"22 22 4 1",
+"b c None",
+". c None",
+"a c #000000",
+"# c #ffffff",
+"......................",
+"......................",
+"....##...#####........",
+"....#a###aaaaa##......",
+"....#aaaabbbbbaa#.....",
+"....#aaa#.....bba#....",
+"....#aaaa#......ba#...",
+"....######......bba#..",
+".................ba#..",
+"..bbb.............ba#.",
+"..#ab.............ba#.",
+"..#ab.............ba#.",
+"..#ab.............ba#.",
+"..#ab.............ba#.",
+"...#ab............bbb.",
+"...#ab.......######...",
+"....#ab......#aaaa#...",
+".....#abbb....#aaa#...",
+"......#aabbbb#aaaa#...",
+".......##aaaaa###a#...",
+".........#####...##...",
+"......................"};
diff --git a/chalk/plugins/tools/tool_transform/tool_transform.cc b/chalk/plugins/tools/tool_transform/tool_transform.cc
new file mode 100644
index 00000000..2ee002de
--- /dev/null
+++ b/chalk/plugins/tools/tool_transform/tool_transform.cc
@@ -0,0 +1,64 @@
+/*
+ * tool_transform.cc -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 <stdlib.h>
+#include <vector>
+
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_tool_registry.h>
+
+#include "tool_transform.h"
+#include "kis_tool_transform.h"
+
+
+typedef KGenericFactory<ToolTransform> ToolTransformFactory;
+K_EXPORT_COMPONENT_FACTORY( chalktooltransform, ToolTransformFactory( "chalk" ) )
+
+
+ToolTransform::ToolTransform(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ToolTransformFactory::instance());
+
+ if ( tqparent->inherits("KisToolRegistry") )
+ {
+ KisToolRegistry * r = dynamic_cast<KisToolRegistry*>(tqparent);
+ KisToolTransformFactory * f = new KisToolTransformFactory();
+ Q_CHECK_PTR(f);
+ r->add(f);
+ }
+
+}
+
+ToolTransform::~ToolTransform()
+{
+}
+
+#include "tool_transform.moc"
diff --git a/chalk/plugins/tools/tool_transform/tool_transform.h b/chalk/plugins/tools/tool_transform/tool_transform.h
new file mode 100644
index 00000000..04bfbaa9
--- /dev/null
+++ b/chalk/plugins/tools/tool_transform/tool_transform.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 TOOL_TRANSFORM_H_
+#define TOOL_TRANSFORM_H_
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+/**
+ * A module that provides a transform tool.
+ */
+class ToolTransform : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ ToolTransform(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ToolTransform();
+
+private:
+
+ KisView * m_view;
+
+};
+
+#endif // TOOL_TRANSFORM_H_
diff --git a/chalk/plugins/tools/tool_transform/tool_transform.png b/chalk/plugins/tools/tool_transform/tool_transform.png
new file mode 100644
index 00000000..6c601433
--- /dev/null
+++ b/chalk/plugins/tools/tool_transform/tool_transform.png
Binary files differ
diff --git a/chalk/plugins/tools/tool_transform/wdg_tool_transform.ui b/chalk/plugins/tools/tool_transform/wdg_tool_transform.ui
new file mode 100644
index 00000000..2f41e1b3
--- /dev/null
+++ b/chalk/plugins/tools/tool_transform/wdg_tool_transform.ui
@@ -0,0 +1,243 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgToolTransform</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgToolTransform</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>377</width>
+ <height>91</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Transform</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <widget class="TQLayoutWidget" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>tqlayout11</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout7</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Move X:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>isbX</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>intStartX</cstring>
+ </property>
+ <property name="maxValue">
+ <number>1000000000</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Scale X:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>isbWidth</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>intEndX</cstring>
+ </property>
+ <property name="maxValue">
+ <number>1000000000</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout8</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Move Y:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>isbY</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>intStartY</cstring>
+ </property>
+ <property name="maxValue">
+ <number>1000000000</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Scale Y:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>isbHeight</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>intEndY</cstring>
+ </property>
+ <property name="maxValue">
+ <number>1000000000</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Filter:</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ <widget class="KisCmbIDList" row="1" column="1">
+ <property name="name">
+ <cstring>cmbFilter</cstring>
+ </property>
+ </widget>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KisCmbIDList</class>
+ <header location="local">kis_cmb_idlist.h</header>
+ <sizehint>
+ <width>1</width>
+ <height>24</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="870">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000032d49444154388db59531681c4714863f892dde8004b320c32e3870020b74458a6b0f5458e581c016a809a8496b42208454098604d2c4904a6954a410511ae752085b858c1208dc35221244b00119f60ac12ee860062c980719708a95a248f129459cd7cceeccf0edb76fff61a706830197d5ed765ff3166a30184c4d5d829fed3c7bdd5e6ce3bda71a5738ef301802e1d6d179477152303c1842bc822797a64fbf7b4a9a43be00ada817cb0e12011c2611205ccd73755f9c087c6b19bef0d7c100f5b8267d07caf10fe8ab9210156320fc01be16aa5a11043307f30b20a21041019985f48ef2f7fa0becc68e80475fd584e831b396f210f67795c3831a4940a3228925bb27f4d652ba4b01a199b73342f3981be0ca57745042ac30c632d853b6373d44b056c8ef0922508d94d14be59b2f4aeaf58cd5751069e06f3436890114332b9487d0bf80f61e64dc5f813c3790045453f67703fd4d4f7f6b4496b5597e689044af194f5f5e841800210478bee3d1a8f41e64acbe0f69ae6852e1cf0ccf7f74f4d652defbc042226c6f55e8f89f91bb6e9c387c9d521c9558db988a3416fe3c67e32b4779ec7167f0e8939ce19ea7fc5d298a80c875f03563930855ed2081bc05e91d5014ef53363eaf288e3d6285ee520a338e76c7a251a94e41e30470d3631004a262672e3eca59cec6978ef2b889979d11f2bb904af3be92081a416e28dfe831983920b1142345d5b0ff2234a6334276d7321ad53c795c511ca654a5a251996f19b83d158ef602b45a423d52f67703abeb29ee4ce9de4fc93378f218462f6b3efdb042cf3d59666977a0aa6fe9310888d25b13342afd4dcffeaee3d147399da540ab13f8f8b39c2cb3f8710d11ba2b96f9c57fcd7180287497a03ecde86f8dd8fe1a867b9ef6bb1612a84a871f6bd35b94e217a53832589970f2dcd85d9c7d4580d57521cbdaf4bfaf288e95e268d4ec8e60e72ccb0f2dbffea454e71e8d29f57882717152509482a48d8924b0bc12e82ee51445a03a6da079cbd0eec0fc22142b06620e89a3fc8d3783870743d814d2bc8994aa6ff286472e764902e5a96f72bbd3b4c37b280e95aa9e604c84e1cf978b37c74935797d7ae2ca7fac6968fe51ff0bf86dc30783c1d49f0baa9bb819e612310000000049454e44ae426082</data>
+ </image>
+</images>
+<tabstops>
+ <tabstop>intStartX</tabstop>
+ <tabstop>intStartY</tabstop>
+ <tabstop>intEndX</tabstop>
+ <tabstop>intEndY</tabstop>
+</tabstops>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>kis_cmb_idlist.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/viewplugins/Makefile.am b/chalk/plugins/viewplugins/Makefile.am
new file mode 100644
index 00000000..e5739b36
--- /dev/null
+++ b/chalk/plugins/viewplugins/Makefile.am
@@ -0,0 +1,24 @@
+if compile_kross
+SCRIPTINGDIR = scripting
+endif
+
+SUBDIRS = \
+ substrate \
+ colorrange \
+ colorspaceconversion \
+ dropshadow \
+ filtersgallery \
+ histogram \
+ histogram_docker \
+ imagesize \
+ modify_selection \
+ rotateimage \
+ screenshot \
+ separate_channels \
+ shearimage \
+ selectopaque \
+ $(SCRIPTINGDIR)
+
+# variations
+# history_docker
+# performancetest
diff --git a/chalk/plugins/viewplugins/colorrange/Makefile.am b/chalk/plugins/viewplugins/colorrange/Makefile.am
new file mode 100644
index 00000000..fc29a370
--- /dev/null
+++ b/chalk/plugins/viewplugins/colorrange/Makefile.am
@@ -0,0 +1,25 @@
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalkcolorrange.la
+
+chalkcolorrange_la_SOURCES = colorrange.cc dlg_colorrange.cc wdg_colorrange.ui
+noinst_HEADERS = wdg_colorrange.h dlg_colorrange.h colorrange.h
+
+chalkcolorrange_la_LIBADD = ../../../libchalkcommon.la
+chalkcolorrange_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) chalkblurfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui
+
+chalkrcdir = $(kde_datadir)/chalkplugins
+chalkrc_DATA = colorrange.rc
+EXTRA_DIST = $(chalkrc_DATA)
+
+kde_services_DATA = chalkcolorrange.desktop
+
+chalkcolorrange_la_METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
diff --git a/chalk/plugins/viewplugins/colorrange/chalkcolorrange.desktop b/chalk/plugins/viewplugins/colorrange/chalkcolorrange.desktop
new file mode 100644
index 00000000..dde9b936
--- /dev/null
+++ b/chalk/plugins/viewplugins/colorrange/chalkcolorrange.desktop
@@ -0,0 +1,40 @@
+[Desktop Entry]
+Name=Colorrange
+Name[bg]=Цветови обхват
+Name[ca]=Rang de color
+Name[da]=Farveområde
+Name[de]=Farbbereich
+Name[el]=Χρωματικό εύρος
+Name[en_GB]=Colourrange
+Name[eo]=Kolorgamo
+Name[et]=Värvivahemik
+Name[fa]=گسترۀ رنگ
+Name[fr]=Plage de couleurs
+Name[fy]=Kleurberik
+Name[gl]=Gamas de Cores
+Name[he]=טווח צבעים
+Name[hu]=Egyszerű
+Name[is]=Litasvið
+Name[it]=Intervallo di colori
+Name[ja]=色の範囲
+Name[km]=ជួរ​ពណ៌
+Name[nb]=Fargeområde
+Name[nds]=Klörenrebeet
+Name[ne]=रङदायरा
+Name[nl]=Kleurbereik
+Name[pl]=Zakres kolorów
+Name[pt]=Gamas de Cores
+Name[pt_BR]=Intervalos de Cores
+Name[ru]=Цвета
+Name[se]=Ivdnegaskkadat
+Name[sk]=Rozsah farieb
+Name[sl]=Barvni razpon
+Name[sr]=Опсег боја
+Name[sr@Latn]=Opseg boja
+Name[sv]=Färgintervall
+Name[uk]=Діапазон кольорів
+Name[zh_TW]=色彩範圍
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalkcolorrange
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/colorrange/colorrange.cc b/chalk/plugins/viewplugins/colorrange/colorrange.cc
new file mode 100644
index 00000000..1bf90bbc
--- /dev/null
+++ b/chalk/plugins/viewplugins/colorrange/colorrange.cc
@@ -0,0 +1,82 @@
+/*
+ * colorrange.h -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 <math.h>
+
+#include <stdlib.h>
+
+#include <tqslider.h>
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_layer.h>
+#include <kis_paint_device.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_view.h>
+#include <kis_selection.h>
+#include <kis_selection_manager.h>
+#include "colorrange.h"
+#include "dlg_colorrange.h"
+
+typedef KGenericFactory<ColorRange> ColorRangeFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkcolorrange, ColorRangeFactory( "chalk" ) )
+
+ColorRange::ColorRange(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+
+ if (tqparent->inherits("KisView")) {
+ setInstance(ColorRangeFactory::instance());
+ setXMLFile(locate("data","chalkplugins/colorrange.rc"), true);
+ m_view = dynamic_cast<KisView*>(tqparent);
+ m_view->canvasSubject()->selectionManager()->addSelectionAction( new KAction(i18n("&Color Range..."), 0, 0, this, TQT_SLOT(slotActivated()), actionCollection(), "colorrange") );
+
+ }
+}
+
+ColorRange::~ColorRange()
+{
+}
+
+void ColorRange::slotActivated()
+{
+ KisPaintDeviceSP layer = m_view->canvasSubject()->currentImg()->activeDevice();
+ if (!layer) return;
+
+ DlgColorRange * dlgColorRange = new DlgColorRange(m_view, layer, m_view, "ColorRange");
+ Q_CHECK_PTR(dlgColorRange);
+
+ dlgColorRange->exec();
+}
+
+#include "colorrange.moc"
+
diff --git a/chalk/plugins/viewplugins/colorrange/colorrange.h b/chalk/plugins/viewplugins/colorrange/colorrange.h
new file mode 100644
index 00000000..38e008d9
--- /dev/null
+++ b/chalk/plugins/viewplugins/colorrange/colorrange.h
@@ -0,0 +1,45 @@
+/*
+ * colorrange.h -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 COLORRANGE_H
+#define COLORRANGE_H
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+class ColorRange : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+ public:
+ ColorRange(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ColorRange();
+
+ private slots:
+ void slotActivated();
+
+ private:
+ KisView * m_view;
+ KisPainter * m_painter;
+
+};
+
+#endif // COLORRANGE_H
diff --git a/chalk/plugins/viewplugins/colorrange/colorrange.rc b/chalk/plugins/viewplugins/colorrange/colorrange.rc
new file mode 100644
index 00000000..39d49cd8
--- /dev/null
+++ b/chalk/plugins/viewplugins/colorrange/colorrange.rc
@@ -0,0 +1,10 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkcolorrange" version="1">
+<MenuBar>
+ <Menu name="Select"><text>Select</text>
+ <Separator/>
+ <Action name="colorrange"/>
+ <Separator/>
+ </Menu>
+</MenuBar>
+</kpartgui>
diff --git a/chalk/plugins/viewplugins/colorrange/dlg_colorrange.cc b/chalk/plugins/viewplugins/colorrange/dlg_colorrange.cc
new file mode 100644
index 00000000..43f98a53
--- /dev/null
+++ b/chalk/plugins/viewplugins/colorrange/dlg_colorrange.cc
@@ -0,0 +1,351 @@
+/*
+ * dlg_colorrange.cc - part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <tqapplication.h>
+#include <tqpushbutton.h>
+#include <tqcheckbox.h>
+#include <tqslider.h>
+#include <tqcombobox.h>
+#include <tqpixmap.h>
+#include <tqimage.h>
+#include <tqlabel.h>
+#include <tqcolor.h>
+#include <tqradiobutton.h>
+
+#include <knuminput.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kaction.h>
+
+#include <kis_canvas_subject.h>
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_paint_device.h>
+#include <kis_selection.h>
+#include <kis_selection_manager.h>
+#include <kis_types.h>
+#include <kis_undo_adapter.h>
+#include <kis_view.h>
+#include <kis_colorspace.h>
+#include <kis_profile.h>
+#include <kis_color_conversions.h>
+#include <kis_selected_transaction.h>
+#include <kis_cursor.h>
+
+#include "dlg_colorrange.h"
+#include "wdg_colorrange.h"
+
+namespace {
+
+// XXX: Poynton says: hsv/hls is not what one ought to use for colour calculations.
+// Unfortunately, I don't know enough to be able to use anything else.
+
+ bool isReddish(int h)
+ {
+ return ((h > 330 && h < 360) || ( h > 0 && h < 40));
+ }
+
+ bool isYellowish(int h)
+ {
+ return (h> 40 && h < 65);
+ }
+
+ bool isGreenish(int h)
+ {
+ return (h > 70 && h < 155);
+ }
+
+ bool isCyanish(int h)
+ {
+ return (h > 150 && h < 190);
+ }
+
+ bool isBlueish(int h)
+ {
+ return (h > 185 && h < 270);
+ }
+
+ bool isMagentaish(int h)
+ {
+ return (h > 265 && h < 330);
+ }
+
+ bool isHighlight(int v)
+ {
+ return (v > 200);
+ }
+
+ bool isMidTone(int v)
+ {
+ return (v > 100 && v < 200);
+ }
+
+ bool isShadow(int v)
+ {
+ return (v < 100);
+ }
+
+}
+
+TQ_UINT32 matchColors(const TQColor & c, enumAction action)
+{
+ int r = c.red();
+ int g = c.green();
+ int b = c.blue();
+
+ int h, s, v;
+ rgb_to_hsv(r, g, b, &h, &s, &v);
+
+
+
+ // XXX: Map the degree in which the colors conform to the requirement
+ // to a range of selectedness between 0 and 255
+
+ // XXX: Implement out-of-gamut using lcms
+
+ switch(action) {
+
+ case REDS:
+ if (isReddish(h))
+ return MAX_SELECTED;
+ else
+ return MIN_SELECTED;
+ case YELLOWS:
+ if (isYellowish(h)) {
+ return MAX_SELECTED;
+ }
+ else
+ return MIN_SELECTED;
+ case GREENS:
+ if (isGreenish(h))
+ return MAX_SELECTED;
+ else
+ return MIN_SELECTED;
+ case CYANS:
+ if (isCyanish(h))
+ return MAX_SELECTED;
+ else
+ return MIN_SELECTED;
+ case BLUES:
+ if (isBlueish(h))
+ return MAX_SELECTED;
+ else
+ return MIN_SELECTED;
+ case MAGENTAS:
+ if (isMagentaish(h))
+ return MAX_SELECTED;
+ else
+ return MIN_SELECTED;
+ case HIGHLIGHTS:
+ if (isHighlight(v))
+ return MAX_SELECTED;
+ else
+ return MIN_SELECTED;
+ case MIDTONES:
+ if (isMidTone(v))
+ return MAX_SELECTED;
+ else
+ return MIN_SELECTED;
+ case SHADOWS:
+ if (isShadow(v))
+ return MAX_SELECTED;
+ else
+ return MIN_SELECTED;
+ };
+
+ return MIN_SELECTED;
+}
+
+
+
+DlgColorRange::DlgColorRange( KisView * view, KisPaintDeviceSP dev, TQWidget * tqparent, const char * name)
+ : super (tqparent, name, true, i18n("Color Range"), Ok | Cancel, Ok)
+{
+ m_dev = dev;
+ m_view = view;
+
+ m_subject = view->canvasSubject();
+
+ m_page = new WdgColorRange(this, "color_range");
+ Q_CHECK_PTR(m_page);
+
+ setCaption(i18n("Color Range"));
+ setMainWidget(m_page);
+ resize(m_page->tqsizeHint());
+
+ if (m_dev->image()->undo()) m_transaction = new KisSelectedTransaction(i18n("Select by Color Range"), m_dev);
+
+ if(! m_dev->hasSelection())
+ m_dev->selection()->clear();
+ m_selection = m_dev->selection();
+
+ updatePreview();
+
+ m_invert = false;
+ m_mode = SELECTION_ADD;
+ m_currentAction = REDS;
+
+ connect(this, TQT_SIGNAL(okClicked()),
+ this, TQT_SLOT(okClicked()));
+
+ connect(this, TQT_SIGNAL(cancelClicked()),
+ this, TQT_SLOT(cancelClicked()));
+
+ connect(m_page->chkInvert, TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(slotInvertClicked()));
+
+ connect(m_page->cmbSelect, TQT_SIGNAL(activated(int)),
+ this, TQT_SLOT(slotSelectionTypeChanged(int)));
+
+ connect (m_page->radioAdd, TQT_SIGNAL(toggled(bool)),
+ this, TQT_SLOT(slotAdd(bool)));
+
+ connect (m_page->radioSubtract, TQT_SIGNAL(toggled(bool)),
+ this, TQT_SLOT(slotSubtract(bool)));
+
+ connect (m_page->bnSelect, TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(slotSelectClicked()));
+
+ connect (m_page->bnDeselect, TQT_SIGNAL(clicked()),
+ this, TQT_SLOT(slotDeselectClicked()));
+
+}
+
+DlgColorRange::~DlgColorRange()
+{
+ delete m_page;
+}
+
+
+void DlgColorRange::updatePreview()
+{
+ if (!m_selection) return;
+
+ TQ_INT32 x, y, w, h;
+ m_dev->exactBounds(x, y, w, h);
+ TQPixmap pix = TQPixmap(m_selection->tqmaskImage().smoothScale(350, 350, TQ_ScaleMin));
+ m_subject->canvasController()->updateCanvas();
+ m_page->pixSelection->setPixmap(pix);
+}
+
+void DlgColorRange::okClicked()
+{
+ m_dev->setDirty();
+ m_dev->emitSelectionChanged();
+
+ if (m_dev->image()->undo()) m_subject->undoAdapter()->addCommand(m_transaction);
+ accept();
+}
+
+void DlgColorRange::cancelClicked()
+{
+ if (m_dev->image()->undo()) m_transaction->unexecute();
+
+ m_subject->canvasController()->updateCanvas();
+ reject();
+}
+
+void DlgColorRange::slotInvertClicked()
+{
+ m_invert = m_page->chkInvert->isChecked();
+}
+
+void DlgColorRange::slotSelectionTypeChanged(int index)
+{
+ m_currentAction = (enumAction)index;
+}
+
+void DlgColorRange::slotSubtract(bool on)
+{
+ if (on)
+ m_mode = SELECTION_SUBTRACT;
+}
+void DlgColorRange::slotAdd(bool on)
+{
+ if (on)
+ m_mode = SELECTION_ADD;
+}
+
+void DlgColorRange::slotSelectClicked()
+{
+ TQApplication::setOverrideCursor(KisCursor::waitCursor());
+ // XXX: Multithread this!
+ TQ_INT32 x, y, w, h;
+ m_dev->exactBounds(x, y, w, h);
+ KisColorSpace * cs = m_dev->colorSpace();
+ TQ_UINT8 opacity;
+ for (int y2 = y; y2 < h - y; ++y2) {
+ KisHLineIterator hiter = m_dev->createHLineIterator(x, y2, w, false);
+ KisHLineIterator selIter = m_selection ->createHLineIterator(x, y2, w, true);
+ while (!hiter.isDone()) {
+ TQColor c;
+
+ cs->toTQColor(hiter.rawData(), &c, &opacity);
+ // Don't try to select transparent pixels.
+ if (opacity > OPACITY_TRANSPARENT) {
+ TQ_UINT8 match = matchColors(c, m_currentAction);
+
+ if (match) {
+ // Personally, I think the invert option a bit silly. But it's possible I don't quite understand it. BSAR.
+ if (!m_invert) {
+ if (m_mode == SELECTION_ADD) {
+ *(selIter.rawData()) = match;
+ }
+ else if (m_mode == SELECTION_SUBTRACT) {
+ TQ_UINT8 selectedness = *(selIter.rawData());
+ if (match < selectedness) {
+ *(selIter.rawData()) = selectedness - match;
+ }
+ else {
+ *(selIter.rawData()) = 0;
+ }
+ }
+ }
+ else {
+ if (m_mode == SELECTION_ADD) {
+ TQ_UINT8 selectedness = *(selIter.rawData());
+ if (match < selectedness) {
+ *(selIter.rawData()) = selectedness - match;
+ }
+ else {
+ *(selIter.rawData()) = 0;
+ }
+ }
+ else if (m_mode == SELECTION_SUBTRACT) {
+ *(selIter.rawData()) = match;
+ }
+ }
+ }
+ }
+ ++hiter;
+ ++selIter;
+ }
+ }
+ updatePreview();
+ TQApplication::restoreOverrideCursor();
+}
+
+void DlgColorRange::slotDeselectClicked()
+{
+ m_dev->selection()->clear();
+ updatePreview();
+}
+
+
+#include "dlg_colorrange.moc"
diff --git a/chalk/plugins/viewplugins/colorrange/dlg_colorrange.h b/chalk/plugins/viewplugins/colorrange/dlg_colorrange.h
new file mode 100644
index 00000000..ce39ebd2
--- /dev/null
+++ b/chalk/plugins/viewplugins/colorrange/dlg_colorrange.h
@@ -0,0 +1,100 @@
+/*
+ * dlg_colorrange.h -- part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 DLG_COLORRANGE
+#define DLG_COLORRANGE
+
+#include <tqcursor.h>
+
+#include <kdialogbase.h>
+
+#include <kis_types.h>
+
+#include <kis_selection.h> // For enums
+#include <kis_types.h>
+#include <kis_global.h>
+
+
+class KisView;
+class KisCanvasSubject;
+class DlgColorRange;
+class KisSelectedTransaction;
+class WdgColorRange;
+
+enum enumAction {
+ REDS,
+ YELLOWS,
+ GREENS,
+ CYANS,
+ BLUES,
+ MAGENTAS,
+ HIGHLIGHTS,
+ MIDTONES,
+ SHADOWS
+};
+
+
+ /**
+ * This dialog allows the user to create a selection tqmask based
+ * on a (range of) colors.
+ */
+class DlgColorRange: public KDialogBase {
+ typedef KDialogBase super;
+ Q_OBJECT
+ TQ_OBJECT
+
+
+
+public:
+
+ DlgColorRange(KisView * view, KisPaintDeviceSP layer, TQWidget * tqparent = 0, const char* name = 0);
+ ~DlgColorRange();
+
+private slots:
+
+ void okClicked();
+ void cancelClicked();
+
+ void slotInvertClicked();
+ void slotSelectionTypeChanged(int index);
+ void updatePreview();
+ void slotSubtract(bool on);
+ void slotAdd(bool on);
+ void slotSelectClicked();
+ void slotDeselectClicked();
+
+private:
+ TQImage createMask(KisSelectionSP selection, KisPaintDeviceSP layer);
+
+private:
+
+ WdgColorRange * m_page;
+ KisSelectionSP m_selection;
+ KisPaintDeviceSP m_dev;
+ KisView * m_view;
+ KisCanvasSubject * m_subject;
+ enumSelectionMode m_mode;
+ TQCursor m_oldCursor;
+ KisSelectedTransaction *m_transaction;
+ enumAction m_currentAction;
+ bool m_invert;
+};
+
+
+#endif // DLG_COLORRANGE
diff --git a/chalk/plugins/viewplugins/colorrange/wdg_colorrange.ui b/chalk/plugins/viewplugins/colorrange/wdg_colorrange.ui
new file mode 100644
index 00000000..3eafd180
--- /dev/null
+++ b/chalk/plugins/viewplugins/colorrange/wdg_colorrange.ui
@@ -0,0 +1,252 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgColorRange</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgColorRange</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>515</width>
+ <height>528</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Color Range</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout10</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout8</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout7</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQComboBox">
+ <item>
+ <property name="text">
+ <string>Reds</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Yellows</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Greens</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Cyans</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Blues</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Magentas</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Highlights</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Midtones</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Shadows</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Out of Gamut</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>cmbSelect</cstring>
+ </property>
+ </widget>
+ <widget class="TQCheckBox">
+ <property name="name">
+ <cstring>chkInvert</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Invert</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQButtonGroup">
+ <property name="name">
+ <cstring>grpSelection</cstring>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQRadioButton">
+ <property name="name">
+ <cstring>radioAdd</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Add to current selection</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQRadioButton">
+ <property name="name">
+ <cstring>radioSubtract</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Subtract from current selection</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout9</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>bnSelect</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Select</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>bnDeselect</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Deselect</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQGroupBox">
+ <property name="name">
+ <cstring>grpPreview</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Preview</string>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>pixSelection</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+</widget>
+<images>
+ <image name="image0">
+ <data format="XPM.GZ" length="55092">789cccbd47b7eb38b2ef397f9fa2d6e5ecae5e7cf266d0035266cb6da7ed77af1ed07b2f1aa9bf7c83883f704c56d5cd7c75bb5f95d6c9ca5f8a22114044202200f0fccffffcdbe7d3fddffef37ffe8fea625c02eb6f966f947ffb4fbb4e92ebfff57fff9fffcffff88fe160f0b7fecf68389bfe6df41fffc7fff80febf96fd6df9401ff5fcff64232ffde36244f7a762ac953fefd56f29cf35cf2a267f3072ff9f733c906e7836493f35eb2c59fd74ab6797b1f243bfcfb46b2cb7fef0a1e72799c5af2907f7f94cce5732cc963fefd483297cf3a8387d43f992999ffde0c25f3dfb79a64de5f662099dfcfe924cf386f24f3fe4a44ff0fd17e5b327f9e772799dfcfb8078fa87d662499cbebbb9249de6fc9bcbd9d2f99dab795ccc7b31a48e6e3b71a4ae6e315ed25f3f1b04f82a93f0dc1636a9ff32999daf32599f757a54ae6fde17e48e6fae23892b97e78a2bd63ea1f438cef849e97e892f9f7652b99b76f3d91cce53763f0947e6f08fd9c1137b664de5e43c83fc7f53bf0022cf475499c8be719c4f113d824de5cc01671fd0eb6895dbaff50d8ab174ae6f2ad3ac9a47f63c924df4832d73f732a99f777f324998fb73993ccfb5f7f96ccc7df3a49e6e3514592b9bd3aa664ae1fd6bd646eaf9a2b98f4ddf52573fdb58e60d89f6d49e6df9b13c97c3c1d45326fbf634826ffb2934cfee40086fdf88164de7ff65232d9eb9b646e1fa607867e9bbe641a8f816092cf14f2423f4d070c7d8b9f25f3e7bbaf60e89fb791ccfb3b15df43ffe22f30f42f13f240ffea1b18fab716bf877ee967b043dc92bf1f0ea16fdd9af3a8f740bc3dbe64f2f70bc9bcbfcd2fc9bcbfbd4432f90b4730f5cff55e3297bfc9c0187f732899f4772099c6e35b321f7f6b0fc6f8daa6649aff7692f9f3724d32d7f7cb4932ef6ffb4e32e9b302c6f86723c9dcdefc50326f9ff32e99f7975382a10fd75c32d7e795906742fdd3bd49e6df67a2bdd09ff20886beb89164fefcd54932ef9ffa2c98fca72bda0b7d6a9f25f3feb0c4f842bf9a07b0d02fd13fd0afe2090cffd6c660e85b24ae87be05a40f63e1df8277c9bc7debab643e5e575732efef6e2799cb1bfcf89ecbdbed2573fd5cfd781e1fcf952d98fa3b91cf277f74cd24f3fe0f3ec08807ba8d64ae9fc54232e98f27993faff9f13df787ae680ff4d57995cce57103c95c7fac3bc97c7c7c5f308d67b8028bf9f72299cbd3dc49e6f2981f92797fd69664de5f7e2499dbb33b92ccdb6f2dc1d067772099fca72e99b7ff6a49a6f946f437f4b9bd48267934b0d0ef77c9bc7dad68df9cee9fee25f3fe69447fcc31df88f1843eaf6e92f9f3da89649a0fee25f3f1cb85be41ff0331bed07f5f8ca7f0a7d43f13a1df9d2a99f777f32899dfffea80111faeae92b93cee41f090f7effa0c463ce77f48a6f9ee51321fafeb4930f547bb01433fecb164fe7cff5b321f2f2f92ccfb3f93d793bd745b30f421ae2593bfd94be6fd1b2692b93cde4e32b79fda164ced8ddec1d017e74332f9dbb564de5e772899e299140c7dcaa692b93db8df92797fe61d18fe3117e303fd59b792e979b164de3f8918ff05f5cf46f40ff4c715e301fdb9bd80e13f57f792797fad4a30fce906bf17f3f51ae331c4fc19a13d43f89780e693a9f0a7ed028cebfd4e321fafe6198c7cc00b2473f9bc77c95cdf4a4ff0908fc75a5c8f78bfb52553fcf02999ebbfdf08a6f10e5ec1c2bfdc49a6f97c2b99e6ff27c9642f3fbee7fab416f2407fc299643efe912f99ec692099cbd3b492b9bc9ab8ff94c63711fd0bfdb2a792c93e2ac9140f689229df5125f3feed5660e85ffd2a99fce34432efdfee00867e5e14c9941f8ec0d0bfcc904cf9572a99b7a76e25f3fe73c760a1afaa646ebf99e85fe86f2ec61bfaea0b79e11f0ba12f2eda8bfb4b7d267b98897c64dd81a1cfeb503297afbd934cf1d45e30fc93f81ef363b896ccefbf3a4a26793dc1149fae7d30f247ff2a99ea1d3fbee7fed68b05a31eb1924cf9c2083ca5f6076bc9542fd948e6fa900e2473fdbbbc09463d630246be1a6692f9f84481643edef95532b73f5df01cfd7993ccdb7be92453beb5924cf3c14432efbf5cfc7e01fffa2999e6bfb1646e5f9b022ce2cba364de3e37114cfec132c0d047f74d32f9e37b30f26b2f05431f5763c9bc7f42c1d04797e6cf99d0c71be41fc21fa52a18fe24207d9f0bfd5a1d04d3f8570fe009d573dca3642e7fbb054f697ca237c1246f3a944cf53a5b32c5a72f60f81bd796ccaf4f2bc994af2d2593be6f2453bea682e7345eed4e32d5ff14c9bcbf2f57c95cff7dd15ef8a35097ccdb93cd25537e2bfa6b3124fffd055ec2bfcc24537c548045fe518331decda7647ebd2eda6ba37fc478c01f6d44ffb8d43e1ded17e3af3960cc97f5022cf481e257a6dd149fd96bf08cc6ffe64aa6f92604c35eec4032b7efab2799e2375b30e94b2aae5f50ff58aa642e6fe148a67ce1065e927fb80d2553bd2494cc9fdf3e49a6fc45c863c07e1dc97cfcd3a3606a5f7d05633e887682497faf4bb08df8e2030cfb2bc9de17a2ff4bf49f886762f4cf10f666bd80618f3e8dff92f5177f5e914be6ed2f36e005c91b5f24533cf22598ecafeec04be467ae64f28757b041bfaf5f040f29fe68c0268d9726da63917e14a2bdd0c7f424998f5f44fdb314fd91bf83a18f8105467fdc4660e86783e789fee94a30e215e3118c78a3a0f9dc60fd45fa34072f491fc329d8a0f685a964aae7dfc0265d5f2f05537f568f60d86bb091ccfbe36248e6fad988dfbba85f8e24533e48f66f88fe892b30fa67634ba6f97508467f6d1cb0a827435ed11f35fa6388f9c9a7f8c814f157fd065e92fe5f6e6083e42f5cb0897ac417d8227dca3fc036f55fb305431fba77c1747f3b02bba4df3ad9ab29e42f669229df46fb647fe460d8d3aa0243fecd2758d4bbefc0a21eb403a33f2a8a772c263f6fff35055ba827d1f85aa2bf2f1a58f4f70a8cfb252a18febdf1c0f02701f58f2dda7f5d48a6fe9b8071fff21d2cfc83603caf51c1b87fb106433f4b1a1f87fd17eebf1b17ec903efbd43e46b0f71a0c79cb2d58c4e72d18cf2f1bb078be0dc6f3339abf5cd11f8906c6f5de1a8cf846e3f6c1cbe724df068cf6548964ae3f1b130c7f9096608c7f7603a3bde90e8ce7bb2f60b4d77e00c39f075c9f98f639e47fa34832d7e7f84c2c9eb7ba80216ffb08c6f3cc042cd64f1a30e42f9760d88fe382d19e1ced19c11e42aebf0cf17cd306435ecb04a33d610e16f20b16f1470a16ed3981457cf9443c82bdae2660e19f79bc341c8be7d70e18cfd71ec022df8ac178feaa05e379d72bf108e3df70ff369cc8fe1d8345bc9c81d1fe60452cfaeb7a03c3be74ba7e2adbd382f1fbcb3b18e3910dc1689f4df24e657fd4603cafb2c168bffb0cc6f32b1ebf0c67e2fe01e9d34cdcef1283e12faa6f30ee67f860e1ffe660a1efdc7f0ee7e2fed58c58b6e70cc6ef8d002cd6173db0a83f2dc0d0b78edbf77021e5bd078bf6aec1f87d41fabd14f2155bb0f8fd108cdfeb2330da93de83f1fc8ac6d310f2ac1a309ed772ff3734c5fdb48d64ee0fb72e58d4e75ec0f87d7202a33f0d713df4a5237bb7e4782a60b11ee681d15eed112cee1782a1cf158f4f86b6b8bf6581c5fa2af5a733823f762d30eed7d2efdd11f2efcd1d18d76bdc5e468311f2a3c007e379f5082cea75f760e8fbfa8d782cf49dfba3d150fcbebc030b7bdc83a17f099faf472371ffe64c2ceed73460e883cefb6b3416f7ab4fc463e10f2c30e46b8927e279b94b2cee6f6cc1d087ec092cec4930c6f342f24f85fc46442caef75660e8cf85fb93d18cfd9ec783f1162ceaa37cfe19cdc5fd3ceabfb990d79d80d13eeb152cd64fe9fa85f8de7c05a33df9188cf66cbec0d0c7f50d0c7df3b8ff1f2d85bcce002ce227078ceb1d0f2cfca54e3c41fb6f74bd21ef5780f17c5d058bf53beeaf46e618ebd77a2299c77f5bba9f25c6b7f4c1c2bfbd80d19eeb07f104fda1933cb678de2603e37eba01c6ef6f57b0a8ff71ff3d72c6a8b7e8d47faee88fb507c6effd188cdf3bdc1ec67d38c739e2e3c5a63393e21723269e60fde4f22c99d677b93e307577285eb7b8fd8f27ecfe9cf50e0c7d8a79ff8ca7ec7bfefb6b412cc627db81c57e823730ead9eb1158d43fb8bce399b8fe7a0716eb5d7330c663c3fb733c67eda1fa484d2cc6c39a83a11fed193ca57a651282b13e16f3f96ebc9860bdc8d880c5fe810c2cf21bae8fe3e544d4cb23c93c5ed30a30ea071b170cff92d0f81813d443d71730eaed9a07c6f53eb7b7b1c9bee7fa117c49a6f5024b30c5b3760cb6b19ec9e3adb13331e8face93ccfbaf3883f13c23013ba8a72e05d3fd0d1b8c7c734df23b53d8df86facf9da03e7e1b80f1fc82f7e76430813e6d63e229fa3be5e333194e4cd40b52b04ded31b8fe4e4653110ff2fa0a73a736f28d9a788afd67fa180cfd6a1db0588fe3fe7f32610accfb77c3f59721f2c77c493cc5fe0aaf00e37eb731788afa4e059ed1f8361f60d48f6dde1f93d914ebc7460a46bd2fe4fd37994fc7940f6cbec1e89f98cf5f93a578def5013c433d86da6f4c51bf09b9bd4dcce982f2b39cebcbc49a22fff6b83e4dec29ea15d95932adb704c433acffebf43c776ad1fd039d7886f5d315bf3f5356f09acf77d3d1d4a5fa65734f3cc3fe035d134cf7372c30ec355b824dc413dc3fb0e9906574dcdf79c4e2f74501c6fa5b74104cdfb73c3e9d4ea6d6887f7fdb10b3e791bef1f9940ddf1ceb078fe005f5b7c5e7e3e96c86f58f8d0246fd3a76c1f311f9b377b043e31bf07c693a9fa1de19df816dec07f804bb584fa3fe5accc47a86069e517b82002cd6f775b043f39bc6e3dde9923d8eeb7332035bd47f3705ec60ff824d3cc7fecf84ebefd498c19e2faf609bfa2be6f9f0d49c2d51cff5c016e5fb2b176c8f78fb8b15d8a5fa99c9e7d7a93543fdab1b831dfafde6287844f5d10e8cf1af49bfac39c63bff024f499e98ee6fb3fb937f7d023bd4fed407bb435aafb124d37e2d5d30b53f03cf87d43eeb0d8cf5dd7803c67cb7e1f63d75587f707df1e9fece7c30a2fd5d7b30f6b3469f9269fdc792cce5594dc1587fba52ffb84c1edebecd5e326f7f41faebceb19f2cda8271bfa6133ca2e727e0118d4fb2164cfa9c2892f978af4c30eca1f1c19321d7bf2bff7e3660e34ff5e53bb043cfaf5dc174bf6c0076a97fdb929805acfcfb6d0446bdbee4ed9f0d857eddd660f89b6e2298da5f05c4ac3f687e6bc0c311ad87e07a263f9f0fda77f094da537f8067245fc5f569369a1963d29f2b31eb5fdabfe20ba6e7a777e0d188ff3eb9815906c29fa78227d04f053ca3f6b65c3f6663260fd553a93d2cfca4fec91bc95cfeea041e517f5fb8fece2662fcdd023c86ff33c1d31167cd06cf21cf5c308d679d8017d41f0df72fb3e9cc1ef3ebab14ec8c69bfc05432ed47d38885fe5d4cc9b4fe37028fc8fecb37c9649f25784cf6ebbf82e7f47dbc042fe87e05f5cf4ce8936b82e7f4fb36113ca6f17a002fe8f986b8de80fe8bef4dd28fc292cce52fa68269fc4d1effb0db2f49decd0c0c7fdc92fe2ce6131a3f6d2d98fcb7bf02cf49bf370330d68fea5a30fdde38831dfabea3fe59b2fea178b0009bd41e4f03db23aeff37713decb5f00593fc2df5a7c1ee47eb6f2330eadd17156c8ea87ff7609bfc45590b267f78d5c02e714bfa6ab2f1207ff80136c87ef22918f34dfe06c67cd186c48b018dafcee3cd99c5ee47faa48217647f99609bf4c7a0f1b2160392afa3f6da6cfc68bcd69279ff949f6093daef4ec1f067f5817831a4e76de8f70ebb9ece177c806d6abfb3235ec0dfba2bc9b4df9bc6d7ed1376ae5f5c3fe703263f6f4f520a1e53fc99102f66d4be8cf7cf7cc8e4e3d7673e784c7cdd82a7d4de5a03c3fe751e9f3265c2fca09be009d94fc2e397394b87c99f186bf08cfa4fe3fd3b9fb0e7717dacc792e97c0b8f5f58f8bb20d6793d613e5f2cc7b49fc5005bd49e35b56fb1c4fcecf1fe9e2fd9f7743dfdde582ca83f8267b049ed59f3f9686eb2eb69fd782699d62fa83de67244f67de1fa3eb79643b237ef2698f4ab9e8347d4feb0008fc99e1c6a8fbd70d05f4762261e6f9f46e3e730a6f3160618fdbbe6f9c6dc5d0ea8bd0df5bf6b88f89aebdfa25f00a5f8ff4e32edd749c0636aff66019ee17939780e7de2f92a73f643e8bb031e537b7c133c237bf5dec073ba7f44f71f1a225ea3e78f447f79dfe011ddcfe3f22dc68c29feff06e379ba0e9ed2ef0b1effb1747d44f3b1fd0d5ed2f78d0236c65cdf367c7e5fb0009858bf07cfd15f7bf082f4a3492473f96f19d8257b6df8f82e66cb05f55fbe223630ff6f797cbc98b3f67079527afe82319d17e1f6b7581a03fafdc693ccc7d7a0fb194b97da7bbb111b63f2af1bae9f0bd31810eb7cbd61612d1dd2bf94da671943c8cfe7af856d8c69be6e0563be594f2573fdd7b8bd2c1c763ded0f53c01392c7bb4ae6fdd3717d5db8c684fa4bbb134cdfa767f094e28180fba3e5c080fff15fc0b309f5ef9764d24ff13dfc43cae7a3e5d0807d6cf8782d47acbdfcfeed0b783ea1fad50ebca0ef6f3ed82079a32f30f2c5644f6c627f5acce7df655fd0e1e3930460a662dc3f1cc14beaaf40133ca178a8069bf47cdf90ccc74ff3c10e8de78dfa676c8afd09b564daff5982b1ff36a6f64c58ffd2fed40b7836a1fac504bc9c50fd6101c6fc97abc426e2b3700fc67911f3018cf33ac99d643e1edd198cf3176e07463da4fa0063bf8826be47bd53e7fe773965e345fded806db217eb1d8c78f29612b3f6923ea9603cbffb0663bf4949d7b38083c663b3022f68fceb7bb043f6118682a9ff8c02ec92bfcbe9fe7dba49f5c30d18fb636c9e2f2ce7ecf7144f2a6097e4bbe5c4ecf7140fcdc0b0b734018bfde03a784af3c53504cfb15f47dc0ffb0bbb8160ecbffc002fa95e58edc1d8bf1a4dc1163d2f36c1a8575495609c5f1a4aa6f3a134febd83e2ed2f376093faafa3e72fcc01f1f50b3c217ddd5660ac37ad63f00cfe5407cf69beef5230ea35c6026c60bfe55532e55b39d8a4eb6f73b0d8df20ee6f637fe04a32cdff03b043fd757b904cf9d9168c7ae7ed2299ce7b3692697fc898d8c2f99ddb128cf3b317f49f85fa6348f75f1a06d9afb604c37ff817b04dfa1c0ec10ee9bb4ef22ecd015d7fdd8047345eb5079e907e598e60d2d7b40363ffe3762598e2d5750e16e703d692297ffc128cf35768af897afb36108cfaee5c32d56b0f9269fe2e24f3f61731d880ff5125d37ed80558ac974c25d37ec09d64de7fe64132f73fea27d8a2f15732c9b4bea008a6f655a23fb1dfb28c24d3fe470d8c7ae1ed5132e95b2099cf8fa6e82fd4e3c32fc9b4bee3125b38ef7723ff641816d99b7d03dbe48fc22bd8a1f9f95a825d9adf4af28706eb1ede5eaf060fe97aaf133ca1fc5605237e6d8ee009e5bbd5198cf58b4efc1efb6fb71730f67bae66e025c5df8a09c6fecae020998fafd248a6f3ba909fd93b6f4f71025bb0af52329ddf9849e6cf533fc036e993924ba6f96726993f2fcec00ef57ff12e99e2c34a32ed7f0cc1f017d5bb649aef7cc9bc3f22f13c97fa4fc3f859388f5a6d25f3f69443c1d86f3b06e37c4be54ae6edd354c9bc7dd791643aefdc4aa67acf2b18e7f134f13dced325a4ef26d3379affc95f9826e2cb952a99c6f7153ca57835fd0463ff691108267fb579028b78c2001b34dee14532bf7f62814df88b4832d52f2ab085f59d0118eba3752899ecff2699eae307c9b43fb405431f9454329d2fbb97ccdb938cc02ee95b2adaebd2f8b590dfc279e448974ce3f12998e67b4d30ce074713c934ff403e0be72d2dba9fc5e607defeca014fc85f5413f094e2313b954cfea0114cfe467901233fd41792a99e6a49a6f527c198afd71bc9549fb9822dea8fba944cf9502799dad782b17e6d7592c9be6782495fea42321fdff8c7f77cbcb477b043fa1deb9229ff4904e37cc697641a7f0decd27828aa647abfc45032ade7b982495f13b25fcbc2fb0c944032d9cb93606abf5949a6f314cf60bc4fc00a24f3f6b79960d29f5a914cf11dfa53d87bf82999d6df303e16ceb755a4cf369b3fc8ff7660ec3f57de04933ff0f760ac5f665bc114df2b67c1a44f57156c507f5f1cc9b49ff3198cfdc69bab60aac7ac4f601be7fd22c1781fc95132ddaf95ccdbabd492b93e794f60e883229e87fd9ef959326fbf3a964cf9e00318fe5d9d4be6fda192fed916ce83a92f92a93dbe64ca8fd11f229e4c6f92f9f3938164ca1f4f82b1fe994ae6df871f60acf79a6bc9bc7f62f49785f3b1b75230d95775914cf30bfacfc279b22df90f47c413a621995f9f7be011f99b6d2b98e2136d021e4f683d63059e4cb83e7ae2fa19dd4f3b83e734df943118f581f22099cba33c8397549f592dc026d69b8f9279fb6f9f60e453d6156c537f5a63c9644f8160aa47695330fc8dee0aa6e7c5b964f28791648a6fe692297e580aa6fa6628da8bf8c3bc974cf9642118fa38954cf58f89649acf1692e93c27e9936361ffbdd149e6df2b9e609c1f7d96ccf549ad24d37974e887d0676721998f8fba924cf1fa9364b247713df687754f92e9fc672399ea45a23d581f35af92f9f7b9f81eef13885ac1181f4b32d5dfa10f16f6a3044bc974dee9158cfd3f892399fcbb2d993fff26fa6786fd3ba23f711ef146d7bbcc7e283f7b944ce7995ec0639aafab25784af671db0a9e52feb200cfc9fe320f2cec650f5e52beae7d49a6f319e2fe4bd457766083f453bf80b11fa878154cf6b2adc1585f37c4fde0af235530f251717fc45b9e90d7c17ca848a67add5530ad1f74a160aa8f76e279c8e7c34630f97f3b174cf2379a645abf247fe35a781f90ff2818f3c1443297571d49a67cfd4930cd87da1b58e8ff5630ece74b32cd1fa564aaef7982697dc87900633f73694ae6faa0be4aa6fd789a648aa724637fd25a32ed3f79924ceb3d3330f6f325ad64de1fd98364927f2598facbd42553fd3594ccafcf311e16cecbdf22c95c5e652a99de7f267e8ff3c9e1bb641a6f4732bf3efb008bfd812f92297eb32473794b31bec87fa30a2ccea3ee0493ff30f79269bfe23718f53e6b2099ea0377609c7f34be2453fc7b914cf91c1f2f63c0e6478a0fb6e019d58be207c1538aff8fe039e503712b99e6eb5c3297a750c04b1afff22618fb1922c1347fc73bc9b47f4630f2f9eda360b2efab2e98fcd1ea158cfd83452598f47f6b48e6cf8feec1a8b7a40bc1f05f3bc9bcffb61918f596f85d32d5e3447fbaa48ff94030f6ffdc24737bf267c416f6a7ac3f2453fe580bc67e99122cceeb9c24533d6b2299f4ad108cfce30773fd500cc9341f7792a9fe6b0ba6f5da6b2399ce372ec1d85f1d9d25f3efd59b60f89f3bc9bc3fd4a364f22f6f60ec97543792797fa8a960d8c74d32f9932918f61ed49269ff832d99e44d24f3f61a23c1d43f96fc1ef1fe1c8cf763448e645a3f16cfc3fe3d632899e2955832cdafd01f0be7d5ad4a32ad9f3792b9fcc64030ced3d792b93e9723c9b41feb02c6fe67732b99f68b7c4aa6faa3180f9c17f6499ffa032dc46bf098ec5d8f24d3fe08133ca1f530ed049e527eb7f50593ffb83c48a6fd570a7846f7d36b30e6fff25b32d5ab73c1145f28ef82299ed1e660d473b64f92a9def92698fcdd5a3cdf46fd24914cfbcd74c9b43e21e445fda611f7437cb1fe124cf65edcc02edd3f7225d3fb001e05d3fc5ebd108b7879bb93ccfbc72f05937e66a9605abf538e92493f56e021d99f6249a6fa5b2b98fc9f72914cedc3785a789f52f12698e42943c964ef17c9e40fe792697e1849e6f2648e60ac470660bc9f243b4aa6fd3fa1647ebda20826f9d24c32ef0ff55e32d5d7447f60fe2f9f25933f5a4aa6f8e62c18f9502299f40ffa61e1fd4b4a2899f6279492495ed19e29e297028cf795048d64dedef05530e29137c9e47fe4efb19f740cc6fed152134ced0f55c9fcfb488c17dedf74b9934cf64dfa3c326754ffab0cc1643f510ac67a78ba04633e77466083ecb309c026cdffa921998f476582b19fa7ba0aa6f93e5e0ba6fca6188051bf4b447bb1bf4aff00237ff60f92e9fd41f792e9bc7d2599e6f717c1d8cf247e8f7a5d160ba6fecf23c1b4bf21a0f86264e13c72f82499f2fd57c1f06727c954bfcec098df755b30d9ef7a2e98ecdf78974cf54cb447d47b3d5330e2cb0fc9b4df47dc0ffbd12ea9647a9fec1e2cde07f92e99f60b1c05239e3e4ba6f9df974cf9d74932ed9ffff17b2e5f70014f90ef288261df8664b25f5332bd6f0ae36be1fc4ef92499f22d4b3297ff593c0fefb7525dc9e4df3c30de5fa53a9229feb12553bc2ec66f46f2565f92c97f37609ca7b4df25d37e825a32adff89fba39eaafb92293fea24f3ebb7627cb13ebbfd944cfbadbf2453fe37154cf287a664d257d15e715e80fa6fcce673f2af117846f94076075e503d2188c1d88f9a9b82c91f2457c954cf38832df2279ba9647adfe70a8cfaecf62098e2ef6e2699ce27ed04533cb2d5c0d8efaa3c09a6fa46f12199ec5d3c0feba51dcd9f63517f5dbd0886bd3f4be6d76f7f30d59b62c164afde5432d5271f2453bdf0118c7abd77124ced4f1ac914afae2553bd5edc0ff3b9f32498ec6d1308a6f66c55c9341fdd83313f9ba23da8ef46a564dabf664aa6fd21f27b8a37e291643abfe249a6f9ce174cfb13a2028cf78b25b9647a1fd4a364f20fdf92c97f0c25d37a512599d607a03f22bf375ac994ffa49229ff78944cf94a2618fe48fe1ef59e4632bd3f270163becf2ac994bf8beb71fe4b0d2453bd27964cf552d13fa807da2f9269ff612499e627d13ed40f424330b55f13d763bfc6ed4332c50f37c1f0f78a64daff3d964cfb43c578637daf7a138cfd39429f719e6745fa30314df21f590ec6fedd32134cfbb10c5d30f98bcb8b64da2f3c01dbd87fbc174cf5c92001e37c4d25eee760fff1b7605a0fc8b792e9fc81b8bf43f149740263ff68fe2a989eb722fb9c8878201849a6f75f9e25d3f37cc974fee15532bdaf752898ecdd0904d37a475080512faf7e30e9432e18e7f56e82914f5482c91e0bf13ce4ff7e2698c627fb924cebcfe2f7d8ff1b3e80719eaa934cfaee3992491e717ff80f6f2699f22ff13dcecfa753c9e4bf0e92293f394aa6fd139660b2cfc8904cf9df4230e68b4a32add78bf1c0feda740ec6fbebcab3648a8f2792c95fd492299e1848a67ccd164cf25b2d58f887ab64f2379d64de3fea4132bd6f4efc7e8e7827944cfb7f1e2553bd4f134cfa6c799269ffb6781eea8df14432b57f2718ebe591645a2f8b05231f15bfc77e0f652699e229f13cbc7faa9a4ba6f361427fb03f5013fa8cf5e2c495ccbfd73dc924af180fec0fd33e24737922f17c9c6f6cc91ea626f69b5e13f082fccfe64d32d547bfc0385f565ec0886fba1cecd07a663394ccfb237b05633d627b144cf6779949a6f75fd682c93f06349f4dc5fa433d154cfaace982697d721b4aa6f3c11918f585742299fce5bd64aa67958229be5ac560ac27ac12c178bfd79b64da0ff1e37b7adf95fc3dcef70592a95ebb174cfe3a10cf47fda01c08c67e1b5f32bdcfb0134cfde12a92493ed17f585fc81f25d378dc49a6f8e253308d57249e3f417c7a904cfbcd7e30c5d382b11e982592797f24df82b1de954ba67aa6907f4af69baec138af6c8d24533d692f99ea733bc1e4ff3c0b2cde37be944cfe712499f2b1b964b2675732c52bd0670bfb45d54832e58fba64da0fb301e3fd8d4a2499d67f857ee0fc72f82d99be5f81713e3e194aa6fd49e27e588fb89ec1884fae13c9d4ffa27fb0bff0229e67537fae481f66e612fb2d776083ec3debc026eaa53618f18a3b0323fe580f04d3f5c98b64da7f63825df217852e99ce77907c33113f6c4dc134df6f1f24d37c9982b17ee04f05537b9a77c9148f88dfa3deb07a92ccfb7f73168cf365778229be48bf25537d19f28bf501e55e309d4fc94f92c97fcec158cf2b12c1e41fbb4fc9b43e3d104cf3f7f6158cf87ebb170cffe448267942c1e47fba05187f1f455049a6f5614330f4ff0d8cf3b88ab83fde3770d94ba6fafc12bca0f6a557c1c80f6dc9644fb964aa7f1492a99eb1934cf3f718bc44fd632199f2ab67c914bfd782518f16e389f78346a23dd8bfa58c25d379ba4030c95b5f2453fc5c824deacfec2299f6eb6c25d37ae74630e2b94632ad170bf9b13fb87b964cf514713df61bd4aa643a9f0f7bb31cecbf10fa28f6e3f89269bd83e2adb9399f52bd33032fa6fcfef9086cd07e8d95f81eeb1b97a964b2bf0dd8a2f958ff02dbb41fbbbb825d9a3f2eb5608a3fe28560caafb6141fcd45fdb11a83b11e180f05d37e5c5f114cfe669d8051ef6f3dc1a40fab108cf3d9e55a30ce3b1a60d4d78bab649a5fe5f7645f978364dededbb360f247452899ea616730d6e7d6779269fdfb4330f9bbd4148cf8e7058cf5b8e44932bdffe25e30f6835c24d3f9d1b964b27f713decdd16ed9b937fd2f792a99ed2082679a247b0380f33964cf3ab18af05c52f57d1df381f5baf2453bcff0046fcacfe60daaf6a4aa6f9ed4b30ce7fce25d3fedd1918f65f8af1c37e6d4f954cf9cf5a32c927fa17fbede254326faf22aec77c1bd582a9fd971d58ecef3524d3fe5ea1bfd84f97d1f82ec47a83be124cf5c8ca07dba4efbab8de9df2dffba44f0b51afeb5cc1747d32154cf61eecc043ccf74f9269ffd3098cf7495c1e25d3f9c14a30ad9f281f92693de2001ee3bcf34430e94f71114cfe259883f17ef6b52599de2f36144cfaa23c4aa6fafd188cfa79d60a267de832c1345f1786649a3f7e30cd97a2bdc86ff55232c54fb9648a6fc4f367e44fbaa1649a5f669269ffb7f87e4ef6915f2453beaf4ba6f9443c1feb655a2c99e47b944cfb532493ff6bef25d3f86ec1e2bc532318ef1712fa82f3cdc55e32b5ff1b0c7b5acd25d3df9fa04ba67ac25e32bd0f44b4cfc0f95ad13f787f759c08c6fb8f34c9141f6e2453fee80b46fe22fac7c2fbafef24933f17fa8efdf9590dc6fb8d4a8a079626ceb3d513b04bfa5a527cb664f645eb65067848f359fd8369bfec063cc27ae45532d5e31f25f3f15c3d83315f5d12c9544f740553fe1e6592a93f3dc158bfb88127145ffb9560b2873a96cce5d75f25537ce90ba6fa62f283a95e2ae49bd2f82b0f82c93ef385645a6f17ed453d39984aa6fac04c32fdfd5607c1a42ff14a30cdb7b74232e5a76f60e483fe5132cdafb960c4fb5f60c4aba52218ebaf7b30d69fb6e27b9c1f0ceec1d82f962b92c95f1d24537da7148cf93d05239f534f92e9bc8bb81fcefb1547c9544fabc1383fe68af1c67e92f807d3fe43213ff6af7662fcb19fdaa37cc410f5ebfc5e30cd1f6b07ecd2f85a347e06332faa8f1cc0d0efdb17784cf6e91a82499ff44ff004eb318f92693fdebd649adf5f05937efa67c1347fe91618e7bb6e7782112faa60ac8736a1601a8fac00a31ee98c05e37d155bc1347ff8aa647a1fc009bca0f1f21682c99f9ae2fe0b6acf360763fd62bb168cfcb0148cf7790879f1be9ad4954cf53cd17fd8bfe49f24533db1164cfdbd7d07e33cd346fc1efb17b789643a4f300423bf303760bcdfec42f669b27885ee47f38169e1bc977e124cf18d3706e3fd11fa163c22fdda9482a7b43e7805c3ff058660ba9f2b9e87f364d14632d5fb4792e9ef37fe02e33cd926028bf364efe039c9b712f747fdd9ad24d3f58231fee58b601affdb9b648a6f7230dedfe12d25d3fa760a467d3817f218145fd99f9269bda1924cefdf93df23fe7e009b349f98623c2c1a5ffb2298ee97d8609c3f32e6609c3f8b2cc9646f0bc914cf3f4aa6786607c6fe958ee20f8bcdafb43f81e20b165e93fe5c3e25d37e30f13dea3ddd093cc27ede2d18f5983804e3fd1d9a25989ed7168269ff61fa089e223f9e8167d47f862699d6f39e25d3fe68152ce2b70318e7c9ec67c9f4fe12138cf70f252918f1932b9e67507caf08f9f1be9938069b648fc15e308dbf32108cf7df88e7637f627c150cff7a0163ff42f000c6f99c88ec9b4d37a867d1fc62b3f1a3fd3c743f5b8c5ff102463cb2da82117fb4df9269bde12498ec510f25d3fef01c8cfcb8b425d37eaa5232bd5f2506235ed85a9269bda4154ce31d89f6cef17ea8037841f76b447b17d84fb6012fa9fd6b211fea49978b608a4f0c156c423f3bc9b49f3602c31e6f7bc1d0bf4a32c50fe44f6c1bfb3be22918e7e93a6287d907adb70ec063eacfd51b784afdb3d1c0c85f8a5232cd97afe0398ddf652d99fcf75130e5879d09c67c961482c97eae7bb049f74b3ac9349e86649a4f2692b93cb978be8df749b88229be509660eca7f39f24d3f922713dd6afaedf8269bcd690c7c6f9d755001e52bc5b533ceb5a63d29fab2199ce63edc1139a9f82083c25f9f5068cf745dd2cf082c6238d25d3fb1d378229bf503ec178dfce6a0946fce9bd0aa6fe5ccf04e37d0af27aca77ac1bd8a2e747df9229fe2dc136f98ffc4530e9f34a934cf9f10fa6e78be739387f48fde9daa8f7273c3e310716f67b260f9269ffde1318efefb91e24537dcd06e3fd79f6156ca0deb1904cf6a080d1fe6a2199e67b5f303d4fbb801dd8fb0a8cf8f9a611db78ff5dac8211df745f60d413133e7e2c389be17ccc183c27ff97459279ffac4b30de27947e0826f94c4532bd7f5d032fa9fd6d2a784af58e21d8a0f9e1aa48a6f53f5b30d58ffd6730de5f94ad89ed01d9ef86eb2b0b2eb0feac6fc04b92af7525d3fbcd8f6093fccde64532d9cb4d30c57fe1128cfd33eb77c1a41feb028cf7355a1f82e9f9ee1cec62ffea9b60f227892918e785f0bd8dfdafe9b3601a4f270463fda81980f17ea59adbbf3966fd41ef472dc14bf2075b1b6c60fdec4132d50f0bc9944f1cc126c693dad7bf5e9ff2075c6f63bd6b45fd33b1e6549fb8adc0580fdc7682c97fdd5ab035a5f74309c67961e50bec523c1de2f736eaf7f11c3ca4feaba8bfa6d664467fffdc080c7f53b492a97e6f08a6f686776013fab4964cf69982717ed224ff30b5b15fe81608c6fbd3ce60c48b2d8dd78cdd8ff2eb5430c5839b5730f2dff60086be74a4af33d6ff148fdd8391ff6a74bf390b30693de808b6917f64c436ce8fdf1230f6bfb7345e0b6b3a27fbe9c0f319bdaf8bfcc782a5f7e43f0f60cc4705f99f256b3fedf71c826d92ef3625b627349f68dcdf9b2c9f9b927f237d3458ffd1fc5b8327f007241f530f1aaf6b00467cad51ffb2f8674efd41fed5b6711ed0e4fac192cf39b57733022fe97ecf977feda32abf7d8c9f3e26ffa7827fa74fcf0afb9da5daaac3fe58ff6a0be8f3df21cb2f72b9ecf3bb5c0afe9b90afff77f7df5116d62247f5d81ffad87ddba87590cbfd87bfb3f1f9779605f20899fa6be8cfffb79fff167b71e9f393743ffadc1663f4e33aa96fbdedf8eccf3f18b9ffff65e16dfbc90e6009240d1fa9bf2b3bc9439ee0df4d1661eb3f64f9313a3f24f3e4e717cbfa7791e5379fecfefa91d758f05a8e94457a8a7f2b590235542335561335553335570b364ea55aa917b5669f86e951ab76ec7365b2de544dd5d99f15ff9dc67eb1fe379365a3aed827652391a85bf6b963d2ecd43dfbec982c07464726dd91fdfb4e3da9f74cce7bf5817d0c76e53ff4daff5b6479e43dfdc446e699fddb597d515fb94ebda9efea87faa906ec9a9449f8c524f85607ea501da96375a24ed5993a67d2fc1bc9c25a7a5637ec9f91ba607f02d8fd92c9f2cafe6929aafaa4284cc7be15431d2ba662b18fad380af31a8aa7f8ff3d92fcf7cc954aa0844aa4c44aa2a44aa6e44ccf5ca63d2dfbf4b6622a059b45064aa954ca45a9954669954eb92a3745537465a5acffe8b5ff37cab251b6ca9db253cf8aa2ec95036bf1513929f7ca83f2a83c29cfca5979515e9537e55df9503e952ff6dfbf9581325446ca589928d37f23596c65a6cc9505d3b393b26413cd83f261288661b044c0b00dc7700dcff08dc0088dc8888dc4488dccc88dc2288dcab8a87746fddf23c99f9345b58ca6ff23a390df6677a3353ae36adc0ccdd08d95b13636c6d6b83376c69efd391847e364dcb3cf897d8e8c1fd8e7d178329e8db3f162bc1a6fc6bbf1c1b4b0cf02685e757f9b797f9aadfe999ff8af6561527c1a5feccfb7313086c6c818315fd4186363624c8d194b9916c6b2370ad3304dd3326de3683aa68b8fc73ebe19b04f684666c465eaa53a9a31936a6726666a66666e16666956e6c5accdc66ccdcebc9a375333757365aecdcd2f33b1f2eb1cfcd764311a736bde3169becd9db9e7b21ccc8379344fe6bdf9603e9a4fe6b379365fcc57f3cd7c373fcc4ff38b7dbecd8139c467648ed967c23e63736aceccb9b960992a3334e3de322cd3b22cdb722cd7f22cdf0aacd08aacd84aacd4caacdc2aac12b9dc2f91c5ffaa2c56655dac4b3f2e566d0cad5a3d5b8dd55a9d75b56e9666e9d6ca5a5b1bd6d3f7ccd96ead3bd6522689b5b3f61677bfd6019f2393666a9dac7beb817d1ead27ebd93ab351da592fd6abf566bd5b1fd6274b98bf5884b0601e3d61b3e9c0faeea3cf1fd1d1bfa2634cb31a8bfe82f001fff74a89aca135b2c6d6c49a5a336b6e2d7acdb196cc74fa4a9ed18f85b5b34d48f2439643bf4c614e6ddb766cd77ab03ddbb7033bb42326cfc178b4633bb1533bb37336abda766197ea935dd997de92fecce74fc932307756cdc6646055aa67d77663b776675fed9badd9ba71303fec95bdb6376c249ef9676fed9924625414662bcc5e602bf766681bf6d6beb377f6de3eb0cfde3eda27fb9e8debde7eb01fed27fbd93eb319d7b35fec57656fbfb1d1b07efffcafc9f27cb16a66274cb78cc6f8b4df992c1ff6a7fd657fdb037bc8faf3c47a7864bbe6dc1edb137b6a2db924bb7e64fab161ff9cb1f6ce85fd9b91bdb0972c485698ddcc1dc3311d662c8eed384cd2bde33a9ee33b8113b218f5dd89545df17fcdecfe155954d7183ab113333bb1edda499cd4c9ec2f27778a5e0ea7640ff0ed3d6b55653d3b17361acf4cc706cc6216dc6ed8ff3b356b6be3b44ca6b9d3998173756e8e66f7938feeac9cb5b3b1b7ecf78eb365d21c8d9d73e7ec9cbd73708ecec9b9771e7ec9107ecb7a7eb6a03f234b2f09f3c683fe7ecea3f3e43c3b67e7c58cadb33db1ced6b33d6656cc3ece2b6b5dc5dab5c0a7f765ec63cfe9e374f8bc39efbd24f6d20e9d0f66fd47e7d3f9ea7fe954ce379366dffff5f6cec8e9ff5acca933b3eb9fe4f8576599ab9db3b05f9c25fba1e21a6ce2b08c23f34accd3bab6ebb8aebd702a73e17ab66b1f5d9ff9a8931b981fccdacfaca5f76ec86c2ae673e6d18ddcd84d98bde0e3746e6a7acc73b02b594fbcd93336be67377373b7704bb7722f6e6d176e63356e6b358ae67656f3afe8987a70afaaeddeecd6d55cdd5db96b3626cfeec6dd9a43f7ceddb97b3622dbde86dd837bb4576e6031ed331df7e4debb0feea3fbe43e1b817b765fdc472195fbeabeb9efec5707f7c3f9703fdd2ff7db1db84377c474f1c0fe7dec4edca93b73e7eec25daabd2f6091b8a7aa81f70fbdda9f91c533d8f46d79b6e778ae937b9e71b2179eef055ec8e4601fdbf0222ff612e6030eb6d1eb8c977a99977b85577a9577f16aaff15aaff3aedecdd33cdd5b796b36e7c7c6c9db785befce7a70471ebb0b1b5d9dfd3ff36fde8e59cec1db7b07efe89dbc7bb5f01e58467af31ebcc71f5af5bb1ff853b23c79cfded97bf15ebd37a730637362dbde3bd32f2e099368cbe6f229b39ae7de76bd0fefd3fbf2bebd8137f446ded89b78536fe6cdbd85b76441d7a3aff8866ffa966ffb8e71f45ddfb31e7c9ff9e8ad6df8811ff663e547ee8069e4831ffb899ffa198bd6be51bffd523c9189fe75599e2f7eee177ee957fec5af0d6603e6d46f7a49fc967d3aff6acead27ffd6cf77bee6ebfeca5ffb1b7febdff93b7fef1ffca37f62f966a2bef8f78aea3ff88ffe93ffec9ffd17ffd57ff3df8da3bdf03ffc4fff8bf9f485bd30c74ee57ffb037fe88f8cbd3ff627fed49ff9737fa1382c27fd6679f70f597ea97dfc99d8d25f066aa004060b112da65f6aff97c0f7fae5b7811d38fe3570cd0fe31478811f04411844411c24411a64411e14411954c14509839a7d1afb3d68838ee59af3e06a3f07b7400bf460c5fc48ef0d9560ddeb99ad30d906f6c27a0e36ecaedbe02ed8057ba50e0e4a191c8353708f0af54f35ab3f2d8b1d3c048fc153f01c9ccdd829ad73f012bcf6da15bc05ef81137c049fccf38c83afe03b1804c360148c8309fb330d66c19c49b47016c1325443253442d3188416fbc39c71e8865ee88741188651c86cc73a8709f3cb4698f29881c50f61d6fbfc300f8bb00cabf012d661e32fd421d3b41fb2387f94e5e77af6cf63d25f1db661175ec39b19875aa8b3bbafac636f27e13a5c33795e8c7b2f0d37e136bc0b77e13e3c84c7f014de870fe163f8143e8767f52d7c095fc337ab08dfc38ff033fc62d2982c22f6d97ff90e07e1301c8563e3184ed82cb40dd6e1943d63e6ee99fd7c9b53f6dfe7e1225c466aa428456444e68fcacdaf5a46b288ff862c28f1d4c8525fd5d7c88e1c7f19b9e673e41987c8376751c02375a61351c8e2f7cf88e524511c25511a65c62dca8347ab65f369cafe3c4645f01895aa1255d125aaa3266a5910d345d7e8166966678ccc75d4467ab48ad6d126da4677c629da452c82f0039ef778d68ecdb40bf6bc7d74888ed129ba77d2e8217aecefcdabed866af4d1eeaff6f2932c068fb043b77516ca2e7a8a9ea373f4629ea357f6a437e6750d16a79ca37773c2e6e8aad7eae823fa8cbea2ef68a0ce153f1a2aea8f2a2c7f9e1b8da27134096d2b8ca6d1cc8aa379b48896b11a2b56111b319bac629b85166eccbc3d9f73962c7f93b29843e33ef6e3200ea3fb388ae3f081f554cadbcafc5a1f25fe2c0b7ff68f7131d4f8f9e22cd4f73889d3388bf3b888cbb86277bcb0f87111d7d6dedd5b4f7c2639b959dcc46ddcc557ff515dfdb4f662cb3bbaca5875e25bacc5ba3f8b57f13adec4dbf82edec57ba5890fea323ec6a7f83e7e881fe327e3143fb3d866c9bc7380b86e689de373fc120ce2d76011bfc5effd88736b3055a38fdeff992c0ad34726cb6b9cb8adba8a3f4c23fe649db7641ec6b09ee3da665ed3fc0c33f6dcaff83b1ec4c378a456eaca7e51ee94713c862c3c1eecff9dfdb7493c55f57816cfe345bc4c54e3c17e4894c448ccc44aecc449dcc44bfc24484263efde9b3e8bd8d887e7a42c3b65f3d6d17c4da2244e92244db2a84872b1baf07765b1c886f8155b36bbb2fe65914fa2b8499194e69b71f26fd69e8dc9d9b998dff6c13ad953e39054c925a99326d6d5f7beea9db4ccca52f40d55c1d97d95bb385332bb4abae49adc12cd38252ceb4956c93ad924dbe42eba26bb641f1c9243724cd82c657a8ec272014364d94c9b4b2f4dee9387e4d158264f09b34ab146d2e722ff4c96e499f5e198e50e2bf6efe7e4257935dfad3e3f3f276f56ff8afa7df26ece8dfb709c7c249fc957f29d0c143d192a8b64c4abe3bdc7b4fbac8dc9c264b2df93713231de9269324be6c63159d8c76469c6a99a2aa9919aa995daa9e3dfa76eeaa5bef1603a2cbfe1b2f45910cb54b769601cd3308dd2384dd294cbc2d76dfa7cc4180aaff6932c96b0fe3453466e6b97cc8e9d344f8bb4343fd22a4c98f75a5afdfe8687f4621becee75daa46ddaa5d7d451f4a04b6fa996ea91c9fd3f978549c3644957e93adda4dbf42eddb15fedd3837d4c8fe9c9d8a7f7e943fa18fae953642b7a344c9fd373fa92bed2c8902c2ca7db4681719fbea5efe947fa997ef5feb197a56f7f9f5bfd2acb8f91e17a78607dbb5412ff2139a7dfce9069eb673ae86da5f7c54ee5fa696f8f553a4ac7e9249da6b3a4b50b65c3f42c5177fe23ef31361a7d0edad724d379ba4897999a29c63163f971b4efb3e3ccecb3e2649559999d39ea57ea0475e6665ee66781e9fa81a3a06ab0eb675096e1c5599845599c25ce23b3172e8b6af5b9d52fb2889a9add3f99d14efd4a064ccf952c553eb2cc74cc2fe61b077dcecbf477613d982316e37efaeb2ccf8aaccc2a61e7e45b98b34db24b56678d5dc763f53b6bb32ebb662c62f343d6df6ff6c2fd66de9c652c99661ce3a74ccf56d93adb306bd3b36d76e74efa5999c53363a603cf76bfcd8445369691edb23d93e5901db313d31d85db7491ddff268bf28b2ca67a973d3032b24743c99eb82ccc37f67d642ebcc4661146f69c9db397ec357bcbde852c1855577d4bdaec23fb8c9e93419a655fd97736c8d8e866a36cec8eb24936355da7cc66d9bcf7ebacbf17d93257734509552b377233b7723b77d8377d3d6dc29edad74398b7cedddccbfdec900779a828ff4496be024a7dabf8bd36f63edacc23c330ee982cbd97efed70c024619219f7799c27fe364ff32c3c30597eac4172bf95e779919779a556f925aff3266f8d63dee5d75eb7dc613f1ef9cdfdeeb3e25cb316f153aee7ab7cad9eed32dfe4dbfcced67396c1b09879c8729a4bafd9feb7719f29f93e3fe4c73cc88e4c9b1392c52afe812cbd0f559209d332db2ed5263f1926f32baed05ca6678eed5877ecbfbce6f7fe5dfe104cf347a3fd690d92d97afe943f671725cecff94bfe9abfe5ef7dd4937ff49909af719cddaf6cca73628dcd8871fe997fe5dff9404d9cc833f3613ecac7f1579ff1997dbc4c51b4cfee30c9a7f92cc9988e1d59a699f47e377c0bdffe200bb75792259fab7b854d65ea77be302c63cfd2fb1dd5bc481673943bf9b2500b8545f5b3e8814547b6dcabc0575793b1fa919f0ba33059b7d9ac557d2cbfe8f312ebaeb7e4c2e96b1785cb62ad53e1157e111461112923d52ee22229d22233f67d5ec365611ac6aecdd98cb92f8aa22caa3c2459faf6b398f5f597f9e5375958c6b34f6fcc62be8b0b7be4ce74a97227646177ae8ba6688b2e288a6b714bf25f7684303d53fc645268855eac8ab5710835e7b597a5d8b06cabaf6a7ef4d5be60cd243916dbe2aed815fbe2a0d8c5317b284ec57df1503c16cc3efa1a279764614e0b268f7128cec54bf15abcfd248b1aaa7f57164fcab22bde59fe742a3ed894b5efa33c5420875c9645f1597c15dfc5a01806398ba2c90bffd8555114a3625c4c8a692f4931ebd72c989ea8c5bc8f467b5b6677e03163b12cd5ecbb544287c540d7d250c2d22cadd22e9dd2354ebc22c2ae36c7f6a1f498cdc6a55f06e1ae64290dd731f7efc822d654c40cf3adb665c472b053191b2ecbef852cfb5e16f3cb3a9749999659996749745f163f564a7824669465599597b22e9b5e92b2cd34661b565f3b6371dc985bb4e10ffaaca7ecca6b79b3be4acd0a4a9d8d67c4a45995eb72536e992cbabdeda326368e5bebbecf64cabb7257ee7b591425cd7a6d28b552fb45961fd13ef773ea8dcd103b75c56439183e1bebc81c5b7d3d2cb0674e63cfcb63792aefcb87f2b17c6271ce86e527a398c594ca9d5d97cfe5b97c295fcbb7f29d79d12eef32adafee9bb3bebec13f337b5f7eb079bc2c3fcbaff2bb1c985d392c47e5b89c94d3c42d67e5bc5c944be3c45c7d156a7c4c0f665f1939564a655466d06746a7e0d4ef2ab2aadf62fedefb3059d8b7663f36c8d834bbaa2c26cbbd19b2deec97483a264b6b06c6a1b22bc79bc5e3a00996e5c4dc562e538ba86236cfa29545e5574115329fca66bb3ea736471513d73a313946fd9a4515dbdb2aa9d22aabf2aaa84a2bacaaea52d55553b5556745c1b1ba062b362e5ba7a355b57ebda3aff254b74aabf42467b21c83a36ad9f51f641151a5cf6571d488e9e246bd315559556b264bc4662c268b193269f64c96a37bf65a6fae2e2387e9eb5bb5a9b6d55db5abf6cab53a54c7ea54f575e17be6c717d681c5d5233e26a3fe2ebd3d570f4c96c7eaa97af646d5b97ab1aaead5dc556fd57bf5517d565ff128afabef5e966ac07ac2e5f5cf678bddb11a56a36a9ce4ce23c6c5339adf627e4bca6270efba60d1ee539ac5a36a524db98e912c51af654c965335f33a8f656bca3c34ccae9a87af9eaac6ac3f17d5f2a26637f7f5a25cb81fb615f38349d17f26b406c3ee7570377d7e75312fd6c5be38e1cbc5bd78179f8d897f092e6134b8449798c9d2b91fccbadefb159cde673059946a7449823e47f6d9c7fea32ca859283c96225912f549bdbfa4ec9e593fc6fdfa9c6df523d4af3d18a774e75d2fb9925e8ad0c8eefbbcfd525eaacbe5525f9a4b6b9c2edde56a6fcdd1e5165f98bd93244764f10773e445d68e5da55df4cbeab2b6c2cbe6b2bddc5d7655a7b697fde57039ba2fbd2c173633b1d8cde27fd5d684fde2fef27079e4b2a0adfd5add3f95256071f24d29c2faf27479eeb585d61bfb95a07ecd81e9d8a377f35545b3df7975c88ca6feec72bebc5c5ecdc4383afae58daf136d8235f75dbd7e8db92c7c3d96f5f196c5dd5333bebc5f3e2e9f97afcb777cbcf06a13d388e16578195dc66c869ddb6c66cd466c967db5ee7adbbf4c2ed3cb8ccba2f0bcc2fe5d16392f4096545373b5cdcf97f9657159f6eb90bdcdb2d8b85fd50accc08d8c83a7298f8a1fb4c620fca8d55a49b6b5519bc98ac9f9565bb56def1cc38bfaf99ecd8d336ef74cc7b8341e9b3146e6dcdef82cdeac9ddaadbddaaf83484b46e9ad0eeba88eeb84e5ca9fcce3796c6e9db008f4c9dd32590e755a67756e325990875bfd0aeaeff9cbcfb2287eaa2b6e5dd4a5f25557c68149c0bc0fb3dfa8978569716cc69eee2b6aa9cc422bfc8caa9a4590ec7f0d6b5beb7eb84347cdaf2c63af9cd73063f67faa22f6ebdeaff7d27875c746f9cbfc626d5cd6d7fa566bb55eafea35d36ca77c8af27a536fcdd8b9b23cdceb6318d6239bdec2eabb7a57efcb3d932515759e3fe695d8112074cc55efd44370523ae5b13e184cb3597e7f6fdbbc12cfda581f599b4ff57dfde0b6a1556d13b77eac9fea67e3549feb17a65b8bfab59f159cd728b02d1691ceeb37bfb1b7fe376fd994b220ca89acbdfb5abfd71ff56738a8bfeaef7a500fcba01e992ed3c27db17077aec3f29881cb324b63578feb493de5b2507ef20f7264f6a797a59ffb13f6ff0d9bfda7f5ac9ed70b9657b2fc8bc52e5b7b592f9d779bcdc98dda288de13f5a35f3ca1f8dd958c64363db47f6d9374e3f438693be6ed3fbb2c665ff34a2d0def09a9af1cb1ae0d074eb5be3357e1334a1f3d4444ddc244dcafae291e54977eeaec9ac2dfb158b429bbc299ab2a9b8bdd09ca8f42b763fcb42732397c5e4b364aa8cd2cc99c77a7369eaa6316377c3eefb7039352d0b8359d6e186c6aee99a6b738badd0b48a466b74fbc18c9b557aecc7c57c6fd64cdfc76c2c3efa5cbdd9345bebdcdcb9dbbe8283d53fac9c9b5ebfb3a4d935fbe6604d9a63736aee9b0726c363f3d43c3799bbeb6be64c2fe3e6dcbc34afcd9b948559c51f65a1d95ecaa2f1959bb5faa138cd7bf3c1a22ac7ff609e89d973bfa6686f9b4fe3e0dbcd57f31dbae167ad3483669828d60b7bde283359ae356bc66c961b46611f41369366dacc9ab971b296eeb6e1e3815566167d9b9ed3354b63efad5bb5555aa3355bcbe8ebd581396efb15c45d9f2b87ba71689dd66dbdd6ef63181e7719aadfaf09ff365752a5cfa4bdc2fdfa937a8bc76de03dc65d1b1afd4afdb658703fbbed6dba8d8c531bb7499b865ef5de666d9e9fdaa22ddbcad8370fed85595585fce4beaddba66ddbaebd5e5876dfded8bcf3ddd70ee4eabfefed5aaddf1de36baddeaeda755bb35f6dda6df0dede056f5ec89eb7734a63d7eedb437b6c4f52163f38fd41161bd97abff39945bc2c951e313ddbe5b9a2b7f7ed43fbc8b4f7686ffa9d05b5d53ef55adf326fdf9edb97f6d518861f4e5c44ed5bb269df59ccb3cf3b7bc9645ef5f949fbd17eb65fed773b6887eda865b3068b697aed123b19f67e906bf6b69db0acf8d44edb593b6751cb397875ed76d12e3bb59fdbeace38754a67746667c571922779af472c8e39fe4116e75759d84c99a94967770e93e6dab99d67192cd770d89cb063be56ef7c7b5b9f7d3753baa00bbba8da767197746997b1b0b8e8ca7e6dc8db75157bfea5abbbc6df756dd775d7eed6699ddeadfaac8e723b5ec95b326b687b8fe2fb4e65dce75db7ee36eeaedb76776c02d875fbe6397aef0eddb13b75f7dd43f7f8ab2cbfc563b40fdae2fbb87b59fabdb76ef7d43de7cfddb97be95e6bc738b9ae7de8ff1a4166c38eb3eddeba77964f9cba8feeb3fbeabe9d85fad80dba6137eac6d19d195b0b33f6b56ed24dbb5937ef16ddf2aa5e95ab71358d9dfbca7763f9bd1ce6d00ffa99fd6ad97bc7bada4cbe73b7bb322bb18ee1cadd5d5deffdea3109dfaffe35b886d7280fa302b66ffe1d1d13eb0b72bf196a7fdcef5de36b52b2d65d53ebe19ab119ef6c9dddcf7eb5f79ab3ff5a5ccb6bc5e29897ebe55a5bfeb5b9b6d7ee7acd27d7db55bb321d5533b30bdf8da69c5c57d7f57573dde6937efe655aa8f4750ce623a2be06c6f7638dd87c74ecfd38d515ade7de5aaa8171bcde5d77d7bdda3847b5edab2c5993353c07367f9c07f8afd7f89ca7ebe17a8cd953afa7eb3d3dddbf998b6641d1eef5e1fa787dba3e5fcfd797eb6bad3069deaeefd78febe7f5ebfa5d75d74139bc0eafa3eb987d26d7e975769d7b6bd60b8bcccccceb92dba2f5f327f2dd7d73c7fc1c27ebcc52c3a79b7263f955348c4c36f3b9aa6dbf33591cbebef31764b99937eb66df1cd6379ecb66877edf8bad140b2fb9b139d0b8f7b51b0b346f8152ddc25b748bd5db2db9a5b7ec96df8a68d025e15755df4a7377ab6e97f0e3c626c65b5bac6e9db1ef772df0fd16d6af1f5eafb0d86cc4246aee7236b3dcaeb7db4d4bc6d133cb2d44fefb87ddf3ffb52ce6e34dbfad6eeb86c5860d1b0d663515f3f8ecff6d8fc5eecc9fe593dbe6b6bdddd5a5fa62d7cae2b65386b7fdeda0d4ea58dd869f55773bde4eb7fbcbddede1f6787bba3ddfce51623f180fb71733643e7af24759983454afa4fbbfdede54f7f67efb48068a226ac97f7d7d3f2a6e9fb7afdbf76dc02b565f2cb35c58776c86d89a73162f6d6e43e3741bddc6b7c96d9abab759eadce6f1241ef77bf56f8bc80a5fa2eab6d4d4a8d394a85202f5ac199aa9599aadb1b16e5acdedade4e78fbbef3396c82759cc58f3345f0bb4508bf242d1d20ce3f287d3597fc25e1eb5584bb454cbfad981dd7b617e7a119385f624cdedad96f733a75668a5566917ad564325615ed0b65fe289b25322add15aadd3aedacdf84c1dd573979aa6e9da4a5b6b1b7ba16da99af0ebc8b03f2a8bb1ad7667dada9db653bba0b9bddbef2c7f37642dcfa1f8f22fc8926a7beda01db59376af3db008efce9cfa1f2c3bda71eb6451633568f92e43ed517bd29eb5b3f6a2bd46b935d2de8c85f61e4fb40f36269f2c216e94246ccb2767e999da97f6ad0d3436a6edeeefd98bf5dcee2c35f2b59136d6260a8bd955d72eed525db37111f562ef2fcbf2a84db59936d716da52578d7da8318f79673d9993b86e6fecb363518056b6bac26c79a71bbad92a9dab5bc64db77527327457c97596ee844e7fe622ce597e32d4033dd4233dd6133dedc7e0d74f98f5b2447e2f95bbd7333dcfebb2d20bf6fbfe0c84266b797c86ff2b3a16157aa957fa45aff5466ff5aedf11c3f2de39af8f322fa45ffb798faffbfaa6ebbe66817ed3355dd757fa5adfe85bfdcef850bff59dbe77c6d5413fe847fda4dfeb0ffaa3fe14bd07aece722db28dde4ef86e0bf3e78fe9e8e764adbfe8af4aa36ead86cdca34abf4f6eff075c43fbd8724c9f537fdbdb8ea1ffaa7fea57febcc07588affed6ed3ca56a3f7beea637afd3a561f4733895c33d687fa888dd0589fe8537da6cff585be5ca92b6565accc95e5eddd3c7ded778d38d5ca5e39b6e1eec90f0b0ff68b2cae7170dc95bbf2567e3c535f56415f310a4e2cdeea57df6a5a7bfb73b2048fab701505b355bc4a56e92a5be5ed78555807166b6efa5ccb3afe248bc9b28265dee5ceed8565b4b755b9aa5697555dcd568d3e5ab5b1c7f7c23129dcddaaeb76abab395e752c5bbbe3f66e626ef955166f7533e3b261f9d270a5b1f178e335567efeafaf2afd9571311f57fa6ab55a6bb362b8daacb6abbbcbc76ad75767d2a05f79b0b67d0ecf64796372ec983c0adfc570cff7819ef85efea3d8cf6bdcbbdf76e87ff8cd6abf3aac8ead1d7cb84edffa7e9e679aa6b63b6627bfcae2af4eab7b9643ad570fcdfbea919fce727f3a052c4f69fca971795a3dafceab176db67ad5ebd5dbea7df5b1fa8cbff26ef595f615a31fbbddf98749f7c177bc0f9d57f6795b7daf06d17e35147b2cfbbdbccd9339ee7739b58bd5a8d72e173b9358e3acdf65b1ceab717d67ec5693d574355bcd51c3b7708ec1fdf3314c92af16abe55a5d2b6b439badcdb5b5b6d7ceda5d7bc69e45cffb1f7bdefb489eaffb32097a7b62b3105fc7e3fba9f9beea7e36627e6318266b7f1dacc3c0091cbecb91452c6431bd17f85d967e7473dbd8d7efeb681dab77e20c2d9745f9b16be9cff8b1f03198af933c5d5bc1789daeb375be2ed6e5ba5a5fd6b5b5b437741601fbf7fbd5b30fbe57a25f6bb15a16fc34ceba757416dfb3e83e9ce9d77ecd807df6ebceefd6cc62bc50c8d2eeb411f366bfd90bd7d26374b7beadb53573e4b2fee5fed5793f628aba5eaf37ebedfa6ebd5befd787f5717d5adfaf1fd68feba790c5fdd69eef5ac1b8b04fbf9ef76a7e704b3e584bbedb9f5950bffba8f7e2eb7e97fcb1df83b63eaf5f02d736cc28effa73246c8e1feb193f73d2e7373edfafe4b23c69bb7e5dbf35cafa7dfdc1e617c8f2f7f78ffdf38ff3283f69566595d196e7f5e7fa6bfdbd1eac87eb11d335bea38c568b980e4db0afbf8fa6c6acc7cffc04c6b2dfadd7cbe90f7a7bea77569a43967505d5e0a69a713e6171d79d36d1f3f5b8f776eb49bfa3b61f93cb389f38de7aba9eade7eabdd8d32b674be7afc8f2d3d9621ecf798f6a11dcaf179774bdcc5f36ea46d9181bb37faead164ebf368979c230a77db5439cb4602336661ab91436d3dc39174ba1fd0a2caa7f6511e4ae0f0b36569fdfacc6cce59f8ce3c6c9271b77e36dfc4d607da94f56f35b9bfed2b8fc7eb6381a2a9ee2da55972acd26dc449b78936cd24db6c9f9aa0bcb6eac27ffdbf68bbc782effdf76ae6549552488eee733a6f615fdba7dbb6356a899203e5a6db51f3b4444f0c14b1489987f9faa8202a4bd37b457331113b9d010943a661645669d93b6d9e37b5a6207f5ce54d90a7b630ee6244ed8f3c2d4532060d9afca32ad349d280e4d481246103617866ae8b10a11c3b2b36c86248e1fe983506f36cb7bd7f59cde1344592e9dd23decc91c0e90c0115250a0014d680104cf80a691efb672cf7c667bc1191af13a6a6c8d2ed758790ea8a041fba8a546ca6681e23a2c67047dffd9b4a1130fb9e20cbad0833e2ce34747a706bc2c0e85fef98baee722bfd4f4404187dc51957668dcd0c2d0b660004318c12b8c61025378f3347fb13bb0acbe5df0f8ab3a31cdd0e01d3ee0136ee036e9c2ddb1ed7437f7e95459c13d7169c0bcfd003fe0117eb2bb700a4ff08c94def1b9eef5e9337dca1557dfc052a8ea8aefae6ed98c216b9d45ef4ffa485524aebeeaa181333471eeaa5edbb7f71bff47100423b4421517519a70a1686ff7106f632dbe471b97ebe0a027b3a4874ec8a276354cdffc603e255ca59dee228325a4b8c2354b719e8d29bbca113774bcb961e319c8f15c1f6327bd3884873ca043ee1bdcda7dce35430f7d0c30740718e10e636fed2f7ddd7f0cc2861b3aa1161991827b3cecfa8d66ec6112bce2115354f693204dfadb96d559cd6ccab25f967cd21655d61b3627a2d61336b0892d72a03dc20e53978ef868d8fa229f5faee75a7fe935c07eb745b764495b08ec7d0311d5f514356ca3bffd70224ff774bfb3f1822818bb5ad8461d3bd8c5de6e837df6fe0507fb088787258ef015c7d68bd0fa1a7cc79ef3f0a8623d21573237714a0f6bb636061dba66de58d0211dac1b76bfe293ef6039b59ad281736c393795d713791dceebf80ee712f96e3009ddd07544a5d179e13613e6e4967d435ca3ec245389a0cad56bfd58aad7bf7aee9fc122ff178e852391e3f3ba9c7d9399eff23a234758aeb7d96b869def6fe7fb0f468e60216ac18678a2378b9890bd31a42ee18c42f1d27b720dcf09969c1fb0909d7904e76ec356026184f0baafc89d66956e3da5fecbf6f6f369d67545d6b5c5d924df135a7ec542cb5e26e49a7cbfc201afa191da8093df3604f79408ae9ab0ad576031ca9ca3caca1635c83935653d22cfb448ce3bcf6adc752c32e62a9eb9443352aa19aaaae7e288acea1ab4729f2cb50e052bf5d4871cf952b02732ae47d9db635ea9689b453c57bc2062244752ad5f5e84c592fcc3e1ee4c949995795bc152fdbea830d827ffc84c20e9088f91d2fb395e4b665b520152c3422492ebf27dce3a1163b10a2cc60916c11710bad85b6ed69a7320cdc09db863ceee0a1533e20c1ccef6c814cd995eb334f9fc9ecf4b7ebda988b5c23b67b1108e04dff03d63da7fc32f8b9a5f4caeec2fc7c9c7e6f5bc5e154b795ce2e596e3679fca7dd222b624e3bc58134fe3a1e0bbcd199677fcb81c4b3d6a7ea7d6aeb0fb7e71ceb9a3f5738b7cbeda2ba7de3ba79caf57e52fff15fb1fcbbfd3fefcfbaf3ffe0193cc32fd</data>
+ </image>
+</images>
+<tabstops>
+</tabstops>
+<tqlayoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/chalk/plugins/viewplugins/colorspaceconversion/Makefile.am b/chalk/plugins/viewplugins/colorspaceconversion/Makefile.am
new file mode 100644
index 00000000..cfc849f9
--- /dev/null
+++ b/chalk/plugins/viewplugins/colorspaceconversion/Makefile.am
@@ -0,0 +1,27 @@
+chalkrcdir = $(kde_datadir)/chalkplugins
+chalkrc_DATA = colorspaceconversion.rc
+
+EXTRA_DIST = $(chalkrc_DATA)
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+
+kde_module_LTLIBRARIES = chalkcolorspaceconversion.la
+
+chalkcolorspaceconversion_la_SOURCES = wdgconvertcolorspace.ui colorspaceconversion.cc dlg_colorspaceconversion.cc
+noinst_HEADERS = wdgconvertcolorspace.h dlg_colorspaceconversion.h colorspaceconversion.h
+
+chalkcolorspaceconversion_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) chalkblurfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui
+chalkcolorspaceconversion_la_LIBADD = ../../../libchalkcommon.la
+
+chalkcolorspaceconversion_la_METASOURCES = AUTO
+
+kde_services_DATA = chalkcolorspaceconversion.desktop
+
diff --git a/chalk/plugins/viewplugins/colorspaceconversion/chalkcolorspaceconversion.desktop b/chalk/plugins/viewplugins/colorspaceconversion/chalkcolorspaceconversion.desktop
new file mode 100644
index 00000000..0993dcc7
--- /dev/null
+++ b/chalk/plugins/viewplugins/colorspaceconversion/chalkcolorspaceconversion.desktop
@@ -0,0 +1,40 @@
+[Desktop Entry]
+Name=Colorspace Conversion
+Name[bg]=Цветово обръщане
+Name[ca]=Conversió d'espai de color
+Name[da]=Farverumskonvertering
+Name[de]=Farbraumumwandlung
+Name[el]=Μετατροπή χρωματικού χώρου
+Name[en_GB]=Colourspace Conversion
+Name[eo]=Kolorspackonvertado
+Name[es]=Conversión de espacio de color
+Name[et]=Värviruumi teisendus
+Name[fa]=تبدیل فاصله رنگ
+Name[fr]=Conversion d'espaces de couleurs
+Name[fy]=Konversje fan kleurspektrum
+Name[gl]=Conversión de Espazos de Cores
+Name[hu]=Színtér-konverzió
+Name[is]=Litasvæðis umbreyting
+Name[it]=Conversione dello spazio dei colori
+Name[ja]=カラースペース変換
+Name[km]=បម្លែង​ប្រភេទ​ពណ៌
+Name[nb]=Fargerom-konvertering
+Name[nds]=Klörenruum-Ümwanneln
+Name[ne]=रङ खालीस्थान रूपानान्तरण
+Name[nl]=Conversie van kleurspectrum
+Name[pl]=Konwersja przestrzeni barw
+Name[pt]=Conversão de Espaços de Cores
+Name[pt_BR]=Conversão de Espaços de Cores
+Name[ru]=Цветовые пространства
+Name[se]=Ivdnegaskkadat-konveršuvdna
+Name[sk]=Konverzia farebného priestoru
+Name[sl]=Pretvorba barvnega prostora
+Name[sr]=Претварање простора боја
+Name[sr@Latn]=Pretvaranje prostora boja
+Name[sv]=Färgrymdskonvertering
+Name[uk]=Перетворення простору кольорів
+Name[zh_TW]=色彩空間轉換
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalkcolorspaceconversion
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/colorspaceconversion/colorspaceconversion.cc b/chalk/plugins/viewplugins/colorspaceconversion/colorspaceconversion.cc
new file mode 100644
index 00000000..10479a3c
--- /dev/null
+++ b/chalk/plugins/viewplugins/colorspaceconversion/colorspaceconversion.cc
@@ -0,0 +1,155 @@
+/*
+ * colorspaceconversion.cc -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 <stdlib.h>
+
+#include <tqradiobutton.h>
+#include <tqcheckbox.h>
+#include <tqlabel.h>
+#include <tqcombobox.h>
+#include <tqbuttongroup.h>
+#include <tqapplication.h>
+#include <tqcursor.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_doc.h>
+#include <kis_config.h>
+#include <kis_cursor.h>
+#include <kis_image.h>
+#include <kis_layer.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include "kis_meta_registry.h"
+#include <kis_view.h>
+#include <kis_paint_device.h>
+#include <kis_colorspace_factory_registry.h>
+#include <kis_cmb_idlist.h>
+#include <squeezedcombobox.h>
+
+#include "colorspaceconversion.h"
+#include "dlg_colorspaceconversion.h"
+#include "wdgconvertcolorspace.h"
+
+typedef KGenericFactory<ColorSpaceConversion> ColorSpaceConversionFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkcolorspaceconversion, ColorSpaceConversionFactory( "chalk" ) )
+
+
+ColorSpaceConversion::ColorSpaceConversion(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+
+ if ( tqparent->inherits("KisView") )
+ {
+ m_view = (KisView*) tqparent;
+
+ setInstance(ColorSpaceConversionFactory::instance());
+ setXMLFile(locate("data","chalkplugins/colorspaceconversion.rc"), true);
+
+ (void) new KAction(i18n("&Convert Image Type..."), 0, 0, this, TQT_SLOT(slotImgColorSpaceConversion()), actionCollection(), "imgcolorspaceconversion");
+ (void) new KAction(i18n("&Convert Layer Type..."), 0, 0, this, TQT_SLOT(slotLayerColorSpaceConversion()), actionCollection(), "layercolorspaceconversion");
+
+ }
+}
+
+ColorSpaceConversion::~ColorSpaceConversion()
+{
+ m_view = 0;
+}
+
+void ColorSpaceConversion::slotImgColorSpaceConversion()
+{
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+
+ if (!image) return;
+
+
+ if (image->colorSpace()->willDegrade(TO_LAB16)) {
+ if (KMessageBox::warningContinueCancel(m_view,
+ i18n("This conversion will convert your %1 image through 16-bit L*a*b* and back.\n"
+ "Watercolor and openEXR colorspaces will even be converted through 8-bit RGB.\n")
+ .tqarg(image->colorSpace()->id().name()),
+ i18n("Colorspace Conversion"),
+ KGuiItem(i18n("Continue")),
+ "lab16degradation") != KMessageBox::Continue) return;
+
+ }
+
+ DlgColorSpaceConversion * dlgColorSpaceConversion = new DlgColorSpaceConversion(m_view, "ColorSpaceConversion");
+ Q_CHECK_PTR(dlgColorSpaceConversion);
+
+ dlgColorSpaceConversion->setCaption(i18n("Convert All Layers From ") + image->colorSpace()->id().name());
+
+ if (dlgColorSpaceConversion->exec() == TQDialog::Accepted) {
+ // XXX: Do the rest of the stuff
+ KisID cspace = dlgColorSpaceConversion->m_page->cmbColorSpaces->currentItem();
+ KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(cspace, dlgColorSpaceConversion->m_page->cmbDestProfile->currentText());
+
+ TQApplication::setOverrideCursor(KisCursor::waitCursor());
+ image->convertTo(cs, dlgColorSpaceConversion->m_page->grpIntent->selectedId());
+ TQApplication::restoreOverrideCursor();
+ }
+ delete dlgColorSpaceConversion;
+}
+
+void ColorSpaceConversion::slotLayerColorSpaceConversion()
+{
+
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+ if (!image) return;
+
+ KisPaintDeviceSP dev = image->activeDevice();
+ if (!dev) return;
+
+ if (dev->colorSpace()->willDegrade(TO_LAB16)) {
+ if (KMessageBox::warningContinueCancel(m_view,
+ i18n("This conversion will convert your %1 layer through 16-bit L*a*b* and back.\n"
+ "Watercolor and openEXR colorspaces will even be converted through 8-bit RGB.\n")
+ .tqarg(dev->colorSpace()->id().name()),
+ i18n("Colorspace Conversion"),
+ KGuiItem(i18n("Continue")),
+ "lab16degradation") != KMessageBox::Continue) return;
+
+ }
+
+ DlgColorSpaceConversion * dlgColorSpaceConversion = new DlgColorSpaceConversion(m_view, "ColorSpaceConversion");
+ Q_CHECK_PTR(dlgColorSpaceConversion);
+
+ dlgColorSpaceConversion->setCaption(i18n("Convert Current Layer From") + dev->colorSpace()->id().name());
+
+ if (dlgColorSpaceConversion->exec() == TQDialog::Accepted) {
+ KisID cspace = dlgColorSpaceConversion->m_page->cmbColorSpaces->currentItem();
+ KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry() ->
+ getColorSpace(cspace, dlgColorSpaceConversion->m_page->cmbDestProfile->currentText());
+
+ TQApplication::setOverrideCursor(KisCursor::waitCursor());
+ dev->convertTo(cs, dlgColorSpaceConversion->m_page->grpIntent->selectedId());
+ TQApplication::restoreOverrideCursor();
+ }
+ delete dlgColorSpaceConversion;
+}
+
+#include "colorspaceconversion.moc"
diff --git a/chalk/plugins/viewplugins/colorspaceconversion/colorspaceconversion.h b/chalk/plugins/viewplugins/colorspaceconversion/colorspaceconversion.h
new file mode 100644
index 00000000..a1f7f5c0
--- /dev/null
+++ b/chalk/plugins/viewplugins/colorspaceconversion/colorspaceconversion.h
@@ -0,0 +1,51 @@
+/*
+ * colorspaceconversion.h -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 COLORSPACECONVERSION_H
+#define COLORSPACECONVERSION_H
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+/**
+ * Dialog for converting between color models.
+ */
+class ColorSpaceConversion : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ ColorSpaceConversion(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ColorSpaceConversion();
+
+private slots:
+
+ void slotImgColorSpaceConversion();
+ void slotLayerColorSpaceConversion();
+
+private:
+
+ KisView * m_view;
+ KisPainter * m_painter;
+
+};
+
+#endif // COLORSPACECONVERSION_H
diff --git a/chalk/plugins/viewplugins/colorspaceconversion/colorspaceconversion.rc b/chalk/plugins/viewplugins/colorspaceconversion/colorspaceconversion.rc
new file mode 100644
index 00000000..94f6066d
--- /dev/null
+++ b/chalk/plugins/viewplugins/colorspaceconversion/colorspaceconversion.rc
@@ -0,0 +1,11 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkcolorspaceconversion" version="1">
+<MenuBar>
+ <Menu name="Image"><text>&amp;Image</text>
+ <Action name="imgcolorspaceconversion"/>
+ </Menu>
+ <Menu name="Layer"><text>La&amp;yer</text>
+ <Action name="layercolorspaceconversion"/>
+ </Menu>
+</MenuBar>
+</kpartgui>
diff --git a/chalk/plugins/viewplugins/colorspaceconversion/dlg_colorspaceconversion.cc b/chalk/plugins/viewplugins/colorspaceconversion/dlg_colorspaceconversion.cc
new file mode 100644
index 00000000..616b1714
--- /dev/null
+++ b/chalk/plugins/viewplugins/colorspaceconversion/dlg_colorspaceconversion.cc
@@ -0,0 +1,91 @@
+/*
+ * dlg_colorspaceconversion.cc - part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <tqradiobutton.h>
+#include <tqcheckbox.h>
+#include <tqlabel.h>
+#include <tqcombobox.h>
+#include <tqptrlist.h>
+
+#include <klocale.h>
+#include <knuminput.h>
+#include <kdebug.h>
+
+#include "kis_meta_registry.h"
+#include <kis_colorspace_factory_registry.h>
+#include "kis_profile.h"
+#include "kis_colorspace.h"
+#include <kis_id.h>
+#include <kis_cmb_idlist.h>
+#include <squeezedcombobox.h>
+
+#include "wdgconvertcolorspace.h"
+#include "dlg_colorspaceconversion.h"
+
+DlgColorSpaceConversion::DlgColorSpaceConversion( TQWidget * tqparent,
+ const char * name)
+ : super (tqparent, name, true, i18n("Image Size"), Ok | Cancel, Ok)
+{
+ m_page = new WdgConvertColorSpace(this, "colorspace_conversion");
+ Q_CHECK_PTR(m_page);
+
+ setMainWidget(m_page);
+ resize(m_page->tqsizeHint());
+
+ m_page->cmbColorSpaces->setIDList(KisMetaRegistry::instance()->csRegistry()->listKeys());
+
+ fillCmbDestProfile(m_page->cmbColorSpaces->currentItem());
+
+ connect(m_page->cmbColorSpaces, TQT_SIGNAL(activated(const KisID &)),
+ this, TQT_SLOT(fillCmbDestProfile(const KisID &)));
+
+
+ connect(this, TQT_SIGNAL(okClicked()),
+ this, TQT_SLOT(okClicked()));
+
+}
+
+DlgColorSpaceConversion::~DlgColorSpaceConversion()
+{
+ delete m_page;
+}
+
+// SLOTS
+
+void DlgColorSpaceConversion::okClicked()
+{
+ accept();
+}
+
+
+void DlgColorSpaceConversion::fillCmbDestProfile(const KisID & s)
+{
+ m_page->cmbDestProfile->clear();
+
+ TQValueVector<KisProfile *> profileList = KisMetaRegistry::instance()->csRegistry()->profilesFor(s);
+ TQValueVector<KisProfile *> ::iterator it;
+ for ( it = profileList.begin(); it != profileList.end(); ++it ) {
+ m_page->cmbDestProfile->insertItem((*it)->productName());
+
+ }
+}
+
+
+#include "dlg_colorspaceconversion.moc"
diff --git a/chalk/plugins/viewplugins/colorspaceconversion/dlg_colorspaceconversion.h b/chalk/plugins/viewplugins/colorspaceconversion/dlg_colorspaceconversion.h
new file mode 100644
index 00000000..608989ab
--- /dev/null
+++ b/chalk/plugins/viewplugins/colorspaceconversion/dlg_colorspaceconversion.h
@@ -0,0 +1,50 @@
+/*
+ * dlg_colorspaceconversion.h -- part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 DLG_COLORSPACECONVERSION
+#define DLG_COLORSPACECONVERSION
+
+#include <kdialogbase.h>
+
+#include <kis_id.h>
+
+class WdgConvertColorSpace;
+
+/**
+ * XXX
+ */
+class DlgColorSpaceConversion: public KDialogBase {
+ typedef KDialogBase super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ DlgColorSpaceConversion(TQWidget * tqparent = 0, const char* name = 0);
+ ~DlgColorSpaceConversion();
+
+ WdgConvertColorSpace * m_page;
+
+public slots:
+
+ void okClicked();
+ void fillCmbDestProfile(const KisID &);
+};
+
+#endif // DLG_COLORSPACECONVERSION
diff --git a/chalk/plugins/viewplugins/colorspaceconversion/wdgconvertcolorspace.ui b/chalk/plugins/viewplugins/colorspaceconversion/wdgconvertcolorspace.ui
new file mode 100644
index 00000000..ae183206
--- /dev/null
+++ b/chalk/plugins/viewplugins/colorspaceconversion/wdgconvertcolorspace.ui
@@ -0,0 +1,218 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgConvertColorSpace</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgConvertColorSpace</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>399</width>
+ <height>228</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Colorspace Conversion</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lblConvert</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Target color space:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>cmbColorSpaces</cstring>
+ </property>
+ </widget>
+ <widget class="KisCmbIDList" row="0" column="1">
+ <property name="name">
+ <cstring>cmbColorSpaces</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="SqueezedComboBox" row="1" column="1">
+ <item>
+ <property name="text">
+ <string>Default</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>cmbDestProfile</cstring>
+ </property>
+ </widget>
+ <widget class="TQButtonGroup" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>grpIntent</cstring>
+ </property>
+ <property name="title">
+ <string>&amp;Rendering Intent</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string></string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>radioPerceptual</cstring>
+ </property>
+ <property name="text">
+ <string>Perceptual</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>For images</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Hue hopefully maintained (but not required),
+lightness and saturation sacrificed to maintain
+the perceived color. White point changed to
+result in neutral grays. Intended for images.</string>
+ </property>
+ </widget>
+ <widget class="TQRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>radioRelativeColorimetric</cstring>
+ </property>
+ <property name="text">
+ <string>Relative colorimetric</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Within and outside gamut; same as Absolute
+Colorimetric. White point changed to result in
+neutral grays.
+
+If adequate table is present in profile,
+then, it is used. Else reverts to perceptual
+intent.</string>
+ </property>
+ </widget>
+ <widget class="TQRadioButton" row="2" column="0">
+ <property name="name">
+ <cstring>radioSaturation</cstring>
+ </property>
+ <property name="text">
+ <string>Saturation</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Best for graphs and charts</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Hue and saturation maintained with lightness
+sacrificed to maintain saturation. White point
+changed to result in neutral grays. Intended for
+business graphics (make it colorful charts,
+graphs, overheads, ...)
+
+If adequate table is present in profile,
+then, it is used. Else reverts to perceptual
+intent.</string>
+ </property>
+ </widget>
+ <widget class="TQRadioButton" row="3" column="0">
+ <property name="name">
+ <cstring>radioAbsoluteColorimetric</cstring>
+ </property>
+ <property name="text">
+ <string>Absolute colorimetric</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Best for spot colours</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Within the destination device gamut; hue,
+lightness and saturation are maintained. Outside
+the gamut; hue and lightness are maintained,
+saturation is sacrificed. White point for source
+and destination; unchanged. Intended for spot
+colors (Pantone, TruMatch, logo colors, ...)</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>lblDestICMProfile</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Destination ICM profile:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>cmbDestProfile</cstring>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KisCmbIDList</class>
+ <header location="local">kis_cmb_idlist.h</header>
+ <sizehint>
+ <width>1</width>
+ <height>24</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+ <customwidget>
+ <class>SqueezedComboBox</class>
+ <header location="local">squeezedcombobox.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>i24</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>3</hordata>
+ <verdata>0</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image1</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="870">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000032d49444154388db59531681c4714863f892dde8004b320c32e3870020b74458a6b0f5458e581c016a809a8496b42208454098604d2c4904a6954a410511ae752085b858c1208dc35221244b00119f60ac12ee860062c980719708a95a248f129459cd7cceeccf0edb76fff61a706830197d5ed765ff3166a30184c4d5d829fed3c7bdd5e6ce3bda71a5738ef301802e1d6d179477152303c1842bc822797a64fbf7b4a9a43be00ada817cb0e12011c2611205ccd73755f9c087c6b19bef0d7c100f5b8267d07caf10fe8ab9210156320fc01be16aa5a11043307f30b20a21041019985f48ef2f7fa0becc68e80475fd584e831b396f210f67795c3831a4940a3228925bb27f4d652ba4b01a199b73342f3981be0ca57745042ac30c632d853b6373d44b056c8ef0922508d94d14be59b2f4aeaf58cd5751069e06f3436890114332b9487d0bf80f61e64dc5f813c3790045453f67703fd4d4f7f6b4496b5597e689044af194f5f5e841800210478bee3d1a8f41e64acbe0f69ae6852e1cf0ccf7f74f4d652defbc042226c6f55e8f89f91bb6e9c387c9d521c9558db988a3416fe3c67e32b4779ec7167f0e8939ce19ea7fc5d298a80c875f03563930855ed2081bc05e91d5014ef53363eaf288e3d6285ee520a338e76c7a251a94e41e30470d3631004a262672e3eca59cec6978ef2b889979d11f2bb904af3be92081a416e28dfe831983920b1142345d5b0ff2234a6334276d7321ad53c795c511ca654a5a251996f19b83d158ef602b45a423d52f67703abeb29ee4ce9de4fc93378f218462f6b3efdb042cf3d59666977a0aa6fe9310888d25b13342afd4dcffeaee3d147399da540ab13f8f8b39c2cb3f8710d11ba2b96f9c57fcd7180287497a03ecde86f8dd8fe1a867b9ef6bb1612a84a871f6bd35b94e217a53832589970f2dcd85d9c7d4580d57521cbdaf4bfaf288e95e268d4ec8e60e72ccb0f2dbffea454e71e8d29f57882717152509482a48d8924b0bc12e82ee51445a03a6da079cbd0eec0fc22142b06620e89a3fc8d3783870743d814d2bc8994aa6ff286472e764902e5a96f72bbd3b4c37b280e95aa9e604c84e1cf978b37c74935797d7ae2ca7fac6968fe51ff0bf86dc30783c1d49f0baa9bb819e612310000000049454e44ae426082</data>
+ </image>
+ <image name="image1">
+ <data format="PNG" length="1003">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b249444154388db5944d4c5c5518869f73ce9db9cc40f929cc30300e18129a50685268a28291982e1a2175212eaab1c49d3f8971e7aec6aedb54a32b435dd8685cb8c0c4b8b0feb421b7bd8186a069d23209144b18cb0c02f3732ff3c3ccbdd705a571941213f1dd9d93739ef37e6fbeef08d334d9d5d0d090c701c8344d2176c1a6697a5d5d5dd8b64d2a95c2b2ac7f05b12c8b783c8e6118d8b6fd685fdb753a39394928e2a7c55724d693a7e214104220242805520a84d8b9e4790f0b1302c7751958f1e30534be9fa41a0c60db362dbe227f64af91b6e7719c2dfc0117a71c603da591de2882a7d3d4ec27122b10acad50aeb88044d542b84de3af7ab44aa55274f4e449dbf354bc347aa096fbf37e7efa2ecbad1b36907d78b289de8120232f37726250c3f52cf0a026a0f6065b9645d929e038167aa096d91b307171059034b5f8e9e9eb44fa052b4b25eeccd9dc99cb71f6ad082fbea2e351c075bdbdc13b9109fc01b83fef63e2e232e03076b68393231a0dcd024daf502c1e66e67a89cb971ef0e5a74bb4b61e6378248094b92ab0ac024b70ca017ef8360394187b2dc6d8b89ffa500e4d4f93d9083275d5e6f9913ade3dd70ee87c7d25c95646a25415aadab152b09ed4f8c5cc130a853839eac3951b684a61e70ef3f9c739668c24eba912afbfddc6d4d506e6a6d7b8b7d082aa8eb8dab19482cdcd220e36dd3dc19df23545de0a71f952861923493456cfd3cf36123c54a0b7bf0e8064621b21f7712c040857071ca4eea0f40a99f510573ec971cb48030e811a1faded3e94be85f2fb00703d1ff26f96ab9f011a5b04d0c4f26fdb948a754c1b25668c2491483d5d5d611617d6b8f0fe32cb779b492ce65168b4c774a4701eefd8f3a02d56e6e8f13aeefe9a63fa5a89d1970e91d908f3d46003e1480d173e28b37827c9b977348ab92ce16890237d1ec907ee3e8e3d8f60d0e1f4583d009f7d9860662acff89bad1c1faad0717493f7ce7713ed8cb0995c255f2a317a26427b67198f6a70f51c0a41b902279ed1187f23cc17130b7c74de65eac77a7a8f05517e41e2deefa4930576db60fa7a8ee1535134df3e93e7b82e0817476439fd6a9070a49f6fbe4a3077739db99b15c001146dd13a46cf1cc1f83943c62e51de76b0738fc9381e8f3390f0236b252e124999e11724fd833196164bacadb87848224fe874f779b43fe9f2dca928956d505a96dbb3f9bdc18661e00534c26d1a7a40e13912a11c9454280da41048a9915c75585df500074d53d816dc9edd229528ef0db66dbbea3ffdaffa471f1f28d8344df1bf800f1a6e9aa6f813c39885bc050f269c0000000049454e44ae426082</data>
+ </image>
+</images>
+<tqlayoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/chalk/plugins/viewplugins/dropshadow/Makefile.am b/chalk/plugins/viewplugins/dropshadow/Makefile.am
new file mode 100644
index 00000000..98ba3550
--- /dev/null
+++ b/chalk/plugins/viewplugins/dropshadow/Makefile.am
@@ -0,0 +1,31 @@
+chalkrcdir = $(kde_datadir)/chalkplugins
+chalkrc_DATA = dropshadow.rc
+EXTRA_DIST = $(chalkrc_DATA)
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../colorspaces/rgb_u8 \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+
+kde_module_LTLIBRARIES = chalkdropshadow.la
+
+chalkdropshadow_la_SOURCES = wdg_dropshadow.ui \
+ kis_dropshadow.cc dlg_dropshadow.cc \
+ kis_dropshadow_plugin.cc
+
+noinst_HEADERS = wdg_dropshadow.h kis_dropshadow_plugin.h \
+ kis_dropshadow.h dlg_dropshadow.h
+
+chalkdropshadow_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) chalkblurfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui
+chalkdropshadow_la_LIBADD = ../../../libchalkcommon.la ../../../colorspaces/rgb_u8/libchalkrgb.la
+
+kde_services_DATA = chalkdropshadow.desktop
+
+chalkdropshadow_la_METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
diff --git a/chalk/plugins/viewplugins/dropshadow/chalkdropshadow.desktop b/chalk/plugins/viewplugins/dropshadow/chalkdropshadow.desktop
new file mode 100644
index 00000000..a48a477e
--- /dev/null
+++ b/chalk/plugins/viewplugins/dropshadow/chalkdropshadow.desktop
@@ -0,0 +1,39 @@
+[Desktop Entry]
+Name=Dropshadow
+Name[bg]=Сянка
+Name[ca]=Gota d'ombra
+Name[da]=Faldskygge
+Name[de]=Schattenwurf
+Name[el]=Ρίψη σκιάς
+Name[et]=Varju heitmine
+Name[fa]=سایۀ قطره
+Name[fr]=Jet d'ombre
+Name[fy]=Skaad sette
+Name[gl]=Sombreado
+Name[hu]=Ejtett árnyék
+Name[is]=Undirskuggi
+Name[it]=Getta ombra
+Name[ja]=影付け
+Name[km]=ទម្លាក់​ស្រមោល
+Name[nb]=Skygge
+Name[nds]=Schaddeneffekt
+Name[ne]=छायाँ छोड्नुहोस्
+Name[nl]=Schaduw plaatsen
+Name[pl]=Dodaj cień
+Name[pt]=Sombreado
+Name[pt_BR]=Sombreado
+Name[ru]=Тень
+Name[se]=Suoivvan
+Name[sk]=Tieň
+Name[sl]=Senca
+Name[sr]=Падајућа сенка
+Name[sr@Latn]=Padajuća senka
+Name[sv]=Fallskugga
+Name[uk]=Тінь
+Name[uz]=Soya tushirish
+Name[uz@cyrillic]=Соя тушириш
+Name[zh_CN]=阴影
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalkdropshadow
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/dropshadow/dlg_dropshadow.cc b/chalk/plugins/viewplugins/dropshadow/dlg_dropshadow.cc
new file mode 100644
index 00000000..797fc098
--- /dev/null
+++ b/chalk/plugins/viewplugins/dropshadow/dlg_dropshadow.cc
@@ -0,0 +1,117 @@
+/*
+ * dlg_dropshadow.cc - part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 <tqbutton.h>
+#include <tqbuttongroup.h>
+#include <tqcheckbox.h>
+#include <tqcolor.h>
+#include <tqcombobox.h>
+#include <tqlabel.h>
+#include <tqradiobutton.h>
+#include <tqslider.h>
+
+#include <kcolorbutton.h>
+#include <kconfig.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <knuminput.h>
+
+#include "dlg_dropshadow.h"
+#include "wdg_dropshadow.h"
+
+DlgDropshadow::DlgDropshadow( const TQString & /*imageCS*/,
+ const TQString & /*layerCS*/,
+ TQWidget * tqparent,
+ const char * name)
+ : super (tqparent, name, true, i18n("Drop Shadow"), Ok | Cancel, Ok)
+{
+ m_page = new WdgDropshadow(this, "dropshadow");
+ Q_CHECK_PTR(m_page);
+ setMainWidget(m_page);
+ resize(m_page->tqsizeHint());
+
+ KConfig * cfg = KGlobal::config();
+ m_page->xOffsetSpinBox->setValue( cfg->readNumEntry("dropshadow_x", 8) );
+ m_page->yOffsetSpinBox->setValue( cfg->readNumEntry("dropshadow_y", 8) );
+ m_page->blurRadiusSpinBox->setValue( cfg->readNumEntry("dropshadow_blurRadius", 5) );
+ TQColor black(0,0,0);
+ m_page->shadowColorButton->setColor( cfg->readColorEntry("dropshadow_color", &black) );
+ m_page->opacitySlider->setValue( cfg->readNumEntry("dropshadow_opacity", 80 ) );
+ m_page->opacitySpinBox->setValue( cfg->readNumEntry("dropshadow_opacity", 80 ) );
+ m_page->allowResizingCheckBox->setChecked( cfg->readBoolEntry("dropshadow_resizing", true ) );
+
+ connect(this, TQT_SIGNAL(okClicked()),
+ this, TQT_SLOT(okClicked()));
+}
+
+DlgDropshadow::~DlgDropshadow()
+{
+ delete m_page;
+}
+
+TQ_INT32 DlgDropshadow::getXOffset()
+{
+ return m_page->xOffsetSpinBox->value();
+}
+
+TQ_INT32 DlgDropshadow::getYOffset()
+{
+ return m_page->yOffsetSpinBox->value();
+}
+
+TQ_INT32 DlgDropshadow::getBlurRadius()
+{
+ return m_page->blurRadiusSpinBox->value();
+}
+
+TQ_UINT8 DlgDropshadow::getShadowOpacity()
+{
+ double opacity = (double)m_page->opacitySpinBox->value();
+ //convert percent to a 8 bit opacity value
+ return (TQ_UINT8)(opacity / 100 * 255);
+}
+
+TQColor DlgDropshadow::getShadowColor()
+{
+ return m_page->shadowColorButton->color();
+}
+
+bool DlgDropshadow::allowResizingChecked()
+{
+ return m_page->allowResizingCheckBox->isChecked();
+}
+
+// SLOTS
+
+void DlgDropshadow::okClicked()
+{
+ KConfig * cfg = KGlobal::config();
+ cfg->writeEntry("dropshadow_x", m_page->xOffsetSpinBox->value());
+ cfg->writeEntry("dropshadow_y", m_page->yOffsetSpinBox->value());
+ cfg->writeEntry("dropshadow_blurRadius", m_page->blurRadiusSpinBox->value());
+ cfg->writeEntry("dropshadow_color", m_page->shadowColorButton->color());
+ cfg->writeEntry("dropshadow_opacity", m_page->opacitySpinBox->value());
+ cfg->writeEntry("dropshadow_resizing", m_page->allowResizingCheckBox->isChecked());
+
+ accept();
+}
+
+#include "dlg_dropshadow.moc"
diff --git a/chalk/plugins/viewplugins/dropshadow/dlg_dropshadow.h b/chalk/plugins/viewplugins/dropshadow/dlg_dropshadow.h
new file mode 100644
index 00000000..9f3ca469
--- /dev/null
+++ b/chalk/plugins/viewplugins/dropshadow/dlg_dropshadow.h
@@ -0,0 +1,60 @@
+/*
+ * dlg_dropshadow.h -- part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 DLG_DROPSHADOW
+#define DLG_DROPSHADOW
+
+#include <kdialogbase.h>
+#include <kis_dropshadow.h>
+
+class WdgDropshadow;
+class TQColor;
+
+/**
+ * This dialog allows the user to configure the decomposition of an image
+ * into layers: one layer for each color channel.
+ */
+class DlgDropshadow: public KDialogBase {
+ typedef KDialogBase super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ DlgDropshadow(const TQString & imageCS, const TQString & layerCS, TQWidget * tqparent = 0,
+ const char* name = 0);
+ ~DlgDropshadow();
+
+public:
+
+ TQ_INT32 getXOffset();
+ TQ_INT32 getYOffset();
+ TQ_INT32 getBlurRadius();
+ TQ_UINT8 getShadowOpacity();
+ TQColor getShadowColor();
+ bool allowResizingChecked();
+private slots:
+ void okClicked();
+
+private:
+
+ WdgDropshadow * m_page;
+};
+
+#endif // DLG_DROPSHADOW
diff --git a/chalk/plugins/viewplugins/dropshadow/dropshadow.rc b/chalk/plugins/viewplugins/dropshadow/dropshadow.rc
new file mode 100644
index 00000000..fcd0be0e
--- /dev/null
+++ b/chalk/plugins/viewplugins/dropshadow/dropshadow.rc
@@ -0,0 +1,11 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkdropshadow" version="6">
+<MenuBar>
+ <Menu name="Layer"><text>La&amp;yer</text>
+ <Separator/>
+ <Menu name="layerEffects"><text>Layer Effects</text>
+ <Action name="dropshadow"/>
+ </Menu>
+ </Menu>
+</MenuBar>
+</kpartgui>
diff --git a/chalk/plugins/viewplugins/dropshadow/kis_dropshadow.cc b/chalk/plugins/viewplugins/dropshadow/kis_dropshadow.cc
new file mode 100644
index 00000000..207c86c3
--- /dev/null
+++ b/chalk/plugins/viewplugins/dropshadow/kis_dropshadow.cc
@@ -0,0 +1,758 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * The gaussian blur algoithm is ported from gimo
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 <limits.h>
+
+#include <stdlib.h>
+#include <vector>
+
+#include <tqcolor.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <knuminput.h>
+
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_paint_layer.h>
+#include <kis_group_layer.h>
+#include "kis_meta_registry.h"
+#include <kis_transaction.h>
+#include <kis_undo_adapter.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_progress_subject.h>
+#include <kis_progress_display_interface.h>
+#include <kis_colorspace.h>
+#include <kis_colorspace_factory_registry.h>
+#include <kis_view.h>
+#include <kis_paint_device.h>
+#include <kis_channelinfo.h>
+#include <kis_convolution_painter.h>
+#include "kis_rgb_colorspace.h"
+
+#include "kis_dropshadow.h"
+
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+KisDropshadow::KisDropshadow(KisView * view)
+ : m_view(view)
+{
+}
+
+void KisDropshadow::dropshadow(KisProgressDisplayInterface * progress, TQ_INT32 xoffset, TQ_INT32 yoffset, TQ_INT32 blurradius, TQColor color, TQ_UINT8 opacity, bool allowResize)
+{
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+ if (!image) return;
+
+ KisLayerSP src = image->activeLayer();
+ if (!src) return;
+
+ KisPaintDeviceSP dev = image->activeDevice();
+ if (!dev) return;
+
+ m_cancelRequested = false;
+ if ( progress )
+ progress->setSubject(this, true, true);
+ emit notifyProgressStage(i18n("Add drop shadow..."), 0);
+
+ if (image->undo()) {
+ image->undoAdapter()->beginMacro(i18n("Add Drop Shadow"));
+ }
+
+ KisPaintDeviceSP shadowDev = new KisPaintDevice( KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA",""),"" ), "Shadow");
+ KisPaintDeviceSP bShadowDev;
+ KisRgbColorSpace *rgb8cs = static_cast<KisRgbColorSpace *>(shadowDev->colorSpace());
+
+ TQRect rect = dev->exactBounds();
+
+ for (TQ_INT32 row = 0; row < rect.height(); ++row)
+ {
+ KisHLineIteratorPixel srcIt = dev->createHLineIterator(rect.x(), rect.y() + row, rect.width(), false);
+ KisHLineIteratorPixel dstIt = shadowDev->createHLineIterator(rect.x(), rect.y() + row, rect.width(), true);
+ while( ! srcIt.isDone() )
+ {
+ if (srcIt.isSelected())
+ {
+ //set the shadow color
+ TQ_UINT8 alpha = dev->colorSpace()->getAlpha(srcIt.rawData());
+ rgb8cs->setPixel(dstIt.rawData(), color.red(), color.green(), color.blue(), alpha);
+ }
+ ++srcIt;
+ ++dstIt;
+ }
+ emit notifyProgress((row * 100) / rect.height() );
+ }
+
+ if( blurradius > 0 )
+ {
+ bShadowDev = new KisPaintDevice( KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA",""),"" ), "bShadow");
+ gaussianblur(shadowDev, bShadowDev, rect, blurradius, blurradius, BLUR_RLE, progress);
+ shadowDev = bShadowDev;
+ }
+
+ if (!m_cancelRequested) {
+ shadowDev->move (xoffset,yoffset);
+
+ KisGroupLayerSP tqparent = image->rootLayer();
+ if (image->activeLayer())
+ tqparent = image->activeLayer()->tqparent().data();
+
+ KisPaintLayerSP l = new KisPaintLayer(image, i18n("Drop Shadow"), opacity, shadowDev);
+ image->addLayer( l.data(), tqparent, src->siblingBelow() );
+
+ if (allowResize)
+ {
+ TQRect shadowBounds = shadowDev->exactBounds();
+
+ if (!image->bounds().tqcontains(shadowBounds)) {
+
+ TQRect newImageSize = image->bounds() | shadowBounds;
+ image->resize(newImageSize.width(), newImageSize.height());
+
+ if (shadowBounds.left() < 0 || shadowBounds.top() < 0) {
+
+ TQ_INT32 newRootX = image->rootLayer()->x();
+ TQ_INT32 newRootY = image->rootLayer()->y();
+
+ if (shadowBounds.left() < 0) {
+ newRootX += -shadowBounds.left();
+ }
+ if (shadowBounds.top() < 0) {
+ newRootY += -shadowBounds.top();
+ }
+
+ KCommand *moveCommand = image->rootLayer()->moveCommand(TQPoint(image->rootLayer()->x(), image->rootLayer()->y()),
+ TQPoint(newRootX, newRootY));
+ Q_ASSERT(moveCommand != 0);
+
+ if (moveCommand) {
+ moveCommand->execute();
+ if (image->undo()) {
+ image->undoAdapter()->addCommand(moveCommand);
+ } else {
+ delete moveCommand;
+ }
+ }
+ }
+ }
+ }
+ m_view->canvasSubject()->document()->setModified(true);
+ }
+
+ if (image->undo()) {
+ image->undoAdapter()->endMacro();
+ }
+
+ emit notifyProgressDone();
+}
+
+void KisDropshadow::gaussianblur (KisPaintDeviceSP srcDev, KisPaintDeviceSP dstDev, TQRect& rect, double horz, double vert, BlurMethod method, KisProgressDisplayInterface *)
+{
+ TQ_INT32 width, height;
+ TQ_INT32 bytes;
+ TQ_UINT8 *dest, *dp;
+ TQ_UINT8 *src, *sp, *sp_p, *sp_m;
+ TQ_INT32 *buf = NULL;
+ TQ_INT32 *bb;
+ double n_p[5], n_m[5];
+ double d_p[5], d_m[5];
+ double bd_p[5], bd_m[5];
+ double *val_p = NULL;
+ double *val_m = NULL;
+ double *vp, *vm;
+ TQ_INT32 x1, y1, x2, y2;
+ TQ_INT32 i, j;
+ TQ_INT32 row, col, b;
+ TQ_INT32 terms;
+ double progress, max_progress;
+ TQ_INT32 initial_p[4];
+ TQ_INT32 initial_m[4];
+ double std_dev;
+ TQ_INT32 pixels;
+ TQ_INT32 total = 1;
+ TQ_INT32 start, end;
+ TQ_INT32 *curve;
+ TQ_INT32 *sum = NULL;
+ TQ_INT32 val;
+ TQ_INT32 length;
+ TQ_INT32 initial_pp, initial_mm;
+
+ x1 = (TQ_INT32)(rect.x() - horz);
+ y1 = (TQ_INT32)(rect.y() - vert);
+ width = (TQ_INT32)(rect.width() + 2 * horz);
+ height = (TQ_INT32)(rect.height() + 2 * vert);
+ x2 = x1 + width;
+ y2 = y1 + height;
+
+ if (width < 1 || height < 1) return;
+
+ emit notifyProgressStage(i18n("Blur..."), 0);
+
+ bytes = srcDev->pixelSize();
+
+ switch (method)
+ {
+ case BLUR_IIR:
+ val_p = new double[MAX (width, height) * bytes];
+ val_m = new double[MAX (width, height) * bytes];
+ break;
+
+ case BLUR_RLE:
+ buf = new TQ_INT32[MAX (width, height) * 2];
+ break;
+ }
+
+ src = new TQ_UINT8[MAX (width, height) * bytes];
+ dest = new TQ_UINT8[MAX (width, height) * bytes];
+
+ progress = 0.0;
+ max_progress = (horz <= 0.0 ) ? 0 : width * height * horz;
+ max_progress += (vert <= 0.0 ) ? 0 : width * height * vert;
+
+
+ /* First the vertical pass */
+ if (vert > 0.0)
+ {
+ vert = fabs (vert) + 1.0;
+ std_dev = sqrt (-(vert * vert) / (2 * log (1.0 / 255.0)));
+
+ switch (method)
+ {
+ case BLUR_IIR:
+ /* derive the constants for calculating the gaussian
+ * from the std dev
+ */
+ find_constants (n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
+ break;
+
+ case BLUR_RLE:
+ curve = make_curve (std_dev, &length);
+ sum = new TQ_INT32[2 * length + 1];
+
+ sum[0] = 0;
+
+ for (i = 1; i <= length*2; i++)
+ sum[i] = curve[i-length-1] + sum[i-1];
+ sum += length;
+
+ total = sum[length] - sum[-length];
+ break;
+ }
+
+ for (col = 0; col < width; col++)
+ {
+ switch (method)
+ {
+ case BLUR_IIR:
+ memset (val_p, 0, height * bytes * sizeof (double));
+ memset (val_m, 0, height * bytes * sizeof (double));
+ break;
+
+ case BLUR_RLE:
+ break;
+ }
+
+ //gimp_pixel_rgn_get_col (&src_rgn, src, col + x1, y1, height);
+ srcDev->readBytes(src, col+x1, y1, 1, height);
+
+ multiply_alpha (src, height, bytes);
+
+ switch (method)
+ {
+ case BLUR_IIR:
+ sp_p = src;
+ sp_m = src + (height - 1) * bytes;
+ vp = val_p;
+ vm = val_m + (height - 1) * bytes;
+
+ /* Set up the first vals */
+ for (i = 0; i < bytes; i++)
+ {
+ initial_p[i] = sp_p[i];
+ initial_m[i] = sp_m[i];
+ }
+
+ for (row = 0; row < height; row++)
+ {
+ double *vpptr, *vmptr;
+ terms = (row < 4) ? row : 4;
+
+ for (b = 0; b < bytes; b++)
+ {
+ vpptr = vp + b; vmptr = vm + b;
+ for (i = 0; i <= terms; i++)
+ {
+ *vpptr += n_p[i] * sp_p[(-i * bytes) + b] -
+ d_p[i] * vp[(-i * bytes) + b];
+ *vmptr += n_m[i] * sp_m[(i * bytes) + b] -
+ d_m[i] * vm[(i * bytes) + b];
+ }
+ for (j = i; j <= 4; j++)
+ {
+ *vpptr += (n_p[j] - bd_p[j]) * initial_p[b];
+ *vmptr += (n_m[j] - bd_m[j]) * initial_m[b];
+ }
+ }
+
+ sp_p += bytes;
+ sp_m -= bytes;
+ vp += bytes;
+ vm -= bytes;
+ }
+
+ transfer_pixels (val_p, val_m, dest, bytes, height);
+ break;
+
+ case BLUR_RLE:
+ sp = src;
+ dp = dest;
+
+ for (b = 0; b < bytes; b++)
+ {
+ initial_pp = sp[b];
+ initial_mm = sp[(height-1) * bytes + b];
+
+ /* Determine a run-length encoded version of the row */
+ run_length_encode (sp + b, buf, bytes, height);
+
+ for (row = 0; row < height; row++)
+ {
+ start = (row < length) ? -row : -length;
+ end = (height <= (row + length) ?
+ (height - row - 1) : length);
+
+ val = 0;
+ i = start;
+ bb = buf + (row + i) * 2;
+
+ if (start != -length)
+ val += initial_pp * (sum[start] - sum[-length]);
+
+ while (i < end)
+ {
+ pixels = bb[0];
+ i += pixels;
+ if (i > end)
+ i = end;
+ val += bb[1] * (sum[i] - sum[start]);
+ bb += (pixels * 2);
+ start = i;
+ }
+
+ if (end != length)
+ val += initial_mm * (sum[length] - sum[end]);
+
+ dp[row * bytes + b] = val / total;
+ }
+ }
+ break;
+ }
+
+ separate_alpha (src, height, bytes);
+
+ dstDev->writeBytes(dest, col + x1, y1, 1, height);
+
+ progress += height * vert;
+ if ((col % 5) == 0) emit notifyProgress( (TQ_UINT32)((progress * 100) / max_progress));
+ }
+ }
+
+ /* Now the horizontal pass */
+ if (horz > 0.0)
+ {
+ horz = fabs (horz) + 1.0;
+
+ if (horz != vert)
+ {
+ std_dev = sqrt (-(horz * horz) / (2 * log (1.0 / 255.0)));
+
+ switch (method)
+ {
+ case BLUR_IIR:
+ /* derive the constants for calculating the gaussian
+ * from the std dev
+ */
+ find_constants (n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
+ break;
+
+ case BLUR_RLE:
+ curve = make_curve (std_dev, &length);
+ sum = new TQ_INT32[2 * length + 1];
+
+ sum[0] = 0;
+
+ for (i = 1; i <= length*2; i++)
+ sum[i] = curve[i-length-1] + sum[i-1];
+ sum += length;
+
+ total = sum[length] - sum[-length];
+ break;
+ }
+ }
+
+ for (row = 0; row < height; row++)
+ {
+ switch (method)
+ {
+ case BLUR_IIR:
+ memset (val_p, 0, width * bytes * sizeof (double));
+ memset (val_m, 0, width * bytes * sizeof (double));
+ break;
+
+ case BLUR_RLE:
+ break;
+ }
+
+
+ //gimp_pixel_rgn_get_row (&src_rgn, src, x1, row + y1, width);
+ dstDev->readBytes(src, x1, row + y1, width, 1);
+
+ multiply_alpha (dest, width, bytes);
+
+ switch (method)
+ {
+ case BLUR_IIR:
+ sp_p = src;
+ sp_m = src + (width - 1) * bytes;
+ vp = val_p;
+ vm = val_m + (width - 1) * bytes;
+
+ /* Set up the first vals */
+ for (i = 0; i < bytes; i++)
+ {
+ initial_p[i] = sp_p[i];
+ initial_m[i] = sp_m[i];
+ }
+
+ for (col = 0; col < width; col++)
+ {
+ double *vpptr, *vmptr;
+ terms = (col < 4) ? col : 4;
+
+ for (b = 0; b < bytes; b++)
+ {
+ vpptr = vp + b; vmptr = vm + b;
+ for (i = 0; i <= terms; i++)
+ {
+ *vpptr += n_p[i] * sp_p[(-i * bytes) + b] -
+ d_p[i] * vp[(-i * bytes) + b];
+ *vmptr += n_m[i] * sp_m[(i * bytes) + b] -
+ d_m[i] * vm[(i * bytes) + b];
+ }
+ for (j = i; j <= 4; j++)
+ {
+ *vpptr += (n_p[j] - bd_p[j]) * initial_p[b];
+ *vmptr += (n_m[j] - bd_m[j]) * initial_m[b];
+ }
+ }
+
+ sp_p += bytes;
+ sp_m -= bytes;
+ vp += bytes;
+ vm -= bytes;
+ }
+
+ transfer_pixels (val_p, val_m, dest, bytes, width);
+ break;
+
+ case BLUR_RLE:
+ sp = src;
+ dp = dest;
+
+ for (b = 0; b < bytes; b++)
+ {
+ initial_pp = sp[b];
+ initial_mm = sp[(width-1) * bytes + b];
+
+ /* Determine a run-length encoded version of the row */
+ run_length_encode (sp + b, buf, bytes, width);
+
+ for (col = 0; col < width; col++)
+ {
+ start = (col < length) ? -col : -length;
+ end = (width <= (col + length)) ? (width - col - 1) : length;
+
+ val = 0;
+ i = start;
+ bb = buf + (col + i) * 2;
+
+ if (start != -length)
+ val += initial_pp * (sum[start] - sum[-length]);
+
+ while (i < end)
+ {
+ pixels = bb[0];
+ i += pixels;
+ if (i > end)
+ i = end;
+ val += bb[1] * (sum[i] - sum[start]);
+ bb += (pixels * 2);
+ start = i;
+ }
+
+ if (end != length)
+ val += initial_mm * (sum[length] - sum[end]);
+
+ dp[col * bytes + b] = val / total;
+ }
+ }
+ break;
+ }
+
+ separate_alpha (dest, width, bytes);
+
+ //gimp_pixel_rgn_set_row (&dest_rgn, dest, x1, row + y1, width);
+ dstDev->writeBytes(dest, x1, row + y1, width, 1);
+
+ progress += width * horz;
+ //if ((row % 5) == 0) gimp_progress_update (progress / max_progress);
+ if ((row % 5) == 0) emit notifyProgress( (TQ_UINT32)((progress * 100) / max_progress ));
+ }
+ }
+
+ /* free up buffers */
+ switch (method)
+ {
+ case BLUR_IIR:
+ delete[] val_p;
+ delete[] val_m;
+ break;
+
+ case BLUR_RLE:
+ delete[] buf;
+ break;
+ }
+
+ delete[] src;
+ delete[] dest;
+}
+
+void KisDropshadow::find_constants (double n_p[], double n_m[], double d_p[], double d_m[], double bd_p[], double bd_m[], double std_dev)
+{
+ TQ_INT32 i;
+ double constants [8];
+ double div;
+
+ /* The constants used in the implemenation of a casual sequence
+ * using a 4th order approximation of the gaussian operator
+ */
+
+ div = sqrt(2 * M_PI) * std_dev;
+ constants [0] = -1.783 / std_dev;
+ constants [1] = -1.723 / std_dev;
+ constants [2] = 0.6318 / std_dev;
+ constants [3] = 1.997 / std_dev;
+ constants [4] = 1.6803 / div;
+ constants [5] = 3.735 / div;
+ constants [6] = -0.6803 / div;
+ constants [7] = -0.2598 / div;
+
+ n_p [0] = constants[4] + constants[6];
+ n_p [1] = exp (constants[1]) *
+ (constants[7] * sin (constants[3]) -
+ (constants[6] + 2 * constants[4]) * cos (constants[3])) +
+ exp (constants[0]) *
+ (constants[5] * sin (constants[2]) -
+ (2 * constants[6] + constants[4]) * cos (constants[2]));
+ n_p [2] = 2 * exp (constants[0] + constants[1]) *
+ ((constants[4] + constants[6]) * cos (constants[3]) * cos (constants[2]) -
+ constants[5] * cos (constants[3]) * sin (constants[2]) -
+ constants[7] * cos (constants[2]) * sin (constants[3])) +
+ constants[6] * exp (2 * constants[0]) +
+ constants[4] * exp (2 * constants[1]);
+ n_p [3] = exp (constants[1] + 2 * constants[0]) *
+ (constants[7] * sin (constants[3]) - constants[6] * cos (constants[3])) +
+ exp (constants[0] + 2 * constants[1]) *
+ (constants[5] * sin (constants[2]) - constants[4] * cos (constants[2]));
+ n_p [4] = 0.0;
+
+ d_p [0] = 0.0;
+ d_p [1] = -2 * exp (constants[1]) * cos (constants[3]) -
+ 2 * exp (constants[0]) * cos (constants[2]);
+ d_p [2] = 4 * cos (constants[3]) * cos (constants[2]) * exp (constants[0] + constants[1]) +
+ exp (2 * constants[1]) + exp (2 * constants[0]);
+ d_p [3] = -2 * cos (constants[2]) * exp (constants[0] + 2 * constants[1]) -
+ 2 * cos (constants[3]) * exp (constants[1] + 2 * constants[0]);
+ d_p [4] = exp (2 * constants[0] + 2 * constants[1]);
+
+ for (i = 0; i <= 4; i++)
+ d_m [i] = d_p [i];
+
+ n_m[0] = 0.0;
+ for (i = 1; i <= 4; i++)
+ n_m [i] = n_p[i] - d_p[i] * n_p[0];
+
+ {
+ double sum_n_p, sum_n_m, sum_d;
+ double a, b;
+
+ sum_n_p = 0.0;
+ sum_n_m = 0.0;
+ sum_d = 0.0;
+ for (i = 0; i <= 4; i++)
+ {
+ sum_n_p += n_p[i];
+ sum_n_m += n_m[i];
+ sum_d += d_p[i];
+ }
+
+ a = sum_n_p / (1.0 + sum_d);
+ b = sum_n_m / (1.0 + sum_d);
+
+ for (i = 0; i <= 4; i++)
+ {
+ bd_p[i] = d_p[i] * a;
+ bd_m[i] = d_m[i] * b;
+ }
+ }
+}
+
+
+void KisDropshadow::transfer_pixels (double *src1, double *src2, TQ_UINT8 *dest, TQ_INT32 bytes, TQ_INT32 width)
+{
+ TQ_INT32 b;
+ TQ_INT32 bend = bytes * width;
+ double sum;
+
+ for(b = 0; b < bend; b++)
+ {
+ sum = *src1++ + *src2++;
+ if (sum > 255) sum = 255;
+ else if(sum < 0) sum = 0;
+
+ *dest++ = (TQ_UINT8) sum;
+ }
+}
+
+//The equations: g(r) = exp (- r^2 / (2 * sigma^2)), r = sqrt (x^2 + y ^2)
+TQ_INT32 * KisDropshadow::make_curve(double sigma, TQ_INT32 *length)
+{
+ int *curve;
+ double sigma2;
+ double l;
+ int temp;
+ int i, n;
+
+ sigma2 = 2 * sigma * sigma;
+ l = sqrt (-sigma2 * log (1.0 / 255.0));
+
+ n = (int)(ceil (l) * 2);
+ if ((n % 2) == 0)
+ n += 1;
+
+ curve = new TQ_INT32[n];
+
+ *length = n / 2;
+ curve += *length;
+ curve[0] = 255;
+
+ for (i = 1; i <= *length; i++)
+ {
+ temp = (TQ_INT32) (exp (- (i * i) / sigma2) * 255);
+ curve[-i] = temp;
+ curve[i] = temp;
+ }
+
+ return curve;
+}
+
+void KisDropshadow::run_length_encode (TQ_UINT8 *src, TQ_INT32 *dest, TQ_INT32 bytes, TQ_INT32 width)
+{
+ TQ_INT32 start;
+ TQ_INT32 i;
+ TQ_INT32 j;
+ TQ_UINT8 last;
+
+ last = *src;
+ src += bytes;
+ start = 0;
+
+ for (i = 1; i < width; i++)
+ {
+ if (*src != last)
+ {
+ for (j = start; j < i; j++)
+ {
+ *dest++ = (i - j);
+ *dest++ = last;
+ }
+ start = i;
+ last = *src;
+ }
+ src += bytes;
+ }
+
+ for (j = start; j < i; j++)
+ {
+ *dest++ = (i - j);
+ *dest++ = last;
+ }
+}
+
+void KisDropshadow::multiply_alpha (TQ_UINT8 *buf, TQ_INT32 width, TQ_INT32 bytes)
+{
+ TQ_INT32 i, j;
+ double alpha;
+
+ for (i = 0; i < width * bytes; i += bytes)
+ {
+ alpha = buf[i + bytes - 1] * (1.0 / 255.0);
+ for (j = 0; j < bytes - 1; j++) {
+ double a = (double)(buf[i + j]) * alpha;
+ buf[i + j] = (TQ_UINT8)a;
+ }
+ }
+}
+
+void KisDropshadow::separate_alpha (TQ_UINT8 *buf, TQ_INT32 width, TQ_INT32 bytes)
+{
+ TQ_INT32 i, j;
+ TQ_UINT8 alpha;
+ double recip_alpha;
+ TQ_UINT32 new_val;
+
+ for (i = 0; i < width * bytes; i += bytes)
+ {
+ alpha = buf[i + bytes - 1];
+ if (alpha != 0 && alpha != 255)
+ {
+ recip_alpha = 255.0 / alpha;
+ for (j = 0; j < bytes - 1; j++)
+ {
+ new_val = (TQ_UINT32)(buf[i + j] * recip_alpha);
+ buf[i + j] = MIN (255, new_val);
+ }
+ }
+ }
+}
+
+#include "kis_dropshadow.moc"
diff --git a/chalk/plugins/viewplugins/dropshadow/kis_dropshadow.h b/chalk/plugins/viewplugins/dropshadow/kis_dropshadow.h
new file mode 100644
index 00000000..94c6decc
--- /dev/null
+++ b/chalk/plugins/viewplugins/dropshadow/kis_dropshadow.h
@@ -0,0 +1,72 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_DROPSHADOW_H_
+#define _KIS_DROPSHADOW_H_
+
+#include <kis_progress_subject.h>
+#include <kis_paint_device.h>
+
+typedef enum
+{
+ BLUR_IIR,
+ BLUR_RLE
+} BlurMethod;
+
+
+class TQColor;
+class KisView;
+class KisProgressDisplayInterface;
+
+class KisDropshadow : public KisProgressSubject {
+
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ KisDropshadow(KisView * view);
+ virtual ~KisDropshadow() {};
+
+ void dropshadow(KisProgressDisplayInterface * progress, TQ_INT32 xoffset, TQ_INT32 yoffset, TQ_INT32 blurradius, TQColor color, TQ_UINT8 opacity, bool allowResize);
+
+public: // Implement KisProgressSubject
+ virtual void cancel() { m_cancelRequested = true; }
+
+private:
+ void gaussianblur (KisPaintDeviceSP src, KisPaintDeviceSP dst,
+ TQRect& rect, double horz, double vert,
+ BlurMethod method,
+ KisProgressDisplayInterface * progressDisplay);
+ //gaussian blur helper functions
+ void find_constants(double n_p[], double n_m[], double d_p[], double d_m[], double bd_p[], double bd_m[], double std_dev);
+ void transfer_pixels(double *src1, double *src2, TQ_UINT8 *dest, TQ_INT32 bytes, TQ_INT32 width);
+ TQ_INT32* make_curve(double sigma, TQ_INT32 *length);
+ void run_length_encode (TQ_UINT8 *src, TQ_INT32 *dest, TQ_INT32 bytes, TQ_INT32 width);
+ void multiply_alpha (TQ_UINT8 *buf, TQ_INT32 width, TQ_INT32 bytes);
+ void separate_alpha (TQ_UINT8 *buf, TQ_INT32 width, TQ_INT32 bytes);
+
+private:
+ KisView * m_view;
+ bool m_cancelRequested;
+
+};
+
+#endif
diff --git a/chalk/plugins/viewplugins/dropshadow/kis_dropshadow_plugin.cc b/chalk/plugins/viewplugins/dropshadow/kis_dropshadow_plugin.cc
new file mode 100644
index 00000000..5dc190f1
--- /dev/null
+++ b/chalk/plugins/viewplugins/dropshadow/kis_dropshadow_plugin.cc
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_view.h>
+#include <kis_types.h>
+#include <kis_image.h>
+#include <kis_paint_device.h>
+#include <kis_layer.h>
+
+#include "kis_dropshadow_plugin.h"
+#include "kis_dropshadow.h"
+#include "dlg_dropshadow.h"
+
+K_EXPORT_COMPONENT_FACTORY( chalkdropshadow, KGenericFactory<KisDropshadowPlugin>( "chalk" ) )
+
+KisDropshadowPlugin::KisDropshadowPlugin(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ if ( tqparent->inherits("KisView") ) {
+
+ setInstance(KGenericFactory<KisDropshadowPlugin>::instance());
+ setXMLFile(locate("data","chalkplugins/dropshadow.rc"), true);
+
+ m_view = (KisView*) tqparent;
+ (void) new KAction(i18n("Add Drop Shadow..."), 0, 0, this, TQT_SLOT(slotDropshadow()), actionCollection(), "dropshadow");
+ }
+}
+
+KisDropshadowPlugin::~KisDropshadowPlugin()
+{
+}
+
+void KisDropshadowPlugin::slotDropshadow()
+{
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+ if (!image) return;
+
+ KisPaintDeviceSP dev = image->activeDevice();
+ if (!dev) return;
+
+ DlgDropshadow * dlgDropshadow = new DlgDropshadow(dev->colorSpace()->id().name(),
+ image->colorSpace()->id().name(),
+ m_view, "Dropshadow");
+ Q_CHECK_PTR(dlgDropshadow);
+
+ dlgDropshadow->setCaption(i18n("Drop Shadow"));
+
+ if (dlgDropshadow->exec() == TQDialog::Accepted) {
+
+ KisDropshadow dropshadow(m_view);
+ dropshadow.dropshadow(m_view->canvasSubject()->progressDisplay(),
+ dlgDropshadow->getXOffset(),
+ dlgDropshadow->getYOffset(),
+ dlgDropshadow->getBlurRadius(),
+ dlgDropshadow->getShadowColor(),
+ dlgDropshadow->getShadowOpacity(),
+ dlgDropshadow->allowResizingChecked());
+
+ }
+
+ delete dlgDropshadow;
+
+}
+
+#include "kis_dropshadow_plugin.moc"
diff --git a/chalk/plugins/viewplugins/dropshadow/kis_dropshadow_plugin.h b/chalk/plugins/viewplugins/dropshadow/kis_dropshadow_plugin.h
new file mode 100644
index 00000000..e2641ed2
--- /dev/null
+++ b/chalk/plugins/viewplugins/dropshadow/kis_dropshadow_plugin.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_DROPSHADOW_PLUGIN_H_
+#define _KIS_DROPSHADOW_PLUGIN_H_
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+
+
+class KisDropshadowPlugin : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ KisDropshadowPlugin(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~KisDropshadowPlugin();
+
+private slots:
+
+ void slotDropshadow();
+
+private:
+
+ KisView * m_view;
+};
+
+#endif
diff --git a/chalk/plugins/viewplugins/dropshadow/wdg_dropshadow.ui b/chalk/plugins/viewplugins/dropshadow/wdg_dropshadow.ui
new file mode 100644
index 00000000..4bd2f38c
--- /dev/null
+++ b/chalk/plugins/viewplugins/dropshadow/wdg_dropshadow.ui
@@ -0,0 +1,235 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgDropshadow</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgDropshadow</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>403</width>
+ <height>258</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Offset X:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Offset Y:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Blur radius:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Color:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="4" column="0">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Opacity:</string>
+ </property>
+ </widget>
+ <widget class="TQSlider" row="4" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>opacitySlider</cstring>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>80</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="TQSpinBox" row="4" column="3">
+ <property name="name">
+ <cstring>opacitySpinBox</cstring>
+ </property>
+ <property name="suffix">
+ <string>%</string>
+ </property>
+ <property name="maxValue">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>80</number>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="5" column="0" rowspan="1" colspan="4">
+ <property name="name">
+ <cstring>allowResizingCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Allow resizing</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQSpinBox" row="0" column="1">
+ <property name="name">
+ <cstring>xOffsetSpinBox</cstring>
+ </property>
+ <property name="minValue">
+ <number>-99</number>
+ </property>
+ <property name="value">
+ <number>8</number>
+ </property>
+ </widget>
+ <spacer row="0" column="2" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>200</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQSpinBox" row="1" column="1">
+ <property name="name">
+ <cstring>yOffsetSpinBox</cstring>
+ </property>
+ <property name="minValue">
+ <number>-99</number>
+ </property>
+ <property name="value">
+ <number>8</number>
+ </property>
+ </widget>
+ <spacer row="1" column="2" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>200</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQSpinBox" row="2" column="1">
+ <property name="name">
+ <cstring>blurRadiusSpinBox</cstring>
+ </property>
+ <property name="value">
+ <number>5</number>
+ </property>
+ </widget>
+ <spacer row="2" column="2" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>190</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KColorButton" row="3" column="1">
+ <property name="name">
+ <cstring>shadowColorButton</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <spacer row="3" column="2" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>120</width>
+ <height>31</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>opacitySpinBox</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>opacitySlider</receiver>
+ <slot>setValue(int)</slot>
+ </connection>
+ <connection>
+ <sender>opacitySlider</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>opacitySpinBox</receiver>
+ <slot>setValue(int)</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>xOffsetSpinBox</tabstop>
+ <tabstop>yOffsetSpinBox</tabstop>
+ <tabstop>blurRadiusSpinBox</tabstop>
+ <tabstop>shadowColorButton</tabstop>
+ <tabstop>opacitySlider</tabstop>
+ <tabstop>opacitySpinBox</tabstop>
+ <tabstop>allowResizingCheckBox</tabstop>
+</tabstops>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcolorbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/viewplugins/filtersgallery/Makefile.am b/chalk/plugins/viewplugins/filtersgallery/Makefile.am
new file mode 100644
index 00000000..90ddcfc6
--- /dev/null
+++ b/chalk/plugins/viewplugins/filtersgallery/Makefile.am
@@ -0,0 +1,26 @@
+chalkrcdir = $(kde_datadir)/chalkplugins
+chalkrc_DATA = chalkfiltersgallery.rc
+
+EXTRA_DIST = $(chalkrc_DATA)
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkfiltersgallery_la_SOURCES = filters_gallery.cc \
+ kis_dlg_filtersgallery.cc kis_wdg_filtersgallery.ui
+
+kde_module_LTLIBRARIES = chalkfiltersgallery.la
+noinst_HEADERS = filters_gallery.h kis_dlg_filtersgallery.h
+
+kde_services_DATA = chalkfiltersgallery.desktop
+
+chalkfiltersgallery_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) chalkblurfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui
+chalkfiltersgallery_la_LIBADD = ../../../libchalkcommon.la
+
+chalkfiltersgallery_la_METASOURCES = AUTO
diff --git a/chalk/plugins/viewplugins/filtersgallery/chalkfiltersgallery.desktop b/chalk/plugins/viewplugins/filtersgallery/chalkfiltersgallery.desktop
new file mode 100644
index 00000000..ed1bb5c9
--- /dev/null
+++ b/chalk/plugins/viewplugins/filtersgallery/chalkfiltersgallery.desktop
@@ -0,0 +1,45 @@
+[Desktop Entry]
+Name=Filters Gallery
+Name[bg]=Галерия с филтри
+Name[ca]=Galeria de filtres
+Name[da]=Filtergalleri
+Name[de]=Filtergallerie
+Name[el]=Συλλογή φίλτρων
+Name[eo]=Filtrilgalerio
+Name[es]=Galería de filtros
+Name[et]=Filtrigalerii
+Name[fa]=گالری پالایه‌ها
+Name[fr]=Galerie de filtres
+Name[fy]=Filtergallerij
+Name[ga]=Gailearaí na Scagairí
+Name[gl]=Galería de Filtros
+Name[he]=גלריית מסננים
+Name[hu]=Szűrőgaléria
+Name[is]=Síusafn
+Name[it]=Galleria dei filtri
+Name[ja]=フィルタギャラリー
+Name[km]=វិចិត្រសាល​តម្រង
+Name[lv]=Filtru galerija
+Name[nb]=Filtergalleri
+Name[nds]=Filtersammeln
+Name[ne]=फिल्टर ग्यालेरी
+Name[nl]=Filtergalerij
+Name[pl]=Galeria filtrów
+Name[pt]=Galeria de Filtros
+Name[pt_BR]=Galeria de Filtros
+Name[ru]=Галерея фильтров
+Name[se]=Sillegalleriija
+Name[sk]=Zbierka filtrov
+Name[sl]=Galerija filtrov
+Name[sr]=Галерија филтера
+Name[sr@Latn]=Galerija filtera
+Name[sv]=Filtrergalleri
+Name[uk]=Галерея фільтрів
+Name[uz]=Filterlar toʻplami
+Name[uz@cyrillic]=Филтерлар тўплами
+Name[zh_CN]=滤镜库
+Name[zh_TW]=濾鏡畫廊
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalkfiltersgallery
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/filtersgallery/chalkfiltersgallery.rc b/chalk/plugins/viewplugins/filtersgallery/chalkfiltersgallery.rc
new file mode 100644
index 00000000..e5fcfa43
--- /dev/null
+++ b/chalk/plugins/viewplugins/filtersgallery/chalkfiltersgallery.rc
@@ -0,0 +1,9 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkfiltersgallery" version="7">
+<MenuBar>
+<Menu name="Filter"><text>&amp;Filter</text>
+ <Seperator/>
+ <Action name="chalk_filters_gallery"/>
+</Menu>
+</MenuBar>
+</kpartgui>
diff --git a/chalk/plugins/viewplugins/filtersgallery/filters_gallery.cc b/chalk/plugins/viewplugins/filtersgallery/filters_gallery.cc
new file mode 100644
index 00000000..8f70b8f7
--- /dev/null
+++ b/chalk/plugins/viewplugins/filtersgallery/filters_gallery.cc
@@ -0,0 +1,138 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 "filters_gallery.h"
+
+#include <tqapplication.h>
+
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <kstandarddirs.h>
+
+#include <kopalettemanager.h>
+
+#include <kis_colorspace_factory_registry.h>
+#include "kis_progress_display_interface.h"
+#include <kis_dlg_filtersgallery.h>
+#include <kis_doc.h>
+#include <kis_filter.h>
+#include <kis_filters_listview.h>
+#include <kis_meta_registry.h>
+#include <kis_paint_device.h>
+#include <kis_selection.h>
+#include <kis_view.h>
+#include <kis_transaction.h>
+
+namespace Chalk {
+namespace Plugins {
+namespace FiltersGallery {
+
+typedef KGenericFactory<ChalkFiltersGallery> ChalkFiltersGalleryFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkfiltersgallery, ChalkFiltersGalleryFactory( "chalk" ) )
+
+ChalkFiltersGallery::ChalkFiltersGallery(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+
+ if ( tqparent->inherits("KisView") )
+ {
+ setInstance(ChalkFiltersGallery::instance());
+ setXMLFile(locate("data","chalkplugins/chalkfiltersgallery.rc"), true);
+
+ m_view = (KisView*) tqparent;
+
+ (void) new KAction(i18n("&Filters Gallery"), 0, 0, this, TQT_SLOT(showFiltersGalleryDialog()), actionCollection(), "chalk_filters_gallery");
+
+ // Add a docker with the list of filters
+// TQImage img;
+// if(img.load(locate("data","chalk/images/previewfilter.png")))
+// {
+// KisPaintDeviceSP preview = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA",""),""));
+// preview->convertFromTQImage(img,"");
+// m_view->canvasSubject()->paletteManager()->addWidget(new KisFiltersListView(preview,m_view),"filterslist",chalk::EFFECTSBOX, 0);
+// }
+
+ }
+
+
+}
+
+ChalkFiltersGallery::~ChalkFiltersGallery()
+{
+}
+
+void ChalkFiltersGallery::showFiltersGalleryDialog()
+{
+ KisDlgFiltersGallery dlg(m_view, m_view);
+ if (dlg.exec())
+ {
+ TQApplication::setOverrideCursor( TQt::waitCursor );
+
+ KisFilter* filter = dlg.currentFilter();
+ if(filter )
+ {
+ KisImageSP img = m_view->canvasSubject()->currentImg();
+ if (!img) return;
+
+ KisPaintDeviceSP dev = img->activeDevice();
+ if (!dev) return;
+ TQRect r1 = dev->exactBounds();
+ TQRect r2 = img->bounds();
+
+ TQRect rect = r1.intersect(r2);
+
+ if (dev->hasSelection()) {
+ TQRect r3 = dev->selection()->selectedExactRect();
+ rect = rect.intersect(r3);
+ }
+ KisFilterConfiguration* config = filter->configuration( dlg.currentConfigWidget());
+
+ filter->enableProgress();
+ m_view->canvasSubject()->progressDisplay()->setSubject(filter, true, true);
+ filter->setProgressDisplay(m_view->canvasSubject()->progressDisplay());
+
+ KisTransaction * cmd = new KisTransaction(filter->id().name(), dev);
+
+ filter->process(dev,dev, config, rect);
+
+ delete config;
+ if (filter->cancelRequested()) {
+ cmd->unexecute();
+ delete cmd;
+ } else {
+ dev->setDirty(rect);
+ if (img->undo())
+ img->undoAdapter()->addCommand(cmd);
+ else
+ delete cmd;
+ }
+ filter->disableProgress();
+ TQApplication::restoreOverrideCursor();
+
+ }
+ }
+}
+
+}
+}
+}
+
+#include "filters_gallery.moc"
diff --git a/chalk/plugins/viewplugins/filtersgallery/filters_gallery.h b/chalk/plugins/viewplugins/filtersgallery/filters_gallery.h
new file mode 100644
index 00000000..89fed386
--- /dev/null
+++ b/chalk/plugins/viewplugins/filtersgallery/filters_gallery.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 _KRITA_FILTERS_PREVIEW_H_
+#define _KRITA_FILTERS_PREVIEW_H_
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+namespace Chalk {
+namespace Plugins {
+namespace FiltersGallery {
+ class ChalkFiltersGallery : public KParts::Plugin
+ {
+ Q_OBJECT
+ TQ_OBJECT
+ public:
+ ChalkFiltersGallery(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ChalkFiltersGallery();
+ public slots:
+ void showFiltersGalleryDialog();
+ private:
+
+ KisView * m_view;
+
+
+ };
+
+}
+}
+}
+
+
+
+#endif
diff --git a/chalk/plugins/viewplugins/filtersgallery/kis_dlg_filtersgallery.cc b/chalk/plugins/viewplugins/filtersgallery/kis_dlg_filtersgallery.cc
new file mode 100644
index 00000000..76676177
--- /dev/null
+++ b/chalk/plugins/viewplugins/filtersgallery/kis_dlg_filtersgallery.cc
@@ -0,0 +1,133 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net>
+ * Copyright (c) 2007 Benjamin Schleimer <bensch128@yahoo.com>
+ *
+ * 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_dlg_filtersgallery.h"
+
+#include <tqgroupbox.h>
+#include <tqlayout.h>
+#include <tqlabel.h>
+#include <tqdatetime.h>
+
+#include <kis_filter.h>
+#include <kis_filter_config_widget.h>
+#include <kis_filters_listview.h>
+#include <kis_paint_device.h>
+#include <kis_paint_layer.h>
+#include <kis_previewwidget.h>
+#include <kis_transaction.h>
+#include <kis_types.h>
+#include <kis_view.h>
+
+#include "kis_wdg_filtersgallery.h"
+
+namespace Chalk {
+namespace Plugins {
+namespace FiltersGallery {
+
+
+KisDlgFiltersGallery::KisDlgFiltersGallery(KisView* view, TQWidget* tqparent,const char *name)
+ : KDialogBase(tqparent,name, true,i18n("Filters Gallery"), Ok | Cancel), m_view(view),m_currentConfigWidget(0), m_currentFilter(0)
+{
+ // Initialize main widget
+ m_widget = new KisWdgFiltersGallery(this);
+ m_widget->filtersList->setLayer(view->canvasSubject()->currentImg()->activeLayer());
+ m_widget->filtersList->setProfile(view->canvasSubject()->monitorProfile());
+
+ setMainWidget(m_widget);
+ // Initialize filters list
+ connect(m_widget->filtersList , TQT_SIGNAL(selectionChanged(TQIconViewItem*)), this, TQT_SLOT(selectionHasChanged(TQIconViewItem* )));
+ // Initialize configWidgetHolder
+ m_widget->configWidgetHolder->setColumnLayout ( 0, Qt::Horizontal );
+ //m_widget->configWidgetHolder->tqsetSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Minimum);
+ // Initialize preview widget
+
+ if (m_view->canvasSubject()->currentImg() && m_view->canvasSubject()->currentImg()->activeDevice())
+ {
+ m_widget->previewWidget->slotSetDevice( m_view->canvasSubject()->currentImg()->activeDevice().data() );
+ }
+ connect( m_widget->previewWidget, TQT_SIGNAL(updated()), this, TQT_SLOT(refreshPreview()));
+ resize( tqminimumSizeHint());
+ m_widget->previewWidget->tqsetSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::MinimumExpanding);
+ m_labelNoCW = new TQLabel(i18n("No configuration options are available for this filter."), m_widget->configWidgetHolder);
+ m_widget->configWidgetHolder->tqlayout()->add(m_labelNoCW);
+ m_labelNoCW->hide();
+}
+
+KisDlgFiltersGallery::~KisDlgFiltersGallery()
+{
+}
+
+void KisDlgFiltersGallery::selectionHasChanged ( TQIconViewItem * item )
+{
+ KisFiltersIconViewItem* kisitem = (KisFiltersIconViewItem*) item;
+ m_currentFilter = kisitem->filter();
+ if(m_currentConfigWidget != 0)
+ {
+ m_widget->configWidgetHolder->tqlayout()->remove(m_currentConfigWidget);
+ delete m_currentConfigWidget;
+ m_currentConfigWidget = 0;
+ } else {
+ m_labelNoCW->hide();
+ }
+ KisImageSP img = m_view->canvasSubject()->currentImg();
+ KisPaintLayerSP activeLayer = dynamic_cast<KisPaintLayer*>(img->activeLayer().data());
+
+ if (activeLayer)
+ m_currentConfigWidget = m_currentFilter->createConfigurationWidget(m_widget->configWidgetHolder, activeLayer->paintDevice());
+
+ if(m_currentConfigWidget != 0) {
+ //m_currentConfigWidget->tqsetSizePolicy(TQSizePolicy::Fixed, TQSizePolicy::Fixed);
+ m_widget->configWidgetHolder->tqlayout()->add(m_currentConfigWidget);
+ m_currentConfigWidget->show();
+ connect(m_currentConfigWidget, TQT_SIGNAL(sigPleaseUpdatePreview()), this, TQT_SLOT(slotConfigChanged()));
+ }
+ else {
+ m_labelNoCW->show();
+ }
+
+ refreshPreview();
+}
+
+void KisDlgFiltersGallery::slotConfigChanged()
+{
+ if(m_widget->previewWidget->getAutoUpdate())
+ {
+ refreshPreview();
+ } else {
+ m_widget->previewWidget->needUpdate();
+ }
+}
+
+
+void KisDlgFiltersGallery::refreshPreview( )
+{
+ if(!m_currentFilter) return;
+
+ KisFilterConfiguration* config = m_currentFilter->configuration(m_currentConfigWidget);
+
+ m_widget->previewWidget->runFilter(m_currentFilter, config);
+}
+
+}
+}
+}
+
+#include "kis_dlg_filtersgallery.moc"
diff --git a/chalk/plugins/viewplugins/filtersgallery/kis_dlg_filtersgallery.h b/chalk/plugins/viewplugins/filtersgallery/kis_dlg_filtersgallery.h
new file mode 100644
index 00000000..09e5cb1f
--- /dev/null
+++ b/chalk/plugins/viewplugins/filtersgallery/kis_dlg_filtersgallery.h
@@ -0,0 +1,69 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net>
+ * Copyright (c) 2007 Benjamin Schleimer <bensch128@yahoo.com>
+ *
+ * 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 KISDLGFILTERSPREVIEW_H
+#define KISDLGFILTERSPREVIEW_H
+
+#include <kdialogbase.h>
+
+class KisView;
+class KisFilter;
+class TQIconViewItem;
+class TQLabel;
+class TQHBoxLayout;
+class KisPreviewWidget;
+class KisWdgFiltersGallery;
+class KisFiltersListView;
+
+namespace Chalk {
+namespace Plugins {
+namespace FiltersGallery {
+
+/**
+@author Cyrille Berger
+*/
+class KisDlgFiltersGallery : public KDialogBase
+{
+ Q_OBJECT
+ TQ_OBJECT
+ public:
+ KisDlgFiltersGallery(KisView* view, TQWidget* tqparent,const char *name = "");
+ ~KisDlgFiltersGallery();
+ public:
+ inline KisFilter* currentFilter() { return m_currentFilter; };
+ inline TQWidget* currentConfigWidget() { return m_currentConfigWidget; }
+ private slots:
+ void slotConfigChanged();
+ void refreshPreview();
+ void selectionHasChanged ( TQIconViewItem * item );
+ private:
+ KisWdgFiltersGallery* m_widget;
+ KisView* m_view;
+ TQWidget* m_currentConfigWidget;
+ KisFilter* m_currentFilter;
+ TQLabel* m_labelNoCW;
+};
+
+}
+}
+}
+
+#endif
diff --git a/chalk/plugins/viewplugins/filtersgallery/kis_wdg_filtersgallery.ui b/chalk/plugins/viewplugins/filtersgallery/kis_wdg_filtersgallery.ui
new file mode 100644
index 00000000..488c9564
--- /dev/null
+++ b/chalk/plugins/viewplugins/filtersgallery/kis_wdg_filtersgallery.ui
@@ -0,0 +1,123 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KisWdgFiltersGallery</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>KisWdgFiltersGallery</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>763</width>
+ <height>296</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="KisPreviewWidget" row="0" column="1">
+ <property name="name">
+ <cstring>previewWidget</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KisFiltersListView" row="0" column="0">
+ <property name="name">
+ <cstring>filtersList</cstring>
+ </property>
+ </widget>
+ <widget class="TQGroupBox" row="0" column="2">
+ <property name="name">
+ <cstring>configWidgetHolder</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="title">
+ <string>Configuration</string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KisPreviewWidget</class>
+ <header location="local">kis_previewwidget.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ <signal>moved(QPoint)</signal>
+ <signal>moving(QPoint)</signal>
+ <signal>startMoving(QPoint)</signal>
+ <slot access="public" specifier="">zoomIn()</slot>
+ <slot access="public" specifier="">slot()</slot>
+ <slot access="public" specifier="">zoomOut()</slot>
+ <slot access="public" specifier="">slot()</slot>
+ <slot access="public" specifier="">slot()</slot>
+ <slot access="public" specifier="">slotMoving(QPoint)</slot>
+ <slot access="public" specifier="">slotMoved(QPoint)</slot>
+ <slot access="public" specifier="">slot()</slot>
+ <slot access="public" specifier="">slotStartMoving(QPoint)</slot>
+ </customwidget>
+ <customwidget>
+ <class>KisFiltersListView</class>
+ <header location="local">kis_filters_listview.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image1</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data>
+ </image>
+ <image name="image1">
+ <data format="PNG" length="1122">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000042949444154388db5954d6c545514c77ff7de37eff1a6a550da994e5ba798868f948fc847a2a2911816c436b0a02ed0083161a1981877ee10d90aa94656063491882c5cd4c4b8103f20cd806909a98604da8482341de80cb69de9bcd799799d79efba980f1da3a80b4f727273939bdff99f9b93f3175a6b6a21849080020c4002a29a8f0a5dcd002803bed63a1035f0d0d0504b6f6fef51d7758fa4d3e98d8ee3fc03af128ee3303939399548242eb8aefb09300f78464de9f0f0f0d148cc7caf3d5424de97a7ec17104220242805520a44557bbd4b21f083801d33e63a6d1bc7bf19c6064e0319a35a58b9ae7ba43d54e4d7c54b64dc097c7f09d30ef04b36736983cc7c11b4456b9b492c5e20dc54a6540e00896a8268a7017010f8bcae1830d2e9f4c69ebe3c197782b2ce60d94ddc9b30f9feeb45ae5d7181c5ead35636ef08d3ffe26a76ee3208b4031a56d80aa00768fda362e9380e25bf80ef3b587613d7afc099533380a4b5dda46fcb5aa42998b9eb7173dce5e6788e434763ec7fc942532008ea436003660d2caa7f8d69c3bd8910674e4d033e83877ad8d36fb0aa4d6058658ac5358c5df6383bf480f31fdda5a3632bbbfb6da4ccd5c00a10b2012cc12fd97cfb5516f0187c25cee0619396480ec3ca909d0f3372d1e5f9fe66de3ad605587c712ec55256a2540d5519d19ae24a29057329839f7ecc138944d833102290f3184ae1e6d6f0e98739c61229e6d21eafbed1c9c8c5558c8f3ee4ceed76946a1c43d97091828585223e2eebfbc295f60d45de89707628cb58224577bc85a79e5d4d786581cddb9b0148259711b20145836221400416e0232d1f6595c9ce4538773ac7b54406f0b15784e8e80aa1ac2594190220d021e49f2437960156b70ba095e95f96f18acd8c263cc6122962b1167a7ba34cdd7ec8c977a699bed546722a8fc2a02b6e2185fff78ab586ce78894ddb9ab9f5738ed14b1e030756929d8ff2e4ae5544632b38f96e89a99b298ebd6950cc2d12ed0eb3618b26f520788462ad09877df60db600f0f1fb49c646f21c7ebd836dcf94e9d9b4c0db27d6d3bd36c6426a96bce731703046d7da129a4670836284a054869d4f1b1c7e2dca67676ef3c1898091ef5ad8bc358c3205c93bf7c9a40ad4c660f4728edd7bbb3142ea2fc1da711cfc200011e08b45f6bd1c261adbce9717928c5f9d63fc6a19f0014567773303073790f8214bd6f5282dfbb8b9fa1f6b40d7c1939393533b92e63ad9240990484aec7e41b27d579cbb531e0f67023492d86316ebb768ba1e0f786e6f37e56550c62237aee7011e54abd7c1412291b8a06de378b4d3c0b215da9708e5a3a442192085404a83d4accfecac067c0c43e13a70e3fa12e96409e0325000966bbb354465339d04a6f9dd15fe6dde07ce030780278088d05ad72cc9a6b2f2daaaa74d75a1f0e8d0d5f60b40868a8364ead6248430000b0857a126ffcdf396abf03ce089ffcb4c7f033046c6b4a995e7a00000000049454e44ae426082</data>
+ </image>
+</images>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kis_previewwidget.h</includehint>
+ <includehint>kis_filters_listview.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/viewplugins/histogram/Makefile.am b/chalk/plugins/viewplugins/histogram/Makefile.am
new file mode 100644
index 00000000..149a523b
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram/Makefile.am
@@ -0,0 +1,25 @@
+chalkrcdir = $(kde_datadir)/chalkplugins
+chalkrc_DATA = histogram.rc
+
+EXTRA_DIST = $(chalkrc_DATA)
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalkhistogram.la
+
+chalkhistogram_la_SOURCES = histogram.cc dlg_histogram.cc wdghistogram.ui kis_histogram_widget.cc
+noinst_HEADERS = dlg_histogram.h histogram.h wdghistogram.h kis_histogram_widget.h
+
+kde_services_DATA = chalkhistogram.desktop
+
+chalkhistogram_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) chalkblurfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui
+chalkhistogram_la_LIBADD = ../../../libchalkcommon.la
+
+chalkhistogram_la_METASOURCES = AUTO
diff --git a/chalk/plugins/viewplugins/histogram/chalkhistogram.desktop b/chalk/plugins/viewplugins/histogram/chalkhistogram.desktop
new file mode 100644
index 00000000..b91e42b6
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram/chalkhistogram.desktop
@@ -0,0 +1,43 @@
+[Desktop Entry]
+Name=Histogram Plugin
+Name[bg]=Приставка за Histogram
+Name[ca]=Connector d'histograma
+Name[da]=Plugin med histogram
+Name[de]=Histogramm-Modul
+Name[el]=Πρόσθετο ιστογράμματος
+Name[eo]=Histograma kromaĵo
+Name[es]=Complemento de histograma
+Name[et]=Histogrammiplugin
+Name[fa]=وصلۀ سابقه‌نما
+Name[fr]=Module d'histogramme
+Name[fy]=Histogramplugin
+Name[gl]=Plugin de Histograma
+Name[hu]=Hisztogram modul
+Name[is]=Súluritssía
+Name[it]=Plugin per gli istogrammi
+Name[ja]=ヒストグラムプラグイン
+Name[km]=កម្មវិធី​ជំនួយ​អ៊ីស្តូក្រាម​
+Name[lt]=Histogramos įskiepis
+Name[nb]=Programtillegg for histogram
+Name[nds]=Histogramm-Moduul
+Name[ne]=हिस्टोग्राम प्लगइन
+Name[nl]=Histogramplugin
+Name[pl]=Wtyczka histogramu
+Name[pt]='Plugin' do Histograma
+Name[pt_BR]=Plugin do Histograma
+Name[ru]=Модуль гистограммы
+Name[se]=Histogram lassemoduvla
+Name[sk]=Modul histogram
+Name[sl]=Vstavek za histograme
+Name[sr]=Хистограмски прикључак
+Name[sr@Latn]=Histogramski priključak
+Name[sv]=Insticksprogram med histogram
+Name[uk]=Втулок гістограм
+Name[uz]=Gistogramma plagini
+Name[uz@cyrillic]=Гистограмма плагини
+Name[zh_CN]=直方图插件
+Name[zh_TW]=直方圖外掛程式
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalkhistogram
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/histogram/dlg_histogram.cc b/chalk/plugins/viewplugins/histogram/dlg_histogram.cc
new file mode 100644
index 00000000..4b781c17
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram/dlg_histogram.cc
@@ -0,0 +1,68 @@
+/*
+ * dlg_histogram.cc - part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <tqbuttongroup.h>
+#include <tqpushbutton.h>
+#include <tqcheckbox.h>
+#include <tqslider.h>
+#include <tqcombobox.h>
+#include <tqpixmap.h>
+#include <tqimage.h>
+#include <tqlabel.h>
+
+#include <knuminput.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "kis_types.h"
+#include "kis_histogram.h"
+#include "kis_layer.h"
+#include "kis_paint_device.h"
+
+#include "dlg_histogram.h"
+#include "kis_histogram_widget.h"
+
+
+DlgHistogram::DlgHistogram( TQWidget * tqparent, const char * name)
+ : super (tqparent, name, true, i18n("Histogram"), Ok | Cancel, Ok)
+{
+ m_page = new KisHistogramWidget(this, "histogram");
+ Q_CHECK_PTR(m_page);
+
+ setCaption(i18n("Histogram"));
+ setMainWidget(m_page);
+ resize(m_page->tqsizeHint());
+}
+
+DlgHistogram::~DlgHistogram()
+{
+ delete m_page;
+}
+
+void DlgHistogram::setPaintDevice(KisPaintDeviceSP dev)
+{
+ m_page->setPaintDevice(dev);
+}
+
+void DlgHistogram::okClicked()
+{
+ accept();
+}
+
+#include "dlg_histogram.moc"
diff --git a/chalk/plugins/viewplugins/histogram/dlg_histogram.h b/chalk/plugins/viewplugins/histogram/dlg_histogram.h
new file mode 100644
index 00000000..d2568f7a
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram/dlg_histogram.h
@@ -0,0 +1,58 @@
+/*
+ * dlg_histogram.h -- part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 DLG_HISTOGRAM
+#define DLG_HISTOGRAM
+
+#include <kdialogbase.h>
+
+#include "kis_types.h"
+
+class KisHistogramWidget;
+
+/**
+ * This dialog shows the histogram for the (selected) portion
+ * of the current layer.
+ *
+ * XXX: Also for complete image?
+ */
+class DlgHistogram: public KDialogBase {
+ typedef KDialogBase super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ DlgHistogram(TQWidget * tqparent = 0,
+ const char* name = 0);
+ ~DlgHistogram();
+
+ void setPaintDevice(KisPaintDeviceSP dev);
+
+private slots:
+ void okClicked();
+
+private:
+
+ KisHistogramWidget * m_page;
+ KisHistogramSP m_histogram;
+ KisLayerSP m_layer;
+};
+
+#endif // DLG_HISTOGRAM
diff --git a/chalk/plugins/viewplugins/histogram/histogram.cc b/chalk/plugins/viewplugins/histogram/histogram.cc
new file mode 100644
index 00000000..8e6968b9
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram/histogram.cc
@@ -0,0 +1,105 @@
+/*
+ * histogram.h -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 <math.h>
+
+#include <stdlib.h>
+
+#include <tqslider.h>
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_layer.h>
+#include <kis_paint_device.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_view.h>
+#include <kis_selection.h>
+
+#include "histogram.h"
+#include "dlg_histogram.h"
+#include "kis_colorspace.h"
+#include "kis_histogram.h"
+
+typedef KGenericFactory<Histogram> HistogramFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkhistogram, HistogramFactory( "chalk" ) )
+
+Histogram::Histogram(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+
+ if ( tqparent->inherits("KisView") ) {
+
+ setInstance(HistogramFactory::instance());
+ setXMLFile(locate("data","chalkplugins/histogram.rc"), true);
+
+ m_action = new KAction(i18n("&Histogram"), 0, 0, this, TQT_SLOT(slotActivated()), actionCollection(), "histogram");
+
+ m_view = (KisView*) tqparent;
+ if (KisImageSP img = m_view->canvasSubject()->currentImg()) {
+ connect(img, TQT_SIGNAL(sigLayersChanged(KisGroupLayerSP)), this, TQT_SLOT(slotLayersChanged()));
+ connect(img, TQT_SIGNAL(sigLayerAdded(KisLayerSP)), this, TQT_SLOT(slotLayersChanged()));
+ connect(img, TQT_SIGNAL(sigLayerActivated(KisLayerSP)), this, TQT_SLOT(slotLayersChanged()));
+ connect(img, TQT_SIGNAL(sigLayerPropertiesChanged(KisLayerSP)), this, TQT_SLOT(slotLayersChanged()));
+ connect(img, TQT_SIGNAL(sigLayerRemoved(KisLayerSP, KisGroupLayerSP, KisLayerSP)),
+ this, TQT_SLOT(slotLayersChanged()));
+ connect(img, TQT_SIGNAL(sigLayerMoved(KisLayerSP, KisGroupLayerSP, KisLayerSP)),
+ this, TQT_SLOT(slotLayersChanged()));
+ m_img = img;
+ }
+ }
+}
+
+Histogram::~Histogram()
+{
+}
+
+void Histogram::slotLayersChanged() {
+ m_action->setEnabled(m_img && m_img->activeLayer() && m_img->activeLayer()->visible());
+}
+
+void Histogram::slotActivated()
+{
+ DlgHistogram * dlgHistogram = new DlgHistogram(m_view, "Histogram");
+ Q_CHECK_PTR(dlgHistogram);
+
+ KisPaintDeviceSP dev = m_view->canvasSubject()->currentImg()->activeDevice();
+ if (dev)
+ dlgHistogram->setPaintDevice(dev);
+
+ if (dlgHistogram->exec() == TQDialog::Accepted) {
+ // Do nothing; this is an informational dialog
+ }
+ delete dlgHistogram;
+}
+
+#include "histogram.moc"
+
diff --git a/chalk/plugins/viewplugins/histogram/histogram.h b/chalk/plugins/viewplugins/histogram/histogram.h
new file mode 100644
index 00000000..2425c0c6
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram/histogram.h
@@ -0,0 +1,50 @@
+/*
+ * histogram.h -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 HISTOGRAM_H
+#define HISTOGRAM_H
+
+#include <kparts/plugin.h>
+
+class KisView;
+class KAction;
+class KisImage;
+
+class Histogram : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+ public:
+ Histogram(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~Histogram();
+
+ private slots:
+ void slotActivated();
+ void slotLayersChanged();
+
+ private:
+ KisImage* m_img;
+ KisView * m_view;
+ KisPainter * m_painter;
+ KAction* m_action;
+
+};
+
+#endif // HISTOGRAM_H
diff --git a/chalk/plugins/viewplugins/histogram/histogram.rc b/chalk/plugins/viewplugins/histogram/histogram.rc
new file mode 100644
index 00000000..db37b4b7
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram/histogram.rc
@@ -0,0 +1,10 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkhistogram" version="6">
+<MenuBar>
+ <Menu name="Layer"><text>&amp;Layer</text>
+ <Separator/>
+ <Action name="histogram"/>
+ <Separator/>
+ </Menu>
+</MenuBar>
+</kpartgui>
diff --git a/chalk/plugins/viewplugins/histogram/kis_histogram_widget.cc b/chalk/plugins/viewplugins/histogram/kis_histogram_widget.cc
new file mode 100644
index 00000000..12005e05
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram/kis_histogram_widget.cc
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2004 Boudewijn Rempt
+ * (c) 2005 Bart Coppens <kde@bartcoppens.be>
+ *
+ * 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 <tqpainter.h>
+#include <tqpixmap.h>
+#include <tqlabel.h>
+#include <tqcombobox.h>
+#include <tqbuttongroup.h>
+#include <tqpushbutton.h>
+#include <tqscrollbar.h>
+#include <tqtooltip.h>
+
+#include <kdebug.h>
+
+#include "kis_channelinfo.h"
+#include "kis_histogram_view.h"
+#include "kis_histogram_widget.h"
+#include "kis_histogram.h"
+#include "kis_global.h"
+#include "kis_types.h"
+#include "kis_layer.h"
+#include "kis_paint_device.h"
+#include "kis_colorspace.h"
+
+
+KisHistogramWidget::KisHistogramWidget(TQWidget *tqparent, const char *name)
+ : super(tqparent, name)
+{
+ m_from = 0.0;
+ m_width = 0.0;
+}
+
+KisHistogramWidget::~KisHistogramWidget()
+{
+}
+
+void KisHistogramWidget::setPaintDevice(KisPaintDeviceSP dev)
+{
+ grpType->disconnect(this);
+ cmbChannel->disconnect(this);
+
+ m_histogramView->setPaintDevice(dev);
+ setActiveChannel(0); // So we have the colored one if there are colors
+
+ // The channels
+ cmbChannel->clear();
+ cmbChannel->insertStringList(m_histogramView->channelStrings());
+ cmbChannel->setCurrentItem(0);
+
+ // View display
+ currentView->setMinValue(0);
+ currentView->setMaxValue(100);
+
+ updateEnabled();
+
+ m_from = m_histogramView->currentProducer()->viewFrom();
+ m_width = m_histogramView->currentProducer()->viewWidth();
+
+ connect(grpType, TQT_SIGNAL(clicked(int)), this, TQT_SLOT(slotTypeSwitched(int)));
+ connect(cmbChannel, TQT_SIGNAL(activated(int)), this, TQT_SLOT(setActiveChannel(int)));
+ connect(zoomIn, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotZoomIn()));
+ connect(zoomOut, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotZoomOut()));
+ connect(currentView, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(slide(int)));
+}
+
+void KisHistogramWidget::setActiveChannel(int channel)
+{
+ m_histogramView->setActiveChannel(channel);
+ updateEnabled();
+}
+
+void KisHistogramWidget::slotTypeSwitched(int id)
+{
+ if (id == LINEAR)
+ m_histogramView->setHistogramType(LINEAR);
+ else if (id == LOGARITHMIC)
+ m_histogramView->setHistogramType(LOGARITHMIC);
+}
+
+void KisHistogramWidget::setView(double from, double size)
+{
+ m_from = from;
+ m_width = size;
+ if (m_from + m_width > 1.0)
+ m_from = 1.0 - m_width;
+ m_histogramView->setView(m_from, m_width);
+ updateEnabled();
+}
+
+void KisHistogramWidget::slotZoomIn() {
+ if ((m_width / 2) >= m_histogramView->currentProducer()->maximalZoom()) {
+ setView(m_from, m_width / 2);
+ }
+}
+
+void KisHistogramWidget::slotZoomOut() {
+ if (m_width * 2 <= 1.0) {
+ setView(m_from, m_width * 2);
+ }
+}
+
+void KisHistogramWidget::slide(int val) {
+ // Beware: at the END (e.g. 100), we want to still view m_width:
+ setView((static_cast<double>(val) / 100.0) * (1.0 - m_width), m_width);
+}
+
+void KisHistogramWidget::updateEnabled() {
+ if (m_histogramView->currentProducer()->maximalZoom() < 1.0) {
+ if ((m_width / 2) >= m_histogramView->currentProducer()->maximalZoom()) {
+ zoomIn->setEnabled(true);
+ } else {
+ zoomIn->setEnabled(false);
+ }
+ if (m_width * 2 <= 1.0) {
+ zoomOut->setEnabled(true);
+ } else {
+ zoomOut->setEnabled(false);
+ }
+ if (m_width < 1.0)
+ currentView->setEnabled(true);
+ else
+ currentView->setEnabled(false);
+ } else {
+ zoomIn->setEnabled(false);
+ zoomOut->setEnabled(false);
+ currentView->setEnabled(false);
+ }
+}
+
+#include "kis_histogram_widget.moc"
+
diff --git a/chalk/plugins/viewplugins/histogram/kis_histogram_widget.h b/chalk/plugins/viewplugins/histogram/kis_histogram_widget.h
new file mode 100644
index 00000000..f83394e7
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram/kis_histogram_widget.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2004 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.
+ */
+#ifndef KIS_HISTOGRAM_WIDGET_
+#define KIS_HISTOGRAM_WIDGET_
+
+#include "kis_types.h"
+#include "wdghistogram.h"
+
+class KisColorSpace;
+
+/**
+ * The histogram widget takes a paint device or an image and
+ * draws a histogram for the given KisHistogram.
+ */
+class KisHistogramWidget : public WdgHistogram {
+ typedef WdgHistogram super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KisHistogramWidget(TQWidget *tqparent, const char *name);
+ virtual ~KisHistogramWidget();
+
+ void setPaintDevice(KisPaintDeviceSP dev);
+
+private slots:
+ void setActiveChannel(int channel);
+ void slotTypeSwitched(int id);
+ void slotZoomIn();
+ void slotZoomOut();
+ void slide(int val);
+
+private:
+ void setView(double from, double size);
+ void updateEnabled();
+ double m_from, m_width;
+};
+
+
+#endif // KIS_HISTOGRAM_WIDGET_
diff --git a/chalk/plugins/viewplugins/histogram/wdghistogram.ui b/chalk/plugins/viewplugins/histogram/wdghistogram.ui
new file mode 100644
index 00000000..77c418ed
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram/wdghistogram.ui
@@ -0,0 +1,229 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgHistogram</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgHistogram</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>450</width>
+ <height>380</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQButtonGroup">
+ <property name="name">
+ <cstring>grpType</cstring>
+ </property>
+ <property name="title">
+ <string>Method</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQRadioButton" row="0" column="2">
+ <property name="name">
+ <cstring>radioLinear</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Linear</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQRadioButton" row="1" column="2" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>radioLog</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Logarithmic</string>
+ </property>
+ </widget>
+ <spacer row="2" column="1">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQComboBox" row="0" column="1" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>cmbChannel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>200</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0" rowspan="2" colspan="1">
+ <property name="name">
+ <cstring>lblChannel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Channel:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>cmbChannel</cstring>
+ </property>
+ </widget>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Preferred</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="KisHistogramView">
+ <property name="name">
+ <cstring>m_histogramView</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>256</width>
+ <height>150</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>View:</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>zoomIn</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>+</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>zoomOut</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>-</string>
+ </property>
+ </widget>
+ <widget class="TQScrollBar">
+ <property name="name">
+ <cstring>currentView</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KisHistogramView</class>
+ <header location="local">kis_histogram_view.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data>
+ </image>
+</images>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kis_histogram_view.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/viewplugins/histogram_docker/Makefile.am b/chalk/plugins/viewplugins/histogram_docker/Makefile.am
new file mode 100644
index 00000000..64341755
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram_docker/Makefile.am
@@ -0,0 +1,22 @@
+kde_services_DATA = chalkhistogramdocker.desktop
+chalkrcdir = $(kde_datadir)/chalkplugins
+chalkrc_DATA = chalkhistogramdocker.rc
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkhistogramdocker_la_SOURCES = histogramdocker.cc kis_imagerasteredcache.cc kis_cachedhistogram.cc kis_accumulating_producer.cc
+
+kde_module_LTLIBRARIES = chalkhistogramdocker.la
+noinst_HEADERS = histogramdocker.h kis_imagerasteredcache.h kis_cachedhistogram.h kis_accumulating_producer.h
+
+chalkhistogramdocker_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) chalkblurfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui
+chalkhistogramdocker_la_LIBADD = ../../../libchalkcommon.la
+
+chalkhistogramdocker_la_METASOURCES = AUTO
diff --git a/chalk/plugins/viewplugins/histogram_docker/chalkhistogramdocker.desktop b/chalk/plugins/viewplugins/histogram_docker/chalkhistogramdocker.desktop
new file mode 100644
index 00000000..aba9ded8
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram_docker/chalkhistogramdocker.desktop
@@ -0,0 +1,40 @@
+[Desktop Entry]
+Name=Histogram Docker
+Name[ca]=Amarrador de l'histograma
+Name[cy]=Bachydd Histogram
+Name[da]=Histogramdokning
+Name[de]=Histogramm-Docker
+Name[el]=Προσάρτηση ιστογράμματος
+Name[eo]=Histogramdokilo
+Name[es]=Anclaje del histograma
+Name[et]=Histogrammi dokk
+Name[fa]=پیونددهندۀ سابقه‌نما
+Name[fr]=Ancrage d'histogramme
+Name[fy]=Histogramkomponint
+Name[gl]=Acoplador de Histogramas
+Name[hu]=Hisztogramdokkoló
+Name[is]=Súluritsspjald
+Name[it]=Aggancia-istogrammi
+Name[ja]=ヒストグラムドッカー
+Name[km]=កន្លែង​ចត​អ៊ីស្តូក្រាម
+Name[nb]=Histogramdokker
+Name[nds]=Histogramm-Docker
+Name[ne]=हिस्टोग्राम डकर
+Name[nl]=Histogramcomponent
+Name[pl]=Doker histogramu
+Name[pt]=Acoplador de Histogramas
+Name[pt_BR]=Acoplador de Histogramas
+Name[ru]=Панель гистограммы
+Name[sk]=Histogram
+Name[sl]=Histogram
+Name[sr]=Сидраш хистограма
+Name[sr@Latn]=Sidraš histograma
+Name[sv]=Histogramdockning
+Name[uk]=Швартувальник гістограм
+Name[uz]=Gistogramma paneli
+Name[uz@cyrillic]=Гистограмма панели
+Name[zh_TW]=直方圖停駐點
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalkhistogramdocker
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/histogram_docker/chalkhistogramdocker.rc b/chalk/plugins/viewplugins/histogram_docker/chalkhistogramdocker.rc
new file mode 100644
index 00000000..2b6006b9
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram_docker/chalkhistogramdocker.rc
@@ -0,0 +1,3 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkhistogramdocker" version="1">
+</kpartgui> \ No newline at end of file
diff --git a/chalk/plugins/viewplugins/histogram_docker/histogramdocker.cc b/chalk/plugins/viewplugins/histogram_docker/histogramdocker.cc
new file mode 100644
index 00000000..df5de24a
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram_docker/histogramdocker.cc
@@ -0,0 +1,192 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be>
+ *
+ * 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 <tqtooltip.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kopalettemanager.h>
+
+#include "kis_meta_registry.h"
+#include <kis_doc.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_view.h>
+
+#include <kis_basic_histogram_producers.h>
+#include <kis_colorspace_factory_registry.h>
+
+#include "histogramdocker.h"
+#include "kis_imagerasteredcache.h"
+#include "kis_accumulating_producer.h"
+
+typedef KGenericFactory<ChalkHistogramDocker> ChalkHistogramDockerFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkhistogramdocker, ChalkHistogramDockerFactory( "chalk" ) )
+
+ChalkHistogramDocker::ChalkHistogramDocker(TQObject *tqparent, const char *name, const TQStringList&)
+ : KParts::Plugin(tqparent, name)
+{
+
+ if ( tqparent->inherits("KisView") ) {
+ m_view = dynamic_cast<KisView*>(tqparent);
+
+ setInstance(ChalkHistogramDockerFactory::instance());
+ setXMLFile(locate("data","chalkplugins/chalkhistogramdocker.rc"), true);
+
+ KisImageSP img = m_view->canvasSubject()->currentImg();
+ if (!img) {
+ m_cache = 0;
+ return;
+ }
+
+ m_hview = 0; // producerChanged wants to setCurrentChannels, prevent that here
+ m_cache = 0; // we try to delete it in producerChanged
+ colorSpaceChanged(img->colorSpace()); // calls producerChanged(0)
+
+
+ m_hview = new KisHistogramView(m_view);
+ TQToolTip::add(m_hview, i18n("Right-click to select histogram type"));
+ m_hview->setHistogram(m_histogram);
+ m_hview->setColor(true);
+ m_hview->setCurrentChannels(m_producer, m_producer->channels());
+ m_hview->setFixedSize(256, 100); // XXX if not it keeps expanding
+ m_hview->setCaption(i18n("Histogram"));
+
+
+ connect(m_hview, TQT_SIGNAL(rightClicked(const TQPoint&)),
+ this, TQT_SLOT(popupMenu(const TQPoint&)));
+ connect(m_cache, TQT_SIGNAL(cacheUpdated()),
+ new HistogramDockerUpdater(this, m_histogram, m_hview, m_producer), TQT_SLOT(updated()));
+ connect(&m_popup, TQT_SIGNAL(activated(int)),
+ this, TQT_SLOT(producerChanged(int)));
+ connect(img, TQT_SIGNAL(sigColorSpaceChanged(KisColorSpace*)),
+ this, TQT_SLOT(colorSpaceChanged(KisColorSpace*))); // No need to force updates here
+
+ // Add it to the control palette
+ m_view->canvasSubject()->paletteManager()->addWidget(
+ m_hview, "histodocker", chalk::CONTROL_PALETTE);
+ } else {
+ m_cache = 0;
+ }
+}
+
+ChalkHistogramDocker::~ChalkHistogramDocker()
+{
+ uint count = m_producers . count();
+ for (uint i = 0; i < count; i++) {
+ delete m_producers . at(i);
+ }
+
+ if (m_cache)
+ m_cache->deleteLater();
+}
+
+void ChalkHistogramDocker::producerChanged(int pos)
+{
+ if (m_cache)
+ m_cache->deleteLater();
+ m_cache = 0;
+
+ if (m_currentProducerPos < m_popup.count())
+ m_popup.setItemChecked(m_currentProducerPos, false);
+ m_currentProducerPos = pos;
+ m_popup.setItemChecked(m_currentProducerPos, true);
+
+ uint count = m_producers . count();
+ for (uint i = 0; i < count; i++) {
+ delete m_producers . at(i);
+ }
+ m_producers.clear();
+
+ KisIDList keys = KisHistogramProducerFactoryRegistry::instance() ->
+ listKeysCompatibleWith(m_cs);
+
+ m_factory = KisHistogramProducerFactoryRegistry::instance()->get(*(keys.at(pos)));
+
+ KisCachedHistogramObserver observer(&m_producers, m_factory, 0, 0, 0, 0, false);
+
+ // We can reference observer because it will be only used as a factory to create new
+ // instances
+ m_cache = new KisImageRasteredCache(m_view, &observer);
+
+ m_producer = new KisAccumulatingHistogramProducer(&m_producers);
+
+ // use dummy layer as a source; we are not going to actually use or need it
+ // All of these are SP, no need to delete them afterwards
+ m_histogram = new KisHistogram( new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getAlpha8(), "dummy histogram"), m_producer, LOGARITHMIC);
+
+ if (m_hview) {
+ m_hview->setHistogram(m_histogram);
+ m_hview->setColor(true);
+ m_hview->setCurrentChannels(m_producer, m_producer->channels());
+
+ connect(m_cache, TQT_SIGNAL(cacheUpdated()),
+ new HistogramDockerUpdater(this, m_histogram, m_hview, m_producer), TQT_SLOT(updated()));
+ }
+}
+
+void ChalkHistogramDocker::popupMenu(const TQPoint& pos)
+{
+ m_popup.popup(pos, m_currentProducerPos);
+}
+
+void ChalkHistogramDocker::colorSpaceChanged(KisColorSpace* cs)
+{
+ m_cs = cs;
+
+ KisIDList keys = KisHistogramProducerFactoryRegistry::instance() ->
+ listKeysCompatibleWith(m_cs);
+
+ m_popup.clear();
+ m_currentProducerPos = 0;
+
+ for (uint i = 0; i < keys.count(); i++) {
+ KisID id(*(keys.at(i)));
+ m_popup . insertItem(id.name(), static_cast<int>(i));
+ }
+
+ producerChanged(0);
+}
+
+HistogramDockerUpdater::HistogramDockerUpdater(TQObject* /*tqparent*/, KisHistogramSP h, KisHistogramView* v,
+ KisAccumulatingHistogramProducer* p)
+ : m_histogram(h), m_view(v), m_producer(p)
+{
+ connect(p, TQT_SIGNAL(completed()), this, TQT_SLOT(completed()));
+}
+
+void HistogramDockerUpdater::updated() {
+ // We don't [!] do m_histogram->updateHistogram();, because that will try to compute
+ // the histogram synchronously, while we want it asynchronously.
+ m_producer->addRegionsToBinAsync();
+}
+
+void HistogramDockerUpdater::completed() {
+ m_histogram->computeHistogram();
+ m_view->updateHistogram();
+}
+
+#include "histogramdocker.moc"
diff --git a/chalk/plugins/viewplugins/histogram_docker/histogramdocker.h b/chalk/plugins/viewplugins/histogram_docker/histogramdocker.h
new file mode 100644
index 00000000..ade0650f
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram_docker/histogramdocker.h
@@ -0,0 +1,81 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be>
+ *
+ * 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 _HISTOGRAMDOCKER_H_
+#define _HISTOGRAMDOCKER_H_
+
+#include <tqobject.h>
+#include <tqpopupmenu.h>
+
+#include <kparts/plugin.h>
+#include <kis_histogram_view.h>
+#include <kis_histogram.h>
+
+#include "kis_cachedhistogram.h"
+
+class KisAccumulatingHistogramProducer;
+class KisColorSpace;
+class KisHistogramView;
+class KisView;
+class KisColorSpace;
+
+class ChalkHistogramDocker : public KParts::Plugin
+{
+Q_OBJECT
+ TQ_OBJECT
+public:
+ ChalkHistogramDocker(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ChalkHistogramDocker();
+private slots:
+ void producerChanged(int pos);
+ void popupMenu(const TQPoint & pos);
+ void colorSpaceChanged(KisColorSpace* cs);
+private:
+ KisHistogramProducerFactory* m_factory;
+ KisCachedHistogramObserver::Producers m_producers;
+ KisAccumulatingHistogramProducer* m_producer;
+ KisColorSpace* m_cs;
+ KisView* m_view;
+ KisHistogramView* m_hview;
+ KisImageRasteredCache* m_cache;
+ TQPopupMenu m_popup;
+ KisHistogramSP m_histogram;
+ uint m_currentProducerPos;
+};
+
+class KisGenericRGBHistogramProducerFactory;
+
+class HistogramDockerUpdater : public TQObject {
+Q_OBJECT
+ TQ_OBJECT
+public:
+ HistogramDockerUpdater(TQObject* tqparent, KisHistogramSP h, KisHistogramView* v,
+ KisAccumulatingHistogramProducer* p);
+public slots:
+ void updated();
+private slots:
+ void completed();
+private:
+ KisHistogramSP m_histogram;
+ KisHistogramView* m_view;
+ KisAccumulatingHistogramProducer* m_producer;
+};
+
+#endif //_HISTOGRAMDOCKER_H_
diff --git a/chalk/plugins/viewplugins/histogram_docker/kis_accumulating_producer.cc b/chalk/plugins/viewplugins/histogram_docker/kis_accumulating_producer.cc
new file mode 100644
index 00000000..217a36d9
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram_docker/kis_accumulating_producer.cc
@@ -0,0 +1,102 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be>
+ *
+ * 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 <tqthread.h>
+#include <tqapplication.h>
+#include <tqevent.h>
+
+#include "kis_accumulating_producer.h"
+
+static const int EmitCompletedType = TQEvent::User + 1;
+
+/**
+ * The threaded producer definition in c++ file because this is really an internal affair.
+ * Note that since we _know_ that we'll only have a single instance of it running, at most,
+ * we don't care too much about locking and synchronization
+ **/
+class KisAccumulatingHistogramProducer::ThreadedProducer : public TQThread {
+ KisAccumulatingHistogramProducer* m_source;
+ bool m_stop;
+protected:
+ virtual void run();
+public:
+ ThreadedProducer(KisAccumulatingHistogramProducer* source)
+ : m_source(source), m_stop(false) {}
+ void cancel() { m_stop = true; }
+};
+
+KisAccumulatingHistogramProducer::KisAccumulatingHistogramProducer(KisCachedHistogramObserver::Producers* source)
+ : KisBasicHistogramProducer(
+ KisID("ACCHISTO", ""),
+ source->at(0)->channels().count(),
+ source->at(0)->numberOfBins(),
+ 0),
+ m_source(source)
+{
+ m_thread = new ThreadedProducer(this);
+}
+
+KisAccumulatingHistogramProducer::~KisAccumulatingHistogramProducer() {
+ m_thread->cancel();
+ m_thread->wait();
+ delete m_thread;
+}
+
+void KisAccumulatingHistogramProducer::addRegionsToBinAsync() {
+ m_thread->cancel();
+ m_thread->wait();
+ clear();
+ m_thread->start();
+}
+
+void KisAccumulatingHistogramProducer::ThreadedProducer::run() {
+ m_stop = false;
+
+ uint count = m_source->m_source->count(); // Talk about bad naming schemes...
+ KisCachedHistogramObserver::Producers* source = m_source->m_source;
+ TQValueVector<vBins>& bins = m_source->m_bins;
+ int channels = m_source->m_channels;
+ int nrOfBins = m_source->m_nrOfBins;
+
+ for (uint i = 0; i < count && !m_stop; i++) {
+ KisHistogramProducer* p = source->at(i);
+ m_source->m_count += p->count();
+
+ for (int j = 0; j < channels && !m_stop; j++) {
+ for (int k = 0; k < nrOfBins; k++) {
+ bins.at(j).at(k) += p->getBinAt(j, k);
+ }
+ }
+ }
+
+ if (!m_stop) {
+ // This function is thread-safe; and it takes ownership of the event
+ TQApplication::postEvent(m_source, new TQCustomEvent(EmitCompletedType));
+ }
+}
+
+void KisAccumulatingHistogramProducer::customEvent(TQCustomEvent* e) {
+ if (e->type() == EmitCompletedType) {
+ emit completed();
+ }
+}
+
+#include "kis_accumulating_producer.moc"
+
diff --git a/chalk/plugins/viewplugins/histogram_docker/kis_accumulating_producer.h b/chalk/plugins/viewplugins/histogram_docker/kis_accumulating_producer.h
new file mode 100644
index 00000000..d74a3ec5
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram_docker/kis_accumulating_producer.h
@@ -0,0 +1,77 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be>
+ *
+ * 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_ACCUMULATING_PRODUCER_H_
+#define _KIS_ACCUMULATING_PRODUCER_H_
+
+#include <tqobject.h>
+
+#include <kis_basic_histogram_producers.h>
+#include "kis_cachedhistogram.h"
+
+/**
+ * Kept very minimalistic because all options would require much reiterating which we don't want.
+ * This class is multithreading! Don't expect it to contain the right data after an
+ * addRegionsToBinAsync call, but await it's completed() signal. Also beware! This function
+ * _does_ clear() before addRegionsToBinAsync! (hence not conforming to the regular semantics
+ * of HistogramProducers if you'd take addRegionsToBinAsync = addRegionToBin, but since that is
+ * already violated with the asynchronousity of it that is not really an issue anymore, I think)
+ **/
+class KisAccumulatingHistogramProducer : public TQObject, public KisBasicHistogramProducer {
+Q_OBJECT
+ TQ_OBJECT
+public:
+ KisAccumulatingHistogramProducer(KisCachedHistogramObserver::Producers* source);
+ ~KisAccumulatingHistogramProducer();
+ /// Does _nothing_, use addRegionsToBinAsync
+ virtual void addRegionToBin(TQ_UINT8 *, TQ_UINT8*, TQ_UINT32, KisColorSpace *) {}
+ virtual void addRegionsToBinAsync();
+ virtual TQString positionToString(double pos) const
+ { return m_source->at(0)->positionToString(pos); }
+
+ virtual void setView(double, double) {} // No view support
+ virtual double maximalZoom() const { return 1.0; }
+
+ virtual TQ_INT32 numberOfBins() { return m_source->at(0)->numberOfBins(); }
+
+ virtual TQValueVector<KisChannelInfo *> channels() { return m_source->at(0)->channels(); }
+
+ /// Call this when the 'source' list has changed colorspace
+ virtual void changedSourceProducer() {
+ m_count = m_source->at(0)->channels().count();
+ m_external.clear();
+ makeExternalToInternal();
+ }
+
+signals:
+ void completed();
+
+protected:
+ virtual void customEvent(TQCustomEvent* e);
+ /// source already converts external to internal
+ virtual int externalToInternal(int ext) { return ext; }
+ KisCachedHistogramObserver::Producers* m_source;
+
+ class ThreadedProducer;
+ friend class ThreadedProducer;
+ ThreadedProducer* m_thread;
+};
+
+#endif // _KIS_ACCUMULATING_PRODUCER_H_
diff --git a/chalk/plugins/viewplugins/histogram_docker/kis_cachedhistogram.cc b/chalk/plugins/viewplugins/histogram_docker/kis_cachedhistogram.cc
new file mode 100644
index 00000000..1ad197f9
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram_docker/kis_cachedhistogram.cc
@@ -0,0 +1,37 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be>
+ *
+ * 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_paint_device.h>
+#include <kis_iterators_pixel.h>
+
+#include "kis_cachedhistogram.h"
+
+void KisCachedHistogramObserver::regionUpdated(KisPaintDeviceSP dev) {
+ m_producer->clear();
+ KisRectIteratorPixel srcIt = dev->createRectIterator(m_x, m_y, m_w, m_h, false);
+ int i;
+ while ( !srcIt.isDone() ) {
+ i = srcIt.nConseqPixels();
+ m_producer->addRegionToBin(srcIt.rawData(), srcIt.selectionMask(), i, dev->colorSpace());
+ srcIt += i;
+ if (i == 0)
+ ++srcIt;
+ }
+}
diff --git a/chalk/plugins/viewplugins/histogram_docker/kis_cachedhistogram.h b/chalk/plugins/viewplugins/histogram_docker/kis_cachedhistogram.h
new file mode 100644
index 00000000..084ff389
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram_docker/kis_cachedhistogram.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be>
+ *
+ * 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 _CACHED_HISTOGRAM_H_
+#define _CACHED_HISTOGRAM_H_
+
+#include <tqvaluevector.h>
+#include <kis_histogram_producer.h>
+
+#include "kis_imagerasteredcache.h"
+
+class KisCachedHistogramObserver : public KisImageRasteredCache::Observer {
+public:
+ typedef TQValueVector<KisHistogramProducer*> Producers;
+ KisCachedHistogramObserver(Producers* p, KisHistogramProducerFactory* f,
+ int x, int y, int w, int h, bool add = true)
+ : m_producers(p), m_factory(f), m_x(x), m_y(y), m_w(w), m_h(h)
+ {
+ m_producer = m_factory->generate();
+ if (add)
+ m_producers->append(m_producer);
+ }
+ virtual ~KisCachedHistogramObserver() {}
+
+ virtual Observer* createNew(int x, int y, int w, int h)
+ { return new KisCachedHistogramObserver(m_producers, m_factory, x, y, w, h); }
+
+ virtual void regionUpdated(KisPaintDeviceSP dev);
+private:
+ Producers* m_producers;
+ KisHistogramProducerFactory* m_factory;
+ KisHistogramProducerSP m_producer;
+ int m_x, m_y, m_w, m_h;
+};
+
+#endif // _CACHED_HISTOGRAM_H_
diff --git a/chalk/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.cc b/chalk/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.cc
new file mode 100644
index 00000000..19599cd9
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.cc
@@ -0,0 +1,162 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be>
+ *
+ * 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 <cmath>
+
+#include <tqapplication.h>
+
+#include <kdebug.h>
+
+#include <kis_doc.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_view.h>
+
+#include "kis_imagerasteredcache.h"
+
+KisImageRasteredCache::KisImageRasteredCache(KisView* view, Observer* o)
+ : m_observer(o->createNew(0, 0, 0, 0)), m_view(view)
+{
+ m_busy = false;
+ m_imageProjection = 0;
+ m_rasterSize = 64*4;
+ m_timeOutMSec = 1000;
+
+ KisImageSP img = view->canvasSubject()->currentImg();
+
+ if (!img) {
+ return;
+ }
+
+ imageSizeChanged(img->width(), img->height());
+
+ connect(img, TQT_SIGNAL(sigImageUpdated(TQRect)),
+ this, TQT_SLOT(imageUpdated(TQRect)));
+ connect(img, TQT_SIGNAL(sigSizeChanged(TQ_INT32, TQ_INT32)),
+ this, TQT_SLOT(imageSizeChanged(TQ_INT32, TQ_INT32)));
+ connect(&m_timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(timeOut()));
+}
+
+KisImageRasteredCache::~KisImageRasteredCache() {
+ cleanUpElements();
+}
+
+void KisImageRasteredCache::imageUpdated(TQRect rc) {
+
+ if (rc.isValid()) {
+ TQRect r(0, 0, m_width * m_rasterSize, m_height * m_rasterSize);
+ r &= rc;
+
+ uint x = static_cast<int>(r.x() / m_rasterSize);
+ uint y = static_cast<int>(r.y() / m_rasterSize);
+ uint x2 = static_cast<int>(ceil(float(r.x() + r.width()) / float(m_rasterSize)));
+ uint y2 = static_cast<int>(ceil(float(r.y() + r.height()) / float(m_rasterSize)));
+
+ if (!m_raster.empty()) {
+ for ( ; x < x2; x++) {
+ for (uint i = y; i < y2; i++) {
+ if (x < m_raster.size()) {
+ if (i < m_raster.at(x).size()) {
+ Element* e = m_raster.at(x).at(i);
+ if (e && e->valid) {
+ e->valid = false;
+ m_queue.push_back(e);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!m_busy) {
+ // If the timer is already started, this resets it. That way, we update always
+ // m_timeOutMSec milliseconds after the lastly monitored activity
+ m_timer.start(m_timeOutMSec, true); // true->singleshot
+ }
+}
+
+void KisImageRasteredCache::imageSizeChanged(TQ_INT32 w, TQ_INT32 h) {
+
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+
+ cleanUpElements();
+ m_busy = false;
+
+ m_width = static_cast<int>(ceil(float(w) / float(m_rasterSize)));
+ m_height = static_cast<int>(ceil(float(h) / float(m_rasterSize)));
+
+ m_raster.resize(m_width);
+
+ int rasterX = 0;
+
+ for (int i = 0; i < m_width * m_rasterSize; i += m_rasterSize) {
+ int rasterY = 0;
+
+ m_raster.at(rasterX).resize(m_height + 1);
+
+ for (int j = 0; j < m_height * m_rasterSize; j += m_rasterSize) {
+ Element* e = new Element(m_observer->createNew(i, j, m_rasterSize, m_rasterSize));
+ m_raster.at(rasterX).at(rasterY) = e;
+ rasterY++;
+ }
+ rasterX++;
+ }
+
+ imageUpdated(TQRect(0,0, image->width(), image->height()));
+}
+
+void KisImageRasteredCache::timeOut() {
+ m_busy = true;
+ KisImageSP img = m_view->canvasSubject()->currentImg();
+
+ // Temporary cache: while we are busy, we won't get the mergeImage time and again.
+ if (!m_imageProjection)
+ m_imageProjection = img->mergedImage();
+
+ // Pick one element of the cache, and update it
+ if (!m_queue.isEmpty()) {
+ m_queue.front()->observer->regionUpdated(m_imageProjection);
+ m_queue.front()->valid = true;
+ m_queue.pop_front();
+ }
+
+ // If there are still elements, we need to be called again (this emulates processEvents)
+ if (!m_queue.isEmpty()) {
+ TQTimer::singleShot(0, this, TQT_SLOT(timeOut()));
+ } else {
+ emit cacheUpdated();
+ m_imageProjection = 0;
+ m_busy = false;
+ }
+}
+
+void KisImageRasteredCache::cleanUpElements() {
+ for (uint i = 0; i < m_raster.count(); i++) {
+ for (uint j = 0; j < m_raster.at(i).count(); j++) {
+ delete m_raster.at(i).at(j);
+ }
+ m_raster.at(i).clear();
+ }
+ m_raster.clear();
+ m_queue.clear();
+}
+
+#include "kis_imagerasteredcache.moc"
diff --git a/chalk/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.h b/chalk/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.h
new file mode 100644
index 00000000..7df7df8f
--- /dev/null
+++ b/chalk/plugins/viewplugins/histogram_docker/kis_imagerasteredcache.h
@@ -0,0 +1,81 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be>
+ *
+ * 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_IMAGE_RASTERED_CACHE_H_
+#define _KIS_IMAGE_RASTERED_CACHE_H_
+
+#include <tqobject.h>
+#include <tqvaluevector.h>
+#include <tqvaluelist.h>
+#include <tqtimer.h>
+
+#include <kis_paint_device.h>
+
+class KisView;
+
+class KisImageRasteredCache : public TQObject {
+Q_OBJECT
+ TQ_OBJECT
+
+public:
+ class Observer {
+ public:
+ virtual Observer* createNew(int x, int y, int w, int h) = 0;
+ virtual void regionUpdated(KisPaintDeviceSP dev) = 0;
+ virtual ~Observer() {}
+ };
+
+ KisImageRasteredCache(KisView* view, Observer* o);
+ virtual ~KisImageRasteredCache();
+
+signals:
+ void cacheUpdated();
+
+private slots:
+ void imageUpdated(TQRect rc);
+ void imageSizeChanged(TQ_INT32 w, TQ_INT32 h);
+ void timeOut();
+
+private:
+ class Element {
+ public:
+ Element(Observer* o) : observer(o), valid(true) {}
+ Observer* observer;
+ bool valid;
+ };
+ typedef TQValueVector< TQValueVector<Element*> > Raster;
+ typedef TQValueList<Element*> Queue;
+
+ void cleanUpElements();
+
+ Observer* m_observer;
+ Raster m_raster;
+ Queue m_queue;
+ TQTimer m_timer;
+ int m_timeOutMSec;
+ int m_rasterSize;
+ int m_width, m_height;
+ KisView * m_view;
+ bool m_busy;
+
+ KisPaintDeviceSP m_imageProjection;
+};
+
+#endif // _KIS_IMAGE_RASTERED_CACHE_H_
diff --git a/chalk/plugins/viewplugins/history_docker/Makefile.am b/chalk/plugins/viewplugins/history_docker/Makefile.am
new file mode 100644
index 00000000..53511b3d
--- /dev/null
+++ b/chalk/plugins/viewplugins/history_docker/Makefile.am
@@ -0,0 +1,18 @@
+#kde_services_DATA = chalkhistorydocker.desktop
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkhistorydocker_la_SOURCES = historydocker.cc
+
+kde_module_LTLIBRARIES = chalkhistorydocker.la
+noinst_HEADERS = historydocker.h
+
+chalkhistorydocker_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+chalkhistorydocker_la_LIBADD = ../../../libchalkcommon.la
+
+chalkhistorydocker_la_METASOURCES = AUTO
diff --git a/chalk/plugins/viewplugins/history_docker/chalkhistorydocker.desktop b/chalk/plugins/viewplugins/history_docker/chalkhistorydocker.desktop
new file mode 100644
index 00000000..270393ce
--- /dev/null
+++ b/chalk/plugins/viewplugins/history_docker/chalkhistorydocker.desktop
@@ -0,0 +1,73 @@
+[Desktop Entry]
+Name=History Docker
+Name[ca]=Amarrador d'història
+Name[cy]=Bachydd Hanes
+Name[da]=Historikdokning
+Name[de]=Verlauf-Docker
+Name[el]=Προσάρτηση ιστορικού
+Name[eo]=Historidokilo
+Name[es]=Anclaje del histórico
+Name[et]=Ajaloo dokk
+Name[fa]=پیونددهندۀ سابقه‌نما
+Name[fr]=Ancrage d'historique
+Name[fy]=Histoarjekomponint
+Name[gl]=Acoplador de Histórico
+Name[hu]=Előzménydokkoló
+Name[is]=Söguspjald
+Name[it]=Aggancia-cronologia
+Name[ja]=履歴ドックパネル
+Name[km]=កន្លែង​ចត​ប្រវត្តិ
+Name[nb]=Hiastoriedokker
+Name[nds]=Vörgeschicht-Docker
+Name[ne]=इतिहास डकर
+Name[nl]=Geschiedeniscomponent
+Name[pl]=Doker historii
+Name[pt]=Acoplador de Histórico
+Name[pt_BR]=Acoplador de Histórico
+Name[ru]=История команд
+Name[sk]=História
+Name[sl]=Zgodovina
+Name[sr]=Сидраш историјата
+Name[sr@Latn]=Sidraš istorijata
+Name[sv]=Historikdockning
+Name[uk]=Швартувальник історії
+Name[zh_TW]=歷史紀錄停駐點
+Comment=Command history docker for Chalk
+Comment[bg]=Основната функционалност на Chalk
+Comment[ca]=Amarrador d'història d'ordres per a Chalk
+Comment[cy]=Bachydd yr hanes gorchmynion ar gyfer Chalk
+Comment[da]=Dokning af kommandohistorik for Chalk
+Comment[de]=Befehlsverlauf-Docker für Chalk
+Comment[el]=Άρθρωμα προσάρτησης ιστορικού εντολών για το Chalk
+Comment[es]=Anclaje con el histórico de órdenes para Chalk
+Comment[et]=Chalk käskude ajaloo dokk
+Comment[fa]=پیونددهنده تاریخچۀ فرمان برای Chalk
+Comment[fr]=Ancrage de l'historique des commandes pour Chalk
+Comment[fy]=Komponint mei bewurkingshistoarje foar Chalk"
+Comment[gl]=Un módulo acoplado co historial de comandos para Chalk
+Comment[hu]=Chalk parancselőzmény-dokkoló
+Comment[is]=Skipanasöguspjald fyrir Chalk
+Comment[it]=Aggancia-cronologia dei comandi di Chalk
+Comment[ja]=Chalk コマンド履歴ドックパネル
+Comment[km]=កន្លែង​ចត​ប្រវត្តិ​ពាក្យបញ្ជា​សម្រាប់ Chalk
+Comment[nb]=Kommandohistorie-dokker for Chalk
+Comment[nds]=Befehlsvörgeschicht-Docker för Chalk
+Comment[ne]=क्रिताका लागि आदेश इतिहास
+Comment[nl]=Component met bewerkingsgeschiedenis voor Chalk
+Comment[pl]=Doker historii poleceń dla Chalk
+Comment[pt]=Um módulo acoplado de histórico de comandos do Chalk
+Comment[pt_BR]=Um módulo acoplado de histórico de comandos do Chalk
+Comment[ru]=Панель истории команд Chalk
+Comment[sk]=História príkazov pre Chalk
+Comment[sl]=Zgodovina ukazov za Krito
+Comment[sr]=Сидраш историјата наредби за Chalk-у
+Comment[sr@Latn]=Sidraš istorijata naredbi za Chalk-u
+Comment[sv]=Dockning av kommandohistorik för Chalk
+Comment[uk]=Швартувальник історії команд для Chalk
+Comment[uz]=Chalk uchun buyruqlar tarixi paneli
+Comment[uz@cyrillic]=Chalk учун буйруқлар тарихи панели
+Comment[zh_TW]=Chalk 的指令紀錄停駐點
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalkhistorydocker
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/history_docker/historydocker.cc b/chalk/plugins/viewplugins/history_docker/historydocker.cc
new file mode 100644
index 00000000..e4f36813
--- /dev/null
+++ b/chalk/plugins/viewplugins/history_docker/historydocker.cc
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_doc.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_view.h>
+
+#include "historydocker.h"
+
+typedef KGenericFactory<ChalkHistoryDocker> ChalkHistoryDockerFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkhistorydocker, ChalkHistoryDockerFactory( "chalk" ) )
+
+ChalkHistoryDocker::ChalkHistoryDocker(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+
+
+
+ if ( tqparent->inherits("KisView") )
+ {
+ setInstance(ChalkHistoryDockerFactory::instance());
+ // Create history docker
+ // Add the docker to the docker manager
+ // Connect the undo system to the docker
+ }
+
+}
+
+ChalkHistoryDocker::~ChalkHistoryDocker()
+{
+}
diff --git a/chalk/plugins/viewplugins/history_docker/historydocker.h b/chalk/plugins/viewplugins/history_docker/historydocker.h
new file mode 100644
index 00000000..82aee9bf
--- /dev/null
+++ b/chalk/plugins/viewplugins/history_docker/historydocker.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 _HISTORYDOCKER_H
+#define _HISTORYDOCKER_H
+
+#include <kparts/plugin.h>
+
+class ChalkHistoryDocker : public KParts::Plugin
+{
+public:
+ ChalkHistoryDocker(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ChalkHistoryDocker();
+};
+
+
+#endif //_HISTORYDOCKER_H
diff --git a/chalk/plugins/viewplugins/imagesize/Makefile.am b/chalk/plugins/viewplugins/imagesize/Makefile.am
new file mode 100644
index 00000000..cf863888
--- /dev/null
+++ b/chalk/plugins/viewplugins/imagesize/Makefile.am
@@ -0,0 +1,25 @@
+chalkrcdir = $(kde_datadir)/chalkplugins
+chalkrc_DATA = imagesize.rc
+EXTRA_DIST = $(chalkrc_DATA)
+
+kde_services_DATA = chalkimagesize.desktop
+
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkimagesize_la_SOURCES = wdg_imagesize.ui wdg_layersize.ui imagesize.cc dlg_imagesize.cc dlg_layersize.cc wdg_resolution.ui
+
+noinst_HEADERS = wdg_imagesize.h dlg_imagesize.h imagesize.h dlg_layersize.h
+
+kde_module_LTLIBRARIES = chalkimagesize.la
+
+chalkimagesize_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) chalkblurfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui
+chalkimagesize_la_LIBADD = ../../../libchalkcommon.la
+
+chalkimagesize_la_METASOURCES = AUTO
diff --git a/chalk/plugins/viewplugins/imagesize/chalkimagesize.desktop b/chalk/plugins/viewplugins/imagesize/chalkimagesize.desktop
new file mode 100644
index 00000000..8505b94e
--- /dev/null
+++ b/chalk/plugins/viewplugins/imagesize/chalkimagesize.desktop
@@ -0,0 +1,39 @@
+[Desktop Entry]
+Name=Image Resize and Scale Plugin
+Name[bg]=Приставка за оразмеряване
+Name[ca]=Connector de redimensionament i escala d'imatge
+Name[da]=Plugin for størrelsesændring og skalering
+Name[de]=Bildgrößenänderungs- und Skalierungsmodul
+Name[el]=Πρόσθετο αλλαγής μεγέθους και κλιμάκωσης εικόνας
+Name[es]=Complemento para cambiar de tamaño y para escalar la imagen
+Name[et]=Pildi suuruse muutmise ja skaleerimise plugin
+Name[fa]=تغییر اندازۀ تصویر و مقیاس‌بندی وصله
+Name[fr]=Module de redimensionnement d'images
+Name[fy]=Grutte wizigje en skale fan de ôfbylding
+Name[gl]=Plugin de Redimensionamento e Escalado da Imaxe
+Name[he]=תוסף לשינוי גודל וזוויות של תמונ
+Name[hu]=Képátméretező és -nyújtó modul
+Name[is]=Breytingar á stærð og skala mynda íforrit
+Name[it]=Plugin di ridimensionamento e riscalamento delle immagini
+Name[ja]=画像 リサイズ/スケール プラグイン
+Name[km]=កម្មវិធី​ជំនួយ​ដើម្បី​ប្ដូរ​ទំហំ និង​ធ្វើ​មាត្រដ្ឋាន​រូបភាព
+Name[nb]=Programtillegg for skalering og endring av bildestørrelse
+Name[nds]=Moduul för't Ännern un Topassen vun de Bildgrött
+Name[ne]=छवि रिसाइज र स्केल प्लगइन
+Name[nl]=Grootte wijzigen en schalen van afbeelding
+Name[pl]=Wtyczka skalowania i zmiany rozmiarów obrazków
+Name[pt]='Plugin' de Dimensionamento e Escala da Imagem
+Name[pt_BR]=Plugin de Redimensionamento e Escala da Imagem
+Name[ru]=Модуль масштабирования и изменения размера
+Name[se]=Lassemoduvla mii skále ja rievdada govvasturrodaga
+Name[sk]=Modul na zmenu veľkosti a škály obrázkov
+Name[sl]=Vstavek za spreminjanje velikosti in povečavo slike
+Name[sr]=Прикључак за промену величине и скалирање слика
+Name[sr@Latn]=Priključak za promenu veličine i skaliranje slika
+Name[sv]=Insticksprogram för bildstorleksändring och skalning
+Name[uk]=Втулок зміни розміру та масштабування зображень
+Name[zh_TW]=圖片大小與縮放外掛程式
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalkimagesize
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/imagesize/configure.in.in b/chalk/plugins/viewplugins/imagesize/configure.in.in
new file mode 100644
index 00000000..0875ce32
--- /dev/null
+++ b/chalk/plugins/viewplugins/imagesize/configure.in.in
@@ -0,0 +1 @@
+AC_CHECK_DECLS([round], [], [], [#include <math.h>])
diff --git a/chalk/plugins/viewplugins/imagesize/dlg_imagesize.cc b/chalk/plugins/viewplugins/imagesize/dlg_imagesize.cc
new file mode 100644
index 00000000..a1eba4f3
--- /dev/null
+++ b/chalk/plugins/viewplugins/imagesize/dlg_imagesize.cc
@@ -0,0 +1,277 @@
+/*
+ * dlg_imagesize.cc - part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <config.h>
+
+#include <math.h>
+
+#include <iostream>
+
+using namespace std;
+
+#include <tqradiobutton.h>
+#include <tqcheckbox.h>
+#include <tqbuttongroup.h>
+#include <tqlabel.h>
+#include <tqcombobox.h>
+
+#include <klocale.h>
+#include <knuminput.h>
+#include <kdebug.h>
+
+#include <kis_cmb_idlist.h>
+#include <kis_filter_strategy.h>
+
+#include "dlg_imagesize.h"
+#include "wdg_imagesize.h"
+
+
+// XXX: I'm really real bad at arithmetic, let alone math. Here
+// be rounding errors. (Boudewijn)
+DlgImageSize::DlgImageSize( TQWidget * tqparent,
+ const char * name)
+ : super (tqparent, name, true, i18n("Image Size"), Ok | Cancel, Ok)
+{
+ m_lock = false;
+
+ m_page = new WdgImageSize(this, "image_size");
+ Q_CHECK_PTR(m_page);
+
+ m_page->cmbFilterType->setIDList(KisFilterStrategyRegistry::instance()->listKeys());
+ m_page->cmbFilterType->setCurrentText("Mitchell");
+
+ setMainWidget(m_page);
+ resize(m_page->tqsizeHint());
+
+ unblockAll();
+
+
+ connect(this, TQT_SIGNAL(okClicked()),
+ this, TQT_SLOT(okClicked()));
+
+}
+
+DlgImageSize::~DlgImageSize()
+{
+ delete m_page;
+}
+
+void DlgImageSize::hideScaleBox()
+{
+ m_page->grpResizeScale->hide();
+}
+
+void DlgImageSize::setWidth(TQ_UINT32 w)
+{
+ blockAll();
+
+ m_page->lblWidthOriginal->setNum((int)w);
+ m_page->intWidth->setValue(w);
+ m_oldW = w;
+ m_origW = w;
+
+ unblockAll();
+}
+
+void DlgImageSize::setWidthPercent(TQ_UINT32 w)
+{
+ blockAll();
+
+ m_page->intWidthPercent->setValue(w);
+ m_oldWPercent = w;
+
+ unblockAll();
+}
+
+
+void DlgImageSize::setMaximumWidth(TQ_UINT32 w)
+{
+ m_page->intWidth->setMaxValue(w);
+ m_maxW = w;
+}
+
+TQ_INT32 DlgImageSize::width()
+{
+ //return (TQ_INT32)tqRound(m_oldW);
+ return (TQ_INT32)tqRound(m_page->intWidth->value());
+}
+
+void DlgImageSize::setHeight(TQ_UINT32 h)
+{
+ blockAll();
+
+ m_page->lblHeightOriginal->setNum((int)h);
+ m_page->intHeight->setValue(h);
+ m_oldH = h;
+ m_origH = h;
+
+ unblockAll();
+}
+
+
+void DlgImageSize::setHeightPercent(TQ_UINT32 h)
+{
+ blockAll();
+
+ m_page->intHeightPercent->setValue(h);
+ m_oldHPercent = h;
+
+ unblockAll();
+}
+
+
+
+void DlgImageSize::setMaximumHeight(TQ_UINT32 h)
+{
+ m_page->intHeight->setMaxValue(h);
+ m_maxH = h;
+}
+
+
+TQ_INT32 DlgImageSize::height()
+{
+ //return (TQ_INT32)tqRound(m_oldH);
+ return (TQ_INT32)tqRound(m_page->intHeight->value());
+}
+
+bool DlgImageSize::scale()
+{
+ return m_page->radioScale->isChecked();
+}
+
+bool DlgImageSize::cropLayers()
+{
+ return m_page->chkCrop->isChecked();
+}
+
+KisFilterStrategy *DlgImageSize::filterType()
+{
+ KisID filterID = m_page->cmbFilterType->currentItem();
+ KisFilterStrategy *filter = KisFilterStrategyRegistry::instance()->get(filterID);
+ return filter;
+}
+
+// SLOTS
+
+void DlgImageSize::okClicked()
+{
+ accept();
+}
+
+void DlgImageSize::slotWidthPixelsChanged(int w)
+{
+ blockAll();
+
+ double wPercent = double(w) * 100 / double(m_origW);
+
+ m_page->intWidthPercent->setValue(tqRound(wPercent));
+
+ // Set height in pixels and percent of necessary
+ if (m_page->chkConstrain->isChecked()) {
+ m_page->intHeightPercent->setValue(tqRound(wPercent));
+
+ m_oldH = tqRound(m_origH * wPercent / 100);
+ m_page->intHeight->setValue(tqRound(m_oldH));
+
+ }
+ m_oldW = w;
+
+ unblockAll();
+}
+
+void DlgImageSize::slotHeightPixelsChanged(int h)
+{
+ blockAll();
+
+ double hPercent = double(h) * 100 / double(m_origH);
+
+ m_page->intHeightPercent->setValue(tqRound(hPercent));
+
+ // Set width in pixels and percent of necessary
+ if (m_page->chkConstrain->isChecked()) {
+ m_page->intWidthPercent->setValue(tqRound(hPercent));
+
+ m_oldW = tqRound(m_origW * hPercent / 100);
+ m_page->intWidth->setValue(tqRound(m_oldW));
+
+ }
+ m_oldH = h;
+
+ unblockAll();
+}
+
+void DlgImageSize::slotWidthPercentChanged(int w)
+{
+ blockAll();
+
+ m_page->intWidth->setValue(tqRound(w * m_origW / 100));
+
+ if (m_page->chkConstrain->isChecked()) {
+ m_page->intHeightPercent->setValue(w);
+ m_page->intHeight->setValue(tqRound( w * m_origH / 100));
+ }
+
+ unblockAll();
+}
+
+void DlgImageSize::slotHeightPercentChanged(int h)
+{
+ blockAll();
+
+ m_page->intHeight->setValue(tqRound(h * m_origH / 100));
+ if (m_page->chkConstrain->isChecked()) {
+ m_page->intWidthPercent->setValue(h);
+ m_page->intWidth->setValue(tqRound( h * m_origW / 100));
+ }
+
+ unblockAll();
+
+}
+
+
+void DlgImageSize::blockAll()
+{
+ // XXX: more efficient to use blockSignals?
+ m_page->intWidth->disconnect();
+ m_page->intHeight->disconnect();
+ m_page->intWidthPercent->disconnect();
+ m_page->intHeightPercent->disconnect();
+
+}
+
+void DlgImageSize::unblockAll()
+{
+ // XXX: more efficient to use blockSignals?
+ connect (m_page->intWidth, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT(slotWidthPixelsChanged(int)));
+
+ connect (m_page->intHeight, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT(slotHeightPixelsChanged(int)));
+
+ connect (m_page->intWidthPercent, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT(slotWidthPercentChanged(int)));
+
+ connect (m_page->intHeightPercent, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT(slotHeightPercentChanged(int)));
+
+
+}
+
+#include "dlg_imagesize.moc"
diff --git a/chalk/plugins/viewplugins/imagesize/dlg_imagesize.h b/chalk/plugins/viewplugins/imagesize/dlg_imagesize.h
new file mode 100644
index 00000000..7983e112
--- /dev/null
+++ b/chalk/plugins/viewplugins/imagesize/dlg_imagesize.h
@@ -0,0 +1,83 @@
+/*
+ * dlg_imagesize.h -- part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 DLG_IMAGESIZE
+#define DLG_IMAGESIZE
+
+#include <kdialogbase.h>
+
+class KisFilterStrategy;
+class WdgImageSize;
+
+/**
+ * This dialog allows the user to create a selection tqmask based
+ * on a (range of) colors.
+ */
+class DlgImageSize: public KDialogBase {
+ typedef KDialogBase super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ DlgImageSize(TQWidget * tqparent = 0,
+ const char* name = 0);
+ ~DlgImageSize();
+
+ void hideScaleBox();
+
+ void setWidth(TQ_UINT32 w);
+ void setWidthPercent(TQ_UINT32 w);
+ void setMaximumWidth(TQ_UINT32 w);
+ TQ_INT32 width();
+
+ void setHeight(TQ_UINT32 h);
+ void setHeightPercent(TQ_UINT32 h);
+ void setMaximumHeight(TQ_UINT32 h);
+ TQ_INT32 height();
+
+ bool scale();
+ bool cropLayers();
+
+ KisFilterStrategy *filterType();
+
+private slots:
+
+ void okClicked();
+ void slotWidthPixelsChanged(int w);
+ void slotHeightPixelsChanged(int h);
+ void slotWidthPercentChanged(int w);
+ void slotHeightPercentChanged(int h);
+
+private:
+
+ void blockAll();
+ void unblockAll();
+
+ WdgImageSize * m_page;
+ double m_oldW, m_oldH;
+ double m_oldWPercent, m_oldHPercent;
+ double m_origW, m_origH;
+ double m_maxW, m_maxH;
+
+ bool m_lock;
+
+};
+
+#endif // DLG_IMAGESIZE
diff --git a/chalk/plugins/viewplugins/imagesize/dlg_layersize.cc b/chalk/plugins/viewplugins/imagesize/dlg_layersize.cc
new file mode 100644
index 00000000..8289d693
--- /dev/null
+++ b/chalk/plugins/viewplugins/imagesize/dlg_layersize.cc
@@ -0,0 +1,261 @@
+/*
+ * dlg_layersize.cc - part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2005 Sven Langkamp <longamp@reallygood.de>
+ *
+ * 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 <config.h>
+
+#include <math.h>
+
+#include <iostream>
+
+using namespace std;
+
+#include <tqradiobutton.h>
+#include <tqcheckbox.h>
+#include <tqbuttongroup.h>
+#include <tqlabel.h>
+#include <tqcombobox.h>
+
+#include <klocale.h>
+#include <knuminput.h>
+#include <kdebug.h>
+
+#include <kis_cmb_idlist.h>
+#include <kis_filter_strategy.h>
+
+#include "dlg_layersize.h"
+#include "wdg_layersize.h"
+
+
+// XXX: I'm really real bad at arithmetic, let alone math. Here
+// be rounding errors. (Boudewijn)
+DlgLayerSize::DlgLayerSize( TQWidget * tqparent,
+ const char * name)
+ : super (tqparent, name, true, i18n("Scale Layer"), Ok | Cancel, Ok)
+{
+ m_lock = false;
+
+ m_page = new WdgLayerSize(this, "layer_size");
+ Q_CHECK_PTR(m_page);
+
+ m_page->cmbFilterType->setIDList(KisFilterStrategyRegistry::instance()->listKeys());
+ m_page->cmbFilterType->setCurrentText("Mitchell");
+
+ setMainWidget(m_page);
+ resize(m_page->tqsizeHint());
+
+ unblockAll();
+
+
+ connect(this, TQT_SIGNAL(okClicked()),
+ this, TQT_SLOT(okClicked()));
+
+}
+
+DlgLayerSize::~DlgLayerSize()
+{
+ delete m_page;
+}
+
+void DlgLayerSize::setWidth(TQ_UINT32 w)
+{
+ blockAll();
+
+ m_page->lblWidthOriginal->setNum((int)w);
+ m_page->intWidth->setValue(w);
+ m_oldW = w;
+ m_origW = w;
+
+ unblockAll();
+}
+
+void DlgLayerSize::setWidthPercent(TQ_UINT32 w)
+{
+ blockAll();
+
+ m_page->intWidthPercent->setValue(w);
+ m_oldWPercent = w;
+
+ unblockAll();
+}
+
+
+void DlgLayerSize::setMaximumWidth(TQ_UINT32 w)
+{
+ m_page->intWidth->setMaxValue(w);
+ m_maxW = w;
+}
+
+TQ_INT32 DlgLayerSize::width()
+{
+ //return (TQ_INT32)tqRound(m_oldW);
+ return (TQ_INT32)tqRound(m_page->intWidth->value());
+}
+
+void DlgLayerSize::setHeight(TQ_UINT32 h)
+{
+ blockAll();
+
+ m_page->lblHeightOriginal->setNum((int)h);
+ m_page->intHeight->setValue(h);
+ m_oldH = h;
+ m_origH = h;
+
+ unblockAll();
+}
+
+
+void DlgLayerSize::setHeightPercent(TQ_UINT32 h)
+{
+ blockAll();
+
+ m_page->intHeightPercent->setValue(h);
+ m_oldHPercent = h;
+
+ unblockAll();
+}
+
+void DlgLayerSize::setMaximumHeight(TQ_UINT32 h)
+{
+ m_page->intHeight->setMaxValue(h);
+ m_maxH = h;
+}
+
+TQ_INT32 DlgLayerSize::height()
+{
+ //return (TQ_INT32)tqRound(m_oldH);
+ return (TQ_INT32)tqRound(m_page->intHeight->value());
+}
+
+KisFilterStrategy *DlgLayerSize::filterType()
+{
+ KisID filterID = m_page->cmbFilterType->currentItem();
+ KisFilterStrategy *filter = KisFilterStrategyRegistry::instance()->get(filterID);
+ return filter;
+}
+
+
+// SLOTS
+
+void DlgLayerSize::okClicked()
+{
+ accept();
+}
+
+void DlgLayerSize::slotWidthPixelsChanged(int w)
+{
+ blockAll();
+
+ double wPercent = double(w) * 100 / double(m_origW);
+
+ m_page->intWidthPercent->setValue(tqRound(wPercent));
+
+ // Set height in pixels and percent of necessary
+ if (m_page->chkConstrain->isChecked()) {
+ m_page->intHeightPercent->setValue(tqRound(wPercent));
+
+ m_oldH = tqRound(m_origH * wPercent / 100);
+ m_page->intHeight->setValue(tqRound(m_oldH));
+
+ }
+ m_oldW = w;
+
+ unblockAll();
+}
+
+void DlgLayerSize::slotHeightPixelsChanged(int h)
+{
+ blockAll();
+
+ double hPercent = double(h) * 100 / double(m_origH);
+
+ m_page->intHeightPercent->setValue(tqRound(hPercent));
+
+ // Set width in pixels and percent of necessary
+ if (m_page->chkConstrain->isChecked()) {
+ m_page->intWidthPercent->setValue(tqRound(hPercent));
+
+ m_oldW = tqRound(m_origW * hPercent / 100);
+ m_page->intWidth->setValue(tqRound(m_oldW));
+
+ }
+ m_oldH = h;
+
+ unblockAll();
+}
+
+void DlgLayerSize::slotWidthPercentChanged(int w)
+{
+ blockAll();
+
+ m_page->intWidth->setValue(tqRound(w * m_origW / 100));
+
+ if (m_page->chkConstrain->isChecked()) {
+ m_page->intHeightPercent->setValue(w);
+ m_page->intHeight->setValue(tqRound( w * m_origH / 100));
+ }
+
+ unblockAll();
+}
+
+void DlgLayerSize::slotHeightPercentChanged(int h)
+{
+ blockAll();
+
+ m_page->intHeight->setValue(tqRound(h * m_origH / 100));
+ if (m_page->chkConstrain->isChecked()) {
+ m_page->intWidthPercent->setValue(h);
+ m_page->intWidth->setValue(tqRound( h * m_origW / 100));
+ }
+
+ unblockAll();
+
+}
+
+
+void DlgLayerSize::blockAll()
+{
+ // XXX: more efficient to use blockSignals?
+ m_page->intWidth->disconnect();
+ m_page->intHeight->disconnect();
+ m_page->intWidthPercent->disconnect();
+ m_page->intHeightPercent->disconnect();
+
+}
+
+void DlgLayerSize::unblockAll()
+{
+ // XXX: more efficient to use blockSignals?
+ connect (m_page->intWidth, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT(slotWidthPixelsChanged(int)));
+
+ connect (m_page->intHeight, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT(slotHeightPixelsChanged(int)));
+
+ connect (m_page->intWidthPercent, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT(slotWidthPercentChanged(int)));
+
+ connect (m_page->intHeightPercent, TQT_SIGNAL(valueChanged(int)),
+ this, TQT_SLOT(slotHeightPercentChanged(int)));
+
+
+}
+
+#include "dlg_layersize.moc"
diff --git a/chalk/plugins/viewplugins/imagesize/dlg_layersize.h b/chalk/plugins/viewplugins/imagesize/dlg_layersize.h
new file mode 100644
index 00000000..0aaf8445
--- /dev/null
+++ b/chalk/plugins/viewplugins/imagesize/dlg_layersize.h
@@ -0,0 +1,74 @@
+/*
+ * dlg_layersize.h -- part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2005 Sven Langkamp <longamp@reallygood.de>
+ *
+ * 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 DLG_LAYERSIZE
+#define DLG_LAYERSIZE
+
+#include <kdialogbase.h>
+
+class WdgLayerSize;
+class KisFilterStrategy;
+
+class DlgLayerSize: public KDialogBase {
+ typedef KDialogBase super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ DlgLayerSize(TQWidget * tqparent = 0,
+ const char* name = 0);
+ ~DlgLayerSize();
+
+ void setWidth(TQ_UINT32 w);
+ void setWidthPercent(TQ_UINT32 w);
+ void setMaximumWidth(TQ_UINT32 w);
+ TQ_INT32 width();
+
+ void setHeight(TQ_UINT32 h);
+ void setHeightPercent(TQ_UINT32 h);
+ void setMaximumHeight(TQ_UINT32 h);
+ TQ_INT32 height();
+ KisFilterStrategy *filterType();
+
+private slots:
+
+ void okClicked();
+ void slotWidthPixelsChanged(int w);
+ void slotHeightPixelsChanged(int h);
+ void slotWidthPercentChanged(int w);
+ void slotHeightPercentChanged(int h);
+
+private:
+
+ void blockAll();
+ void unblockAll();
+
+ WdgLayerSize * m_page;
+ double m_oldW, m_oldH;
+ double m_oldWPercent, m_oldHPercent;
+ double m_origW, m_origH;
+ double m_maxW, m_maxH;
+
+ bool m_lock;
+
+};
+
+#endif // DLG_IMAGESIZE
diff --git a/chalk/plugins/viewplugins/imagesize/imagesize.cc b/chalk/plugins/viewplugins/imagesize/imagesize.cc
new file mode 100644
index 00000000..c23d2717
--- /dev/null
+++ b/chalk/plugins/viewplugins/imagesize/imagesize.cc
@@ -0,0 +1,190 @@
+/*
+ * imagesize.cc -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 <math.h>
+
+#include <stdlib.h>
+
+#include <tqslider.h>
+#include <tqrect.h>
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <kstdaction.h>
+
+#include <kis_doc.h>
+#include <kis_config.h>
+#include <kis_image.h>
+#include <kis_layer.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_view.h>
+#include <kis_selection.h>
+#include <kis_selection_manager.h>
+#include <kis_transaction.h>
+#include <kis_canvas_controller.h>
+#include <kis_scale_visitor.h>
+
+#include "imagesize.h"
+#include "dlg_imagesize.h"
+#include "dlg_layersize.h"
+#include "kis_filter_strategy.h"
+
+typedef KGenericFactory<ImageSize> ImageSizeFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkimagesize, ImageSizeFactory( "chalk" ) )
+
+ImageSize::ImageSize(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ if ( tqparent->inherits("KisView") )
+ {
+ setInstance(ImageSizeFactory::instance());
+ setXMLFile(locate("data","chalkplugins/imagesize.rc"), true);
+
+ (void) new KAction(i18n("Change &Image Size..."), 0, "Shift-s", this, TQT_SLOT(slotImageSize()), actionCollection(), "imagesize");
+ (void) new KAction(i18n("&Scale Layer..."), 0, 0, this, TQT_SLOT(slotLayerSize()), actionCollection(), "layerscale");
+
+
+ m_view = (KisView*) tqparent;
+ // Selection manager takes ownership?
+ KAction * a = new KAction(i18n("&Scale Selection..."), 0, 0, this, TQT_SLOT(slotSelectionScale()), actionCollection(), "selectionscale");
+ Q_CHECK_PTR(a);
+ m_view ->canvasSubject()-> selectionManager()->addSelectionAction(a);
+ }
+}
+
+ImageSize::~ImageSize()
+{
+ m_view = 0;
+}
+
+void ImageSize::slotImageSize()
+{
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+
+ if (!image) return;
+
+ DlgImageSize * dlgImageSize = new DlgImageSize(m_view, "ImageSize");
+ Q_CHECK_PTR(dlgImageSize);
+
+ dlgImageSize->setCaption(i18n("Image Size"));
+
+ KisConfig cfg;
+
+ dlgImageSize->setWidth(image->width());
+ dlgImageSize->setHeight(image->height());
+
+ if (dlgImageSize->exec() == TQDialog::Accepted) {
+ TQ_INT32 w = dlgImageSize->width();
+ TQ_INT32 h = dlgImageSize->height();
+
+ if (dlgImageSize->scale()) {
+ m_view->scaleCurrentImage((double)w / ((double)(image->width())),
+ (double)h / ((double)(image->height())),
+ dlgImageSize->filterType());
+ }
+ else {
+ m_view->resizeCurrentImage(w, h, dlgImageSize->cropLayers());
+ }
+ }
+
+ delete dlgImageSize;
+}
+
+void ImageSize::slotLayerSize()
+{
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+
+ if (!image) return;
+
+ DlgLayerSize * dlgLayerSize = new DlgLayerSize(m_view, "LayerSize");
+ Q_CHECK_PTR(dlgLayerSize);
+
+ dlgLayerSize->setCaption(i18n("Layer Size"));
+
+ KisConfig cfg;
+ KisPaintDeviceSP dev = image->activeDevice();
+
+ TQRect rc = dev->exactBounds();
+
+ dlgLayerSize->setWidth(rc.width());
+ dlgLayerSize->setHeight(rc.height());
+
+ if (dlgLayerSize->exec() == TQDialog::Accepted) {
+ TQ_INT32 w = dlgLayerSize->width();
+ TQ_INT32 h = dlgLayerSize->height();
+
+ m_view->scaleLayer((double)w / ((double)(rc.width())),
+ (double)h / ((double)(rc.height())),
+ dlgLayerSize->filterType());
+ }
+ delete dlgLayerSize;
+}
+
+void ImageSize::slotSelectionScale()
+{
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+
+ if (!image) return;
+
+ KisPaintDeviceSP layer = image->activeDevice();
+
+ if (!layer) return;
+
+ if (!layer->hasSelection()) return;
+
+
+ DlgLayerSize * dlgLayerSize = new DlgLayerSize(m_view, "SelectionScale");
+ Q_CHECK_PTR(dlgLayerSize);
+
+ dlgLayerSize->setCaption(i18n("Scale Selection"));
+
+ KisConfig cfg;
+ TQRect rc = layer->selection()->selectedRect();
+
+ dlgLayerSize->setWidth(rc.width());
+ dlgLayerSize->setHeight(rc.height());
+
+ if (dlgLayerSize->exec() == TQDialog::Accepted) {
+ TQ_INT32 w = dlgLayerSize->width();
+ TQ_INT32 h = dlgLayerSize->height();
+
+ KisScaleWorker worker (layer->selection().data(),
+ (double)w / ((double)(rc.width())),
+ (double)h / ((double)(rc.height())),
+ dlgLayerSize->filterType());
+ worker.run();
+
+ m_view->getCanvasController()->updateCanvas();
+
+ }
+ delete dlgLayerSize;
+}
+
+
+#include "imagesize.moc"
diff --git a/chalk/plugins/viewplugins/imagesize/imagesize.h b/chalk/plugins/viewplugins/imagesize/imagesize.h
new file mode 100644
index 00000000..989a603f
--- /dev/null
+++ b/chalk/plugins/viewplugins/imagesize/imagesize.h
@@ -0,0 +1,49 @@
+/*
+ * imagesize.h -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 IMAGESIZE_H
+#define IMAGESIZE_H
+
+#include <kparts/plugin.h>
+
+class KisView;
+class KisPainter;
+
+class ImageSize : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ ImageSize(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ImageSize();
+
+private slots:
+
+ void slotImageSize();
+ void slotLayerSize();
+ void slotSelectionScale();
+
+private:
+
+ KisView * m_view;
+ KisPainter * m_painter;
+
+};
+
+#endif // IMAGESIZE_H
diff --git a/chalk/plugins/viewplugins/imagesize/imagesize.rc b/chalk/plugins/viewplugins/imagesize/imagesize.rc
new file mode 100644
index 00000000..2efb4ed8
--- /dev/null
+++ b/chalk/plugins/viewplugins/imagesize/imagesize.rc
@@ -0,0 +1,15 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkimagesize" version="6">
+<MenuBar>
+ <Menu name="Image"><text>Image</text>
+ <Action name="imagesize"/>
+ <Action name="imageresolution"/>
+ </Menu>
+ <Menu name="Layer"><text>Layer</text>
+ <Action name="layerscale"/>
+ </Menu>
+ <Menu name="Select"><text>&amp;Select</text>
+ <Action name="selectionscale"/>
+ </Menu>
+</MenuBar>
+</kpartgui>
diff --git a/chalk/plugins/viewplugins/imagesize/wdg_imagesize.ui b/chalk/plugins/viewplugins/imagesize/wdg_imagesize.ui
new file mode 100644
index 00000000..4cdd5c95
--- /dev/null
+++ b/chalk/plugins/viewplugins/imagesize/wdg_imagesize.ui
@@ -0,0 +1,365 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgImageSize</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgImageSize</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>397</width>
+ <height>382</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Image Size</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQButtonGroup" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>grpResizeScale</cstring>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>pixmapLabel1_2</cstring>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer row="1" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>spacer2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>65</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="0" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>spacer1_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>65</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLabel" row="0" column="3">
+ <property name="name">
+ <cstring>pixmapLabel2_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="pixmap">
+ <pixmap>image1</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>radioResize</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Resize</string>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>chkCrop</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Crop layers on image resize</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer row="2" column="2" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>121</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQRadioButton" row="1" column="3">
+ <property name="name">
+ <cstring>radioScale</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Scale</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQButtonGroup" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>grpPixelDimensions</cstring>
+ </property>
+ <property name="title">
+ <string>&amp;Pixel Dimensions</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="1">
+ <property name="name">
+ <cstring>lblWidth</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Width:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>intWidth</cstring>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="2" column="2">
+ <property name="name">
+ <cstring>intHeight</cstring>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="2">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Height:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>intHeight</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="1">
+ <property name="name">
+ <cstring>lblWidthOriginal</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>WinPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="2">
+ <property name="name">
+ <cstring>lblHeightOriginal</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>WinPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>lblOrignal</cstring>
+ </property>
+ <property name="text">
+ <string>Original:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>lblNew</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;New:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>intWidth</cstring>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="2" column="1">
+ <property name="name">
+ <cstring>intWidth</cstring>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="3" column="1">
+ <property name="name">
+ <cstring>intWidthPercent</cstring>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="referencePoint">
+ <number>100</number>
+ </property>
+ <property name="suffix">
+ <string>%</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="3" column="2">
+ <property name="name">
+ <cstring>intHeightPercent</cstring>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="suffix">
+ <string>%</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>lblPercent</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Percent:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>intWidthPercent</cstring>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="4" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>chkConstrain</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Constrain proportions</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>lblFilterType</cstring>
+ </property>
+ <property name="text">
+ <string>Filter:</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>cmbFilterType</cstring>
+ </property>
+ </widget>
+ <widget class="KisCmbIDList" row="2" column="1">
+ <property name="name">
+ <cstring>cmbFilterType</cstring>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KisCmbIDList</class>
+ <header location="local">kis_cmb_idlist.h</header>
+ <sizehint>
+ <width>1</width>
+ <height>24</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image2</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="4407">89504e470d0a1a0a0000000d494844520000006e0000002e0806000000c9032c97000010fe49444154789ced9b79741455bec73f55bdd0d94893054212c32a10821064095b44458119c1618928038af8e61c78e3783cfee13bcfa7c020eaf00e1c90a3ce24f890454438a0cce8cc1b8808610f04599c17c0b0bcb0042421fbda55d575df1f9dea7477ba4967018ecefb9e53dd55f7debaf7d6ef5bbfe52e256566660aee31de78e38da4f2f2f26b0042dcf3e6bd2049120053a64c99f6d24b2fcda8abab76754880d0759001dd5556a7b1afba2b411702245759d0119ee58c0b570202dd558d68fcf14c6b2ce3be4f074c8de94e5709a70024937cf6ecf9a3595959996680050b1674a028ee8cacac2c2c164b8210e29a21b4fb0d21043367ce1c3b65ca53cf5b2cd6b6d6e2f11fe89c46428d73e17e7185e7b96ebc3b02a10bd7bf10d842ecfc61f97fc6039f995bd5b5c6ca8510e88d6f9defb9bfc3c88b8c8c0440922491959545972e5d5ad3fc5d8549128ef628bf10783cab679a77beeb5a6a2c2b79dc27f994c1230d9c4e1d4b278184e604ac72dbbbda7e582c96fbd9fc7dc5a64d9bda76a370a971ab34aeb2b2124d034992319bcd5cb97295ae5dedd8ed76005455e51fff384f48880db359263a3aaaf1dc7f33aaaab6adf3f719959595389d2049264c261357ae5c253e3ec66d415455e5cc997c424242b0584c74ed1a4b48880d93c9d442cdc12368e284101417979094d4039bcde507745da3aaaaca4d5c6e6e1e13274e70df535454cadebd393cf9e404b739f5447b346e6786940aec03ecc00660fef41d6db775cd7b171825252524262679c9a1babada4ddc9123b93cfef8a3eef24545a51c3efc2d93264d74a7bdf0c20b6dee2bb86226bff0f45d062449c2330ad434dd1d951d3f7e82f1e31ff52affd5573b193870406359ad591bed0c4ea645f64cb58ffab79d58c2ec2f02eb7766b4bd3e4df34f5d70727022cb2e511e3b96c7b871e95ee5fffad7bf909232b0cd7df384ea74fd0724eef0e1a3e4e4e472e2c477ee20c36432a1aa4d0408a1131616c6a54b97494979884e9d9a4cc1575fed2239b92f090909e8baee65163bca445ac2ec74ef7d86f4e72bb0d878917692e70f9e723060369bbde4a0eb82b0b0302e5ebc44fffe03b05a9be4f0f5d7bb193c3899c4c444af7a376ddae415bcf98367bed3e9f4caf34b5c4ece7e060c18c4e38f8fa173e7ae6cdcb88d8b170b5154d9cbbc454444b06fdf615455101d1de94e3f72e43bcaca7e64e8d0a10821d034edee8dd76a7388ec06e97331c83bb53343b2770481be72d8b0612b172ffe2f0d0ec94b0e9d3b87f3cd37fba9afd7888a6a92c3d1a327a9aa2a65d8b0615ef5fa93c59d481442347bd9fd1267b3d9282cbc0140bf7e0ff0e4939349ead58b7e7dba633635dd121e16c6238f3c4a6a6a8a3bede6cddbe4e61e64c68c1900e8ba8ed3d9644a3a1cbaeb888c85f467c1d209b7ef6b2f79fee490d8a3170ff68ef3924358681863c7a6336448b23bede6cddb9c387194679ec970a77912f3fcf3cffb6dd373f8042eb3acaa2abaae7bb916bfc1c9a85169ac5bb789f8f8ae444686939060a7fe87cd545cdc43f8843fba6f33994c8485857addfbe9a79b98376f8edb37a8aa8a2449adf2673b33a447815771051e81d0d3f5844d47642c4c7a090e6e27b5f236fb80c776664815c1042dbaae377be3db23872d5b36f39bdfcc7775d1673c6bc0dfe0db13469aa669cde41730aa9c356b3abb771f2423e397949fde4897ca3d848c7f0fc5d4d4c1eef1b15ef7e4e59da57bf738424242703a9d7e1bf444205f278469677cda54bbbd474f709ef622c7f3088ded09da69b7d6a183c502e9d3e0e04e522b4b5b479e3f3cfbec0c76ed3ad06a392426261212121290904f3ffd94b973e70624d280a669e8badecc620524aea2a29291a3d36828caa3cba53fc2137f42682ac2ac40e3b450e9ed4a6c61a18485b8ec7dbf7e7dd8bb771f0e87c35d4fdb2247c93eeaf5d5503b14d40a70025a80a38e66845a2c903e050e7e4d6a6519fb80e93b33a4c2b690d75639ecdf7f004dd3bc047e271fe69b67a419160b086c2a2b2baba9ad55282baba4b4b49c31e9c350774c064b0d2857118e4244a77877f9db37afa02b95f4199c8e5353e8d44966fcf8f1e4e49c202c2c045d57e9d7af07515151ad16187a21e8152e32749fc357fbfce45b2c903e190efe9dd4ca724ee1d2bcd3c190d7117218376e1cbb761d2222220c703270601fa2a2a2dc8418da168830c3b719e7be0ae0a57f870ee51217174d4a4a6f06a73e447dd975421d27c0741e6a73c079d12b2c359914ba687fa3f8da251c0a5455d592981847dfbe0f327a741afdfba7909777b2451f1730af1544f9cbb79821fd09888b97ed20ed734de5b78c8e9243af5ebd193efc617af6eccbd1a3c75b6cd793444f577347e25455c5643223cb20498dd1a0a31642711d35eb41ca4773368d5f1455c16e3b80f5e6124acbeb70284eeaea1a703a9d5cba7495babafaa08213bf26a40d44f9cb979189eb6e45088b5d88c033359ec1c9dd9083a2285e1ab679f366bfcf6f9c1bfebf45e26a6a6ab87af532efbfbf961d3bb2b978e93ad6d028549b09a281f02a74d39f716a0e340d1c0aa8ce320447e96afb8cba4b1f515ee5a4b6b61e4d7372fb76159b366d2639b95faba3ca2669e29fac2089742a3237ae59f9fe1408216d1022b83edcba7583356b3eee30396cdebc85e4e47ecddaf14718e0652203c14d9c2449cc9a3593a95327101bdb8983fb77610a8da53ee2510807ba8008ed82a2eaa8aac0a180a2e888082016faaa6f71bb20879a3a27d5d575984c269292fa60b158da4e5cb064f9e6e9e0545da49d3c0e9ac60690e6cbb21254b3f3e6cd61eedc19f4ee1dc3f1dc7ded96c3030ff4f29a6817423067ce9c663e4e0881d3e9748fd9fc1d06dcb51989313131c4c4c4d0ad5b37f24ee633a2d7121aae7d8bad0f5033829a6a1587e336d5d555a8ea752c76a01684650c515d92c9bf5c04ba46616121b76e5d253e3e843e7dfa0078459b2da1aea404ab2a7b47943ed1a58c4016a219914e55e6c6152b278f81a6893f03f31f1e2171ea44f093dad1d1d1444747131717c777a7ce31ac1d72282ebe46626238bd7bf7f622c91746e8efef250f388ef3cd50558d9a8a4aaafa8dc512b50dcefe165b3f33f6a8f398cd7d4888fb0eb335072aa1b6280547ff6d5c3dfd2385970b3199ca18336638c9c9bf222222c25da7b1ac11c4aa4045de87efd823a2ad4da4786a5ae37f648c469f215a73f378c5cac95c706ada6959d6e6037c7fca46b0a6d2130e8742754539550fb65e0e66733963c70e2739791ae1e1e14053d4b865cb1666cf9e0d34cd2ef95b41090437712693c96ba47ef9f20d9e7e7a2267ce5c24a6dbafb03184b2efdec71ef337cc09a3a1e67fa8bf7213a779314a8f57d97d209ff8b808626234a033050505141414f86d54b4204149d2a6979ecf7fb5f48e3327a267ec80213dfb8c125079daad6965c556ce9e72912649da6340852cdbd03498f96543c0dafccd9c689a467efe259e7a6a42abe53069523af9f9798c1c39d278e680ed1aa4dd695a30288ddbbbf70053a63c8d2441dfbe496cd9f2df24f54a62d8a095dcae3c8b282802691452e779dcaa0b277bcbdfe999d49dd4d4019c3f7f8ca953a762369bd175dd2d108bc582aeeb2c5dba34bbb8b8f872604260fa0e91f3e54c4bcee40fb760559ff36b2ebf7e47ff3de6c825987091a6c894ddb272f230d4567b9066b2a1a9e28ea405c2eedd7b983871b2971c7af44ee2e1944072d845cfa438525307a0eb3ac78e9de1cc99ef193cf821c09bbcd9b367a3ebba7bb9abb531805fe2c2c343d8b7ef2003060c64edda8f090f97e9da1532d7e5f0d0e03144dafba3282a47fff22d3555579930611c172efcc0f6ede500c4c6c6fa35874b962cd9939999f92f0d0d0dc51b366c68b173791fbe4340734923119ea41d84da2a6fd29c9a862c375f0b0c06e1e1a1e4e41ca27fff643efef8bf888cb4a0392cac5d7f809441a33ce4b097daeaab3cf1443a05052e398c1b379acb97cf9192e29a0ef39cce32b4aca5c8d11341695c7afa38f2f24eb0614316cf3cf34bfaf7ef0fc0a04137c8cfbfc6d0c1432829a9e49b5d452c5dfa1fc8b2cc638f491c3d7a948282db343434b807a856ab6b5a68d1a2457bde7befbdf9353535d783f17592a4517a3e9fd280f98090d11c50fea39593fba1b64a3d2d49cec7808ad0701bb5d51a92a411ec5497e7ac05c0f8f18f70ecd871366f5ec7af7f3d95010306208460d0a0419c3953c8d0c13d2929a964cfee22de7efb4d64d93573949b9bcbba75993cfdf404860f1fee55bf6116b76fdf4e464646fb89f3c58811c3193162b8575a42423cfbf7e761b78770e1c2351e78a09b975d1e397224050505ee7188c562415114962e5dba67f9f2e5f3333333af071a78faa22561efcc90a82a2aa4ac7c3ca7f61fa1ae5a392d49ba8bb4081bb555ad23cde84f4d4d0db22cd3a95327cc6633696923494b1be9b5129e9090c0b7dfe6bae5909414e7b52a9e9696465a5a9abb7ca0e0a33d3b0002469581101e6e66e5ca3f71eb5609191993bc26408d73d72c8c09455178f7dd77f7ac58b1627e5151d1751f5f477171719b3b0e6c70545c7df5d0dacfec92a49d86f691064d2f92c3e14051144c26d766205996ddff0622222cac5c994971b14b0e060c9f6e9842cfb19aa78c67cd9ad5aabe053d1c088469d3a606acd878305996a9abab63e5ca957b56ad5a355f0871ddb3ec92254bc8cccc6c55c77d317d8728dc9921758919f838a3a740f9b9239ccc81da2a154972b69a34dfe730846f987ccf41b02ccbfce21713dd323366f10dd2fc5992f66efe0d38e565369b3be400d72ea8575e7965c3aa55ab5eacafafbfded0d0e08e30df7cf34dde7efbed0edbcae032973d38b91feaaa953693e6cf8cf9ce58782e0eabaa8aa228288a82a6696e0df377af3fd2b66ddbd686a76d825be3eaebebdb254ccf0ebef6da6b6bb2b3b3ffbdb4b4b44151144f5fc7f2e5cb3b74ff89a3e22a87d67e86246980de664d332049925ba8cf3df71c005bb76ef5ba6e293fd8ebd668a16f59e96e7cf4b170e1c2ce999999d5d3a64dc366b301f0eebbefb262c50a2fd27cb7b9dd0f187d983c79f23b3b76ec78539224bf5b09ef372449a273e7ce2c5bb62c7bf1e2c573cc0b172e948410646565b160c102f7f2437b1a98376f1e1b376ef4f475ac5ab5ea9e9154121d4d6c69a081c49d21cbf2dddbd8e481400ba4069a6958e3b5d137b39168040b66b3b9ddc419fea2a4a484c58b17f3c5175ff8edcc3f33645946d3341c0e4750f23648d6755d0624b37153565616d0e1be8eececec7b6e0edba26dc6cbd6e625a856429665aaaaaa3877ee1c56abd53dce332259df0db02693899090100a0b0beb01cd6b006e90d751b81fa4b517f7923887c34174743483070f769b4e7ff2926519555559bd7af5f91d3b767c0054bb89bb1b1f37decb0f263dd11e1f772f2184409665ac56abd7e2a92f545565e3c68d17962d5bf63b87c371005f8dfb67474b014347c268c330d19edbf0dc0148e3b878cd9a353fbcf5d65b2f3b1c8e7d42085d92a4e03fb3fa29a13dda76af89337c9be78e2e5dd7b15aad343434f0c1071f9c5fba74e9ef1c0ec77e219a3e2cff5912d716b466f5b92360f8332320f124ce6c36535757c7faf5eb2f2c5ab4c820cd6b70795f3f25be5b28898ebedf5d080a9ec419e4812b82fce8a38f2ebcfefaebbf6d348fcd6604fe5fe37c702f4da5a7d6699a86c562c1e974f2f9e79fdf5cbd7af56287c371c8d33c7ae26749dc4fc5c719ed18df0fcab2cc975f7e59fcf2cb2fff6b7d7dfd2e2144c06d713f4be2da83fb419c2ccb288ac2279f7cf2c39a356b7edf1269f03325eea7328e03dc0bce5bb76e2d688c1e0fb5441adc07e28cc0c110ecddba6e2d244992434343dd03e27b81b0b030cacacad8b871e30f8b162d7ad9e170e408219c2ddf791f88f3d584bb7d1d2c144569c8ceceae976559ba1743035996a9a9a9e1d0a14317d6af5fff5a63c81f146900d24f6d2eb1a3e1e1cfecb83e4fb601f74a281250015c0682fbb0a111ff075b8fc771a1b0847a0000000049454e44ae426082</data>
+ </image>
+ <image name="image1">
+ <data format="PNG" length="5498">89504e470d0a1a0a0000000d494844520000006e0000002e0806000000c9032c970000154149444154789ced9b797014d79dc73fdd3df7a19991348390408045c469a4981b1b13c026ae0427c626c956eda61cb27f381b672b9baaddd42665cc5249586fd965c7760ec9a9d8e0d871126393908a8d09e6306064c020620e21400c022124746b46337dbefd6334c38c90401cb6e38abf552df5bc7efddeebf77dbfb35f4b555555828f183ff8c10f4a3b3b3bcf0208f191779f0349920058ba74e97ddffce637efefebeb4d0d4880b02c90012b55d7a27fac56aac01202a4545db010d9f5d23f520508ac5433a2ff4f76597f9dcc7d16a0f4979ba91aa60024453e7ab46e4f757575950de0a1871eba8953716554575763b7db4b841067d393f6714308c1030f3c70fbd2a55ffcbaddeeb8de56b2fe0f754e3fa1e9739159b822fbdc4aaf1d81b044eabf10b8dc41fef7b1ff2b065eb65dd3d0fa1b174260f5afba81e7831de96b81400000499244757535a150e85abaff50a14842bd11e11782ac67cd2ecbbd9efa2df5d795b2ee9306d421ab0c4cd3c2ee14481826e090af7fa8370ebbddfe7176ffc9844889f135495c7777378601922463b3d93873a69148244830180440d7753ef8a00eb7db85cd26535090df7f3e7837baaedff073fca362d8c40921686dbd4869e9185cae941db02c839e9e9e0c713535fb58b26471e69ea6a676b66eddcedd772fcea8d36cdc88c46d582e5502db8020b01658b16cfdf5ebbacb47f7f78d215565b6ed4a439224b2bd40c3b0325ed9debdfb59b0e07339f5376edcc0e4c913fbeb1a97f57183cec97d81b195c139dfdf80dd1bfc06f0c286e5d7df9e617c78d4f5f6f6a169faa08bf75aa19ba9ff434adceedd7bd034c8cb73327dfa6d08215014055d3770bb9d000861e1f57a3975aa8129536ec5e95432f76fdcb8894993c6535252826559396af166a948bb37c8c85b0e31ffeb5dec5ccb37f4246c582edd90e45d0fb217732cd6475b5b179aa6e376bbb02c8b4442c56e87c2c2104ea713594ec98ba6e9ecdf7f0cbfdf4b3299c4e773130e07f1f93c993ae9b64dd3cce97350e2b66fdfc1d4a99fa5b0308ffafab3ac5bf77be6cd9b8525941cf5e6f7fbd9b66d3753a64ca6a02090297ff7ddf7e9e8b8c08205cb10426018c68717afc5b7131801f3ff0576bec437f424951b964b0b81ae8f92c0f4f3e9ba4e414190bc3c6fe65a47470fc78e1dc3e9b461b7db339ae6f0e10666cf9e86d7eb02e0c28576dadabaa9a9394a45c52d8c185198697be0621f5455ba5c2ea2d1f30094978fe6eebbefa174dc38cacb4662532edde2f37ab9f3cecf5159392553d6dcdc464dcd4eeebfff7e002ccbc234cdcc0abae9b05247200cf3bf06762719db7723aaf35a910e7d4cd3c2b22e5f30f1781c555533049f3c7996d2d29119d2008a8a0a0885fc184692eeee0e20654e743da566b34dcba0123767ce6c7efdeb17292e8e1008f82829099238fe125d27b7e05bfc8bcc6d8aa2e0f57a72eefdcd6f5ee4c107ff396323755d4792a46bb2671b964b9f03be4bcaf1180a63814b31ae4891f7f96fc2ce57a9ec6e631bb070c3726958926759d6756985ec5835fdfb52d09d2ebbd4b61082aeae5e34cd64d4a8484e3d55d578fbed3de4e7cb39fe84611897cddf9036eeab5f5dc65b6fed64f9f22fd059bb8e50f716dc0bd6a02997881a591cceb967dfbea38c1c5984dbedc634cd413bccc650b64e086543f1ec7b83c13163c1accd2127fbf084c782519b913a2cb0db61fe7db0730395ddedd746de7071faf479eaea4e138904993cf9961cf5971b40a790ed93e8bac1b16351162e9c99f5bc00828d1bb7e1f3598442051416a6d4a4611858967599c61a92b8aeae6e66cd9d4db2691fa153bf80bb7e893074844d83feb4507b5b372eaf07af3b65f7cacbcbd8ba751baaaa66dab93ecf510acef9afa720fe59d0bbc0048c218e3e2e23d46e87f94b61e79fa9ecee601bb06cc372297a33c86b68680260d1a299ecd9f301afbcb289850ba7337264049bcd4667672f91c8c0b49940557584101c3c788239736ebd74a59fe8b7dfde871071f2f3f3894422f87cbe8c6d4bcf61f65ce6d0d8ddddcbf9f3ed1c3edc4043430b23471660edfe36c83da0352262b588ace4695bf3191a8fd6a0e9904868389d320b162c60fbf6fdecdb7784f7deaba5b3b3f39a5525005614acae1419d68063a0f40d72dd6e87f9f7402044257010a8bc1936eff0e1939494847138ec2c58701bf3e74fe70f7fd8caae5d07397cf8d4a0c90621c0e1f070e8d019cacbc7e0f5bafbcb536af6e8d1d3343737120af9894422040201ec767bc6a91b6cfe7288dbb5ab86a2a202a64cb9856995b792e8388747dd0f4a1dc4b7837932c72d55148d90f1175acf9e42d5a0a727cea851458c1fff19e6ce9dcd840953d8b7efc055891bf2da351035d875bb0de6df0545c57210a46da954fe8da1a0208f9a9a2399df858521962c99c3fcf9d3a9a828efb74db9f15ada568d193392d1a347f4dbffd4d1dadac9c183870887bd84c36142a1100e8723c7d45c91385dd751141bb20c92d4ef0daa71f0903a622f807404c3bc14486bba46d0f50e8ee655b477f6a16a267d7d494cd3e4d4a946fafa12c3724e06750aae83a8c1aecbc8148d7420843d28c4d0999ae13a27b7dd3691fdfb3fa0b1f1025d5d31baba7aa8ac9c4047470f275ffd1ad21bf730589cadeb3073e694ace47b2abedbb2e55df2f2140a0a0a282828c0e572653c49e0eac4c562311a1b1bf8e94f9f63fdfacd9c3c750e87271fdda54001e0ebc152fe8869a81806a81ae86607823d445c2fd377eae774f698c4e3090cc3a4adad87175f7c894993caaf4f55c2d0640d93485393397fd6c1df0e8210d25a216e5ce29c4e270b174ee7f5d7b7d2d4d4cad8b1c51cfb5b2dd6efa730deefc07fdf1f19e85586427e962c999b1532080cc362e3c61db85c060505f984c3617c3e1fb22ca3eb7a46450e850c719224f1d5af3ec0bdf72e261c76b273c726144f9884ff73e00342203c2134dd42d705aa069a6621fc4018c6eb8fd056bf9d589f496f6f1f8aa2505a5a96f1b8ae8bb8e19235f09a05a69e22edc05e300cd682b44296b56b1fc3004892c4e4c96594978f66ca945b387daa8150ed7f503cf7df61d1cf11b2eb32afd26eb761b7dbb0ac14699665d2d5d54b6beb455a5a7ac9cbcbc3ebf522cb32a6696662b6c18e346cd90302282c2ca4b0b090112346b0efc011668e5b45f2ecdbb8ca80d84c62bd3aaada466f6f0fba7e0e7b108883b0cf233f3489230d4d601944a3515a5a1a292e765356560690e36d5e0d7d172fe2d0e55c8f72807729239085b88c485397397fc6c181f7c030c41f8115b7cd9438b8ffe6bc468ac51254544c2099d4481efe35e312e760dc17a1bb0111d720303e535708c1c58b5df4f4c4282d2dea4f4808dc6e27b7dd36852d5bf6108f27b02c2be3fa0fb6c8878ce3065ed075835857373de5b763cfff3d1cfd36ae721bc1fc3a6cb6324a8adec7e6d80edd106f9a823ae1f734d65e20da1045513a98376f0693267d19bfdf9f69535152b9cc61bc15e8daf7b31f07fd058e4ba4644b5affff40a141598571b97a3ce3e0400d9886512bcbc60a80bf1d7471a3aa5208414b4b3bcdcd6d54549473fce04e269daf8611b320d690da6e909411796599d8ccb204c9a4ca3b3bdee3fe07eec16653300c13d3b49830612c0d0de73870e00489844924924f4141004551aeaaa132c4298a9213a937349ce74b5f5ac2a14327291cf1655c54d0f1fe4f0916fe055bc95c881d2671a619d3f628da98eff2d63b47282ef25358680079d4d7d7535f5f3fd4045c715492642c6baf3bf2ddf62b664ec4d8f0c48ab165730474d76624ada3d5c1d18329d224c9580874c9b20bc380075e4f0ed9da50ce89ae1b1c39728ae6e68bb4b474e0f57a282a2a484d6ce36fa0b3038a7b403d033610ba3bd3961016a669611826e3020d6cddb293858befe827ce44d70de6ce9dc65b6fd5609a360e1d8ad2d6d6452492c71d77dc8ac77329d9312c89dbbaf51d962efd129204e3c797f2dbdfbe41e9b852a64f7d82b6eea388fa2690e620e53d484b9f8fcdbf7d93b1a523a9ac9c485ddd7bdc7befbdd86c362ccbca3c84dd6ec7b22c56af5ebdb9b5b5b5e14ac42d5b2fb6bffe807dfb3d3ffb2d0efd9f0655977ffeb1f53fd802ab504891a6c974b43838b01be2bd59a4292e0c5d5c91b42ba1a3a31b97cbc1a245b37038529ae2fdf78f01201adf49d9ff9e0360cc00c012a17e5b662184d5af022dfcce0b947863d4d6869930610c8691224e089832a58c8e8e1eeeba6b168661b2756b0d6d6d6d9496960e39ae4189f3f9dc6cdbb693891327f3dc73bfc2e7938944a0ead7dbb975da3c02c109689ace9e3fbd4daca791c58befe0c489e3bcfa6a2700e170785075b86ad5aa2d555555ff9a4c265bd7ae5d7bd549dbf7b31f33a4baa49f886cd27642bc279734d33090e5cbdf050e17ba6ee0f77b33a4c1a5fd237629095ec09584f657a1682ea0f62f5813cb4a798fa6698068a73cd2c8b1fd161de115381c0e745def6fdf43347a9ebaba28e3c615a3aa0962b1580e27c392b8f9f3ef60dfbefdac5d5bcd57bef205264c9800c0d4a9e73972e42c9f9d56c1c58bddfc755313ab57ff10599659b85062cf9e3dd4d7b7914c263381bac3914affac5cb972cb9a356b56c462b173c3b1759264d05e7784f621af0342c650a1f38283033b20dea3d74a92b910e8f2f85cc47b0d24c960b8a9aeb4bb9e3d17866170f8f069dadb7b2829091308f8323196092989f3034a33a86f20a4b91886d94f58ca96e9ba8910a7207188cf8fd8c8baed6398b76011baaea3693aaaaa535a3a929a9a0f3870e018f1782fe5e545c3236e2066ce9cc1cc993372ca4a4a8ad9b1631fc1a09b1327ce327af4889ce4e7ac59b3a8afafcfc42176bb1d4dd358bd7af596c71e7b6c455555d5b9975e7a2967a286c2d5267bc372899ea6281d9d0b38b8e35dfa7ab55a49b252a4f95dc47bae8db4f47862b118b22ce3743ab1d96c8c1a358296968becdd7b8053a79a48262deebcf3368400dd3f013c6753090a3fe04b226227310c0b5d37fadf8e182995289f01571c5700ee8eac66776d316565a35155ad9f3c8dd1a38b387ab49e193346e3743aaf38d621bdcaa1e0f3d978e2895fd2d27291e5cb3f9f93004d9fa7b2300a9aa6f1939ffc64cbe38f3fbea2a9a9e9dc005b476b6bebb0277510ac55bb1abfbbebb997839264d4c28d9106971692aaaa689a86a228c8b2ccf8f1a3894402cc9e3d894422c1e9d3eda8aa86145e8c2eb660f792923c1f08358069a6c84aa7ad745d47764aa93a26dc12394fedfb3fe382f7fb389d2995994c6ae8ba4e7e7e8868b483f1e3c75fbbaabc12eebbefde41cb2549ca489f2ccbf4f5f5f1c4134f6c79f2c927570821ce65d75db56a15555555c3ea6f282c5b2fa21b964ba1c2c98b98bb143a8fbdcb81ed10efd19124f39a491bf81ca90c879951f93e9f0fa7d389699ac4e32667cfb65072fbc39c5dff14b78c6b053760cf03a9045d33d1753de380689a8ec3e64bd55101274c0eaabc113d47696909aaaa914caa24931af17882e6e6362a2bbb183d7a74ceb8b29121ce66b3ddd0f6024992329b612e5ebcc8a38f3ebaf6b5d75e7b249148342593c96c5bc79a356bae9ad2192e06a84b24c9ba2ed206db189586a22828caa56d1b93268d63f7eec32c59328fbecf3c4b4fe3d7c88b48a0e423a40867cfb6108d9ea7a7bb1387a31b35719cb99536b02b6037397fc28967f61aa69e879a9a0f70b91cc46271ec764138ec63dab4a9b8dd578e7533c42512891b262efdb0dffbdef79edebc79f37fb7b7b727354dcbb6753cf6d8633775ff89dad5c8aee75e46920ce0fa48cbc670d27389848e65a5c2823973be4c74cb4a8c236bc89fee62444441b30e533062066ea70f97bd15cce65428a3cbb41eb3a14dde80e519454dcd9b4812381c0633668cc2e7f3e1f57af1783cf8fdfeababcaeaeaea1b7ad881d8bc79f3caaaaaaae4005bc7e38f3f7e5349fba87773413a208f72c71d951c3f1ee5fdf7ebf8eca21f12dd5bc1c53ffc276316b732fe9638d862a91b8c38584962d15e5a8f4ec236b90ad3338a975f7a83b2b252c2e1207bf71e22180c52545484cfe7c3e1700cb989380ddbb7bef52d4908417575350f3df4109aa6ddb0e43df8e083ac5bb72edbd6f1e4934f7eec5fe60c07b22c5f7163d3c993e7282d1d4928e467f6eca9ecde7d88b7dedac3bc790b51a61e205af322e6aefdb8f38ee00a87e96bacc73083d84b7e8cf3f6bb696ebec89b1b52a4cd993315d3141c3f7e86baba26c68e1d8bdfef4796e5cb242cfd3b3d365bba30ed2c7c08b68ed75e7b2da7f34f2ababa7a89c5542a2a2666623e97cbc9a64dbb3975aa91a9533fc3b8cfdc47b8e01b5896891002dfb8d4a6a933679a39f0a7ed44a38d949414535e3e3af3a6e0f6db2b79fef9d799366d5c7f9baecbfa4eab70cbb26440b2a5494aabcb9b6cebd8bc79f32742d2d28bed4a362e10f0a169492e5ce8c0eff7b07efd5f696838cdd4a9c5141515d0d6769ea347eb89c7351c0e278a22d1dd1da7bbbb07b75ba1ac2cc25d77dd8aaec3b66dfb2829194138ace0703858b66c16bdbdbd747575e578b369288a82dbed261a8d26002347917e08b6ee13415a36ae449c2ccb4c9f3e814d9bdee5f8f1b31417fb59b4e85682c120a15088f2723badad1d3435f5306fde342ccb4255759e79e6156ebfbd9cc2c242f2f3f3713a9d8c19338a37dfdccdc489d399366d5ac6cb1e6cbed22f579f7aeaa9baf5ebd73f0bf46688fb303e6efc283f98fc282049126eb79bc58b67525131ae7fdbb88f502884d7eb4551140281007bf7fe359364eee8e8c1b2343c1e0f914884c2c2421445213f3f9f050b2a90651987c391f3f27420745d67ddba75277ef4a31f7d4755d577182871ffe8186a4755366c361b81400097cb856118381c0e1c0e47c66970b95cc8f2a5d744a74f9f2714f2e076bbf17abd9978d6e17010080488c7e30039dbf0320e48bf67f9f4d34f1f7fe491471e5655759b10c2922469f89f59fda36038719ccd661bd25d972489bc3c2f7bf71e2114f2535f1f251209e0f1787236ce4a9284a22899ad0ad93bba2ccbc2e170904c2679f6d967eb56af5efd1d55557788aced631feb17a97f4fb8199f40a5b178f10cfc7e85d6d67394947899366d3c7ebf3f236d70e993b5f4b7158661640e21047d7d7dfcea57bf3ab172e5caefc4e3f11d42889c77539f4adc8780fcfc2077de39fbaaf5b2894b7b9176bb1d455178e699674eac5ab5eadb69f538f0de4f891b80ebde91769dfda4c9330c03bbdd8e699abcf2ca2bcd4f3df5d4a3aaaaee1a8c34f894b8cbf051130764d4a32ccbbcfefaebad0f3ffcf0bf2512894d428821b7c57d4adc007c1cc4c9b28ca6693cfffcf3c79f7efae9ffb91a69f029711f3bd249f8dffdee77f5fddee3aeab91069f1297812449b2c7e3c904c41f05bc5e2f1d1d1dac5bb7eef8ca952b1f565575bb10c2bcfa9d9f129781a669c9cd9b37276459966e66683014645926168bb16bd7ae132fbcf0c2f7fae3b4619106207dd27289371b59f62c48eaf3641703bfdaf810bb07ba8006e09a3e6cf87fd8857d4933e0288e0000000049454e44ae426082</data>
+ </image>
+ <image name="image2">
+ <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data>
+ </image>
+</images>
+<tabstops>
+ <tabstop>intWidth</tabstop>
+ <tabstop>intHeight</tabstop>
+ <tabstop>intWidthPercent</tabstop>
+ <tabstop>intHeightPercent</tabstop>
+ <tabstop>chkConstrain</tabstop>
+ <tabstop>radioScale</tabstop>
+</tabstops>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/viewplugins/imagesize/wdg_layersize.ui b/chalk/plugins/viewplugins/imagesize/wdg_layersize.ui
new file mode 100644
index 00000000..fb7547d2
--- /dev/null
+++ b/chalk/plugins/viewplugins/imagesize/wdg_layersize.ui
@@ -0,0 +1,234 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgLayerSize</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgLayerSize</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>391</width>
+ <height>224</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Image Size</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="TQButtonGroup" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>grpPixelDimensions</cstring>
+ </property>
+ <property name="title">
+ <string>&amp;Pixel Dimensions</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="1">
+ <property name="name">
+ <cstring>lblWidth</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Width:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>intWidth</cstring>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="2" column="2">
+ <property name="name">
+ <cstring>intHeight</cstring>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="2">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Height:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>intHeight</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="1">
+ <property name="name">
+ <cstring>lblWidthOriginal</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>WinPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="2">
+ <property name="name">
+ <cstring>lblHeightOriginal</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>WinPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>lblOrignal</cstring>
+ </property>
+ <property name="text">
+ <string>Original:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>lblNew</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;New:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>intWidth</cstring>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="2" column="1">
+ <property name="name">
+ <cstring>intWidth</cstring>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="3" column="1">
+ <property name="name">
+ <cstring>intWidthPercent</cstring>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="referencePoint">
+ <number>100</number>
+ </property>
+ <property name="suffix">
+ <string>%</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="3" column="2">
+ <property name="name">
+ <cstring>intHeightPercent</cstring>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="suffix">
+ <string>%</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>lblPercent</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Percent:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>intWidthPercent</cstring>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="4" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>chkConstrain</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Constrain proportions</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>lblFilterType</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Filter:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>cmbFilterType</cstring>
+ </property>
+ </widget>
+ <widget class="KisCmbIDList" row="1" column="1">
+ <property name="name">
+ <cstring>cmbFilterType</cstring>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KisCmbIDList</class>
+ <header location="local">kis_cmb_idlist.h</header>
+ <sizehint>
+ <width>1</width>
+ <height>24</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data>
+ </image>
+</images>
+<tabstops>
+ <tabstop>intWidth</tabstop>
+ <tabstop>intHeight</tabstop>
+ <tabstop>intWidthPercent</tabstop>
+ <tabstop>intHeightPercent</tabstop>
+ <tabstop>chkConstrain</tabstop>
+</tabstops>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/viewplugins/imagesize/wdg_resolution.ui b/chalk/plugins/viewplugins/imagesize/wdg_resolution.ui
new file mode 100644
index 00000000..df0e010d
--- /dev/null
+++ b/chalk/plugins/viewplugins/imagesize/wdg_resolution.ui
@@ -0,0 +1,152 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgResolution</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgResolution</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>487</width>
+ <height>265</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Image Resolution</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQGroupBox" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>grpSize</cstring>
+ </property>
+ <property name="title">
+ <string>Print Size</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>lblHeight</cstring>
+ </property>
+ <property name="text">
+ <string>Height:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lblWidth</cstring>
+ </property>
+ <property name="text">
+ <string>Width:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="0" column="1">
+ <property name="name">
+ <cstring>intWidth</cstring>
+ </property>
+ <property name="suffix">
+ <string> "</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="1" column="1">
+ <property name="name">
+ <cstring>intHeight</cstring>
+ </property>
+ <property name="suffix">
+ <string> "</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQGroupBox" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>grpResolution</cstring>
+ </property>
+ <property name="title">
+ <string>Image Resolution</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lblScreen</cstring>
+ </property>
+ <property name="text">
+ <string>Screen resolution:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="1">
+ <property name="name">
+ <cstring>lblScreenResolution</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>Panel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="text">
+ <string>100</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>lblYResolution</cstring>
+ </property>
+ <property name="text">
+ <string>Image Y resolution:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>lblImageXRes</cstring>
+ </property>
+ <property name="text">
+ <string>Image X resolution:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="1" column="1">
+ <property name="name">
+ <cstring>intXRes</cstring>
+ </property>
+ <property name="suffix">
+ <string> dpi</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="2" column="1">
+ <property name="name">
+ <cstring>intYRes</cstring>
+ </property>
+ <property name="suffix">
+ <string> dpi</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/viewplugins/modify_selection/Makefile.am b/chalk/plugins/viewplugins/modify_selection/Makefile.am
new file mode 100644
index 00000000..6e0f14c5
--- /dev/null
+++ b/chalk/plugins/viewplugins/modify_selection/Makefile.am
@@ -0,0 +1,27 @@
+chalkrcdir = $(kde_datadir)/chalkplugins
+chalkrc_DATA = modify_selection.rc
+EXTRA_DIST = $(chalkrc_DATA)
+
+kde_services_DATA = chalkmodifyselection.desktop
+
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkmodifyselection_la_SOURCES = wdg_grow_selection.ui wdg_shrink_selection.ui wdg_border_selection.ui \
+dlg_grow_selection.cc dlg_shrink_selection.cc dlg_border_selection.cc modify_selection.cc
+
+noinst_HEADERS = wdg_grow_selection.h wdg_shrink_selection.h wdg_border_selection.h dlg_grow_selection.h \
+dlg_shrink_selection.h dlg_border_selection.h modify_selection.h
+
+kde_module_LTLIBRARIES = chalkmodifyselection.la
+
+chalkmodifyselection_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) chalkblurfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui
+chalkmodifyselection_la_LIBADD = ../../../libchalkcommon.la
+
+chalkmodifyselection_la_METASOURCES = AUTO
diff --git a/chalk/plugins/viewplugins/modify_selection/chalkmodifyselection.desktop b/chalk/plugins/viewplugins/modify_selection/chalkmodifyselection.desktop
new file mode 100644
index 00000000..aa4a9d58
--- /dev/null
+++ b/chalk/plugins/viewplugins/modify_selection/chalkmodifyselection.desktop
@@ -0,0 +1,40 @@
+[Desktop Entry]
+Name=Modify Selection
+Name[bg]=Промяна на маркираното
+Name[br]=Kemmañ an dibab
+Name[ca]=Selecció de modificació
+Name[da]=Ændr markering
+Name[de]=Auswahl verändern
+Name[el]=Τροποποίηση επιλογής
+Name[eo]=Modifi elekton
+Name[es]=Modificar selección
+Name[et]=Valiku muutmine
+Name[fa]=تغییر گزینش
+Name[fr]=Modifier la sélection
+Name[fy]=Seleksje oanpasse
+Name[ga]=Athraigh an Roghnúchán
+Name[gl]=Modificación da Selección
+Name[hu]=A kijelölés módosítása
+Name[it]=Modifica la selezione
+Name[ja]=選択領域を変更
+Name[km]=កែប្រែ​ការ​ជ្រើស
+Name[lv]=Mainīt izvēli
+Name[nb]=Endre utvalg
+Name[nds]=Utwahl ännern
+Name[ne]=चयन परिमार्जन गर्नुहोस्
+Name[nl]=Selectie aanpassen
+Name[pl]=Zmiana wyboru
+Name[pt]=Modificar a Selecção
+Name[pt_BR]=Modificar a Seleção
+Name[ru]=Выделение
+Name[sk]=Zmeniť výber
+Name[sl]=Spremeni izbiro
+Name[sr]=Измена избора
+Name[sr@Latn]=Izmena izbora
+Name[sv]=Ändra markering
+Name[uk]=Зміна виділення
+Name[zh_TW]=變更選取
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalkmodifyselection
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/modify_selection/dlg_border_selection.cc b/chalk/plugins/viewplugins/modify_selection/dlg_border_selection.cc
new file mode 100644
index 00000000..dcda5c7e
--- /dev/null
+++ b/chalk/plugins/viewplugins/modify_selection/dlg_border_selection.cc
@@ -0,0 +1,76 @@
+/*
+ * dlg_border_selection.cc - part of Chalk
+ *
+ * Copyright (c) 2006 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <config.h>
+
+#include <math.h>
+
+#include <iostream>
+
+using namespace std;
+
+#include <tqradiobutton.h>
+#include <tqcheckbox.h>
+#include <tqbuttongroup.h>
+#include <tqlabel.h>
+#include <tqcombobox.h>
+
+#include <klocale.h>
+#include <knuminput.h>
+#include <kdebug.h>
+
+#include "dlg_border_selection.h"
+#include "wdg_border_selection.h"
+
+DlgBorderSelection::DlgBorderSelection( TQWidget * tqparent, const char * name) : super (tqparent, name, true, i18n("Border Selection"), Ok | Cancel, Ok)
+{
+ m_page = new WdgBorderSelection(this, "border_selection");
+ Q_CHECK_PTR(m_page);
+
+ setMainWidget(m_page);
+ resize(m_page->tqsizeHint());
+
+ connect(this, TQT_SIGNAL(okClicked()), this, TQT_SLOT(okClicked()));
+}
+
+DlgBorderSelection::~DlgBorderSelection()
+{
+ delete m_page;
+}
+
+TQ_INT32 DlgBorderSelection::xradius()
+{
+ return m_page->radiusSpinBox->value();
+}
+
+TQ_INT32 DlgBorderSelection::yradius()
+{
+ return m_page->radiusSpinBox->value();
+}
+
+
+// SLOTS
+
+void DlgBorderSelection::okClicked()
+{
+ accept();
+}
+
+#include "dlg_border_selection.moc"
diff --git a/chalk/plugins/viewplugins/modify_selection/dlg_border_selection.h b/chalk/plugins/viewplugins/modify_selection/dlg_border_selection.h
new file mode 100644
index 00000000..472f01ef
--- /dev/null
+++ b/chalk/plugins/viewplugins/modify_selection/dlg_border_selection.h
@@ -0,0 +1,49 @@
+/*
+ * dlg_border_selection.h -- part of Chalk
+ *
+ * Copyright (c) 2006 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 DLG_BORDER_SELECTION_H
+#define DLG_BORDER_SELECTION_H
+
+#include <kdialogbase.h>
+
+class WdgBorderSelection;
+
+class DlgBorderSelection: public KDialogBase {
+ typedef KDialogBase super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ DlgBorderSelection(TQWidget * tqparent = 0, const char* name = 0);
+ ~DlgBorderSelection();
+
+ TQ_INT32 xradius();
+ TQ_INT32 yradius();
+
+private slots:
+
+ void okClicked();
+
+private:
+
+ WdgBorderSelection * m_page;
+};
+
+#endif // DLG_BORDER_SELECTION_H
diff --git a/chalk/plugins/viewplugins/modify_selection/dlg_grow_selection.cc b/chalk/plugins/viewplugins/modify_selection/dlg_grow_selection.cc
new file mode 100644
index 00000000..b889ccde
--- /dev/null
+++ b/chalk/plugins/viewplugins/modify_selection/dlg_grow_selection.cc
@@ -0,0 +1,76 @@
+/*
+ * dlg_grow_selection.cc - part of Chalk
+ *
+ * Copyright (c) 2006 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <config.h>
+
+#include <math.h>
+
+#include <iostream>
+
+using namespace std;
+
+#include <tqradiobutton.h>
+#include <tqcheckbox.h>
+#include <tqbuttongroup.h>
+#include <tqlabel.h>
+#include <tqcombobox.h>
+
+#include <klocale.h>
+#include <knuminput.h>
+#include <kdebug.h>
+
+#include "dlg_grow_selection.h"
+#include "wdg_grow_selection.h"
+
+DlgGrowSelection::DlgGrowSelection( TQWidget * tqparent, const char * name) : super (tqparent, name, true, i18n("Grow Selection"), Ok | Cancel, Ok)
+{
+ m_page = new WdgGrowSelection(this, "grow_selection");
+ Q_CHECK_PTR(m_page);
+
+ setMainWidget(m_page);
+ resize(m_page->tqsizeHint());
+
+ connect(this, TQT_SIGNAL(okClicked()), this, TQT_SLOT(okClicked()));
+}
+
+DlgGrowSelection::~DlgGrowSelection()
+{
+ delete m_page;
+}
+
+TQ_INT32 DlgGrowSelection::xradius()
+{
+ return m_page->radiusSpinBox->value();
+}
+
+TQ_INT32 DlgGrowSelection::yradius()
+{
+ return m_page->radiusSpinBox->value();
+}
+
+
+// SLOTS
+
+void DlgGrowSelection::okClicked()
+{
+ accept();
+}
+
+#include "dlg_grow_selection.moc"
diff --git a/chalk/plugins/viewplugins/modify_selection/dlg_grow_selection.h b/chalk/plugins/viewplugins/modify_selection/dlg_grow_selection.h
new file mode 100644
index 00000000..61785b20
--- /dev/null
+++ b/chalk/plugins/viewplugins/modify_selection/dlg_grow_selection.h
@@ -0,0 +1,49 @@
+/*
+ * dlg_grow_selection.h -- part of Chalk
+ *
+ * Copyright (c) 2006 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 DLG_GROW_SELECTION_H
+#define DLG_GROW_SELECTION_H
+
+#include <kdialogbase.h>
+
+class WdgGrowSelection;
+
+class DlgGrowSelection: public KDialogBase {
+ typedef KDialogBase super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ DlgGrowSelection(TQWidget * tqparent = 0, const char* name = 0);
+ ~DlgGrowSelection();
+
+ TQ_INT32 xradius();
+ TQ_INT32 yradius();
+
+private slots:
+
+ void okClicked();
+
+private:
+
+ WdgGrowSelection * m_page;
+};
+
+#endif // DLG_GROW_SELECTION_H
diff --git a/chalk/plugins/viewplugins/modify_selection/dlg_shrink_selection.cc b/chalk/plugins/viewplugins/modify_selection/dlg_shrink_selection.cc
new file mode 100644
index 00000000..eb50c6cf
--- /dev/null
+++ b/chalk/plugins/viewplugins/modify_selection/dlg_shrink_selection.cc
@@ -0,0 +1,81 @@
+/*
+ * dlg_shrink_selection.cc - part of Chalk
+ *
+ * Copyright (c) 2006 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <config.h>
+
+#include <math.h>
+
+#include <iostream>
+
+using namespace std;
+
+#include <tqradiobutton.h>
+#include <tqcheckbox.h>
+#include <tqbuttongroup.h>
+#include <tqlabel.h>
+#include <tqcombobox.h>
+
+#include <klocale.h>
+#include <knuminput.h>
+#include <kdebug.h>
+
+#include "dlg_shrink_selection.h"
+#include "wdg_shrink_selection.h"
+
+DlgShrinkSelection::DlgShrinkSelection( TQWidget * tqparent, const char * name) : super (tqparent, name, true, i18n("Shrink Selection"), Ok | Cancel, Ok)
+{
+ m_page = new WdgShrinkSelection(this, "shrink_selection");
+ Q_CHECK_PTR(m_page);
+
+ setMainWidget(m_page);
+ resize(m_page->tqsizeHint());
+
+ connect(this, TQT_SIGNAL(okClicked()), this, TQT_SLOT(okClicked()));
+}
+
+DlgShrinkSelection::~DlgShrinkSelection()
+{
+ delete m_page;
+}
+
+TQ_INT32 DlgShrinkSelection::xradius()
+{
+ return m_page->radiusSpinBox->value();
+}
+
+TQ_INT32 DlgShrinkSelection::yradius()
+{
+ return m_page->radiusSpinBox->value();
+}
+
+bool DlgShrinkSelection::shrinkFromImageBorder()
+{
+ return m_page->shrinkFromImageBorderCheckBox->isChecked();
+}
+
+
+// SLOTS
+
+void DlgShrinkSelection::okClicked()
+{
+ accept();
+}
+
+#include "dlg_shrink_selection.moc"
diff --git a/chalk/plugins/viewplugins/modify_selection/dlg_shrink_selection.h b/chalk/plugins/viewplugins/modify_selection/dlg_shrink_selection.h
new file mode 100644
index 00000000..53ce386b
--- /dev/null
+++ b/chalk/plugins/viewplugins/modify_selection/dlg_shrink_selection.h
@@ -0,0 +1,50 @@
+/*
+ * dlg_shrink_selection.h -- part of Chalk
+ *
+ * Copyright (c) 2006 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 DLG_SHRINK_SELECTION_H
+#define DLG_SHRINK_SELECTION_H
+
+#include <kdialogbase.h>
+
+class WdgShrinkSelection;
+
+class DlgShrinkSelection: public KDialogBase {
+ typedef KDialogBase super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ DlgShrinkSelection(TQWidget * tqparent = 0, const char* name = 0);
+ ~DlgShrinkSelection();
+
+ TQ_INT32 xradius();
+ TQ_INT32 yradius();
+ bool shrinkFromImageBorder();
+
+private slots:
+
+ void okClicked();
+
+private:
+
+ WdgShrinkSelection * m_page;
+};
+
+#endif // DLG_SHRINK_SELECTION_H
diff --git a/chalk/plugins/viewplugins/modify_selection/modify_selection.cc b/chalk/plugins/viewplugins/modify_selection/modify_selection.cc
new file mode 100644
index 00000000..78a75778
--- /dev/null
+++ b/chalk/plugins/viewplugins/modify_selection/modify_selection.cc
@@ -0,0 +1,158 @@
+/*
+ * modify_selection.cc -- Part of Chalk
+ *
+ * Copyright (c) 2006 Michael Thaler (michael.thaler@physik.tu-muenchen.de)
+ *
+ * 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 <math.h>
+
+#include <stdlib.h>
+
+#include <tqslider.h>
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <kstdaction.h>
+
+#include <kis_doc.h>
+#include <kis_config.h>
+#include <kis_image.h>
+#include <kis_layer.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_view.h>
+#include <kis_selection.h>
+#include <kis_selection_manager.h>
+#include <kis_transaction.h>
+
+#include "modify_selection.h"
+#include "dlg_grow_selection.h"
+#include "dlg_shrink_selection.h"
+#include "dlg_border_selection.h"
+
+typedef KGenericFactory<ModifySelection> ModifySelectionFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkmodifyselection, ModifySelectionFactory( "chalk" ) )
+
+ModifySelection::ModifySelection(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ if ( tqparent->inherits("KisView") )
+ {
+ setInstance(ModifySelectionFactory::instance());
+ setXMLFile(locate("data","chalkplugins/modify_selection.rc"), true);
+
+ m_view = (KisView*) tqparent;
+
+ // Selection manager takes ownership?
+ KAction* a = new KAction(i18n("Grow Selection..."), 0, 0, this, TQT_SLOT(slotGrowSelection()), actionCollection(), "growselection");
+ KAction* b = new KAction(i18n("Shrink Selection..."), 0, 0, this, TQT_SLOT(slotShrinkSelection()), actionCollection(), "shrinkselection");
+ KAction* c = new KAction(i18n("Border Selection..."), 0, 0, this, TQT_SLOT(slotBorderSelection()), actionCollection(), "borderselection");
+
+ Q_CHECK_PTR(a);
+ Q_CHECK_PTR(b);
+ Q_CHECK_PTR(c);
+
+ m_view ->canvasSubject()-> selectionManager()->addSelectionAction(a);
+ m_view ->canvasSubject()-> selectionManager()->addSelectionAction(b);
+ m_view ->canvasSubject()-> selectionManager()->addSelectionAction(c);
+ }
+}
+
+ModifySelection::~ModifySelection()
+{
+ m_view = 0;
+}
+
+void ModifySelection::slotGrowSelection()
+{
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+
+ if (!image) return;
+
+ DlgGrowSelection * dlgGrowSelection = new DlgGrowSelection(m_view, "GrowSelection");
+ Q_CHECK_PTR(dlgGrowSelection);
+
+ dlgGrowSelection->setCaption(i18n("Grow Selection"));
+
+ KisConfig cfg;
+
+ if (dlgGrowSelection->exec() == TQDialog::Accepted) {
+ TQ_INT32 xradius = dlgGrowSelection->xradius();
+ TQ_INT32 yradius = dlgGrowSelection->yradius();
+
+ m_view ->canvasSubject()-> selectionManager()->grow(xradius, yradius);
+ }
+
+ delete dlgGrowSelection;
+}
+
+void ModifySelection::slotShrinkSelection()
+{
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+
+ if (!image) return;
+
+ DlgShrinkSelection * dlgShrinkSelection = new DlgShrinkSelection(m_view, "ShrinkSelection");
+ Q_CHECK_PTR(dlgShrinkSelection);
+
+ dlgShrinkSelection->setCaption(i18n("Shrink Selection"));
+
+ KisConfig cfg;
+
+ if (dlgShrinkSelection->exec() == TQDialog::Accepted) {
+ TQ_INT32 xradius = dlgShrinkSelection->xradius();
+ TQ_INT32 yradius = dlgShrinkSelection->yradius();
+ bool shrinkFromImageBorder = dlgShrinkSelection->shrinkFromImageBorder();
+
+ m_view ->canvasSubject()-> selectionManager()->shrink(xradius, yradius, shrinkFromImageBorder);
+ }
+
+ delete dlgShrinkSelection;
+}
+
+void ModifySelection::slotBorderSelection()
+{
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+
+ if (!image) return;
+
+ DlgBorderSelection * dlgBorderSelection = new DlgBorderSelection(m_view, "BorderSelection");
+ Q_CHECK_PTR(dlgBorderSelection);
+
+ dlgBorderSelection->setCaption(i18n("Border Selection"));
+
+ KisConfig cfg;
+
+ if (dlgBorderSelection->exec() == TQDialog::Accepted) {
+ TQ_INT32 xradius = dlgBorderSelection->xradius();
+ TQ_INT32 yradius = dlgBorderSelection->yradius();
+
+ m_view ->canvasSubject()-> selectionManager()->border(xradius, yradius);
+ }
+
+ delete dlgBorderSelection;
+}
+
+#include "modify_selection.moc"
diff --git a/chalk/plugins/viewplugins/modify_selection/modify_selection.h b/chalk/plugins/viewplugins/modify_selection/modify_selection.h
new file mode 100644
index 00000000..db5dd1b7
--- /dev/null
+++ b/chalk/plugins/viewplugins/modify_selection/modify_selection.h
@@ -0,0 +1,47 @@
+/*
+ * modify_selection.h -- Part of Chalk
+ *
+ * Copyright (c) 2006 Michael Thaler (michael.thaler@physik.tu-muenchen.de)
+ *
+ * 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 MODIFY_SELECTION_H
+#define MODIFY_SELECTION_H
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+class ModifySelection : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ ModifySelection(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ModifySelection();
+
+private slots:
+
+ void slotGrowSelection();
+ void slotShrinkSelection();
+ void slotBorderSelection();
+
+private:
+
+ KisView * m_view;
+
+};
+
+#endif // MODIFY_SELECTION_H
diff --git a/chalk/plugins/viewplugins/modify_selection/modify_selection.rc b/chalk/plugins/viewplugins/modify_selection/modify_selection.rc
new file mode 100644
index 00000000..999aaaaa
--- /dev/null
+++ b/chalk/plugins/viewplugins/modify_selection/modify_selection.rc
@@ -0,0 +1,10 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkmodifyselection" version="6">
+ <MenuBar>
+ <Menu name="Select"><text>&amp;Select</text>
+ <Action name="growselection"/>
+ <Action name="shrinkselection"/>
+ <Action name="borderselection"/>
+ </Menu>
+ </MenuBar>
+</kpartgui>
diff --git a/chalk/plugins/viewplugins/modify_selection/wdg_border_selection.ui b/chalk/plugins/viewplugins/modify_selection/wdg_border_selection.ui
new file mode 100644
index 00000000..06d01e9f
--- /dev/null
+++ b/chalk/plugins/viewplugins/modify_selection/wdg_border_selection.ui
@@ -0,0 +1,57 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgBorderSelection</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgBorderSelection</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>255</width>
+ <height>101</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Border selection by</string>
+ </property>
+ </widget>
+ <widget class="TQSpinBox" row="1" column="0">
+ <property name="name">
+ <cstring>radiusSpinBox</cstring>
+ </property>
+ <property name="maxValue">
+ <number>10000</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>1</number>
+ </property>
+ </widget>
+ <widget class="TQComboBox" row="1" column="1">
+ <item>
+ <property name="text">
+ <string>pixels</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>comboBox1</cstring>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>radiusSpinBox</tabstop>
+</tabstops>
+<tqlayoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/chalk/plugins/viewplugins/modify_selection/wdg_grow_selection.ui b/chalk/plugins/viewplugins/modify_selection/wdg_grow_selection.ui
new file mode 100644
index 00000000..d1180803
--- /dev/null
+++ b/chalk/plugins/viewplugins/modify_selection/wdg_grow_selection.ui
@@ -0,0 +1,57 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgGrowSelection</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgGrowSelection</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>255</width>
+ <height>101</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Grow selection by</string>
+ </property>
+ </widget>
+ <widget class="TQSpinBox" row="1" column="0">
+ <property name="name">
+ <cstring>radiusSpinBox</cstring>
+ </property>
+ <property name="maxValue">
+ <number>10000</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>1</number>
+ </property>
+ </widget>
+ <widget class="TQComboBox" row="1" column="1">
+ <item>
+ <property name="text">
+ <string>pixels</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>comboBox1</cstring>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>radiusSpinBox</tabstop>
+</tabstops>
+<tqlayoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/chalk/plugins/viewplugins/modify_selection/wdg_shrink_selection.ui b/chalk/plugins/viewplugins/modify_selection/wdg_shrink_selection.ui
new file mode 100644
index 00000000..28429d72
--- /dev/null
+++ b/chalk/plugins/viewplugins/modify_selection/wdg_shrink_selection.ui
@@ -0,0 +1,68 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgShrinkSelection</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgShrinkSelection</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>255</width>
+ <height>117</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Shrink selection by</string>
+ </property>
+ </widget>
+ <widget class="TQSpinBox" row="1" column="0">
+ <property name="name">
+ <cstring>radiusSpinBox</cstring>
+ </property>
+ <property name="maxValue">
+ <number>10000</number>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>1</number>
+ </property>
+ </widget>
+ <widget class="TQComboBox" row="1" column="1">
+ <item>
+ <property name="text">
+ <string>pixels</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>comboBox1</cstring>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>shrinkFromImageBorderCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Shrink from image border</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>radiusSpinBox</tabstop>
+</tabstops>
+<tqlayoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/chalk/plugins/viewplugins/performancetest/Makefile.am b/chalk/plugins/viewplugins/performancetest/Makefile.am
new file mode 100644
index 00000000..e2d7dfac
--- /dev/null
+++ b/chalk/plugins/viewplugins/performancetest/Makefile.am
@@ -0,0 +1,25 @@
+chalkrcdir = $(kde_datadir)/chalkplugins
+chalkrc_DATA = perftest.rc
+
+EXTRA_DIST = $(chalkrc_DATA)
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalkperftest.la
+
+chalkperftest_la_SOURCES = wdg_perftest.ui perftest.cc dlg_perftest.cc
+noinst_HEADERS = wdg_perftest.h dlg_perftest.h perftest.h
+
+chalkperftest_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) chalkblurfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui
+chalkperftest_la_LIBADD = ../../../libchalkcommon.la
+
+kde_services_DATA = chalkperftest.desktop
+
+chalkperftest_la_METASOURCES = AUTO
diff --git a/chalk/plugins/viewplugins/performancetest/chalkperftest.desktop b/chalk/plugins/viewplugins/performancetest/chalkperftest.desktop
new file mode 100644
index 00000000..74aee7ed
--- /dev/null
+++ b/chalk/plugins/viewplugins/performancetest/chalkperftest.desktop
@@ -0,0 +1,41 @@
+[Desktop Entry]
+Name=Performance Test
+Name[bg]=Тест за производителност
+Name[ca]=Prova d'execució
+Name[da]=Ydelsestest
+Name[de]=Leistungstest
+Name[el]=Δοκιμή επίδοσης
+Name[es]=Prueba de rendimiento
+Name[et]=Jõudlustest
+Name[fa]=آزمون کارایی
+Name[fr]=Test de performances
+Name[fy]=Prestaasjemjitting
+Name[gl]=Probas de Rendemento
+Name[he]=בדיקת ביצועים
+Name[hu]=Teljesítményteszt
+Name[is]=Afkastapróf
+Name[it]=Prova delle prestazioni
+Name[ja]=パフォーマンステスト
+Name[km]=សាកល្បង​ការ​សម្ដែង
+Name[lv]=Veiktspējas tests
+Name[nb]=Ytelsestest
+Name[nds]=Leistenprööv
+Name[ne]=कार्य सम्पादन परीक्षण
+Name[nl]=Prestatiemeting
+Name[pl]=Test wydajności
+Name[pt]=Teste de Performance
+Name[pt_BR]=Teste de Desempenho
+Name[ru]=Модуль производительности
+Name[sk]=Test výkonnosti
+Name[sl]=Preizkus zmogljivosti
+Name[sr]=Проба перформанси
+Name[sr@Latn]=Proba performansi
+Name[sv]=Prestandatest
+Name[uk]=Тест швидкодії
+Name[uz]=Unumdorilkni tekshirish
+Name[uz@cyrillic]=Унумдорилкни текшириш
+Name[zh_TW]=效能測試
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalkperftest
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/performancetest/dlg_perftest.cc b/chalk/plugins/viewplugins/performancetest/dlg_perftest.cc
new file mode 100644
index 00000000..12e3f42c
--- /dev/null
+++ b/chalk/plugins/viewplugins/performancetest/dlg_perftest.cc
@@ -0,0 +1,110 @@
+/*
+ * dlg_perftest.cc - part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <config.h>
+
+#include <math.h>
+
+#include <iostream>
+
+using namespace std;
+
+#include <tqradiobutton.h>
+#include <tqpushbutton.h>
+#include <tqcheckbox.h>
+#include <tqlabel.h>
+
+#include <klocale.h>
+#include <knuminput.h>
+#include <kdebug.h>
+
+#include "dlg_perftest.h"
+#include "wdg_perftest.h"
+
+
+DlgPerfTest::DlgPerfTest( TQWidget * tqparent,
+ const char * name)
+ : super (tqparent, name, true, i18n("Performance Test"), Ok | Cancel, Ok)
+{
+ m_lock = false;
+
+ m_page = new WdgPerfTest(this, "perf_test");
+ Q_CHECK_PTR(m_page);
+
+ setMainWidget(m_page);
+ resize(m_page->tqsizeHint());
+
+ connect(this, TQT_SIGNAL(okClicked()),
+ this, TQT_SLOT(okClicked()));
+
+ connect(m_page->btnSelectAll, TQT_SIGNAL(clicked()), this, TQT_SLOT(selectAllClicked()));
+ connect(m_page->btnDeselectAll, TQT_SIGNAL(clicked()), this, TQT_SLOT(deselectAllClicked()));
+}
+
+DlgPerfTest::~DlgPerfTest()
+{
+ delete m_page;
+}
+
+WdgPerfTest * DlgPerfTest::page()
+{
+ return m_page;
+}
+
+// SLOTS
+
+void DlgPerfTest::okClicked()
+{
+ accept();
+}
+
+void DlgPerfTest::setAllTestCheckBoxes(bool checked)
+{
+ m_page->chkBitBlt->setChecked(checked);
+ m_page->chkFill->setChecked(checked);
+ m_page->chkGradient->setChecked(checked);
+ m_page->chkPixel->setChecked(checked);
+ m_page->chkShape->setChecked(checked);
+ m_page->chkLayer->setChecked(checked);
+ m_page->chkScale->setChecked(checked);
+ m_page->chkRotate->setChecked(checked);
+ m_page->chkRender->setChecked(checked);
+ m_page->chkSelection->setChecked(checked);
+ m_page->chkColorConversion->setChecked(checked);
+ m_page->chkFilter->setChecked(checked);
+ m_page->chkReadBytes->setChecked(checked);
+ m_page->chkWriteBytes->setChecked(checked);
+ m_page->chkIterators->setChecked(checked);
+ m_page->chkPaintView->setChecked(checked);
+ m_page->chkPaintViewFPS->setChecked(checked);
+}
+
+void DlgPerfTest::selectAllClicked()
+{
+ setAllTestCheckBoxes(true);
+}
+
+void DlgPerfTest::deselectAllClicked()
+{
+ setAllTestCheckBoxes(false);
+}
+
+
+#include "dlg_perftest.moc"
diff --git a/chalk/plugins/viewplugins/performancetest/dlg_perftest.h b/chalk/plugins/viewplugins/performancetest/dlg_perftest.h
new file mode 100644
index 00000000..aae398fa
--- /dev/null
+++ b/chalk/plugins/viewplugins/performancetest/dlg_perftest.h
@@ -0,0 +1,56 @@
+/*
+ * dlg_perftest.h -- part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 DLG_PERFTEST_H_
+#define DLG_PERFTEST_H_
+
+#include <kdialogbase.h>
+
+class WdgPerfTest;
+
+class DlgPerfTest: public KDialogBase {
+ typedef KDialogBase super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ DlgPerfTest(TQWidget * tqparent = 0,
+ const char* name = 0);
+ ~DlgPerfTest();
+
+ WdgPerfTest * page();
+
+private slots:
+
+ void okClicked();
+ void selectAllClicked();
+ void deselectAllClicked();
+
+ void setAllTestCheckBoxes(bool checked);
+
+private:
+
+ WdgPerfTest * m_page;
+ double m_oldAngle;
+ bool m_lock;
+
+};
+
+#endif // DLG_PERFTEST_H
diff --git a/chalk/plugins/viewplugins/performancetest/perftest.cc b/chalk/plugins/viewplugins/performancetest/perftest.cc
new file mode 100644
index 00000000..88a50e85
--- /dev/null
+++ b/chalk/plugins/viewplugins/performancetest/perftest.cc
@@ -0,0 +1,1198 @@
+/*
+ * perftest.cc -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <math.h>
+
+#include <stdlib.h>
+
+#include <tqslider.h>
+#include <tqpoint.h>
+#include <tqradiobutton.h>
+#include <tqcheckbox.h>
+#include <tqlabel.h>
+#include <tqtextedit.h>
+#include <tqdatetime.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kdialogbase.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <knuminput.h>
+
+#include <tqcolor.h>
+
+#include "kis_meta_registry.h"
+#include <kis_resourceserver.h>
+#include "kis_cursor.h"
+#include <kis_doc.h>
+#include <kis_config.h>
+#include <kis_image.h>
+#include <kis_layer.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_view.h>
+#include <kis_selection.h>
+#include <kis_colorspace_factory_registry.h>
+#include <kis_colorspace.h>
+#include <kis_painter.h>
+#include <kis_fill_painter.h>
+#include <kis_id.h>
+#include <kis_paint_device.h>
+#include <kis_iterators_pixel.h>
+#include "perftest.h"
+#include "kis_filter_config_widget.h"
+#include "kis_factory.h"
+
+#include "dlg_perftest.h"
+#include "wdg_perftest.h"
+
+#define USE_CALLGRIND 0
+
+#if USE_CALLGRIND
+#include <valgrind/callgrind.h>
+#endif
+
+
+typedef KGenericFactory<PerfTest> PerfTestFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkperftest, PerfTestFactory( "chalk" ) )
+
+PerfTest::PerfTest(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ if ( tqparent->inherits("KisView") )
+ {
+ setInstance(PerfTestFactory::instance());
+ setXMLFile(locate("data","chalkplugins/perftest.rc"), true);
+
+ (void) new KAction(i18n("&Performance Test..."), 0, 0, this, TQT_SLOT(slotPerfTest()), actionCollection(), "perf_test");
+
+ m_view = (KisView*) tqparent;
+ }
+}
+
+PerfTest::~PerfTest()
+{
+ m_view = 0;
+}
+
+void PerfTest::slotPerfTest()
+{
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+
+ if (!image) return;
+
+ DlgPerfTest * dlgPerfTest = new DlgPerfTest(m_view, "PerfTest");
+ Q_CHECK_PTR(dlgPerfTest);
+
+ dlgPerfTest->setCaption(i18n("Performance Test"));
+
+ TQString report = TQString("");
+
+ if (dlgPerfTest->exec() == TQDialog::Accepted) {
+
+ TQ_INT32 testCount = (TQ_INT32)tqRound(dlgPerfTest->page()->intTestCount->value());
+
+ if (dlgPerfTest->page()->chkBitBlt->isChecked()) {
+ kdDebug() << "bltTest:\n";
+ TQString s = bltTest(testCount);
+ report = report.append(s);
+ kdDebug() << s << "\n";
+ }
+ if (dlgPerfTest->page()->chkFill->isChecked()) {
+ kdDebug() << "Filltest\n";
+ TQString s= fillTest(testCount);
+ report = report.append(s);
+ kdDebug() << s << "\n";
+ }
+ if (dlgPerfTest->page()->chkGradient->isChecked()) {
+ kdDebug() << "Gradienttest\n";
+ TQString s = gradientTest(testCount);
+ report = report.append(s);
+ kdDebug() << s << "\n";
+ }
+ if (dlgPerfTest->page()->chkPixel->isChecked()) {
+ kdDebug() << "Pixeltest\n";
+ TQString s = pixelTest(testCount);
+ report = report.append(s);
+ kdDebug() << s << "\n";
+ }
+ if (dlgPerfTest->page()->chkShape->isChecked()) {
+ kdDebug() << "Shapetest\n";
+ TQString s = tqshapeTest(testCount);
+ report = report.append(s);
+ kdDebug() << s << "\n";
+ }
+ if (dlgPerfTest->page()->chkLayer->isChecked()) {
+ kdDebug() << "LayerTest\n";
+ TQString s = layerTest(testCount);
+ report = report.append(s);
+ kdDebug() << s << "\n";
+ }
+ if (dlgPerfTest->page()->chkScale->isChecked()) {
+ kdDebug() << "Scaletest\n";
+ TQString s = scaleTest(testCount);
+ report = report.append(s);
+ kdDebug() << s << "\n";
+ }
+ if (dlgPerfTest->page()->chkRotate->isChecked()) {
+ kdDebug() << "Rotatetest\n";
+ TQString s = rotateTest(testCount);
+ report = report.append(s);
+ kdDebug() << s << "\n";
+ }
+ if (dlgPerfTest->page()->chkRender->isChecked()) {
+ kdDebug() << "Rendertest\n";
+ TQString s = renderTest(testCount);
+ report = report.append(s);
+ kdDebug() << s << "\n";
+ }
+ if (dlgPerfTest->page()->chkSelection->isChecked()) {
+ kdDebug() << "Selectiontest\n";
+ TQString s = selectionTest(testCount);
+ report = report.append(s);
+ kdDebug() << s << "\n";
+ }
+ if (dlgPerfTest->page()->chkColorConversion->isChecked()) {
+ kdDebug() << "Colorconversiontest\n";
+ TQString s = colorConversionTest(testCount);
+ report = report.append(s);
+ kdDebug() << s << "\n";
+ }
+ if (dlgPerfTest->page()->chkFilter-> isChecked()) {
+ kdDebug() << "filtertest\n";
+ TQString s = filterTest(testCount);
+ report = report.append(s);
+ kdDebug() << s << "\n";
+ }
+ if (dlgPerfTest->page()->chkReadBytes->isChecked()) {
+ kdDebug() << "Readbytes test\n";
+ TQString s = readBytesTest(testCount);
+ report = report.append(s);
+ kdDebug() << s << "\n";
+ }
+ if (dlgPerfTest->page()->chkWriteBytes-> isChecked()) {
+ kdDebug() << "Writebytes test\n";
+ TQString s = writeBytesTest(testCount);
+ report = report.append(s);
+ kdDebug() << s << "\n";
+ }
+ if (dlgPerfTest->page()->chkIterators->isChecked()) {
+ kdDebug() << "Iterators test\n";
+ TQString s = iteratorTest(testCount);
+ report = report.append(s);
+ kdDebug() << s << "\n";
+ }
+ if (dlgPerfTest->page()->chkPaintView->isChecked()) {
+ kdDebug() << "paintview test\n";
+ TQString s = paintViewTest(testCount);
+ report = report.append(s);
+ kdDebug() << s << "\n";
+ }
+ if (dlgPerfTest->page()->chkPaintViewFPS->isChecked()) {
+ kdDebug() << "paint current view (fps) test\n";
+ TQString s = paintViewFPSTest();
+ report = report.append(s);
+ kdDebug() << s << "\n";
+ }
+ KDialogBase * d = new KDialogBase(m_view, "", true, "", KDialogBase::Ok);
+ Q_CHECK_PTR(d);
+
+ d->setCaption("Performance test results");
+ TQTextEdit * e = new TQTextEdit(d);
+ Q_CHECK_PTR(e);
+ d->setMainWidget(e);
+ e->setText(report);
+ e->setMinimumWidth(600);
+ e->setMinimumHeight(600);
+ d->exec();
+ delete d;
+
+ }
+ delete dlgPerfTest;
+}
+
+TQString PerfTest::bltTest(TQ_UINT32 testCount)
+{
+ TQString report = TQString("* bitBlt test\n");
+
+ KisDoc * doc = m_view->canvasSubject()->document();
+ KisIDList l = KisMetaRegistry::instance()->csRegistry()->listKeys();
+
+ for (KisIDList::Iterator it = l.begin(); it != l.end(); ++it) {
+
+ kdDebug() << "Image->" << (*it).name() << "\n";
+
+ report = report.append( " Testing blitting on " + (*it).name() + "\n");
+
+ KisImageSP img = doc->newImage("blt-" + (*it).name(), 1000, 1000,
+ KisMetaRegistry::instance()->csRegistry()->getColorSpace(*it,""));
+
+ report = report.append(doBlit(COMPOSITE_OVER, *it, OPACITY_OPAQUE, testCount, img));
+ report = report.append( "\n");
+ report = report.append(doBlit(COMPOSITE_OVER, *it, OPACITY_OPAQUE / 2, testCount, img));
+ report = report.append( "\n");
+ report = report.append(doBlit(COMPOSITE_COPY, *it, OPACITY_OPAQUE, testCount, img));
+ report = report.append( "\n");
+ report = report.append(doBlit(COMPOSITE_COPY, *it, OPACITY_OPAQUE / 2, testCount, img));
+ report = report.append( "\n");
+ }
+
+ return report;
+
+
+}
+
+
+TQString PerfTest::doBlit(const KisCompositeOp& op,
+ KisID cspace,
+ TQ_UINT8 opacity,
+ TQ_UINT32 testCount,
+ KisImageSP img)
+{
+
+ TQTime t;
+ TQString report;
+
+ // ------------------------------------------------------------------------------
+ // Small
+
+ KisPaintDeviceSP small = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getColorSpace(cspace,""), "small blit");
+ Q_CHECK_PTR(small);
+
+ KisFillPainter pf(small.data()) ;
+ pf.fillRect(0, 0, 32, 32, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ pf.end();
+
+ t.restart();
+ KisPainter p(img->activeDevice());
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ p.bitBlt(0, 0, op, small.data(),0,0,32, 32);
+ }
+ p.end();
+
+ report = report.append(TQString(" %1 blits of rectangles < tilesize with opacity %2 and composite op %3: %4ms\n")
+ .tqarg(testCount)
+ .tqarg(opacity)
+ .tqarg(op.id().name())
+ .tqarg(t.elapsed()));
+
+
+ // ------------------------------------------------------------------------------
+ // Medium
+ KisPaintDeviceSP medium = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getColorSpace(cspace,""), "medium blit");
+ Q_CHECK_PTR(medium);
+
+ pf.begin(medium.data()) ;
+ pf.fillRect(0, 0, 64 * 3, 64 * 3, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ pf.end();
+
+ t.restart();
+ p.begin(img->activeDevice().data());
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ p.bitBlt(0, 0, op, medium.data(),0,0,96, 96);
+ }
+ p.end();
+
+ report = report.append(TQString(" %1 blits of rectangles 3 * tilesize with opacity %2 and composite op %3: %4ms\n")
+ .tqarg(testCount)
+ .tqarg(opacity)
+ .tqarg(op.id().name())
+ .tqarg(t.elapsed()));
+
+
+ // ------------------------------------------------------------------------------
+ // Big
+ KisPaintDeviceSP big = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getColorSpace(cspace,""), "big blit");
+ Q_CHECK_PTR(big);
+
+ pf.begin(big.data()) ;
+ pf.fillRect(0, 0, 800, 800, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ pf.end();
+
+ t.restart();
+ p.begin(img->activeDevice().data());
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ p.bitBlt(0, 0, op, big.data(),0,0,800,800);
+
+ }
+ p.end();
+ report = report.append(TQString(" %1 blits of rectangles 800 x 800 with opacity %2 and composite op %3: %4ms\n")
+ .tqarg(testCount)
+ .tqarg(opacity)
+ .tqarg(op.id().name())
+ .tqarg(t.elapsed()));
+
+
+ // ------------------------------------------------------------------------------
+ // Outside
+
+ KisPaintDeviceSP outside = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getColorSpace(cspace,""), "outside blit");
+ Q_CHECK_PTR(outside);
+ pf.begin(outside.data()) ;
+ pf.fillRect(0, 0, 500, 500, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ pf.end();
+
+ t.restart();
+ p.begin(img->activeDevice().data());
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ p.bitBlt(600, 600, op, outside.data(),0,0,500,500);
+
+ }
+ p.end();
+ report = report.append(TQString(" %1 blits of rectangles 500 x 500 at 600,600 with opacity %2 and composite op %3: %4ms\n")
+ .tqarg(testCount)
+ .tqarg(opacity)
+ .tqarg(op.id().name())
+ .tqarg(t.elapsed()));
+
+ // ------------------------------------------------------------------------------
+ // Small with varied source opacity
+
+ KisPaintDeviceSP small_with_alpha = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getColorSpace(cspace,""), "small blit with alpha");
+ Q_CHECK_PTR(small_with_alpha);
+
+ pf.begin(small_with_alpha.data()) ;
+ pf.fillRect(0, 0, 32, 32, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()), OPACITY_TRANSPARENT);
+ pf.fillRect(4, 4, 24, 24, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()), OPACITY_OPAQUE / 2);
+ pf.fillRect(8, 8, 16, 16, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()), OPACITY_OPAQUE);
+ pf.end();
+
+ t.restart();
+ p.begin(img->activeDevice().data());
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ p.bitBlt(0, 0, op, small_with_alpha.data(), 0, 0, 32, 32);
+ }
+ p.end();
+
+ report = report.append(TQString(" %1 blits of rectangles < tilesize with source alpha, with opacity %2 and composite op %3: %4ms\n")
+ .tqarg(testCount)
+ .tqarg(opacity)
+ .tqarg(op.id().name())
+ .tqarg(t.elapsed()));
+
+ return report;
+
+}
+
+TQString PerfTest::fillTest(TQ_UINT32 testCount)
+{
+ TQString report = TQString("* Fill test\n");
+
+ KisDoc * doc = m_view->canvasSubject()->document();
+ KisIDList l = KisMetaRegistry::instance()->csRegistry()->listKeys();
+
+ for (KisIDList::Iterator it = l.begin(); it != l.end(); ++it) {
+ kdDebug() << "Filltest on " << (*it).name() + "\n";
+
+ report = report.append( " Testing blitting on " + (*it).name() + "\n");
+
+ KisImageSP img = doc->newImage("fill-" + (*it).name(), 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(*it,""));
+ KisPaintDeviceSP l = img->activeDevice();
+
+ // Rect fill
+ KisFillPainter p(l.data());
+ TQTime t;
+ t.restart();
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ p.eraseRect(0, 0, 1000, 1000);
+ }
+ report = report.append(TQString(" Erased 1000 x 1000 layer %1 times: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+
+
+ t.restart();
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ p.eraseRect(50, 50, 500, 500);
+ }
+ report = report.append(TQString(" Erased 500 x 500 layer %1 times: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+
+
+ t.restart();
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ p.eraseRect(-50, -50, 1100, 1100);
+ }
+ report = report.append(TQString(" Erased rect bigger than layer %1 times: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+
+
+ // Opaque Rect fill
+ t.restart();
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ p.fillRect(0, 0, 1000, 1000, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ }
+ report = report.append(TQString(" Opaque fill 1000 x 1000 layer %1 times: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+
+
+ t.restart();
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ p.fillRect(50, 50, 500, 500, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ }
+ report = report.append(TQString(" Opaque fill 500 x 500 layer %1 times: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+
+
+ t.restart();
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ p.fillRect(-50, -50, 1100, 1100, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ }
+ report = report.append(TQString(" Opaque fill rect bigger than layer %1 times: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+
+ // Transparent rect fill
+
+ t.restart();
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ p.fillRect(0, 0, 1000, 1000, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()), OPACITY_OPAQUE / 2);
+ }
+ report = report.append(TQString(" Opaque fill 1000 x 1000 layer %1 times: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+
+
+ t.restart();
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ p.fillRect(50, 50, 500, 500, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()), OPACITY_OPAQUE / 2);
+ }
+ report = report.append(TQString(" Opaque fill 500 x 500 layer %1 times: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+
+
+ t.restart();
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ p.fillRect(-50, -50, 1100, 1100, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()), OPACITY_OPAQUE / 2);
+ }
+ report = report.append(TQString(" Opaque fill rect bigger than layer %1 times: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+
+ // Colour fill
+
+ t.restart();
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ p.eraseRect(0, 0, 1000, 1000);
+// p.paintEllipse(500, 1000, 100, 0, 0);
+ p.setPaintColor(KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ p.setFillThreshold(15);
+ p.setCompositeOp(COMPOSITE_OVER);
+ p.fillColor(0,0);
+ }
+ report = report.append(TQString(" Opaque floodfill of whole circle (incl. erase and painting of circle) %1 times: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+
+
+ // Pattern fill
+ t.restart();
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ p.eraseRect(0, 0, 1000, 1000);
+// p.paintEllipse(500, 1000, 100, 0, 0);
+ p.setPaintColor(KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ KisResourceServerBase* r = KisResourceServerRegistry::instance()->get("PatternServer");
+ Q_CHECK_PTR(r);
+ p.setPattern((KisPattern*)r->resources().first());
+ p.setFillThreshold(15);
+ p.setCompositeOp(COMPOSITE_OVER);
+ p.fillPattern(0,0);
+ }
+ report = report.append(TQString(" Opaque patternfill of whole circle (incl. erase and painting of circle) %1 times: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+
+
+
+ }
+
+
+
+ return report;
+
+}
+
+TQString PerfTest::gradientTest(TQ_UINT32 testCount)
+{
+ return TQString("Gradient test\n");
+}
+
+TQString PerfTest::pixelTest(TQ_UINT32 testCount)
+{
+ TQString report = TQString("* pixel/setpixel test\n");
+
+ KisDoc * doc = m_view->canvasSubject()->document();
+ KisIDList l = KisMetaRegistry::instance()->csRegistry()->listKeys();
+
+
+ for (KisIDList::Iterator it = l.begin(); it != l.end(); ++it) {
+ report = report.append( " Testing pixel/setpixel on " + (*it).name() + "\n");
+
+ KisImageSP img = doc->newImage("fill-" + (*it).name(), 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(*it,""));
+
+ KisPaintDeviceSP l = img->activeDevice();
+
+ TQTime t;
+ t.restart();
+
+ TQColor c = TQt::black;
+ TQ_UINT8 opacity = OPACITY_OPAQUE;
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ for (TQ_UINT32 x = 0; x < 1000; ++x) {
+ for (TQ_UINT32 y = 0; y < 1000; ++y) {
+ l->pixel(x, y, &c, &opacity);
+ }
+ }
+ }
+ report = report.append(TQString(" read 1000 x 1000 pixels %1 times: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+
+ c= TQt::black;
+ t.restart();
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ for (TQ_UINT32 x = 0; x < 1000; ++x) {
+ for (TQ_UINT32 y = 0; y < 1000; ++y) {
+ l->setPixel(x, y, c, 128);
+ }
+ }
+ }
+ report = report.append(TQString(" written 1000 x 1000 pixels %1 times: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+
+ }
+
+
+
+
+ return report;
+
+}
+
+TQString PerfTest::tqshapeTest(TQ_UINT32 testCount)
+{
+ return TQString("Shape test\n");
+}
+
+TQString PerfTest::layerTest(TQ_UINT32 testCount)
+{
+ return TQString("Layer test\n");
+}
+
+TQString PerfTest::scaleTest(TQ_UINT32 testCount)
+{
+ return TQString("Scale test\n");
+}
+
+TQString PerfTest::rotateTest(TQ_UINT32 testCount)
+{
+ TQString report = TQString("* Rotate test\n");
+
+ KisDoc * doc = m_view->canvasSubject()->document();
+ KisIDList l = KisMetaRegistry::instance()->csRegistry()->listKeys();
+ for (KisIDList::Iterator it = l.begin(); it != l.end(); ++it) {
+
+ doc->undoAdapter()->setUndo( false );
+ TQTime t;
+
+ for (uint i = 0; i < testCount; ++i) {
+ for (double angle = 0; angle < 360; ++angle) {
+ kdDebug() << "Rotating " << (*it).name() << " at " << angle << " degrees\n";
+ KisImage * img = doc->newImage("cs-" + (*it).name(), 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(*it,""));
+ img->rotate(angle, m_view->canvasSubject()->progressDisplay());
+ kdDebug() << "Size: " << img->projection()->extent() << endl;
+ delete img;
+ }
+ }
+ report = report.append(TQString(" rotated 1000 x 1000 pixels over 360 degrees, degree by degree, %1 times: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+ }
+ return report;
+}
+
+TQString PerfTest::renderTest(TQ_UINT32 restCount)
+{
+ return TQString("Render test\n");
+}
+
+TQString PerfTest::selectionTest(TQ_UINT32 testCount)
+{
+ return TQString("Selection test\n");
+}
+
+TQString PerfTest::colorConversionTest(TQ_UINT32 testCount)
+{
+ TQString report = TQString("* Colorspace conversion test\n");
+
+ KisDoc * doc = m_view->canvasSubject()->document();
+ KisIDList l = KisMetaRegistry::instance()->csRegistry()->listKeys();
+ for (KisIDList::Iterator it = l.begin(); it != l.end(); ++it) {
+
+ KisImage * img = doc->newImage("cs-" + (*it).name(), 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(*it,""));
+
+ TQTime t;
+
+ KisIDList l2 = KisMetaRegistry::instance()->csRegistry()->listKeys();
+ for (KisIDList::Iterator it2 = l2.begin(); it2 != l2.end(); ++it2) {
+ kdDebug() << "test conversion from " << (*it).name() << " to " << (*it2).name() << endl;
+
+ t.restart();
+ for (uint i = 0; i < testCount; ++i) {
+ KisImage * img2 = new KisImage(*img);
+ img2->convertTo(KisMetaRegistry::instance()->csRegistry()->getColorSpace(*it2,""));
+ delete img2;
+ }
+ report = report.append(TQString(" converted from " + (*it).name() + " to " + (*it2).name() + " 1000 x 1000 pixels %1 times: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+
+ }
+
+ delete img;
+
+ }
+ return report;
+
+}
+
+TQString PerfTest::filterTest(TQ_UINT32 testCount)
+{
+
+ TQString report = TQString("* Filter test\n");
+
+ KisIDList filters = KisFilterRegistry::instance()->listKeys();
+ KisDoc * doc = m_view->canvasSubject()->document();
+ KisIDList l = KisMetaRegistry::instance()->csRegistry()->listKeys();
+
+ for (KisIDList::Iterator it = l.begin(); it != l.end(); ++it) {
+ report = report.append( " Testing filtering on " + (*it).name() + "\n");
+
+ KisImageSP img = doc->newImage("filter-" + (*it).name(), 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(*it,""));
+ KisPaintDeviceSP l = img->activeDevice();
+
+ TQTime t;
+
+ for (KisIDList::Iterator it = filters.begin(); it != filters.end(); ++it) {
+
+ KisFilterSP f = KisFilterRegistry::instance()->get(*it);
+ t.restart();
+ kdDebug() << "test filter " << f->id().name() << " on " << img->colorSpace()->id().name() << endl;
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ f->enableProgress();
+ f->process(l.data(), l.data(), f->configuration(f->createConfigurationWidget(m_view, l.data())), TQRect(0, 0, 1000, 1000));
+ f->disableProgress();
+ }
+ report = report.append(TQString(" filtered " + (*it).name() + "1000 x 1000 pixels %1 times: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+
+ }
+
+ }
+ return report;
+
+}
+
+TQString PerfTest::readBytesTest(TQ_UINT32 testCount)
+{
+ TQString report = TQString("* Read bytes test\n\n");
+
+ // On default tiles
+ KisDoc * doc = m_view->canvasSubject()->document();
+ KisImageSP img = doc->newImage("Readbytes ", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA",""),""));
+ KisPaintDeviceSP l = img->activeDevice();
+
+ TQTime t;
+ t.restart();
+
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ TQ_UINT8 * newData = new TQ_UINT8[1000 * 1000 * l->pixelSize()];
+ Q_CHECK_PTR(newData);
+ l->readBytes(newData, 0, 0, 1000, 1000);
+ delete[] newData;
+ }
+
+ report = report.append(TQString(" read 1000 x 1000 pixels %1 times from empty image: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+
+ // On tiles with data
+
+ KisFillPainter p(l.data());
+ p.fillRect(0, 0, 1000, 1000, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ p.end();
+
+ t.restart();
+
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ TQ_UINT8 * newData = new TQ_UINT8[1000 * 1000 * l->pixelSize()];
+ Q_CHECK_PTR(newData);
+ l->readBytes(newData, 0, 0, 1000, 1000);
+ delete[] newData;
+ }
+
+ report = report.append(TQString(" read 1000 x 1000 pixels %1 times from filled image: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+
+ return report;
+}
+
+
+TQString PerfTest::writeBytesTest(TQ_UINT32 testCount)
+{
+ TQString report = TQString("* Write bytes test");
+
+ // On default tiles
+ KisDoc * doc = m_view->canvasSubject()->document();
+ KisImageSP img = doc->newImage("Writebytes ", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),""));
+ KisPaintDeviceSP l = img->activeDevice();
+ KisFillPainter p(l.data());
+ p.fillRect(0, 0, 1000, 1000, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ p.end();
+
+
+ TQ_UINT8 * data = new TQ_UINT8[1000 * 1000 * l->pixelSize()];
+ Q_CHECK_PTR(data);
+ l->readBytes(data, 0, 0, 1000, 1000);
+
+ TQTime t;
+ t.restart();
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ l->writeBytes(data, 0, 0, 1000, 1000);
+ }
+ delete[] data;
+ report = report.append(TQString(" written 1000 x 1000 pixels %1 times: %2\n").tqarg(testCount).tqarg(t.elapsed()));
+ return report;
+
+
+}
+
+/////// Iterator tests
+
+
+TQString hlineRODefault(KisDoc * doc, TQ_UINT32 testCount)
+{
+ KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),""));
+ KisPaintDeviceSP l = img->activeDevice();
+
+ TQTime t;
+ t.restart();
+
+
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ int adv;
+
+ for(TQ_INT32 y2 = 0; y2 < 0 + 1000; y2++)
+ {
+ KisHLineIterator hiter = l->createHLineIterator(0, y2, 1000, false);
+ while(! hiter.isDone())
+ {
+ adv = hiter.nConseqHPixels();
+ hiter += adv;
+ }
+ }
+
+ }
+
+ return TQString(" hline iterated read-only 1000 x 1000 pixels %1 times over default tile: %2\n").tqarg(testCount).tqarg(t.elapsed());
+
+
+}
+
+TQString hlineRO(KisDoc * doc, TQ_UINT32 testCount)
+{
+ KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),""));
+ KisPaintDeviceSP l = img->activeDevice();
+
+ KisFillPainter p(l.data());
+ p.fillRect(0, 0, 1000, 1000, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ p.end();
+
+ TQTime t;
+ t.restart();
+
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ int adv;
+
+ for(TQ_INT32 y2 = 0; y2 < 0 + 1000; y2++)
+ {
+ KisHLineIterator hiter = l->createHLineIterator(0, y2, 1000, false);
+ while(! hiter.isDone())
+ {
+ adv = hiter.nConseqHPixels();
+ hiter += adv;
+ }
+ }
+
+ }
+
+ return TQString(" hline iterated read-only 1000 x 1000 pixels %1 times over existing tile: %2\n").tqarg(testCount).tqarg(t.elapsed());
+
+}
+
+TQString hlineWRDefault(KisDoc * doc, TQ_UINT32 testCount)
+{
+ KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),""));
+ KisPaintDeviceSP l = img->activeDevice();
+
+ TQTime t;
+ t.restart();
+
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ int adv;
+
+ for(TQ_INT32 y2 = 0; y2 < 0 + 1000; y2++)
+ {
+ KisHLineIterator hiter = l->createHLineIterator(0, y2, 1000, true);
+ while(! hiter.isDone())
+ {
+ adv = hiter.nConseqHPixels();
+ hiter += adv;
+ }
+ }
+
+ }
+
+ return TQString(" hline iterated writable 1000 x 1000 pixels %1 times over default tile: %2\n").tqarg(testCount).tqarg(t.elapsed());
+
+}
+
+TQString hlineWR(KisDoc * doc, TQ_UINT32 testCount)
+{
+ KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),""));
+ KisPaintDeviceSP l = img->activeDevice();
+
+ KisFillPainter p(l.data());
+ p.fillRect(0, 0, 1000, 1000, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ p.end();
+
+
+ TQTime t;
+ t.restart();
+
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ int adv;
+ for(TQ_INT32 y2 = 0; y2 < 0 + 1000; y2++)
+ {
+ KisHLineIterator hiter = l->createHLineIterator(0, y2, 1000, true);
+ while(! hiter.isDone())
+ {
+ adv = hiter.nConseqHPixels();
+ hiter += adv;
+ }
+ }
+
+ }
+
+ return TQString(" hline iterated writable 1000 x 1000 pixels %1 times over existing tile: %2\n").tqarg(testCount).tqarg(t.elapsed());
+
+}
+
+
+TQString vlineRODefault(KisDoc * doc, TQ_UINT32 testCount)
+{
+ KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),""));
+ KisPaintDeviceSP l = img->activeDevice();
+
+ TQTime t;
+ t.restart();
+
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ for(TQ_INT32 y2 = 0; y2 < 0 + 1000; y2++)
+ {
+ KisVLineIterator hiter = l->createVLineIterator(y2, 0, 1000, true);
+ while(! hiter.isDone())
+ {
+ ++hiter;
+ }
+ }
+
+ }
+
+ return TQString(" vline iterated read-only 1000 x 1000 pixels %1 times over default tile: %2\n").tqarg(testCount).tqarg(t.elapsed());
+
+}
+
+TQString vlineRO(KisDoc * doc, TQ_UINT32 testCount)
+{
+ KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),""));
+ KisPaintDeviceSP l = img->activeDevice();
+
+ KisFillPainter p(l.data());
+ p.fillRect(0, 0, 1000, 1000, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ p.end();
+
+
+ TQTime t;
+ t.restart();
+
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ for(TQ_INT32 y2 = 0; y2 < 0 + 1000; y2++)
+ {
+ KisVLineIterator hiter = l->createVLineIterator(y2, 0, 1000, true);
+ while(! hiter.isDone())
+ {
+ ++hiter;
+ }
+ }
+
+ }
+
+ return TQString(" vline iterated read-only 1000 x 1000 pixels %1 times over existing tile: %2\n").tqarg(testCount).tqarg(t.elapsed());
+
+}
+
+TQString vlineWRDefault(KisDoc * doc, TQ_UINT32 testCount)
+{
+ KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),""));
+ KisPaintDeviceSP l = img->activeDevice();
+
+ TQTime t;
+ t.restart();
+
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+
+ for(TQ_INT32 y2 = 0; y2 < 0 + 1000; y2++)
+ {
+ KisVLineIterator hiter = l->createVLineIterator(y2, 0, 1000, true);
+ while(! hiter.isDone())
+ {
+ ++hiter;
+ }
+ }
+
+ }
+
+ return TQString(" vline iterated writable 1000 x 1000 pixels %1 times over default tile: %2\n").tqarg(testCount).tqarg(t.elapsed());
+}
+
+TQString vlineWR(KisDoc * doc, TQ_UINT32 testCount)
+{
+
+ KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),""));
+ KisPaintDeviceSP l = img->activeDevice();
+
+ KisFillPainter p(l.data());
+ p.fillRect(0, 0, 1000, 1000, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ p.end();
+
+ TQTime t;
+ t.restart();
+
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ for(TQ_INT32 y2 = 0; y2 < 0 + 1000; y2++)
+ {
+ KisHLineIterator hiter = l->createHLineIterator(y2, 0, 1000, true);
+ while(! hiter.isDone())
+ {
+ ++hiter;
+ }
+ }
+
+ }
+
+ return TQString(" vline iterated writable 1000 x 1000 pixels %1 times over existing tile: %2\n").tqarg(testCount).tqarg(t.elapsed());
+
+}
+
+TQString rectRODefault(KisDoc * doc, TQ_UINT32 testCount)
+{
+ KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),""));
+ KisPaintDeviceSP l = img->activeDevice();
+;
+ TQTime t;
+ t.restart();
+
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ KisRectIterator r = l->createRectIterator(0, 0, 1000, 1000, false);
+ while(! r.isDone())
+ {
+ ++r;
+ }
+ }
+
+ return TQString(" rect iterated read-only 1000 x 1000 pixels %1 times over default tile: %2\n").tqarg(testCount).tqarg(t.elapsed());
+
+
+}
+
+TQString rectRO(KisDoc * doc, TQ_UINT32 testCount)
+{
+ KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),""));
+ KisPaintDeviceSP l = img->activeDevice();
+
+ KisFillPainter p(l.data());
+ p.fillRect(0, 0, 1000, 1000, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ p.end();
+
+ TQTime t;
+ t.restart();
+
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ KisRectIterator r = l->createRectIterator(0, 0, 1000, 1000, false);
+ while(! r.isDone())
+ {
+ ++r;
+ }
+ }
+
+ return TQString(" rect iterated read-only 1000 x 1000 pixels %1 times over existing tile: %2\n").tqarg(testCount).tqarg(t.elapsed());
+
+}
+
+TQString rectWRDefault(KisDoc * doc, TQ_UINT32 testCount)
+{
+
+
+ KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),""));
+ KisPaintDeviceSP l = img->activeDevice();
+
+ TQTime t;
+ t.restart();
+
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ KisRectIterator r = l->createRectIterator(0, 0, 1000, 1000, true);
+ while(! r.isDone())
+ {
+ ++r;
+ }
+ }
+
+ return TQString(" rect iterated writable 1000 x 1000 pixels %1 times over default tile: %2\n").tqarg(testCount).tqarg(t.elapsed());
+
+}
+
+TQString rectWR(KisDoc * doc, TQ_UINT32 testCount)
+{
+ KisImageSP img = doc->newImage("", 1000, 1000, KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""),""));
+ KisPaintDeviceSP l = img->activeDevice();
+
+ KisFillPainter p(l.data());
+ p.fillRect(0, 0, 1000, 1000, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ p.end();
+
+
+ TQTime t;
+ t.restart();
+
+
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ KisRectIterator r = l->createRectIterator(0, 0, 1000, 1000, true);
+ while(! r.isDone())
+ {
+ ++r;
+ }
+ }
+
+
+ return TQString(" rect iterated writable 1000 x 1000 pixels %1 times over existing tile: %2\n").tqarg(testCount).tqarg(t.elapsed());
+
+
+}
+TQString PerfTest::iteratorTest(TQ_UINT32 testCount)
+{
+ TQString report = "Iterator test";
+
+ KisDoc * doc = m_view->canvasSubject()->document();
+
+ report = report.append(hlineRODefault(doc, testCount));
+ report = report.append(hlineRO(doc, testCount));
+ report = report.append(hlineWRDefault(doc, testCount));
+ report = report.append(hlineWR(doc, testCount));
+
+ report = report.append(vlineRODefault(doc, testCount));
+ report = report.append(vlineRO(doc, testCount));
+ report = report.append(vlineWRDefault(doc, testCount));
+ report = report.append(vlineWR(doc, testCount));
+
+ report = report.append(rectRODefault(doc, testCount));
+ report = report.append(rectRO(doc, testCount));
+ report = report.append(rectWRDefault(doc, testCount));
+ report = report.append(rectWR(doc, testCount));
+
+ return report;
+
+
+}
+
+TQString PerfTest::paintViewTest(TQ_UINT32 testCount)
+{
+ TQString report = TQString("* paintView test\n\n");
+
+ KisDoc * doc = m_view->canvasSubject()->document();
+
+ KisImageSP img = doc->currentImage();
+ img->resize(512,512);
+
+
+ KisPaintDeviceSP l = img->activeDevice();
+
+ KisFillPainter p(l.data());
+ p.fillRect(0, 0, 512, 512, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ p.end();
+
+ TQTime t;
+ t.restart();
+
+#if USE_CALLGRIND
+ CALLGRIND_ZERO_STATS();
+#endif
+
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ m_view->getCanvasController()->updateCanvas(TQRect(0, 0, 512, 512));
+ }
+
+#if USE_CALLGRIND
+ CALLGRIND_DUMP_STATS();
+#endif
+
+ report = report.append(TQString(" painted a 512 x 512 image %1 times: %2 ms\n").tqarg(testCount).tqarg(t.elapsed()));
+
+ img->newLayer("layer 2", OPACITY_OPAQUE);
+ l = img->activeDevice();
+
+ p.begin(l.data());
+ p.fillRect(0, 0, 512, 512, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ p.end();
+
+ img->newLayer("layer 3", OPACITY_OPAQUE);
+ l = img->activeDevice();
+
+ p.begin(l.data());
+ p.fillRect(0, 0, 512, 512, KisColor(TQt::black, KisMetaRegistry::instance()->csRegistry()->getRGB8()));
+ p.end();
+
+ t.restart();
+
+ for (TQ_UINT32 i = 0; i < testCount; ++i) {
+ m_view->getCanvasController()->updateCanvas(TQRect(0, 0, 512, 512));
+ }
+
+ report = report.append(TQString(" painted a 512 x 512 image with 3 layers %1 times: %2 ms\n").tqarg(testCount).tqarg(t.elapsed()));
+
+ return report;
+}
+
+TQString PerfTest::paintViewFPSTest()
+{
+ TQString report = TQString("* paintView (fps) test\n\n");
+
+ TQTime t;
+ t.restart();
+
+#if USE_CALLGRIND
+ CALLGRIND_ZERO_STATS();
+#endif
+
+ int numViewsPainted = 0;
+ const int millisecondsPerSecond = 1000;
+
+ while (t.elapsed() < millisecondsPerSecond) {
+ m_view->getCanvasController()->updateCanvas();
+ numViewsPainted++;
+ }
+
+#if USE_CALLGRIND
+ CALLGRIND_DUMP_STATS();
+#endif
+
+ report = report.append(TQString(" painted current view at %1 frames per second\n").tqarg(numViewsPainted));
+
+ return report;
+}
+
+#include "perftest.moc"
diff --git a/chalk/plugins/viewplugins/performancetest/perftest.h b/chalk/plugins/viewplugins/performancetest/perftest.h
new file mode 100644
index 00000000..5bae3c8c
--- /dev/null
+++ b/chalk/plugins/viewplugins/performancetest/perftest.h
@@ -0,0 +1,76 @@
+/*
+ * perftest.h -- Part of Chalk
+ *
+ * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 PERFTEST_H_
+#define PERFTEST_H_
+
+#include <kparts/plugin.h>
+#include <kis_types.h>
+#include <kis_global.h>
+
+class KisView;
+class KisID;
+
+class PerfTest : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ PerfTest(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~PerfTest();
+
+private slots:
+
+ void slotPerfTest();
+
+private:
+
+ TQString bltTest(TQ_UINT32 testCount);
+ TQString fillTest(TQ_UINT32 testCount);
+ TQString gradientTest(TQ_UINT32 testCount);
+ TQString pixelTest(TQ_UINT32 testCount);
+ TQString tqshapeTest(TQ_UINT32 testCount);
+ TQString layerTest(TQ_UINT32 testCount);
+ TQString scaleTest(TQ_UINT32 testCount);
+ TQString rotateTest(TQ_UINT32 testCount);
+ TQString renderTest(TQ_UINT32 restCount);
+ TQString selectionTest(TQ_UINT32 testCount);
+ TQString colorConversionTest(TQ_UINT32 testCount);
+ TQString filterTest(TQ_UINT32 testCount);
+ TQString readBytesTest(TQ_UINT32 testCount);
+ TQString writeBytesTest(TQ_UINT32 testCount);
+ TQString iteratorTest(TQ_UINT32 testCount);
+ TQString paintViewTest(TQ_UINT32 testCount);
+ TQString paintViewFPSTest();
+
+ TQString doBlit(const KisCompositeOp& op,
+ KisID cspace,
+ TQ_UINT8 opacity,
+ TQ_UINT32 testCount,
+ KisImageSP img);
+
+private:
+
+ KisView * m_view;
+ KisPainter * m_painter;
+
+};
+
+#endif // PERFTEST_H_
diff --git a/chalk/plugins/viewplugins/performancetest/perftest.rc b/chalk/plugins/viewplugins/performancetest/perftest.rc
new file mode 100644
index 00000000..de404a34
--- /dev/null
+++ b/chalk/plugins/viewplugins/performancetest/perftest.rc
@@ -0,0 +1,9 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkperftest" version="1">
+<MenuBar>
+ <Menu name="Tools"><text>&amp;Tools</text>
+ <Separator/>
+ <Action name="perf_test"/>
+ </Menu>
+</MenuBar>
+</kpartgui> \ No newline at end of file
diff --git a/chalk/plugins/viewplugins/performancetest/wdg_perftest.ui b/chalk/plugins/viewplugins/performancetest/wdg_perftest.ui
new file mode 100644
index 00000000..7dc14f17
--- /dev/null
+++ b/chalk/plugins/viewplugins/performancetest/wdg_perftest.ui
@@ -0,0 +1,283 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>WdgPerfTest</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgPerfTest</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>377</width>
+ <height>566</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Image Size</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>grpPerfTest</cstring>
+ </property>
+ <property name="title">
+ <string>&amp;Performance Test</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lblTests</cstring>
+ </property>
+ <property name="text">
+ <string>Number of tests:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>intWidth</cstring>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>chkBitBlt</cstring>
+ </property>
+ <property name="text">
+ <string>bitBlt</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="2" column="0">
+ <property name="name">
+ <cstring>chkFill</cstring>
+ </property>
+ <property name="text">
+ <string>Fill</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="3" column="0">
+ <property name="name">
+ <cstring>chkGradient</cstring>
+ </property>
+ <property name="text">
+ <string>Gradients</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="4" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>chkPixel</cstring>
+ </property>
+ <property name="text">
+ <string>setPixel/getPixel</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="5" column="0">
+ <property name="name">
+ <cstring>chkShape</cstring>
+ </property>
+ <property name="text">
+ <string>Shapes</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="6" column="0">
+ <property name="name">
+ <cstring>chkLayer</cstring>
+ </property>
+ <property name="text">
+ <string>Layers</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="7" column="0">
+ <property name="name">
+ <cstring>chkScale</cstring>
+ </property>
+ <property name="text">
+ <string>Scaling</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="8" column="0">
+ <property name="name">
+ <cstring>chkRotate</cstring>
+ </property>
+ <property name="text">
+ <string>Rotating</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="9" column="0">
+ <property name="name">
+ <cstring>chkRender</cstring>
+ </property>
+ <property name="text">
+ <string>Rendering</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="10" column="0">
+ <property name="name">
+ <cstring>chkSelection</cstring>
+ </property>
+ <property name="text">
+ <string>Selection</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="11" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>chkColorConversion</cstring>
+ </property>
+ <property name="text">
+ <string>Color conversion</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="12" column="0">
+ <property name="name">
+ <cstring>chkFilter</cstring>
+ </property>
+ <property name="text">
+ <string>Filters</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="0" column="1">
+ <property name="name">
+ <cstring>intTestCount</cstring>
+ </property>
+ <property name="value">
+ <number>10</number>
+ </property>
+ <property name="minValue">
+ <number>0</number>
+ </property>
+ <property name="maxValue">
+ <number>1000000</number>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="13" column="0">
+ <property name="name">
+ <cstring>chkReadBytes</cstring>
+ </property>
+ <property name="text">
+ <string>Read bytes</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="14" column="0">
+ <property name="name">
+ <cstring>chkWriteBytes</cstring>
+ </property>
+ <property name="text">
+ <string>Write bytes</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="15" column="0">
+ <property name="name">
+ <cstring>chkIterators</cstring>
+ </property>
+ <property name="text">
+ <string>Iterators</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="16" column="0">
+ <property name="name">
+ <cstring>chkPaintView</cstring>
+ </property>
+ <property name="text">
+ <string>PaintView</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget" row="18" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>tqlayout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>btnSelectAll</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Select All</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>btnDeselectAll</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Deselect All</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQCheckBox" row="17" column="0">
+ <property name="name">
+ <cstring>chkPaintViewFPS</cstring>
+ </property>
+ <property name="text">
+ <string>PaintView (fps)</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>intTestCount</tabstop>
+</tabstops>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/viewplugins/rotateimage/Makefile.am b/chalk/plugins/viewplugins/rotateimage/Makefile.am
new file mode 100644
index 00000000..d4ff4e63
--- /dev/null
+++ b/chalk/plugins/viewplugins/rotateimage/Makefile.am
@@ -0,0 +1,25 @@
+chalkrcdir = $(kde_datadir)/chalkplugins
+chalkrc_DATA = rotateimage.rc
+
+EXTRA_DIST = $(chalkrc_DATA)
+
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalkrotateimage.la
+
+chalkrotateimage_la_SOURCES = wdg_rotateimage.ui rotateimage.cc dlg_rotateimage.cc
+noinst_HEADERS = wdg_rotateimage.h dlg_rotateimage.h rotateimage.h
+
+chalkrotateimage_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) chalkblurfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui
+chalkrotateimage_la_LIBADD = ../../../libchalkcommon.la
+
+kde_services_DATA = chalkrotateimage.desktop
+
+chalkrotateimage_la_METASOURCES = AUTO
diff --git a/chalk/plugins/viewplugins/rotateimage/chalkrotateimage.desktop b/chalk/plugins/viewplugins/rotateimage/chalkrotateimage.desktop
new file mode 100644
index 00000000..e855492e
--- /dev/null
+++ b/chalk/plugins/viewplugins/rotateimage/chalkrotateimage.desktop
@@ -0,0 +1,40 @@
+[Desktop Entry]
+Name=Rotate Image Plugin
+Name[bg]=Приставка за въртене на изображение
+Name[ca]=Connector de rotació d'imatge
+Name[da]=Plugin for rotering af billede
+Name[de]="Bild rotieren"-Modul
+Name[el]=Πρόσθετο περιστροφής εικόνας
+Name[es]=Complemento para girar la imagen
+Name[et]=Pildi pööramise plugin
+Name[fa]=چرخش وصلۀ تصویر
+Name[fr]=Module de rotation d'images
+Name[fy]=Plugin foar ôfbyldingsrotaasje
+Name[gl]=Plugin para Rodar a Imaxe
+Name[he]=תוסף לשינוי גודל של תמונה
+Name[hu]=Képelforgató modul
+Name[is]=Snúa mynd íforrit
+Name[it]=Plugin per ruotare le immagini
+Name[ja]=画像回転プラグイン
+Name[km]=កម្មវិធី​ត្រឡប់​រូបភាព
+Name[nb]=Programtillegg for bilderotering
+Name[nds]=Moduul för't Bilddreihen
+Name[ne]=छवि प्लगइन परिक्रमा गर्नुहोस्
+Name[nl]=Plugin voor afbeeldingrotatie
+Name[pl]=Wtyczka obrotu obrazków
+Name[pt]='Plugin' para Rodar a Imagem
+Name[pt_BR]=Plugin para Rodar a Imagem
+Name[ru]=Модуль вращения
+Name[sk]=Modul rotácia obrázkov
+Name[sl]=Vstavek za vrtenje slike
+Name[sr]=Прикључак за ротирање слике
+Name[sr@Latn]=Priključak za rotiranje slike
+Name[sv]=Insticksprogram för rotera bild
+Name[uk]=Втулок обертання зображень
+Name[uz]=Rasmni burish plagini
+Name[uz@cyrillic]=Расмни буриш плагини
+Name[zh_TW]=旋轉圖片外掛程式
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalkrotateimage
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/rotateimage/dlg_rotateimage.cc b/chalk/plugins/viewplugins/rotateimage/dlg_rotateimage.cc
new file mode 100644
index 00000000..6e3cc9f7
--- /dev/null
+++ b/chalk/plugins/viewplugins/rotateimage/dlg_rotateimage.cc
@@ -0,0 +1,147 @@
+/*
+ * dlg_rotateimage.cc - part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <config.h>
+
+#include <math.h>
+
+#include <iostream>
+
+using namespace std;
+
+#include <tqgroupbox.h>
+#include <tqradiobutton.h>
+#include <tqcheckbox.h>
+#include <tqlabel.h>
+
+#include <klocale.h>
+#include <knuminput.h>
+#include <kdebug.h>
+
+#include "dlg_rotateimage.h"
+#include "wdg_rotateimage.h"
+
+
+DlgRotateImage::DlgRotateImage( TQWidget * tqparent,
+ const char * name)
+ : super (tqparent, name, true, i18n("Rotate Image"), Ok | Cancel, Ok)
+{
+ m_lock = false;
+
+ m_page = new WdgRotateImage(this, "rotate_image");
+ Q_CHECK_PTR(m_page);
+
+ setMainWidget(m_page);
+ resize(m_page->tqsizeHint());
+
+ connect(this, TQT_SIGNAL(okClicked()),
+ this, TQT_SLOT(okClicked()));
+ connect( m_page->doubleCustom, TQT_SIGNAL( valueChanged ( double ) ),
+ this, TQT_SLOT( slotAngleValueChanged( double ) ) );
+
+}
+
+DlgRotateImage::~DlgRotateImage()
+{
+ delete m_page;
+}
+
+void DlgRotateImage::slotAngleValueChanged( double )
+{
+ m_page->radioCustom->setChecked(true);
+}
+
+void DlgRotateImage::setAngle(double angle)
+{
+ if (angle == 90) {
+ m_page->radio90->setChecked(true);
+ }
+ else if (angle == 180) {
+ m_page->radio180->setChecked(true);
+ }
+ else if (angle == 270) {
+ m_page->radio270->setChecked(true);
+ }
+ else {
+ m_page->radioCustom->setChecked(true);
+ m_page->doubleCustom->setValue(angle);
+ }
+
+ if (m_oldAngle != angle)
+ resetPreview();
+
+ m_oldAngle = angle;
+
+}
+
+double DlgRotateImage::angle()
+{
+ double angle = 0;
+ if (m_page->radio90->isChecked()) {
+ angle = 90;
+ }
+ else if (m_page->radio180->isChecked()) {
+ angle = 180;
+ }
+ else if (m_page->radio270->isChecked()) {
+ angle = 270;
+ }
+ else {
+ angle = tqRound(m_page->doubleCustom->value());
+ }
+ if (m_page->radioCW->isChecked()) {
+ return angle;
+ }
+ else {
+ return -angle;
+ }
+}
+
+void DlgRotateImage::setDirection (enumRotationDirection direction)
+{
+ if (direction == CLOCKWISE) {
+ m_page->radioCW->setChecked(true);
+ }
+ else if (direction== COUNTERCLOCKWISE) {
+ m_page->radioCCW->setChecked(true);
+ }
+}
+
+enumRotationDirection DlgRotateImage::direction()
+{
+ if (m_page->radioCCW->isChecked()) {
+ return COUNTERCLOCKWISE;
+ }
+ else {
+ return CLOCKWISE;
+ }
+}
+
+void DlgRotateImage::okClicked()
+{
+ accept();
+}
+
+void DlgRotateImage::resetPreview()
+{
+ // Code to update preview here.
+}
+
+#include "dlg_rotateimage.moc"
diff --git a/chalk/plugins/viewplugins/rotateimage/dlg_rotateimage.h b/chalk/plugins/viewplugins/rotateimage/dlg_rotateimage.h
new file mode 100644
index 00000000..47ddd344
--- /dev/null
+++ b/chalk/plugins/viewplugins/rotateimage/dlg_rotateimage.h
@@ -0,0 +1,66 @@
+/*
+ * dlg_rotateimage.h -- part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 DLG_ROTATEIMAGE
+#define DLG_ROTATEIMAGE
+
+#include <kdialogbase.h>
+
+#include <kis_global.h>
+
+class WdgRotateImage;
+
+enum enumRotationDirection {
+ CLOCKWISE,
+ COUNTERCLOCKWISE
+};
+
+
+class DlgRotateImage: public KDialogBase {
+ typedef KDialogBase super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ DlgRotateImage(TQWidget * tqparent = 0,
+ const char* name = 0);
+ ~DlgRotateImage();
+
+ void setAngle(double w);
+ double angle();
+
+ void setDirection (enumRotationDirection direction);
+ enumRotationDirection direction();
+
+private slots:
+
+ void okClicked();
+ void resetPreview();
+ void slotAngleValueChanged( double );
+
+private:
+
+ WdgRotateImage * m_page;
+ double m_oldAngle;
+ bool m_lock;
+
+};
+
+#endif // DLG_ROTATEIMAGE
diff --git a/chalk/plugins/viewplugins/rotateimage/rotateimage.cc b/chalk/plugins/viewplugins/rotateimage/rotateimage.cc
new file mode 100644
index 00000000..e8961cec
--- /dev/null
+++ b/chalk/plugins/viewplugins/rotateimage/rotateimage.cc
@@ -0,0 +1,134 @@
+/*
+ * rotateimage.cc -- Part of Chalk
+ *
+ * Copyright (c) 2004 Michael Thaler
+ *
+ * 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 <math.h>
+
+#include <stdlib.h>
+
+#include <tqslider.h>
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_doc.h>
+#include <kis_config.h>
+#include <kis_image.h>
+#include <kis_layer.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_view.h>
+#include <kis_selection.h>
+
+#include "rotateimage.h"
+#include "dlg_rotateimage.h"
+
+typedef KGenericFactory<RotateImage> RotateImageFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkrotateimage, RotateImageFactory( "chalk" ) )
+
+// XXX: this plugin could also provide layer scaling/resizing
+RotateImage::RotateImage(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+
+ if ( tqparent->inherits("KisView") ) {
+ setInstance(RotateImageFactory::instance());
+ setXMLFile(locate("data","chalkplugins/rotateimage.rc"), true);
+ m_view = (KisView*) tqparent;
+ (void) new KAction(i18n("&Rotate Image..."), 0, 0, TQT_TQOBJECT(this), TQT_SLOT(slotRotateImage()), actionCollection(), "rotateimage");
+ (void) new KAction(i18n("Rotate Image CW"), "rotate_cw", 0, TQT_TQOBJECT(this), TQT_SLOT(slotRotateImage90()), actionCollection(), "rotateImageCW90");
+ (void) new KAction(i18n("Rotate Image 1&80"), 0, 0, TQT_TQOBJECT(this), TQT_SLOT(slotRotateImage180()), actionCollection(), "rotateImage180");
+ (void) new KAction(i18n("Rotate Image CCW"), "rotate_ccw", 0, TQT_TQOBJECT(this), TQT_SLOT(slotRotateImage270()), actionCollection(), "rotateImageCCW90");
+
+ (void) new KAction(i18n("&Rotate Layer..."), 0, 0, TQT_TQOBJECT(this), TQT_SLOT(slotRotateLayer()), actionCollection(), "rotatelayer");
+
+ (void)new KAction(i18n("Rotate 1&80"), 0, TQT_TQOBJECT(m_view), TQT_SLOT(rotateLayer180()), actionCollection(), "rotateLayer180");
+ (void)new KAction(i18n("Rotate CCW"), "rotate_ccw", 0, TQT_TQOBJECT(m_view), TQT_SLOT(rotateLayerLeft90()), actionCollection(), "rotateLayerCCW90");
+ (void)new KAction(i18n("Rotate CW"), "rotate_cw", 0, TQT_TQOBJECT(m_view), TQT_SLOT(rotateLayerRight90()), actionCollection(), "rotateLayerCW90");
+ }
+}
+
+RotateImage::~RotateImage()
+{
+ m_view = 0;
+}
+
+void RotateImage::slotRotateImage()
+{
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+
+ if (!image) return;
+
+ DlgRotateImage * dlgRotateImage = new DlgRotateImage(m_view, "RotateImage");
+ Q_CHECK_PTR(dlgRotateImage);
+
+ dlgRotateImage->setCaption(i18n("Rotate Image"));
+
+ if (dlgRotateImage->exec() == TQDialog::Accepted) {
+ double angle = dlgRotateImage->angle();
+ angle *= M_PI/180;
+ m_view->rotateCurrentImage(angle);
+ }
+ delete dlgRotateImage;
+}
+
+void RotateImage::slotRotateImage90()
+{
+ m_view->rotateCurrentImage( M_PI/2);
+}
+
+void RotateImage::slotRotateImage180()
+{
+ m_view->rotateCurrentImage( M_PI );
+}
+
+
+void RotateImage::slotRotateImage270()
+{
+ m_view->rotateCurrentImage( - M_PI/2 + M_PI*2 );
+}
+
+void RotateImage::slotRotateLayer()
+{
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+
+ if (!image) return;
+
+ DlgRotateImage * dlgRotateImage = new DlgRotateImage(m_view, "RotateLayer");
+ Q_CHECK_PTR(dlgRotateImage);
+
+ dlgRotateImage->setCaption(i18n("Rotate Layer"));
+
+ if (dlgRotateImage->exec() == TQDialog::Accepted) {
+ double angle = dlgRotateImage->angle();
+ angle *= M_PI/180;
+ m_view->rotateLayer(angle);
+ }
+ delete dlgRotateImage;
+}
+
+#include "rotateimage.moc"
diff --git a/chalk/plugins/viewplugins/rotateimage/rotateimage.h b/chalk/plugins/viewplugins/rotateimage/rotateimage.h
new file mode 100644
index 00000000..6b262608
--- /dev/null
+++ b/chalk/plugins/viewplugins/rotateimage/rotateimage.h
@@ -0,0 +1,50 @@
+/*
+ * rotateimage.h -- Part of Chalk
+ *
+ * Copyright (c) 2004 Michael Thaler (michael.thaler@physik.tu-muenchen.de)
+ *
+ * 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 ROTATEIMAGE_H
+#define ROTATEIMAGE_H
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+class RotateImage : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ RotateImage(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~RotateImage();
+
+private slots:
+
+ void slotRotateImage();
+ void slotRotateImage90();
+ void slotRotateImage180();
+ void slotRotateImage270();
+ void slotRotateLayer();
+
+private:
+
+ KisView * m_view;
+ KisPainter * m_painter;
+
+};
+
+#endif // ROTATEIMAGE_H
diff --git a/chalk/plugins/viewplugins/rotateimage/rotateimage.rc b/chalk/plugins/viewplugins/rotateimage/rotateimage.rc
new file mode 100644
index 00000000..78ae6f4f
--- /dev/null
+++ b/chalk/plugins/viewplugins/rotateimage/rotateimage.rc
@@ -0,0 +1,25 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkrotateimage" version="7">
+<MenuBar>
+ <Menu name="Image"><text>&amp;Image</text>
+ <Menu name="Rotate"><text>&amp;Rotate</text>
+ <Action name="rotateimage"/>
+ <Separator />
+ <Action name="rotateImageCW90"/>
+ <Action name="rotateImageCCW90"/>
+ <Action name="rotateImage180"/>
+ </Menu>
+ </Menu>
+
+ <Menu name="Layer"><text>La&amp;yer</text>
+ <Menu name="Rotate"><text>&amp;Rotate</text>
+ <Action name="rotatelayer"/>
+ <Separator />
+ <Action name="rotateLayerCW90"/>
+ <Action name="rotateLayerCCW90"/>
+ <Action name="rotateLayer180"/>
+ </Menu>
+ </Menu>
+</MenuBar>
+
+</kpartgui>
diff --git a/chalk/plugins/viewplugins/rotateimage/wdg_rotateimage.ui b/chalk/plugins/viewplugins/rotateimage/wdg_rotateimage.ui
new file mode 100644
index 00000000..d58c458d
--- /dev/null
+++ b/chalk/plugins/viewplugins/rotateimage/wdg_rotateimage.ui
@@ -0,0 +1,245 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgRotateImage</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgRotateImage</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>489</width>
+ <height>447</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Rotate Image</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>grpDirection</cstring>
+ </property>
+ <property name="title">
+ <string>Direction</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>tqlayout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>pixmapLabel1</cstring>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>41</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>pixmapLabel2</cstring>
+ </property>
+ <property name="pixmap">
+ <pixmap>image1</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>false</bool>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>31</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="TQRadioButton" row="1" column="1">
+ <property name="name">
+ <cstring>radioCW</cstring>
+ </property>
+ <property name="text">
+ <string>C&amp;lockwise</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>radioCCW</cstring>
+ </property>
+ <property name="text">
+ <string>Cou&amp;nter-clockwise</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQButtonGroup" row="1" column="0">
+ <property name="name">
+ <cstring>grpAngle</cstring>
+ </property>
+ <property name="title">
+ <string>Angle</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQRadioButton">
+ <property name="name">
+ <cstring>radio90</cstring>
+ </property>
+ <property name="text">
+ <string>90 &amp;degrees</string>
+ </property>
+ </widget>
+ <widget class="TQRadioButton">
+ <property name="name">
+ <cstring>radio180</cstring>
+ </property>
+ <property name="text">
+ <string>180 d&amp;egrees</string>
+ </property>
+ </widget>
+ <widget class="TQRadioButton">
+ <property name="name">
+ <cstring>radio270</cstring>
+ </property>
+ <property name="text">
+ <string>270 de&amp;grees</string>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQRadioButton">
+ <property name="name">
+ <cstring>radioCustom</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Custom:</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="KDoubleSpinBox">
+ <property name="name">
+ <cstring>doubleCustom</cstring>
+ </property>
+ <property name="maxValue">
+ <number>360</number>
+ </property>
+ <property name="lineStep">
+ <number>1</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>91</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="371">89504e470d0a1a0a0000000d494844520000002c0000002e0806000000534cfb0a0000013a494441545885ed994b0ec330084487aaf7bf32dd5689297f9b489d6d24fc3c02db106266a445c460a67c205daf7404a2821ddb9503de0c0b64800fc00251e043b00040eea28bc21615a50fb8cad904bc1db8230d02e0671cbeca01ee2bbaaecbc16184bfe8a405b4cd58a00c86c48eb588d3cc54b1a9f8c5114d0f0d5c81ce5dcd999c0e42e71f3f5dd0826245572dc9d1c586f20e57a8ed1cdead85f373808d2ecf01366a16f0cae54b5acc0236e80fdcadc701bfc52f99c77ae35065edf0c1ae58d31d78302c302d870d9dcc2c6083e4a2bbaa7b3a694cc5bbc39bc6a626a5dec39dc5e888bd06965cee8076741b40a4e82aa103b164e0442b6ed2af183fd6d69b500dce5ba4c978b6aeb962cc5434aa3a3b6efd56794fd7793e3b62d74d2f23da3ef939f0bfa36e54557d9a48cb8c98ad39f4b8e7e5e3803f91a1a32701eeec170000000049454e44ae426082</data>
+ </image>
+ <image name="image1">
+ <data format="PNG" length="363">89504e470d0a1a0a0000000d494844520000002c0000002e0806000000534cfb0a00000132494441545885ed994b12032108449b54ee7f65b3cd5440f92a56a5f7326f5a11451a63608b8806c6a0689857068b5a446177f6020361e8fdc04008fa0c30e086a6b4a4f3ba664cc418704212013041fb80b340bfa5847e9b825680022687f549d70016d03aac815d7d988be1a87c6be015acb7dc3ac7cd8167b091734160acbc861bc2029e4a77101690f661c9dd840f46a577b8012cc00157edb749d239dcc45de0e4f1d2a927705235aad4e50e5fa03f70b56c0778ab227bba90ec7d1d167eb62f30c0423f81b9696856aa7b3bcc487fa7f3543ccb18e54cfe3adca914332ce7aff9c6d83cb0e47205b4f176634fba4c68472c1978b69633a09db7f2753330bb91128ca7eb5e56b5aaac316069b756573ce54cf5b8e65fd3d0769870e6c920305bfb1e659296541ef0265d77bcbc0ef803779f9c39421cd9b50000000049454e44ae426082</data>
+ </image>
+</images>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/viewplugins/screenshot/Makefile.am b/chalk/plugins/viewplugins/screenshot/Makefile.am
new file mode 100644
index 00000000..9887b7a2
--- /dev/null
+++ b/chalk/plugins/viewplugins/screenshot/Makefile.am
@@ -0,0 +1,27 @@
+chalkrcdir = $(kde_datadir)/chalkplugins
+chalkrc_DATA = screenshot-chalk.rc
+
+EXTRA_DIST = $(chalkrc_DATA)
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalkscreenshot.la
+
+chalkscreenshot_la_SOURCES = screenshot.cpp ksnapshot.cpp regiongrabber.cpp ksnapshotwidget.ui
+noinst_HEADERS = screenshot.h ksnapshot.h regiongrabber.h ksnapshotwidget.h ksnapshotwidget.ui.h
+
+chalkscreenshot_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui -lkdeprint
+chalkscreenshot_la_LIBADD = ../../../libchalkcommon.la
+
+kde_services_DATA = chalkscreenshot.desktop
+
+chalkscreenshot_la_METASOURCES = AUTO
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/kscreenshot_plugin.pot
diff --git a/chalk/plugins/viewplugins/screenshot/chalkscreenshot.desktop b/chalk/plugins/viewplugins/screenshot/chalkscreenshot.desktop
new file mode 100644
index 00000000..7b9b0d4b
--- /dev/null
+++ b/chalk/plugins/viewplugins/screenshot/chalkscreenshot.desktop
@@ -0,0 +1,47 @@
+[Desktop Entry]
+Name=Screenshot
+Name[bg]=Снимка на екрана
+Name[br]=Skrammpaker
+Name[ca]=Captura de pantalla
+Name[cy]=Sgrinlun
+Name[da]=Skærmaftryk
+Name[de]=Bildschirmphoto
+Name[el]=Στιγμιότυπο οθόνης
+Name[eo]=Ekrankopio
+Name[es]=Captura de pantalla
+Name[et]=Ekraanipilt
+Name[fa]=تصویر پرده
+Name[fr]=Capture d'écran
+Name[fy]=Skermôfbylding
+Name[ga]=Seat den Scáileán
+Name[gl]=Captura de Pantalla
+Name[he]=תמונת מסך
+Name[hu]=Képernyőfelvétel
+Name[is]=Skjámynd
+Name[it]=Schermata
+Name[ja]=スクリーンショット
+Name[km]=រូបថត​អេក្រង់
+Name[lv]=Ekrānattēls
+Name[nb]=Skjermbilde
+Name[nds]=Schirmbild
+Name[ne]=स्क्रिनसट
+Name[nl]=Schermafbeelding
+Name[pl]=Zrzut ekranu
+Name[pt]=Captura
+Name[pt_BR]=Captura de Tela
+Name[ru]=Снимок экрана
+Name[se]=Šearbmagovva
+Name[sk]=Snímač obrazovky
+Name[sl]=Posnetek zaslona
+Name[sr]=Снимак екрана
+Name[sr@Latn]=Snimak ekrana
+Name[sv]=Skärmdump
+Name[uk]=Знімок екрана
+Name[uz]=Skrinshot
+Name[uz@cyrillic]=Скриншот
+Name[zh_CN]=抓图
+Name[zh_TW]=螢幕快照
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalkscreenshot
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/screenshot/ksnapshot.cpp b/chalk/plugins/viewplugins/screenshot/ksnapshot.cpp
new file mode 100644
index 00000000..f9887821
--- /dev/null
+++ b/chalk/plugins/viewplugins/screenshot/ksnapshot.cpp
@@ -0,0 +1,499 @@
+/*
+ * KSnapshot
+ *
+ * (c) Richard J. Moore 1997-2002
+ * (c) Matthias Ettrich 2000
+ * (c) Aaron J. Seigo 2002
+ * (c) Nadeem Hasan 2003
+ * This adaptation: (c) Boudewijn Rempt 2005
+ *
+ * Released under the GPL see file LICENSE for details.
+ */
+
+#include <kapplication.h>
+#include <klocale.h>
+#include <kimageio.h>
+#include <kfiledialog.h>
+#include <kimagefilepreview.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <kprinter.h>
+#include <kio/netaccess.h>
+#include <ksavefile.h>
+#include <ktempfile.h>
+
+#include <tqbitmap.h>
+#include <tqdragobject.h>
+#include <tqimage.h>
+#include <tqclipboard.h>
+#include <tqvbox.h>
+
+#include <kaccel.h>
+#include <knotifyclient.h>
+#include <khelpmenu.h>
+#include <kpopupmenu.h>
+#include <kpushbutton.h>
+#include <kstartupinfo.h>
+
+#include <tqcursor.h>
+#include <tqregexp.h>
+#include <tqpainter.h>
+#include <tqpaintdevicemetrics.h>
+#include <tqwhatsthis.h>
+
+#include <stdlib.h>
+
+#include "ksnapshot.h"
+#include "regiongrabber.h"
+#include "ksnapshotwidget.h"
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#include <config.h>
+
+#ifdef HAVE_X11_EXTENSIONS_SHAPE_H
+#include <X11/extensions/shape.h>
+#endif
+
+#include <kglobal.h>
+
+KSnapshot::KSnapshot(TQWidget *tqparent, const char *name)
+ : super(tqparent, name, false, TQString(), Ok|Cancel)
+{
+ grabber = new TQWidget( 0, 0, WStyle_Customize | WX11BypassWM );
+ Q_CHECK_PTR(grabber);
+ grabber->move( -1000, -1000 );
+ grabber->installEventFilter( this );
+
+#ifdef HAVE_X11_EXTENSIONS_SHAPE_H
+ int tmp1, tmp2;
+ //Check whether the extension is available
+ haveXShape = XShapeQueryExtension( qt_xdisplay(), &tmp1, &tmp2 );
+#endif
+
+ TQVBox *vbox = makeVBoxMainWidget();
+ mainWidget = new KSnapshotWidget( vbox, "mainWidget" );
+ Q_CHECK_PTR(mainWidget);
+
+ mainWidget->btnSave->hide();
+ mainWidget->btnPrint->hide();
+ connect(mainWidget, TQT_SIGNAL(startImageDrag()), TQT_SLOT(slotDragSnapshot()));
+
+ connect( mainWidget, TQT_SIGNAL( newClicked() ), TQT_SLOT( slotGrab() ) );
+ connect( mainWidget, TQT_SIGNAL( printClicked() ), TQT_SLOT( slotPrint() ) );
+
+ grabber->show();
+ grabber->grabMouse( waitCursor );
+
+ snapshot = TQPixmap::grabWindow( qt_xrootwin() );
+ updatePreview();
+ grabber->releaseMouse();
+ grabber->hide();
+
+ KConfig *conf=KGlobal::config();
+ conf->setGroup("GENERAL");
+ mainWidget->setDelay(conf->readNumEntry("delay",0));
+ mainWidget->setMode( conf->readNumEntry( "mode", 0 ) );
+ mainWidget->setIncludeDecorations(conf->readBoolEntry("includeDecorations",true));
+
+ connect( &grabTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( grabTimerDone() ) );
+
+ KAccel* accel = new KAccel(this);
+ Q_CHECK_PTR(accel);
+ accel->insert(KStdAccel::Print, TQT_TQOBJECT(this), TQT_SLOT(slotPrint()));
+ accel->insert(KStdAccel::New, TQT_TQOBJECT(this), TQT_SLOT(slotGrab()));
+
+ accel->insert( "Print2", TQt::Key_P, TQT_TQOBJECT(this), TQT_SLOT(slotPrint()));
+ accel->insert( "New2", TQt::Key_N, TQT_TQOBJECT(this), TQT_SLOT(slotGrab()));
+ accel->insert( "New3", TQt::Key_Space, TQT_TQOBJECT(this), TQT_SLOT(slotGrab()));
+
+ mainWidget->btnNew->setFocus();
+
+}
+
+KSnapshot::~KSnapshot()
+{
+}
+
+bool KSnapshot::save( const TQString &filename )
+{
+ return save( KURL::fromPathOrURL( filename ));
+}
+
+bool KSnapshot::save( const KURL& url )
+{
+ TQString type( KImageIO::type(url.path()) );
+ if ( type.isNull() )
+ type = "PNG";
+
+ bool ok = false;
+
+ if ( url.isLocalFile() ) {
+ KSaveFile saveFile( url.path() );
+ if ( saveFile.status() == 0 ) {
+ if ( snapshot.save( saveFile.file(), type.latin1() ) )
+ ok = saveFile.close();
+ }
+ }
+ else {
+ KTempFile tmpFile;
+ tmpFile.setAutoDelete( true );
+ if ( tmpFile.status() == 0 ) {
+ if ( snapshot.save( tmpFile.file(), type.latin1() ) ) {
+ if ( tmpFile.close() )
+ ok = KIO::NetAccess::upload( tmpFile.name(), url, this );
+ }
+ }
+ }
+
+ TQApplication::restoreOverrideCursor();
+ if ( !ok ) {
+ kdWarning() << "KSnapshot was unable to save the snapshot" << endl;
+
+ TQString caption = i18n("Unable to Save Image");
+ TQString text = i18n("KSnapshot was unable to save the image to\n%1.")
+ .tqarg(url.prettyURL());
+ KMessageBox::error(this, text, caption);
+ }
+
+ return ok;
+}
+
+void KSnapshot::slotCopy()
+{
+ TQClipboard *cb = TQApplication::tqclipboard();
+ cb->setPixmap( snapshot );
+}
+
+void KSnapshot::slotDragSnapshot()
+{
+ TQDragObject *drobj = new TQImageDrag(snapshot.convertToImage(), this);
+ Q_CHECK_PTR(drobj);
+ drobj->setPixmap(mainWidget->preview());
+ drobj->dragCopy();
+}
+
+void KSnapshot::slotGrab()
+{
+ hide();
+ if ( mainWidget->mode() == Region )
+ {
+ rgnGrab = new RegionGrabber();
+ Q_CHECK_PTR(rgnGrab);
+ connect( rgnGrab, TQT_SIGNAL( regionGrabbed( const TQPixmap & ) ),
+ TQT_SLOT( slotRegionGrabbed( const TQPixmap & ) ) );
+ }
+ else
+ {
+ if ( mainWidget->delay() )
+ grabTimer.start( mainWidget->delay() * 1000, true );
+ else {
+ grabber->show();
+ grabber->grabMouse( crossCursor );
+ }
+ }
+}
+
+void KSnapshot::slotPrint()
+{
+ KPrinter printer;
+ if (snapshot.width() > snapshot.height())
+ printer.setOrientation(KPrinter::Landscape);
+ else
+ printer.setOrientation(KPrinter::Portrait);
+
+ tqApp->processEvents();
+
+ if (printer.setup(this, i18n("Print Screenshot")))
+ {
+ tqApp->processEvents();
+
+ TQPainter painter(&printer);
+ TQPaintDeviceMetrics metrics(painter.device());
+
+ float w = snapshot.width();
+ float dw = w - metrics.width();
+ float h = snapshot.height();
+ float dh = h - metrics.height();
+ bool scale = false;
+
+ if ( (dw > 0.0) || (dh > 0.0) )
+ scale = true;
+
+ if ( scale ) {
+
+ TQImage img = snapshot.convertToImage();
+ tqApp->processEvents();
+
+ float newh, neww;
+ if ( dw > dh ) {
+ neww = w-dw;
+ newh = neww/w*h;
+ }
+ else {
+ newh = h-dh;
+ neww = newh/h*w;
+ }
+
+ img = img.smoothScale( int(neww), int(newh), TQ_ScaleMin );
+ tqApp->processEvents();
+
+ int x = (metrics.width()-img.width())/2;
+ int y = (metrics.height()-img.height())/2;
+
+ painter.drawImage( x, y, img);
+ }
+ else {
+ int x = (metrics.width()-snapshot.width())/2;
+ int y = (metrics.height()-snapshot.height())/2;
+ painter.drawPixmap( x, y, snapshot );
+ }
+ }
+
+ tqApp->processEvents();
+}
+
+void KSnapshot::slotRegionGrabbed( const TQPixmap &pix )
+{
+ if ( !pix.isNull() )
+ {
+ snapshot = pix;
+ updatePreview();
+ modified = true;
+ }
+
+ delete rgnGrab;
+ TQApplication::restoreOverrideCursor();
+ show();
+}
+
+bool KSnapshot::eventFilter( TQObject* o, TQEvent* e)
+{
+ if ( TQT_BASE_OBJECT(o) == TQT_BASE_OBJECT(grabber) && e->type() == TQEvent::MouseButtonPress ) {
+ TQMouseEvent* me = (TQMouseEvent*) e;
+ if ( TQWidget::mouseGrabber() != grabber )
+ return false;
+ if ( me->button() == Qt::LeftButton )
+ performGrab();
+ }
+ return false;
+}
+
+void KSnapshot::updatePreview()
+{
+ TQImage img = snapshot.convertToImage();
+ double r1 = ((double) snapshot.height() ) / snapshot.width();
+ if ( r1 * mainWidget->previewWidth() < mainWidget->previewHeight() )
+ img = img.smoothScale( mainWidget->previewWidth(),
+ int( mainWidget->previewWidth() * r1 ));
+ else
+ img = img.smoothScale( (int) (((double)mainWidget->previewHeight()) / r1),
+ (mainWidget->previewHeight() ) );
+
+ TQPixmap pm;
+ pm.convertFromImage( img );
+ mainWidget->setPreview( pm );
+}
+
+void KSnapshot::grabTimerDone()
+{
+ performGrab();
+ KNotifyClient::beep(i18n("The screen has been successfully grabbed."));
+}
+
+static
+Window findRealWindow( Window w, int depth = 0 )
+{
+ if( depth > 5 )
+ return None;
+ static Atom wm_state = XInternAtom( qt_xdisplay(), "WM_STATE", False );
+ Atom type;
+ int format;
+ unsigned long nitems, after;
+ unsigned char* prop;
+ if( XGetWindowProperty( qt_xdisplay(), w, wm_state, 0, 0, False, AnyPropertyType,
+ &type, &format, &nitems, &after, &prop ) == Success ) {
+ if( prop != NULL )
+ XFree( prop );
+ if( type != None )
+ return w;
+ }
+ Window root, tqparent;
+ Window* tqchildren;
+ unsigned int ntqchildren;
+ Window ret = None;
+ if( XQueryTree( qt_xdisplay(), w, &root, &tqparent, &tqchildren, &ntqchildren ) != 0 ) {
+ for( unsigned int i = 0;
+ i < ntqchildren && ret == None;
+ ++i )
+ ret = findRealWindow( tqchildren[ i ], depth + 1 );
+ if( tqchildren != NULL )
+ XFree( tqchildren );
+ }
+ return ret;
+}
+
+void KSnapshot::performGrab()
+{
+ grabber->releaseMouse();
+ grabber->hide();
+ grabTimer.stop();
+ XGrabServer( qt_xdisplay());
+ if ( mainWidget->mode() == WindowUnderCursor ) {
+ Window root;
+ Window child;
+ uint tqmask;
+ int rootX, rootY, winX, winY;
+ XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child,
+ &rootX, &rootY, &winX, &winY,
+ &tqmask);
+ if( child == None )
+ child = qt_xrootwin();
+ if( !mainWidget->includeDecorations()) {
+ Window real_child = findRealWindow( child );
+ if( real_child != None ) // test just in case
+ child = real_child;
+ }
+ int x, y;
+ unsigned int w, h;
+ unsigned int border;
+ unsigned int depth;
+ XGetGeometry( qt_xdisplay(), child, &root, &x, &y,
+ &w, &h, &border, &depth );
+ w += 2 * border;
+ h += 2 * border;
+
+ Window tqparent;
+ Window* tqchildren;
+ unsigned int ntqchildren;
+ if( XQueryTree( qt_xdisplay(), child, &root, &tqparent,
+ &tqchildren, &ntqchildren ) != 0 ) {
+ if( tqchildren != NULL )
+ XFree( tqchildren );
+ int newx, newy;
+ Window dummy;
+ if( XTranslateCoordinates( qt_xdisplay(), tqparent, qt_xrootwin(),
+ x, y, &newx, &newy, &dummy )) {
+ x = newx;
+ y = newy;
+ }
+ }
+
+ snapshot = TQPixmap::grabWindow( qt_xrootwin(), x, y, w, h );
+
+#ifdef HAVE_X11_EXTENSIONS_SHAPE_H
+ //No XShape - no work.
+ if (haveXShape) {
+ TQBitmap tqmask(w, h);
+ //As the first step, get the tqmask from XShape.
+ int count, order;
+ XRectangle* rects = XShapeGetRectangles( qt_xdisplay(), child,
+ ShapeBounding, &count, &order);
+ //The ShapeBounding region is the outermost tqshape of the window;
+ //ShapeBounding - ShapeClipping is defined to be the border.
+ //Since the border area is part of the window, we use bounding
+ // to limit our work region
+ if (rects) {
+ //Create a TQRegion from the rectangles describing the bounding tqmask.
+ TQRegion contents;
+ for (int pos = 0; pos < count; pos++)
+ contents += TQRegion(rects[pos].x, rects[pos].y,
+ rects[pos].width, rects[pos].height);
+ XFree(rects);
+
+ //Create the bounding box.
+ TQRegion bbox(0, 0, snapshot.width(), snapshot.height());
+
+ if( border > 0 ) {
+ contents.translate( border, border );
+ contents += TQRegion( 0, 0, border, h );
+ contents += TQRegion( 0, 0, w, border );
+ contents += TQRegion( 0, h - border, w, border );
+ contents += TQRegion( w - border, 0, border, h );
+ }
+
+ //Get the tqmasked away area.
+ TQRegion tqmaskedAway = bbox - contents;
+ TQMemArray<TQRect> tqmaskedAwayRects = tqmaskedAway.rects();
+
+ //Construct a bitmap tqmask from the rectangles
+ TQPainter p(&tqmask);
+ p.fillRect(0, 0, w, h, TQt::color1);
+ for (uint pos = 0; pos < tqmaskedAwayRects.count(); pos++)
+ p.fillRect(tqmaskedAwayRects[pos], TQt::color0);
+ p.end();
+
+ snapshot.setMask(tqmask);
+ }
+ }
+#endif
+ }
+ else {
+ snapshot = TQPixmap::grabWindow( qt_xrootwin() );
+ }
+ XUngrabServer( qt_xdisplay());
+ updatePreview();
+ TQApplication::restoreOverrideCursor();
+ modified = true;
+// show();
+ slotOk();
+}
+
+void KSnapshot::setTime(int newTime)
+{
+ mainWidget->setDelay(newTime);
+}
+
+void KSnapshot::setURL( const TQString &url )
+{
+ KURL newURL = KURL::fromPathOrURL( url );
+ if ( newURL == filename )
+ return;
+
+ filename = newURL;
+}
+
+void KSnapshot::setGrabMode( int m )
+{
+ mainWidget->setMode( m );
+}
+
+void KSnapshot::slotMovePointer(int x, int y)
+{
+ TQCursor::setPos( x, y );
+}
+
+void KSnapshot::exit()
+{
+
+ KConfig *conf=KGlobal::config();
+ conf->setGroup("GENERAL");
+ conf->writeEntry("delay",mainWidget->delay());
+ conf->writeEntry("mode",mainWidget->mode());
+ conf->writeEntry("includeDecorations",mainWidget->includeDecorations());
+ KURL url = filename;
+ url.setPass( TQString() );
+ conf->writePathEntry("filename",url.url());
+
+ reject();
+}
+
+void KSnapshot::slotOk()
+{
+
+ KConfig *conf=KGlobal::config();
+ conf->setGroup("GENERAL");
+ conf->writeEntry("delay",mainWidget->delay());
+ conf->writeEntry("mode",mainWidget->mode());
+ conf->writeEntry("includeDecorations",mainWidget->includeDecorations());
+ KURL url = filename;
+ url.setPass( TQString() );
+ conf->writePathEntry("filename",url.url());
+
+ emit screenGrabbed();
+
+ accept();
+}
+
+#include "ksnapshot.moc"
diff --git a/chalk/plugins/viewplugins/screenshot/ksnapshot.h b/chalk/plugins/viewplugins/screenshot/ksnapshot.h
new file mode 100644
index 00000000..030cad12
--- /dev/null
+++ b/chalk/plugins/viewplugins/screenshot/ksnapshot.h
@@ -0,0 +1,137 @@
+// -*- c++ -*-
+/*
+ * (c) Richard J. Moore 1997-2002
+ * (c) Matthias Ettrich 2000
+ * (c) Aaron J. Seigo 2002
+ * (c) Nadeem Hasan 2003
+ *
+ * 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 KSNAPSHOT_H
+#define KSNAPSHOT_H
+
+#include <tqlabel.h>
+#include <tqpixmap.h>
+#include <tqtimer.h>
+
+#include <dcopclient.h>
+#include <kglobalsettings.h>
+#include <kdialogbase.h>
+#include <kurl.h>
+
+class RegionGrabber;
+class KSnapshotWidget;
+
+class KSnapshotThumb : public TQLabel
+{
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KSnapshotThumb(TQWidget *tqparent, const char *name = 0)
+ : TQLabel(tqparent, name)
+ {
+ tqsetAlignment(AlignHCenter | AlignVCenter);
+ }
+ virtual ~KSnapshotThumb() {}
+
+signals:
+ void startDrag();
+
+protected:
+ void mousePressEvent(TQMouseEvent * e)
+ {
+ mClickPt = e->pos();
+ }
+
+ void mouseMoveEvent(TQMouseEvent * e)
+ {
+ if (mClickPt != TQPoint(0, 0) &&
+ (e->pos() - mClickPt).manhattanLength() > KGlobalSettings::dndEventDelay())
+ {
+ mClickPt = TQPoint(0, 0);
+ emit startDrag();
+ }
+ }
+
+ void mouseReleaseEvent(TQMouseEvent * /*e*/)
+ {
+ mClickPt = TQPoint(0, 0);
+ }
+
+ TQPoint mClickPt;
+};
+
+class KSnapshot : public KDialogBase
+{
+ typedef KDialogBase super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ KSnapshot(TQWidget *tqparent= 0, const char *name= 0);
+ ~KSnapshot();
+
+ enum CaptureMode { FullScreen=0, WindowUnderCursor=1, Region=2 };
+
+ bool save( const TQString &filename );
+ bool save( const KURL& url );
+
+ TQString url() const { return filename.url(); }
+
+signals:
+ void screenGrabbed();
+
+protected slots:
+ void slotGrab();
+ void slotCopy();
+ void slotPrint();
+ void slotMovePointer( int x, int y );
+
+ void setTime(int newTime);
+ void setURL(const TQString &newURL);
+ void setGrabMode( int m );
+ void exit();
+
+ void slotOk();
+
+
+protected:
+ void reject() { close(); }
+ bool eventFilter( TQObject*, TQEvent* );
+
+private slots:
+ void grabTimerDone();
+ void slotDragSnapshot();
+ void slotRegionGrabbed( const TQPixmap & );
+
+private:
+ void updatePreview();
+ void performGrab();
+ void autoincFilename();
+
+ TQPixmap snapshot;
+ TQTimer grabTimer;
+ TQWidget* grabber;
+ KURL filename;
+ KSnapshotWidget *mainWidget;
+ RegionGrabber *rgnGrab;
+ bool modified;
+ bool haveXShape;
+};
+
+#endif // KSNAPSHOT_H
+
diff --git a/chalk/plugins/viewplugins/screenshot/ksnapshotwidget.ui b/chalk/plugins/viewplugins/screenshot/ksnapshotwidget.ui
new file mode 100644
index 00000000..0672215e
--- /dev/null
+++ b/chalk/plugins/viewplugins/screenshot/ksnapshotwidget.ui
@@ -0,0 +1,335 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>KSnapshotWidget</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>KSnapshotWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>358</width>
+ <height>241</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="KSnapshotThumb" row="0" column="0" rowspan="4" colspan="3">
+ <property name="name">
+ <cstring>lblImage</cstring>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>200</width>
+ <height>130</height>
+ </size>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Thumbnail of the current snapshot</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is a thumbnail of the current snapshot.
+
+The image can be dragged to another application or document to copy the full screenshot there. Try it with the Konqueror file manager.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="0" column="3">
+ <property name="name">
+ <cstring>btnNew</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;New Snapshot</string>
+ </property>
+ <property name="iconSet">
+ <iconset>"tool_screenshot"</iconset>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click this button to take a new snapshot.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="2" column="3">
+ <property name="name">
+ <cstring>btnSave</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Save As...</string>
+ </property>
+ <property name="iconSet">
+ <iconset>"filesave"</iconset>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click this button to save the current snapshot. To quickly save the snapshot without showing the file dialog, press Ctrl+Shift+S. The filename is automatically incremented after each save.</string>
+ </property>
+ </widget>
+ <spacer row="1" column="3">
+ <property name="name">
+ <cstring>Spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KPushButton" row="3" column="3">
+ <property name="name">
+ <cstring>btnPrint</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Print...</string>
+ </property>
+ <property name="iconSet">
+ <iconset>"fileprint"</iconset>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click this button to print the current screenshot.</string>
+ </property>
+ </widget>
+ <widget class="Line" row="4" column="0" rowspan="1" colspan="4">
+ <property name="name">
+ <cstring>line1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="TQSpinBox" row="6" column="1">
+ <property name="name">
+ <cstring>spinDelay</cstring>
+ </property>
+ <property name="suffix">
+ <string> sec</string>
+ </property>
+ <property name="specialValueText">
+ <string>No delay</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Snapshot delay in seconds</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;
+This is the number of seconds to wait after clicking the &lt;i&gt;New Snapshot&lt;/i&gt; button before taking the snapshot.
+&lt;p&gt;
+This is very useful for getting windows, menus and other items on the screen set up just the way you want.
+&lt;p&gt;
+If &lt;i&gt;no delay&lt;/i&gt; is set, the program will wait for a mouse click before taking a snapshot.
+&lt;/p&gt;
+&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="6" column="0">
+ <property name="name">
+ <cstring>lblDelay</cstring>
+ </property>
+ <property name="text">
+ <string>Snapshot &amp;delay:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>spinDelay</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="5" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Cap&amp;ture mode:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>comboMode</cstring>
+ </property>
+ </widget>
+ <spacer row="6" column="2" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>156</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQCheckBox" row="7" column="0" rowspan="1" colspan="4">
+ <property name="name">
+ <cstring>cbIncludeDecorations</cstring>
+ </property>
+ <property name="text">
+ <string>Include &amp;window decorations</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When enabled, snapshot of a window will also include the window decorations</string>
+ </property>
+ </widget>
+ <widget class="TQComboBox" row="5" column="1" rowspan="1" colspan="3">
+ <item>
+ <property name="text">
+ <string>Full Screen</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Window Under Cursor</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Region</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>comboMode</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Using this menu, you can select from the three following snapshot modes:
+&lt;p&gt;
+&lt;b&gt;Full Screen&lt;/b&gt; - captures the entire desktop.&lt;br&gt;
+&lt;b&gt;Window Under Cursor&lt;/b&gt; - captures only the window (or menu) that is under the mouse cursor when the snapshot is taken.&lt;br&gt;
+&lt;b&gt;Region&lt;/b&gt; - captures only the region of the desktop that you specify. When taking a new snapshot in this mode you will be able to select any area of the screen by clicking and dragging the mouse.&lt;/p&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <spacer row="8" column="1">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>31</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KSnapshotThumb</class>
+ <header location="local">ksnapshot.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ <signal>startDrag()</signal>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="XPM.GZ" length="5230">789c9597db4e1d4b0e86eff31428be8b46b5fb54dd551acd051020211c4320c0682eecaa5e9ccf90005bf3ee53cbbfe9d9c9c548a38ea27c2977b5cbfe6dd7fae3c3c2e1cee6c2873fde3d3cf2e3595a48a77cbff0213f5d5dbdfcf35ffff8f3ddfba65998fff161a179ffb777ef771f17d2c2d6cdf53807c705a889cdac6ee72c47736eebd637b5f2b672d70ecd30e744ca7d9b9a4ad7579587363433e527e5d072abefbb03636978ceb4a31c5bc13a91716ad41f89e0aec2fe74abcc6d6ad5f9e4945357375ef75f997357751dd61d19c71afb61bdef421b951f274ebaffb6716cb3f2b2f230f18d3183dd95b1b441d7d59f2e94757ccf1b27eceff69563618d0f5dcfd9d7beeb7a5dd7f3fac6fb4ee32b87c619f1168d976f7d6ff6df26d6ef4b301e1bac7f54f63e747a5e87f5c173276aff605c22a8fefc540e5e3af5972f956359577bf2c6d978cb78d6697edc9eb2f8b143fed7945359d778b0e6c3e7be81bf7465dce23cf4ac3c16567f19fecefaae53bd081b7baccbb131b7d05f679ca03f27c6b9d1f388c6bbaffab7f80dca4d1fed7bfafdbeedb9533d490f1e2ae8d5693ccacb83d77cd027e3d4416faa97beefa3d7f8f086f168f9d9020f43a3f5c5aa877e28eb88f74fe319becfaa873e0c15de775f95639f3dec37c143d361bf2be3cef4b76bdcb7d84ff5d2cbd0227facf1ecd360fa67d54b9f078ffcd10f636e11ff53e3847853ad3c1b668837e9fe43358c2df45a81430b3db2e6676842d368fd48abdc068b87e0fd2e788bf792b21f861e7afd0e0e5ce37dcdd7d0872218e5d789f57b3218a71ae7bb501eca3af67b510e21c05fd27a1b6218ac3ef17d0ed68fe8cb1be3fc6e5159863ca0bfed824340fe687d62c4838c23f677f0370de380fcdd2be7e03dfab1d6cf300bcd80fa80bfb358dbf9547fa18abe413d68fe421d63ade7737aded094cf63fdcc38f4d0bfee17dac2d08380a3a0dff24cb90bdc23ffaa87e0636c912fed87612e38d4df1e982bc4dbdd29872001f14aca319413eb793e83cbfbe8af27606e4c0f5f8d3bcb7763ec6b8da73b57e69083d61f9d82b9b5fada31f635fcaf8d7b7b5ffb41f16e34ff34fe214dfc0c8e1ef1a22330bfcdc345e31e4c33e3c1e6e181b1609e3ac43f8759803e8cd9f2e7e0ff18ab80ef5d8239e2fc0ef129f90ff0bf0773347fee8d13ce279bc6b34af5c61abf58157bf4b765b05435f4abfec726968c2b67e536fa80fe388279067f680d2c750dff75fe9766da07e44bc02521ba4e1d584c1fb261dcc23fd97f63f8c3af136bfc687362c4e76962ed8fac7a2ecdb7853f7c63ec6bf467bd3fc421c680780c60b6f9275fc045aea84fadaf18a2e0fc04ff0237bd9e8fefc0d236e8ef3f8d83c57fdd38daf94edeb886be74fec618b3ed7f3731e66b0fe67a403e76c0454ef8de9231dbfe9f8dc5fc47be38a6887ad2f950964d2fdc1a27d3c7b6710693f6ef9864b4fdb4ffc6cc5540fea0972c339c87afc1c9f4443a5fe2c84d40bd2f82cb3ae6c7b1716dbc37b1e68bf5be118b7e3dead78125d87d0bfa99bd7d8fb78c1bdb4fcfcfd51bcb9d716bebda3fb8966cf7cf57709103f2e327c6fe5a2fdc4ab4fb01deef5283fa65d50ffb54c13fd67ec37d61e845fb070f8571df7c341eec7e7a691c6ae453fb771937d1fa999ebfa43358bf573d3327c6fdd0a9de59b87414e59f60911ef3ff07380d16bf0b63b6fbb8ce0f4e523a80ee8ff8a5f21fe83f384f2e8cf9d419db7d4bb4bff32cb1dd871ae38c79417962dd9f8f2786bfaa3fa992ddbf68d5d8d6797d62dc27b4bf4a9bdeee5be7c619efbb169c2b9bb7aa67e972857a67d59bf8943cf4a6f5237dae3b9c3f4f8cef5713637e6a3c6548e546a7eb87e0b28e7cf7c68ddd2fb15f28acf166bd2f484c19f921f8cbc57de84ff52c397b8f7e178d7bbb7f7e9f18f743d593ccd210d12f9e8c05fd8417c1e5e704e2afefa7aa5cf850ff4fc6a1473debfc4d7561c4ebd3c48897f69fd4e4d8eb7e4efb736a0b23fe9adfd465bb3f388d6ff22933fa1df6f7597ad483c62371f6e6ff8671b6f89e198fb8cfb0ea3f49619c6f6562cc27d5474a7906e6b589d1df549f29e78479450fe0b1c2fc67d5731a0ba33ffc97a167fd7d92ebb1b1f9a87acdcdd8a23ff2e3c4a81fed0fb91bbb88f8e9f772f9b9c6b8bfac187bd41febbcc8c35831f4bb6edc227eeec8b847bc58ef0f398d91a1179d6f391746bdebfd60ac4716b0180bd8a97e473f8ea2dfdb7d9c3f8e1cff8f8760057b27e57f92cb6e743377e24efff29cb97377e12edd55b190c99eddb5bb71b7eeceddbb07f7e89edc0ff7d33dbb17f7ea16dd925b761fdd8a63d8174f52b15e756bee93fbecd6dd17b7e136dd96db763b6ed77d2dd67bee9bdb77078ed49e8b27b7c5fabb3b7447eed855ae768d6bcbd339ef7a37b8e022392a2734fbd1dd119350a24c23cde8844ee98ccee9c2f9c2977445d77443b793fd8ceee89e1ee8919ee807fdb4e7995ee8b5d82fd252b15ffe8bfd097da4155aa535fa34597fa6f5f2f717da28f69bb445dbb433d99fd22e7da53dfa3659efd3017da7c3f2af233aa68aeadfec1b6aa9236fd63d0d14ca15c0719913737b965fedcbf0c83cc29a677cc2a77cc6e77cc1977cc5d7c5fee637fbdbb2db9d5adff343b17ee427fec1737ee69762fffa9bfd222ff17259fdc82bbcca6bfc893ff33a7fe10ddee42ddee69ddfec77f92beff137dee703fece877cc4c7aee58a6b6ee8b8fc10ed7eb13f635f9a4bc5e54719477152ba671977a505c84845c57222a7bfd89fcb999ccb855cca955cbfc5546ee456ee68b14cf67b799047799aec2fdc92fc28999cef567224cff222afb2c85b32e36d599265f9282bb23ad95fba6559934f2593f3e798b74acc8fd5f6b3accb17d9904dd9926db3a7520d1fdd37d9915df95a72599e1291566df7e49beccb817c974339829eb55e56dc7e51ec0d2dcbb1545297a791563af1c5eff2d3beb4faf8562f568f0744745b9e9d5f1f7992d5e412a186ffef7afff7dfdffd077c99ae99</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>comboMode</sender>
+ <signal>activated(int)</signal>
+ <receiver>KSnapshotWidget</receiver>
+ <slot>slotModeChanged(int)</slot>
+ </connection>
+ <connection>
+ <sender>btnNew</sender>
+ <signal>clicked()</signal>
+ <receiver>KSnapshotWidget</receiver>
+ <slot>slotNewClicked()</slot>
+ </connection>
+ <connection>
+ <sender>btnPrint</sender>
+ <signal>clicked()</signal>
+ <receiver>KSnapshotWidget</receiver>
+ <slot>slotPrintClicked()</slot>
+ </connection>
+ <connection>
+ <sender>btnSave</sender>
+ <signal>clicked()</signal>
+ <receiver>KSnapshotWidget</receiver>
+ <slot>slotSaveClicked()</slot>
+ </connection>
+ <connection>
+ <sender>lblImage</sender>
+ <signal>startDrag()</signal>
+ <receiver>KSnapshotWidget</receiver>
+ <slot>slotStartDrag()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>btnNew</tabstop>
+ <tabstop>btnSave</tabstop>
+ <tabstop>btnPrint</tabstop>
+ <tabstop>comboMode</tabstop>
+ <tabstop>spinDelay</tabstop>
+ <tabstop>cbIncludeDecorations</tabstop>
+</tabstops>
+<includes>
+ <include location="global" impldecl="in implementation">kdialog.h</include>
+ <include location="global" impldecl="in implementation">kiconloader.h</include>
+ <include location="global" impldecl="in implementation">kglobalsettings.h</include>
+ <include location="local" impldecl="in implementation">ksnapshotwidget.ui.h</include>
+</includes>
+<Q_SIGNALS>
+ <signal>newClicked()</signal>
+ <signal>saveClicked()</signal>
+ <signal>printClicked()</signal>
+ <signal>startImageDrag()</signal>
+</Q_SIGNALS>
+<Q_SLOTS>
+ <slot access="protected" specifier="non virtual">slotModeChanged( int mode )</slot>
+ <slot access="protected" specifier="non virtual">slotNewClicked()</slot>
+ <slot access="protected" specifier="non virtual">slotSaveClicked()</slot>
+ <slot access="protected" specifier="non virtual">slotPrintClicked()</slot>
+ <slot access="protected" specifier="non virtual">slotStartDrag()</slot>
+ <slot specifier="non virtual" returnType="int">previewWidth()</slot>
+ <slot specifier="non virtual" returnType="int">previewHeight()</slot>
+</Q_SLOTS>
+<functions>
+ <function specifier="non virtual">setPreview( const TQPixmap &amp; pm )</function>
+ <function specifier="non virtual">setDelay( int i )</function>
+ <function specifier="non virtual">setIncludeDecorations( bool b )</function>
+ <function specifier="non virtual">setMode( int mode )</function>
+ <function specifier="non virtual" returnType="int">delay()</function>
+ <function specifier="non virtual" returnType="bool">includeDecorations()</function>
+ <function specifier="non virtual" returnType="int">mode()</function>
+ <function specifier="non virtual" returnType="TQPixmap">preview()</function>
+</functions>
+<pixmapfunction>SmallIconSet</pixmapfunction>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<tqlayoutfunctions spacing="KDialog::spacingHint" margin="KDialog::marginHint"/>
+</UI>
diff --git a/chalk/plugins/viewplugins/screenshot/ksnapshotwidget.ui.h b/chalk/plugins/viewplugins/screenshot/ksnapshotwidget.ui.h
new file mode 100644
index 00000000..3c552868
--- /dev/null
+++ b/chalk/plugins/viewplugins/screenshot/ksnapshotwidget.ui.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** TQt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+
+void KSnapshotWidget::slotModeChanged( int mode )
+{
+ switch ( mode )
+ {
+ case 0:
+ lblDelay->setEnabled(true);
+ spinDelay->setEnabled(true);
+ cbIncludeDecorations->setEnabled(false);
+ break;
+ case 1:
+ lblDelay->setEnabled(true);
+ spinDelay->setEnabled(true);
+ cbIncludeDecorations->setEnabled(true);
+ break;
+ case 2:
+ lblDelay->setEnabled(false);
+ spinDelay->setEnabled(false);
+ cbIncludeDecorations->setEnabled(false);
+ default:
+ break;
+ }
+}
+
+
+void KSnapshotWidget::setPreview( const TQPixmap &pm )
+{
+ lblImage->setPixmap(pm);
+}
+
+
+void KSnapshotWidget::setDelay( int i )
+{
+ spinDelay->setValue(i);
+}
+
+
+void KSnapshotWidget::setIncludeDecorations( bool b )
+{
+ cbIncludeDecorations->setChecked(b);
+}
+
+
+void KSnapshotWidget::setMode( int mode )
+{
+ comboMode->setCurrentItem(mode);
+ slotModeChanged(mode);
+}
+
+
+int KSnapshotWidget::delay()
+{
+ return spinDelay->value();
+}
+
+
+bool KSnapshotWidget::includeDecorations()
+{
+ return cbIncludeDecorations->isChecked();
+}
+
+
+int KSnapshotWidget::mode()
+{
+ return comboMode->currentItem();
+}
+
+
+void KSnapshotWidget::slotNewClicked()
+{
+ emit newClicked();
+}
+
+
+void KSnapshotWidget::slotSaveClicked()
+{
+ emit saveClicked();
+}
+
+
+void KSnapshotWidget::slotPrintClicked()
+{
+ emit printClicked();
+}
+
+
+void KSnapshotWidget::slotStartDrag()
+{
+ emit startImageDrag();
+}
+
+
+TQPixmap KSnapshotWidget::preview()
+{
+ return *lblImage->pixmap();
+}
+
+
+int KSnapshotWidget::previewWidth()
+{
+ return lblImage->width();
+}
+
+
+int KSnapshotWidget::previewHeight()
+{
+ return lblImage->height();
+}
+
diff --git a/chalk/plugins/viewplugins/screenshot/main.cpp b/chalk/plugins/viewplugins/screenshot/main.cpp
new file mode 100644
index 00000000..70f61349
--- /dev/null
+++ b/chalk/plugins/viewplugins/screenshot/main.cpp
@@ -0,0 +1,38 @@
+#include <kapplication.h>
+#include "ksnapshot.h"
+#include <kimageio.h>
+#include <klocale.h>
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <kiconloader.h>
+
+static const char description[] =
+ I18N_NOOP("KDE Screenshot Utility");
+
+int main(int argc, char **argv)
+{
+ KAboutData aboutData( "ksnapshot", I18N_NOOP("KSnapshot"),
+ KSNAPVERSION, description, KAboutData::License_GPL,
+ "(c) 1997-2003, Richard J. Moore,\n(c) 2000, Matthias Ettrich,\n(c) 2002-2003 Aaron J. Seigo");
+ aboutData.addAuthor("Richard J. Moore",0, "rich@kde.org");
+ aboutData.addAuthor("Matthias Ettrich",0, "ettrich@kde.org");
+ aboutData.addAuthor("Aaron J. Seigo", 0, "aseigo@kde.org");
+ aboutData.addCredit( "Nadeem Hasan", "Region Grabbing\nReworked GUI",
+ "nhasan@kde.org" );
+ KCmdLineArgs::init( argc, argv, &aboutData );
+
+ KApplication app;
+
+ KImageIO::registerFormats();
+
+ // Create top level window
+ KSnapshot *toplevel= new KSnapshot();
+ Q_CHECK_PTR(toplevel);
+ app.dcopClient()->setDefaultObject( toplevel->objId() );
+ toplevel->setCaption( app.makeStdCaption("") );
+ toplevel->setIcon(SmallIcon("tool_screenshot"));
+ app.setMainWidget(toplevel);
+ toplevel->show();
+ return app.exec();
+}
+
diff --git a/chalk/plugins/viewplugins/screenshot/regiongrabber.cpp b/chalk/plugins/viewplugins/screenshot/regiongrabber.cpp
new file mode 100644
index 00000000..1d3a451d
--- /dev/null
+++ b/chalk/plugins/viewplugins/screenshot/regiongrabber.cpp
@@ -0,0 +1,170 @@
+/*
+ * This file was copied from ksnapshot
+ *
+ * Copyright (C) 2003 Nadeem Hasan <nhasan@kde.org>
+ *
+ * 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 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 "regiongrabber.h"
+
+#include <tqpainter.h>
+#include <tqpalette.h>
+#include <tqstyle.h>
+#include <tqtimer.h>
+#include <tqtooltip.h>
+
+#include <kglobalsettings.h>
+
+SizeTip::SizeTip( TQWidget *tqparent, const char *name )
+ : TQLabel( tqparent, name, WStyle_Customize | WX11BypassWM |
+ WStyle_StaysOnTop | WStyle_NoBorder | WStyle_Tool )
+{
+ setMargin( 2 );
+ setIndent( 0 );
+ setFrameStyle( TQFrame::Plain | TQFrame::Box );
+
+ setPalette( TQToolTip::palette() );
+}
+
+void SizeTip::setTip( const TQRect &rect )
+{
+ TQString tip = TQString( "%1x%2" ).tqarg( rect.width() )
+ .tqarg( rect.height() );
+
+ setText( tip );
+ adjustSize();
+
+ positionTip( rect );
+}
+
+void SizeTip::positionTip( const TQRect &rect )
+{
+ TQRect tipRect = tqgeometry();
+ tipRect.moveTopLeft( TQPoint( 0, 0 ) );
+
+ if ( rect.intersects( tipRect ) )
+ {
+ TQRect deskR = KGlobalSettings::desktopGeometry( TQPoint( 0, 0 ) );
+
+ tipRect.moveCenter( TQPoint( deskR.width()/2, deskR.height()/2 ) );
+ if ( !rect.tqcontains( tipRect, true ) && rect.intersects( tipRect ) )
+ tipRect.moveBottomRight( tqgeometry().bottomRight() );
+ }
+
+ move( tipRect.topLeft() );
+}
+
+RegionGrabber::RegionGrabber()
+ : TQWidget( 0, 0 ),
+ mouseDown( false ), sizeTip( 0L )
+{
+ sizeTip = new SizeTip( ( TQWidget * )0L );
+
+ tipTimer = new TQTimer( this );
+ Q_CHECK_PTR(tipTimer);
+ connect( tipTimer, TQT_SIGNAL( timeout() ), TQT_SLOT( updateSizeTip() ) );
+
+ TQTimer::singleShot( 200, this, TQT_SLOT( initGrabber() ) );
+}
+
+RegionGrabber::~RegionGrabber()
+{
+ delete sizeTip;
+}
+
+void RegionGrabber::initGrabber()
+{
+ pixmap = TQPixmap::grabWindow( qt_xrootwin() );
+ setPaletteBackgroundPixmap( pixmap );
+
+ showFullScreen();
+
+ grabMouse( crossCursor );
+}
+
+void RegionGrabber::mousePressEvent( TQMouseEvent *e )
+{
+ if ( e->button() == Qt::LeftButton )
+ {
+ mouseDown = true;
+ grabRect = TQRect( e->pos(), e->pos() );
+ }
+}
+
+void RegionGrabber::mouseMoveEvent( TQMouseEvent *e )
+{
+ if ( mouseDown )
+ {
+ sizeTip->hide();
+ tipTimer->start( 250, true );
+
+ drawRubber();
+ grabRect.setBottomRight( e->pos() );
+ drawRubber();
+ }
+}
+
+void RegionGrabber::mouseReleaseEvent( TQMouseEvent *e )
+{
+ mouseDown = false;
+ drawRubber();
+ sizeTip->hide();
+
+ grabRect.setBottomRight( e->pos() );
+ grabRect = grabRect.normalize();
+
+ TQPixmap region = TQPixmap::grabWindow( winId(), grabRect.x(), grabRect.y(),
+ grabRect.width(), grabRect.height() );
+
+ releaseMouse();
+
+ emit regionGrabbed( region );
+}
+
+void RegionGrabber::keyPressEvent( TQKeyEvent *e )
+{
+ if ( e->key() == TQt::Key_Escape )
+ {
+ releaseMouse();
+ emit regionGrabbed( TQPixmap() );
+ }
+ else
+ e->ignore();
+}
+
+void RegionGrabber::updateSizeTip()
+{
+ TQRect rect = grabRect.normalize();
+
+ sizeTip->setTip( rect );
+ sizeTip->show();
+}
+
+void RegionGrabber::drawRubber()
+{
+ TQPainter p;
+ p.begin( this );
+ p.setRasterOp( NotROP );
+ p.setPen( TQPen( color0, 1 ) );
+ p.setBrush( NoBrush );
+
+ tqstyle().tqdrawPrimitive( TQStyle::PE_FocusRect, &p, grabRect, tqcolorGroup(),
+ TQStyle::Style_Default, TQStyleOption( tqcolorGroup().base() ) );
+
+ p.end();
+}
+
+#include "regiongrabber.moc"
diff --git a/chalk/plugins/viewplugins/screenshot/regiongrabber.h b/chalk/plugins/viewplugins/screenshot/regiongrabber.h
new file mode 100644
index 00000000..b1da1049
--- /dev/null
+++ b/chalk/plugins/viewplugins/screenshot/regiongrabber.h
@@ -0,0 +1,72 @@
+/*
+ * This file is copied from ksnapshot.
+ *
+ * Copyright (C) 2003 Nadeem Hasan <nhasan@kde.org>
+ *
+ * This library 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
+ * Library 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 REGIONGRABBER_H
+#define REGIONGRABBER_H
+
+#include <tqlabel.h>
+#include <tqpixmap.h>
+
+class TQTimer;
+
+class SizeTip : public TQLabel
+{
+public:
+ SizeTip( TQWidget *tqparent, const char *name=0 );
+ ~SizeTip() {}
+
+ void setTip( const TQRect &rect );
+ void positionTip( const TQRect &rect );
+};
+
+class RegionGrabber : public TQWidget
+{
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+ RegionGrabber();
+ ~RegionGrabber();
+
+protected slots:
+ void initGrabber();
+ void updateSizeTip();
+
+ signals:
+ void regionGrabbed( const TQPixmap & );
+
+protected:
+ void mousePressEvent( TQMouseEvent *e );
+ void mouseReleaseEvent( TQMouseEvent *e );
+ void mouseMoveEvent( TQMouseEvent *e );
+ void keyPressEvent( TQKeyEvent *e );
+
+ void drawRubber();
+
+ bool mouseDown;
+ TQRect grabRect;
+ TQPixmap pixmap;
+
+ SizeTip *sizeTip;
+ TQTimer *tipTimer;
+};
+
+#endif // REGIONGRABBER_H
+
diff --git a/chalk/plugins/viewplugins/screenshot/screenshot-chalk.rc b/chalk/plugins/viewplugins/screenshot/screenshot-chalk.rc
new file mode 100644
index 00000000..ec96bf11
--- /dev/null
+++ b/chalk/plugins/viewplugins/screenshot/screenshot-chalk.rc
@@ -0,0 +1,9 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkscreenshot" version="1">
+<MenuBar>
+ <Menu name="Tools"><text>&amp;Tools</text>
+ <Seperator/>
+ <Action name="screenshot"/>
+ </Menu>
+</MenuBar>
+</kpartgui>
diff --git a/chalk/plugins/viewplugins/screenshot/screenshot-kpresenter.rc b/chalk/plugins/viewplugins/screenshot/screenshot-kpresenter.rc
new file mode 100644
index 00000000..8f1f2033
--- /dev/null
+++ b/chalk/plugins/viewplugins/screenshot/screenshot-kpresenter.rc
@@ -0,0 +1,9 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkscreenshot" version="1">
+<MenuBar>
+ <Menu name="Insert"><text>&amp;Insert</text>
+ <Separator/>
+ <Action name="screenshot"/>
+ </Menu>
+</MenuBar>
+</kpartgui>
diff --git a/chalk/plugins/viewplugins/screenshot/screenshot-kword.rc b/chalk/plugins/viewplugins/screenshot/screenshot-kword.rc
new file mode 100644
index 00000000..f923f87f
--- /dev/null
+++ b/chalk/plugins/viewplugins/screenshot/screenshot-kword.rc
@@ -0,0 +1,9 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkscreenshot" version="1">
+<MenuBar>
+ <Menu name="insert"><text>&amp;Insert</text>
+ <Separator/>
+ <Action name="screenshot"/>
+ </Menu>
+</MenuBar>
+</kpartgui>
diff --git a/chalk/plugins/viewplugins/screenshot/screenshot.cpp b/chalk/plugins/viewplugins/screenshot/screenshot.cpp
new file mode 100644
index 00000000..ff762925
--- /dev/null
+++ b/chalk/plugins/viewplugins/screenshot/screenshot.cpp
@@ -0,0 +1,78 @@
+/*
+ * This file is part of the KDE project
+ *
+ * This file was copied from ksnapshot
+ *
+ * Copyright (C) 2001 Nikolas Zimmermann <wildfox@kde.org>
+ *
+ * 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 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 <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <KoView.h>
+#include <KoDocument.h>
+#include <kgenericfactory.h>
+#include <klocale.h>
+
+#include "ksnapshot.h"
+#include <kimageio.h>
+#include <kis_view.h>
+#include <kis_image.h>
+#include "screenshot.moc"
+
+
+K_EXPORT_COMPONENT_FACTORY( chalkscreenshot, KGenericFactory<Screenshot>( "chalk" ) )
+
+Screenshot::Screenshot(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ KGlobal::locale()->insertCatalogue("kscreenshot_plugin");
+ setInstance(KGenericFactory<Screenshot>::instance());
+ setXMLFile(locate("data","chalkplugins/screenshot-chalk.rc"), true);
+ KImageIO::registerFormats();
+
+ snapshot = new KSnapshot();
+ Q_CHECK_PTR(snapshot);
+ connect( snapshot, TQT_SIGNAL( screenGrabbed() ), TQT_SLOT( slotScreenGrabbed() ) );
+
+ (void) new KAction(i18n("&Screenshot..."), SmallIcon("tool_screenshot"), 0, this, TQT_SLOT(slotScreenshot()), actionCollection(), "screenshot");
+
+}
+
+Screenshot::~Screenshot()
+{
+ delete snapshot;
+}
+
+void Screenshot::slotScreenshot()
+{
+ snapshot->show();
+}
+
+void Screenshot::slotScreenGrabbed()
+{
+ KTempFile temp(locateLocal("tmp", "screenshot"), ".png");
+ snapshot->save(temp.name());
+
+ KisView *view = dynamic_cast<KisView *>(tqparent());
+ if(view)
+ view->importImage(temp.name());
+}
diff --git a/chalk/plugins/viewplugins/screenshot/screenshot.h b/chalk/plugins/viewplugins/screenshot/screenshot.h
new file mode 100644
index 00000000..d1100836
--- /dev/null
+++ b/chalk/plugins/viewplugins/screenshot/screenshot.h
@@ -0,0 +1,43 @@
+/* This file is part of the KDE project
+ * Copyright (C) 2001 Nikolas Zimmermann <wildfox@kde.org>
+ * Copyright (C) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 SCREENSHOT_H
+#define SCREENSHOT_H
+
+#include <kparts/plugin.h>
+
+class KSnapshot;
+
+class Screenshot : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ Screenshot(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~Screenshot();
+
+private slots:
+ void slotScreenshot();
+ void slotScreenGrabbed();
+
+private:
+ KSnapshot * snapshot;
+};
+
+#endif
diff --git a/chalk/plugins/viewplugins/scripting/Makefile.am b/chalk/plugins/viewplugins/scripting/Makefile.am
new file mode 100644
index 00000000..2bc6c1fd
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/Makefile.am
@@ -0,0 +1,29 @@
+SUBDIRS = chalkscripting chalkcore samples
+
+chalkrcdir = $(kde_datadir)/chalkplugins
+chalkrc_DATA = scripting.rc
+
+kde_services_DATA = chalkscripting.desktop
+
+
+INCLUDES = -I$(top_srcdir)/chalk/sdk \
+ -I$(top_srcdir)/chalk/core \
+ -I$(top_srcdir)/chalk/chalkcolor/ \
+ -I$(top_srcdir)/chalk/ui \
+ -I$(top_builddir)/lib/kross/main \
+ $(KROSS_INCLUDES) \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+chalkscripting_la_SOURCES = scripting.cc
+
+kde_module_LTLIBRARIES = chalkscripting.la
+noinst_HEADERS = scripting.h
+
+chalkscripting_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) chalkblurfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui
+chalkscripting_la_LIBADD = $(top_builddir)/chalk/libchalkcommon.la $(top_builddir)/lib/kross/main/libkrossmain.la ./chalkscripting/libchalkscripting.la
+
+KDE_CXXFLAGS = $(USE_EXCEPTIONS)
+
+chalkscripting_la_METASOURCES = AUTO
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/Makefile.am b/chalk/plugins/viewplugins/scripting/chalkcore/Makefile.am
new file mode 100644
index 00000000..448c7c59
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/Makefile.am
@@ -0,0 +1,30 @@
+
+INCLUDES = -I$(top_srcdir)/core -I$(top_srcdir)/chalk/plugins/viewplugins/scripting/chalkscripting \
+ -I$(top_srcdir)/chalk $(KOFFICECORE_INCLUDES) $(KROSS_INCLUDES) \
+ -I$(top_srcdir)/chalk/ui -I$(top_srcdir)/chalk/core -I$(top_srcdir)/chalk/sdk \
+ -I$(top_srcdir)/chalk/chalkcolor $(all_includes)
+
+kde_module_LTLIBRARIES = krosschalkcore.la
+
+krosschalkcore_la_SOURCES = chalkcoremodule.cpp krs_doc.cpp krs_paint_layer.cpp \
+ krs_image.cpp krs_histogram.cpp krs_script_progress.cpp krs_painter.cpp krs_color.cpp \
+ krs_brush.cpp krs_pattern.cpp krs_filter.cpp krs_filter_configuration.cpp \
+ krs_wavelet.cpp
+
+krosschalkcore_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../../chalk/ui/.libs -lchalkui -L../../../../../lib/kofficeui/.libs -lkofficeui -L../../../../../lib/kofficecore/.libs -lkofficecore
+krosschalkcore_la_LIBADD = \
+ $(LIB_QT) \
+ $(LIB_KDECORE) \
+ $(top_builddir)/lib/kross/api/libkrossapi.la \
+ $(top_builddir)/lib/kross/main/libkrossmain.la \
+ $(top_builddir)/chalk/libchalkcommon.la \
+ $(top_builddir)/chalk/plugins/viewplugins/scripting/chalkscripting/libchalkscripting.la
+
+METASOURCES = AUTO
+SUBDIRS = .
+
+KDE_CXXFLAGS = $(USE_EXCEPTIONS)
+
+noinst_HEADERS = krs_doc.h krs_iterator.h krs_painter.h krs_color.h krs_brush.h \
+ krs_filter.h krs_filter_configuration.h krs_wavelet.h
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/chalkcoremodule.cpp b/chalk/plugins/viewplugins/scripting/chalkcore/chalkcoremodule.cpp
new file mode 100644
index 00000000..04f7b653
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/chalkcoremodule.cpp
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 "chalkcoremodule.h"
+
+#include <kdebug.h>
+
+//#include <api/variant.h>
+#include <api/qtobject.h>
+#include <main/manager.h>
+
+#include <kis_autobrush_resource.h>
+#include <kis_brush.h>
+#include <kis_colorspace_factory_registry.h>
+#include <kis_doc.h>
+#include <kis_filter.h>
+#include <kis_filter_registry.h>
+#include <kis_image.h>
+#include <kis_meta_registry.h>
+#include <kis_pattern.h>
+#include <kis_resourceserver.h>
+
+#include "kis_script_progress.h"
+
+#include "krs_brush.h"
+#include "krs_color.h"
+#include "krs_doc.h"
+#include "krs_filter.h"
+#include "krs_image.h"
+#include "krs_pattern.h"
+#include "krs_script_progress.h"
+
+extern "C"
+{
+ /**
+ * Exported an loadable function as entry point to use
+ * the \a KexiAppModule.
+ */
+ Kross::Api::Object* KDE_EXPORT init_module(Kross::Api::Manager* manager)
+ {
+ return new Kross::ChalkCore::ChalkCoreModule(manager);
+ }
+}
+
+
+using namespace Kross::ChalkCore;
+
+ChalkCoreFactory::ChalkCoreFactory(TQString packagePath) : Kross::Api::Event<ChalkCoreFactory>("ChalkCoreFactory"), m_packagePath(packagePath)
+{
+ addFunction("newRGBColor", &ChalkCoreFactory::newRGBColor);
+ addFunction("newHSVColor", &ChalkCoreFactory::newHSVColor);
+ addFunction("getPattern", &ChalkCoreFactory::getPattern);
+ addFunction("loadPattern", &ChalkCoreFactory::loadPattern);
+ addFunction("getBrush", &ChalkCoreFactory::getBrush);
+ addFunction("loadBrush", &ChalkCoreFactory::loadBrush);
+ addFunction("getFilter", &ChalkCoreFactory::getFilter);
+ addFunction("newCircleBrush", &ChalkCoreFactory::newCircleBrush);
+ addFunction("newRectBrush", &ChalkCoreFactory::newRectBrush);
+ addFunction("newImage", &ChalkCoreFactory::newImage);
+ addFunction("getPackagePath", &ChalkCoreFactory::getPackagePath);
+}
+
+Kross::Api::Object::Ptr ChalkCoreFactory::newRGBColor(Kross::Api::List::Ptr args)
+{
+ Color* c = new Color(Kross::Api::Variant::toUInt(args->item(0)), Kross::Api::Variant::toUInt(args->item(1)), Kross::Api::Variant::toUInt(args->item(2)), TQColor::Rgb);
+ return c;
+}
+Kross::Api::Object::Ptr ChalkCoreFactory::newHSVColor(Kross::Api::List::Ptr args)
+{
+ return new Color(Kross::Api::Variant::toUInt(args->item(0)), Kross::Api::Variant::toUInt(args->item(1)), Kross::Api::Variant::toUInt(args->item(2)), TQColor::Hsv);
+}
+
+Kross::Api::Object::Ptr ChalkCoreFactory::getPattern(Kross::Api::List::Ptr args)
+{
+ KisResourceServerBase* rServer = KisResourceServerRegistry::instance()->get("PatternServer");
+ TQValueList<KisResource*> resources = rServer->resources();
+
+ TQString name = Kross::Api::Variant::toString(args->item(0));
+
+ for (TQValueList<KisResource*>::iterator it = resources.begin(); it != resources.end(); ++it )
+ {
+ if((*it)->name() == name)
+ {
+ return new Pattern(dynamic_cast<KisPattern*>(*it), true);
+ }
+ }
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("Unknown pattern") ) );
+ return 0;
+
+}
+
+Kross::Api::Object::Ptr ChalkCoreFactory::loadPattern(Kross::Api::List::Ptr args)
+{
+ TQString filename = Kross::Api::Variant::toString(args->item(0));
+ KisPattern* pattern = new KisPattern(filename);
+ if(pattern->load())
+ {
+ return new Pattern( pattern, false );
+ } else {
+ delete pattern;
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("Unknown pattern") ) );
+ return 0;
+ }
+}
+
+Kross::Api::Object::Ptr ChalkCoreFactory::getBrush(Kross::Api::List::Ptr args)
+{
+ KisResourceServerBase* rServer = KisResourceServerRegistry::instance()->get("BrushServer");
+ TQValueList<KisResource*> resources = rServer->resources();
+
+ TQString name = Kross::Api::Variant::toString(args->item(0));
+
+ for (TQValueList<KisResource*>::iterator it = resources.begin(); it != resources.end(); ++it )
+ {
+ if((*it)->name() == name)
+ {
+ return new Brush(dynamic_cast<KisBrush*>(*it), true);
+ }
+ }
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("Unknown brush") ) );
+ return 0;
+}
+
+Kross::Api::Object::Ptr ChalkCoreFactory::loadBrush(Kross::Api::List::Ptr args)
+{
+ TQString filename = Kross::Api::Variant::toString(args->item(0));
+ KisBrush* brush = new KisBrush(filename);
+ if(brush->load())
+ {
+ return new Brush( brush, false );
+ } else {
+ delete brush;
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("Unknown brush") ) );
+ return 0;
+ }
+}
+
+Kross::Api::Object::Ptr ChalkCoreFactory::getFilter(Kross::Api::List::Ptr args)
+{
+ TQString name = Kross::Api::Variant::toString(args->item(0));
+ KisFilter* filter = KisFilterRegistry::instance()->get(name);
+ if(filter)
+ {
+ return new Filter(filter);
+ } else {
+ return 0;
+ }
+}
+
+Kross::Api::Object::Ptr ChalkCoreFactory::newCircleBrush(Kross::Api::List::Ptr args)
+{
+ uint w = TQMAX(1, Kross::Api::Variant::toUInt(args->item(0)));
+ uint h = TQMAX(1, Kross::Api::Variant::toUInt(args->item(1)));
+ uint hf = 0;
+ uint vf = 0;
+ if( args.count() > 2)
+ {
+ hf = Kross::Api::Variant::toUInt(args->item(2));
+ vf = Kross::Api::Variant::toUInt(args->item(3));
+ }
+ KisAutobrushShape* kas = new KisAutobrushCircleShape(w, h, hf, vf);
+ TQImage* brsh = new TQImage();
+ kas->createBrush(brsh);
+ return new Brush(new KisAutobrushResource(*brsh), false);
+}
+Kross::Api::Object::Ptr ChalkCoreFactory::newRectBrush(Kross::Api::List::Ptr args)
+{
+ uint w = TQMAX(1, Kross::Api::Variant::toUInt(args->item(0)));
+ uint h = TQMAX(1, Kross::Api::Variant::toUInt(args->item(1)));
+ uint hf = 0;
+ uint vf = 0;
+ if( args.count() > 2)
+ {
+ hf = Kross::Api::Variant::toUInt(args->item(2));
+ vf = Kross::Api::Variant::toUInt(args->item(3));
+ }
+ KisAutobrushShape* kas = new KisAutobrushRectShape(w, h, hf, vf);
+ TQImage* brsh = new TQImage();
+ kas->createBrush(brsh);
+ return new Brush(new KisAutobrushResource(*brsh), false);;
+}
+
+Kross::Api::Object::Ptr ChalkCoreFactory::newImage(Kross::Api::List::Ptr args)
+{
+ int w = Kross::Api::Variant::toInt(args->item(0));
+ int h = Kross::Api::Variant::toInt(args->item(1));
+ TQString csname = Kross::Api::Variant::toString(args->item(2));
+ TQString name = Kross::Api::Variant::toString(args->item(3));
+ if( w < 0 || h < 0)
+ {
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("Invalid image size") ) );
+ return 0;
+ }
+ KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID(csname, ""), "");
+ if(!cs)
+ {
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("Colorspace %0 is not available, please check your installation.").tqarg(csname ) ) );
+ return 0;
+ }
+
+ return new Image(new KisImage(0,w,h, cs, name));
+}
+
+Kross::Api::Object::Ptr ChalkCoreFactory::getPackagePath(Kross::Api::List::Ptr)
+{
+ return new Kross::Api::Variant(m_packagePath);
+}
+
+ChalkCoreModule::ChalkCoreModule(Kross::Api::Manager* manager)
+ : Kross::Api::Module("chalkcore") , m_manager(manager), m_factory(0)
+{
+
+ TQMap<TQString, Object::Ptr> tqchildren = manager->getChildren();
+ kdDebug(41011) << " there are " << tqchildren.size() << endl;
+ for(TQMap<TQString, Object::Ptr>::const_iterator it = tqchildren.begin(); it != tqchildren.end(); it++)
+ {
+ kdDebug(41011) << it.key() << " " << it.data() << endl;
+ }
+
+ // Wrap doc
+ Kross::Api::Object::Ptr chalkdocument = manager->getChild("ChalkDocument");
+ if(chalkdocument) {
+ Kross::Api::QtObject* chalkdocumentqt = (Kross::Api::QtObject*)( chalkdocument.data() );
+ if(chalkdocumentqt) {
+ ::KisDoc* document = (::KisDoc*)( chalkdocumentqt->getObject() );
+ if(document) {
+ addChild( new Doc(document) );
+ } else {
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception("There was no 'ChalkDocument' published.") );
+ }
+ }
+ }
+ // Wrap ChalkScriptProgress
+ TQString packagePath;
+ Kross::Api::Object::Ptr chalkscriptprogress = manager->getChild("ChalkScriptProgress");
+ if(chalkdocument) {
+ Kross::Api::QtObject* chalkscriptprogressqt = (Kross::Api::QtObject*)( chalkscriptprogress.data() );
+ if(chalkscriptprogressqt) {
+ ::KisScriptProgress* scriptprogress = (::KisScriptProgress*)( chalkscriptprogressqt->getObject() );
+ scriptprogress->activateAsSubject();
+ packagePath = scriptprogress->packagePath();
+ if(scriptprogress) {
+ addChild( new ScriptProgress(scriptprogress) );
+ } else {
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception("There was no 'ChalkScriptProgress' published.") );
+ }
+ }
+ }
+ m_factory = new ChalkCoreFactory(packagePath);
+}
+
+ChalkCoreModule::~ChalkCoreModule()
+{
+ if(m_factory)
+ delete m_factory;
+}
+
+
+const TQString ChalkCoreModule::getClassName() const
+{
+ return "Kross::ChalkCore::ChalkCoreModule";
+}
+
+Kross::Api::Object::Ptr ChalkCoreModule::call(const TQString& name, Kross::Api::List::Ptr arguments)
+{
+ kdDebug(41011) << "ChalkCoreModule::call = " << name << endl;
+ if( m_factory->isAFunction(name))
+ {
+ return m_factory->call(name, arguments);
+ } else {
+ return Kross::Api::Module::call(name, arguments);
+ }
+}
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/chalkcoremodule.h b/chalk/plugins/viewplugins/scripting/chalkcore/chalkcoremodule.h
new file mode 100644
index 00000000..d719edd6
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/chalkcoremodule.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 KRITA_KROSS_KRITACOREMODULE_H
+#define KRITA_KROSS_KRITACOREMODULE_H
+
+#include <tqstring.h>
+#include <tqvariant.h>
+
+#define KROSS_MAIN_EXPORT KDE_EXPORT
+
+#include <api/module.h>
+#include <api/event.h>
+
+namespace Kross { namespace Api {
+ class Manager;
+}}
+
+namespace Kross { namespace ChalkCore {
+ /**
+ * This class contains functions use to create new Kross object in a script
+ */
+ class ChalkCoreFactory : public Kross::Api::Event<ChalkCoreFactory>
+ {
+ public:
+ ChalkCoreFactory(TQString packagePath);
+ private:
+ /**
+ * This function return a new Image.
+ * It takes four arguments :
+ * - width
+ * - height
+ * - colorspace id
+ * - name of the image
+ *
+ * And in return you get an Image object.
+ *
+ * For example (in ruby) :
+ * @code
+ * Krosschalkcore::newImage(10,20, "RGBA", "kikoo")
+ * @endcode
+ */
+ Kross::Api::Object::Ptr newImage(Kross::Api::List::Ptr);
+ /**
+ * This function return a new Color with the given RGB triplet
+ * It takes three arguments :
+ * - red color (0 to 255)
+ * - blue color (0 to 255)
+ * - green color (0 to 255)
+ *
+ * For example (in ruby) :
+ * @code
+ * Krosschalkcore::newRGBColor(255,0,0) # create a red color
+ * Krosschalkcore::newRGBColor(255,255,255) # create a white color
+ * @endcode
+ */
+ Kross::Api::Object::Ptr newRGBColor(Kross::Api::List::Ptr);
+ /**
+ * This function return a new Color with the given HSV triplet
+ * It takes three arguments :
+ * - hue color (0 to 255)
+ * - saturation color (0 to 255)
+ * - value color (0 to 255)
+ *
+ * For example (in ruby) :
+ * @code
+ * Krosschalkcore::newRGBColor(255,125,0)
+ * @endcode
+ */
+ Kross::Api::Object::Ptr newHSVColor(Kross::Api::List::Ptr);
+ /**
+ * This function return a Pattern taken from the list of ressources
+ * of chalk
+ * It takes one argument :
+ * - the name of the pattern
+ *
+ * For example (in ruby) :
+ * @code
+ * Krosschalkcore::getPattern("Bricks")
+ * @endcode
+ */
+ Kross::Api::Object::Ptr getPattern(Kross::Api::List::Ptr);
+ /**
+ * This function return a Brush taken from the list of ressources
+ * of chalk
+ * It takes one argument :
+ * - the name of the pattern
+ *
+ * For example (in ruby) :
+ * @code
+ * Krosschalkcore::getBrush("Circle (05)")
+ * @endcode
+ */
+ Kross::Api::Object::Ptr getBrush(Kross::Api::List::Ptr);
+ /**
+ * This function return a Brush with a circular tqshape
+ * It takes at least two arguments :
+ * - width
+ * - height
+ *
+ * It can takes two other arguments :
+ * - width of the shading
+ * - height of the shading
+ *
+ * If the shading isn't specified, no shading will be used.
+ *
+ * For example (in ruby) :
+ * @code
+ * Krosschalkcore::newCircleBrush(10,20) # create a plain circle
+ * Krosschalkcore::newCircleBrush(10,20,5,10) # create a gradient
+ * @endcode
+ */
+ Kross::Api::Object::Ptr newCircleBrush(Kross::Api::List::Ptr);
+ /**
+ * This function return a Brush with a rectangular tqshape
+ * It takes at least two arguments :
+ * - width
+ * - height
+ *
+ * It can takes two other arguments :
+ * - width of the shading
+ * - height of the shading
+ *
+ * If the shading isn't specified, no shading will be used.
+ *
+ * For example (in ruby) :
+ * @code
+ * Krosschalkcore::newRectBrush(10,20) # create a plain rectangle
+ * Krosschalkcore::newRectBrush(10,20,5,10) # create a gradient
+ * @endcode
+ */
+ Kross::Api::Object::Ptr newRectBrush(Kross::Api::List::Ptr);
+ /**
+ * This function return a Filter taken from the list of ressources
+ * of chalk
+ * It takes one argument :
+ * - the name of the filter
+ *
+ * For example (in ruby) :
+ * @code
+ * Krosschalkcore::getFilter("invert")
+ * @endcode
+ */
+ Kross::Api::Object::Ptr getFilter(Kross::Api::List::Ptr);
+ /**
+ * This function loads a Brush and then returns it.
+ * It takes one argument: the filename of the brush.
+ */
+ Kross::Api::Object::Ptr loadBrush(Kross::Api::List::Ptr);
+ /**
+ * This function loads a Pattern and then returns it.
+ * It takes one argument: the filename of the pattern.
+ */
+ Kross::Api::Object::Ptr loadPattern(Kross::Api::List::Ptr);
+ /**
+ * This function return the directory where the script is located.
+ */
+ Kross::Api::Object::Ptr getPackagePath(Kross::Api::List::Ptr);
+ private:
+ TQString m_packagePath;
+ };
+ /**
+ *
+ */
+ class ChalkCoreModule : public Kross::Api::Module
+ {
+ public:
+ /**
+ * Constructor.
+ */
+ ChalkCoreModule(Kross::Api::Manager* manager);
+
+ /**
+ * Destructor.
+ */
+ virtual ~ChalkCoreModule();
+
+ /// \see Kross::Api::Object::getClassName
+ virtual const TQString getClassName() const;
+ virtual Kross::Api::Object::Ptr call(const TQString& name, Kross::Api::List::Ptr arguments);
+ private:
+ Kross::Api::Manager* m_manager;
+ ChalkCoreFactory* m_factory;
+ };
+
+
+}}
+
+#endif
+
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_brush.cpp b/chalk/plugins/viewplugins/scripting/chalkcore/krs_brush.cpp
new file mode 100644
index 00000000..d3f1cb8a
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_brush.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 "krs_brush.h"
+
+#include <kis_brush.h>
+
+namespace Kross {
+
+namespace ChalkCore {
+
+Brush::Brush(KisBrush* brush, bool sharedBrush) : Kross::Api::Class<Brush>("ChalkBrush"), m_brush(brush), m_sharedBrush(sharedBrush)
+{
+}
+
+Brush::~Brush()
+{
+ if(!m_sharedBrush)
+ {
+ delete m_brush;
+ }
+}
+
+}
+
+}
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_brush.h b/chalk/plugins/viewplugins/scripting/chalkcore/krs_brush.h
new file mode 100644
index 00000000..7a6bdef5
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_brush.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 KROSS_KRITACOREKRS_BRUSH_H
+#define KROSS_KRITACOREKRS_BRUSH_H
+
+#include <api/class.h>
+
+class KisBrush;
+
+namespace Kross {
+
+namespace ChalkCore {
+
+class Brush : public Kross::Api::Class<Brush>{
+ public:
+ /**
+ * @param sharedBrush tell if the brush should be deleted or not when this object is deleted
+ */
+ Brush(KisBrush*, bool sharedBrush );
+ ~Brush();
+ public:
+ inline KisBrush* getBrush() { return m_brush; }
+ private:
+ KisBrush* m_brush;
+ bool m_sharedBrush;
+};
+
+}
+
+}
+
+#endif
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_color.cpp b/chalk/plugins/viewplugins/scripting/chalkcore/krs_color.cpp
new file mode 100644
index 00000000..b02a36f0
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_color.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 "krs_color.h"
+
+namespace Kross {
+
+namespace ChalkCore {
+
+Color::Color ( int x, int y, int z, TQColor::Spec colorSpec )
+ : Kross::Api::Class<Color>("ChalkColor"), m_color(x,y,z,colorSpec)
+{
+}
+
+Color::Color()
+ : Kross::Api::Class<Color>("ChalkColor")
+{
+}
+
+Color::~Color()
+{
+}
+
+
+}
+
+}
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_color.h b/chalk/plugins/viewplugins/scripting/chalkcore/krs_color.h
new file mode 100644
index 00000000..7955dc92
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_color.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 KROSS_APIKRS_COLOR_H
+#define KROSS_APIKRS_COLOR_H
+
+#include <tqcolor.h>
+
+#include <api/class.h>
+
+namespace Kross {
+
+namespace ChalkCore {
+
+class Color : public Kross::Api::Class<Color>
+{
+ public:
+ Color ( int x, int y, int z, TQColor::Spec colorSpec );
+ Color ();
+
+ ~Color();
+ public:
+ inline const TQString getClassName() const
+ { return "Kross::Chalk::Color"; };
+ inline TQColor toTQColor() { return m_color; };
+ private:
+ TQColor m_color;
+};
+
+}
+
+}
+
+#endif
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_doc.cpp b/chalk/plugins/viewplugins/scripting/chalkcore/krs_doc.cpp
new file mode 100644
index 00000000..4fc37fab
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_doc.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 "krs_doc.h"
+
+#include <kis_doc.h>
+#include <kis_image.h>
+
+#include "krs_image.h"
+
+namespace Kross { namespace ChalkCore {
+
+Doc::Doc(::KisDoc* doc) : Kross::Api::Class<Doc>("ChalkDocument"), m_doc(doc) {
+ addFunction("getImage", &Doc::getImage);
+}
+
+Doc::~Doc() {
+
+}
+
+const TQString Doc::getClassName() const {
+ return "Kross::ChalkCore::Doc";
+}
+
+Kross::Api::Object::Ptr Doc::getImage(Kross::Api::List::Ptr)
+{
+ return new Image(m_doc->currentImage(), m_doc);
+}
+
+}
+}
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_doc.h b/chalk/plugins/viewplugins/scripting/chalkcore/krs_doc.h
new file mode 100644
index 00000000..c06e530a
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_doc.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 _KROSS_KRS_DOC_H_
+#define _KROSS_KRS_DOC_H_
+
+class KisDoc;
+
+#include <api/class.h>
+
+namespace Kross { namespace ChalkCore {
+
+class Doc : public Kross::Api::Class<Doc>
+{
+ public:
+ explicit Doc(::KisDoc* doc);
+ virtual ~Doc();
+ virtual const TQString getClassName() const;
+ private:
+ /**
+ * This function return the Image associated with this Doc.
+ *
+ * Example (in Ruby) :
+ * @code
+ * doc = krosschalkcore::get("ChalkDocument")
+ * image = doc.getImage()
+ * @endcode
+ */
+ Kross::Api::Object::Ptr getImage(Kross::Api::List::Ptr);
+ private:
+ KisDoc* m_doc;
+
+};
+}
+}
+
+
+#endif
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_filter.cpp b/chalk/plugins/viewplugins/scripting/chalkcore/krs_filter.cpp
new file mode 100644
index 00000000..ecac5501
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_filter.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 "krs_filter.h"
+
+#include <kis_filter.h>
+#include <kis_paint_layer.h>
+
+#include "krs_filter_configuration.h"
+#include "krs_paint_layer.h"
+
+namespace Kross {
+namespace ChalkCore {
+
+Filter::Filter(KisFilter* filter)
+ : Kross::Api::Class<Filter>("ChalkFilter"), m_filter(filter), m_config( new FilterConfiguration(filter->configuration()) )
+{
+ addFunction("process", &Filter::process);
+ addFunction("getFilterConfiguration", &Filter::getFilterConfiguration);
+
+}
+
+Filter::~Filter()
+{
+}
+
+const TQString Filter::getClassName() const {
+ return "Kross::ChalkCore::Filter";
+}
+
+Kross::Api::Object::Ptr Filter::getFilterConfiguration(Kross::Api::List::Ptr )
+{
+ return m_config;
+}
+
+Kross::Api::Object::Ptr Filter::process(Kross::Api::List::Ptr args)
+{
+ PaintLayer* src = (PaintLayer*)args->item(0).data();
+ if(!m_filter->workWith( src->paintLayer()->paintDevice()->colorSpace()))
+ {
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("An error has occured in %1").tqarg("process") ) );
+ }
+ TQRect rect;
+ if( args->count() >1)
+ {
+ uint x = Kross::Api::Variant::toVariant(args->item(1)).toUInt();
+ uint y = Kross::Api::Variant::toVariant(args->item(2)).toUInt();
+ uint w = Kross::Api::Variant::toVariant(args->item(3)).toUInt();
+ uint h = Kross::Api::Variant::toVariant(args->item(4)).toUInt();
+ rect = TQRect(x, y, w, h);
+ } else {
+ TQRect r1 = src->paintLayer()->paintDevice()->extent();
+ TQRect r2 = src->paintLayer()->image()->bounds();
+ rect = r1.intersect(r2);
+ }
+ m_filter->process( src->paintLayer()->paintDevice(), src->paintLayer()->paintDevice(), m_config->filterConfiguration(), rect );
+ return 0;
+}
+
+}
+}
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_filter.h b/chalk/plugins/viewplugins/scripting/chalkcore/krs_filter.h
new file mode 100644
index 00000000..1576574b
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_filter.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 KROSS_KRITACOREKRS_FILTER_H
+#define KROSS_KRITACOREKRS_FILTER_H
+
+#include <api/class.h>
+
+class KisFilter;
+
+namespace Kross {
+namespace ChalkCore {
+ class FilterConfiguration;
+
+class Filter : public Kross::Api::Class<Filter>
+{
+ public:
+ Filter(KisFilter*);
+ ~Filter();
+ private:
+ /**
+ * This function return the FilterConfiguration associated with this filter.
+ */
+ Kross::Api::Object::Ptr getFilterConfiguration(Kross::Api::List::Ptr args);
+ /**
+ * This function will apply the filter.
+ * It takes one argument :
+ * - the source layer
+ * You can also use this four aguments :
+ * - x
+ * - y
+ * - width
+ * - height
+ *
+ * (x,y, width, height) defines the rectangular area on which the filter will be computed.
+ * If the rectangle is not defined, then the filter will be apply on alll the source layer.
+ *
+ * For example (in ruby)
+ * @code
+ * doc = Krosschalkcore::get("ChalkDocument")
+ * image = doc.getImage()
+ * layer = image.getActivePaintLayer()
+ * width = layer.getWidth()
+ * height = layer.getHeight()
+ * filter = Krosschalkcore::getFilter("invert")
+ * filter.process(layer, layer)
+ * filter.process(layer, layer, 10, 10, 20, 20 )
+ * @endcode
+ */
+ Kross::Api::Object::Ptr process(Kross::Api::List::Ptr args);
+ public:
+ virtual const TQString getClassName() const;
+ private:
+ KisFilter* m_filter;
+ FilterConfiguration* m_config;
+};
+
+}
+}
+
+#endif
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_filter_configuration.cpp b/chalk/plugins/viewplugins/scripting/chalkcore/krs_filter_configuration.cpp
new file mode 100644
index 00000000..976af321
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_filter_configuration.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 "krs_filter_configuration.h"
+
+#include <api/variant.h>
+
+#include <kis_filter_configuration.h>
+
+namespace Kross {
+namespace ChalkCore {
+
+ FilterConfiguration::FilterConfiguration(KisFilterConfiguration* fConfig)
+ : Kross::Api::Class<FilterConfiguration>("ChalkFilterConfiguration"), m_fConfig(fConfig)
+{
+ addFunction("setProperty", &FilterConfiguration::setProperty);
+ addFunction("getProperty", &FilterConfiguration::getProperty);
+ addFunction("fromXML", &FilterConfiguration::fromXML);
+}
+
+FilterConfiguration::~FilterConfiguration()
+{
+}
+
+const TQString FilterConfiguration::getClassName() const {
+ return "Kross::ChalkCore::FilterConfiguration";
+}
+
+
+Kross::Api::Object::Ptr FilterConfiguration::setProperty(Kross::Api::List::Ptr args)
+{
+ TQString name = Kross::Api::Variant::toString(args->item(0));
+ TQVariant value = Kross::Api::Variant::toVariant(args->item(1));
+ m_fConfig->setProperty(name, value);
+ return 0;
+}
+Kross::Api::Object::Ptr FilterConfiguration::getProperty(Kross::Api::List::Ptr args)
+{
+ TQString name = Kross::Api::Variant::toString(args->item(0));
+ TQVariant value;
+ if(m_fConfig->getProperty( name, value))
+ {
+ return new Kross::Api::Variant(value);
+ } else {
+ return 0;
+ }
+}
+
+Kross::Api::Object::Ptr FilterConfiguration::fromXML(Kross::Api::List::Ptr args)
+{
+ TQString xml = Kross::Api::Variant::toString(args->item(0));
+ m_fConfig->fromXML( xml );
+ return 0;
+}
+
+}
+}
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_filter_configuration.h b/chalk/plugins/viewplugins/scripting/chalkcore/krs_filter_configuration.h
new file mode 100644
index 00000000..61378cf4
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_filter_configuration.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 KROSS_KRITACOREKRS_FILTER_CONFIGURATION_H
+#define KROSS_KRITACOREKRS_FILTER_CONFIGURATION_H
+
+#include <api/class.h>
+
+class KisFilterConfiguration;
+
+namespace Kross {
+namespace ChalkCore {
+
+/**
+ @author Cyrille Berger <cberger@cberger.net>
+*/
+class FilterConfiguration : public Kross::Api::Class<FilterConfiguration>
+{
+ public:
+ FilterConfiguration(KisFilterConfiguration*);
+ ~FilterConfiguration();
+ public:
+ virtual const TQString getClassName() const;
+ inline KisFilterConfiguration* filterConfiguration() { return m_fConfig; };
+ private:
+ /**
+ * This function define a parameter of the associated Filter.
+ * It takes two arguments :
+ * - the name of the parameter
+ * - the value, whose type depends of the Filter
+ */
+ Kross::Api::Object::Ptr setProperty(Kross::Api::List::Ptr args);
+ /**
+ * This function return the value of a parameter of the associated Filter.
+ * It takes one argument :
+ * - the name of the parameter
+ */
+ Kross::Api::Object::Ptr getProperty(Kross::Api::List::Ptr args);
+ /**
+ * Deserialize
+ */
+ Kross::Api::Object::Ptr fromXML(Kross::Api::List::Ptr args);
+ private:
+ KisFilterConfiguration* m_fConfig;
+};
+
+}
+}
+
+#endif
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_histogram.cpp b/chalk/plugins/viewplugins/scripting/chalkcore/krs_histogram.cpp
new file mode 100644
index 00000000..ea121d7c
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_histogram.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 "krs_histogram.h"
+
+#include <kis_paint_layer.h>
+
+namespace Kross {
+
+namespace ChalkCore {
+
+Histogram::Histogram(KisPaintLayerSP layer,
+ KisHistogramProducerSP producer,
+ const enumHistogramType type)
+ : Kross::Api::Class<Histogram>("ChalkHistogram")
+{
+ m_histogram = new KisHistogram(layer, producer, type);
+ addFunction("getMax", &Histogram::getMax);
+ addFunction("getMin", &Histogram::getMin);
+ addFunction("getHighest", &Histogram::getHighest);
+ addFunction("getLowest", &Histogram::getLowest);
+ addFunction("getMean", &Histogram::getMean);
+ addFunction("getCount", &Histogram::getCount);
+ addFunction("getTotal", &Histogram::getTotal);
+ addFunction("setChannel", &Histogram::setChannel);
+ addFunction("getChannel", &Histogram::getChannel);
+ addFunction("getValue", &Histogram::getValue);
+ addFunction("getNumberOfBins", &Histogram::getNumberOfBins);
+}
+
+Histogram::~Histogram()
+{
+}
+
+const TQString Histogram::getClassName() const {
+ return "Kross::ChalkCore::Histogram";
+}
+
+Kross::Api::Object::Ptr Histogram::setChannel(Kross::Api::List::Ptr args)
+{
+ m_histogram->setChannel(Kross::Api::Variant::toUInt(args->item(0)));
+ return 0;
+}
+Kross::Api::Object::Ptr Histogram::getChannel(Kross::Api::List::Ptr)
+{
+ return new Kross::Api::Variant( m_histogram->channel());
+}
+Kross::Api::Object::Ptr Histogram::getMax(Kross::Api::List::Ptr)
+{
+ return new Kross::Api::Variant( m_histogram->calculations().getMax());
+}
+Kross::Api::Object::Ptr Histogram::getMin(Kross::Api::List::Ptr)
+{
+ return new Kross::Api::Variant( m_histogram->calculations().getMin() );
+}
+Kross::Api::Object::Ptr Histogram::getHighest(Kross::Api::List::Ptr)
+{
+ return new Kross::Api::Variant( m_histogram->calculations().getHighest() );
+}
+Kross::Api::Object::Ptr Histogram::getLowest(Kross::Api::List::Ptr)
+{
+ return new Kross::Api::Variant( m_histogram->calculations().getLowest() );
+}
+Kross::Api::Object::Ptr Histogram::getMean(Kross::Api::List::Ptr)
+{
+ return new Kross::Api::Variant( m_histogram->calculations().getMean() );
+}
+Kross::Api::Object::Ptr Histogram::getCount(Kross::Api::List::Ptr)
+{
+ return new Kross::Api::Variant( m_histogram->calculations().getCount() );
+}
+Kross::Api::Object::Ptr Histogram::getTotal(Kross::Api::List::Ptr)
+{
+ return new Kross::Api::Variant( m_histogram->calculations().getTotal() );
+}
+Kross::Api::Object::Ptr Histogram::getValue(Kross::Api::List::Ptr args)
+{
+ return new Kross::Api::Variant( m_histogram->getValue( Kross::Api::Variant::toUInt(args->item(0)) ) );
+}
+
+Kross::Api::Object::Ptr Histogram::getNumberOfBins(Kross::Api::List::Ptr)
+{
+ return new Kross::Api::Variant( m_histogram->producer()->numberOfBins() );
+}
+
+
+}
+
+}
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_histogram.h b/chalk/plugins/viewplugins/scripting/chalkcore/krs_histogram.h
new file mode 100644
index 00000000..50b66ca4
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_histogram.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 KROSS_KRITACOREHISTOGRAM_H
+#define KROSS_KRITACOREHISTOGRAM_H
+
+#include <api/class.h>
+
+#include <kis_types.h>
+#include <kis_histogram.h>
+
+namespace Kross {
+
+namespace ChalkCore {
+
+/**
+ * This class allow to access the histogram of a PaintLayer.
+ *
+ * Example (in Ruby) :
+ * @code
+ * doc = krosschalkcore::get("ChalkDocument")
+ * image = doc.getImage()
+ * layer = image.getActiveLayer()
+ * histo = layer.createHistogram("RGB8HISTO",0)
+ * min = layer.getMin() * 255
+ * max = layer.getMax() * 255
+ * for i in min..max
+ * print layer.getValue(i)
+ * print "\n"
+ * end
+ * @endcode
+ */
+class Histogram : public Kross::Api::Class<Histogram>
+{
+ public:
+ Histogram(KisPaintLayerSP layer, KisHistogramProducerSP producer, const enumHistogramType type);
+ ~Histogram();
+ virtual const TQString getClassName() const;
+ private:
+ /**
+ * This function return the maximum bound of the histogram
+ * (values at greater position than the maximum are null).
+ * The value is in the range 0.0 - 1.0.
+ */
+ Kross::Api::Object::Ptr getMax(Kross::Api::List::Ptr);
+ /**
+ * This function return the minimum bound of the histogram
+ * (values at smaller position than the minimum are null)
+ * The value is in the range 0.0 - 1.0.
+ */
+ Kross::Api::Object::Ptr getMin(Kross::Api::List::Ptr);
+ /**
+ * This function return the highest value of the histogram
+ */
+ Kross::Api::Object::Ptr getHighest(Kross::Api::List::Ptr);
+ /**
+ * This function return the lowest value of the histogram
+ */
+ Kross::Api::Object::Ptr getLowest(Kross::Api::List::Ptr);
+ /**
+ * This function return the mean of the histogram
+ */
+ Kross::Api::Object::Ptr getMean(Kross::Api::List::Ptr);
+ /**
+ * This function return the number of pixels used by the histogram
+ */
+ Kross::Api::Object::Ptr getCount(Kross::Api::List::Ptr);
+ /**
+ * This function return the sum of all values of the histogram
+ */
+ Kross::Api::Object::Ptr getTotal(Kross::Api::List::Ptr);
+ /**
+ * Select the channel of the layer on which to get the result of the histogram.
+ * This function takes one argument :
+ * - channel number
+ */
+ Kross::Api::Object::Ptr setChannel(Kross::Api::List::Ptr);
+ /**
+ * Return the selected channel
+ */
+ Kross::Api::Object::Ptr getChannel(Kross::Api::List::Ptr);
+ /**
+ * Return the value of a bin of the histogram.
+ * This function takes one argument :
+ * - index, in the range [0..255],
+ */
+ Kross::Api::Object::Ptr getValue(Kross::Api::List::Ptr);
+ /**
+ * Return the number of bins of this histogram.
+ */
+ Kross::Api::Object::Ptr getNumberOfBins(Kross::Api::List::Ptr);
+ private:
+ KisHistogram* m_histogram;
+};
+
+}
+
+}
+
+#endif
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_image.cpp b/chalk/plugins/viewplugins/scripting/chalkcore/krs_image.cpp
new file mode 100644
index 00000000..c93d6e88
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_image.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 "krs_image.h"
+
+#include <klocale.h>
+
+#include <kis_colorspace_factory_registry.h>
+#include <kis_image.h>
+#include <kis_filter_strategy.h>
+#include <kis_group_layer.h>
+#include <kis_paint_layer.h>
+#include <kis_meta_registry.h>
+
+
+#include "krs_paint_layer.h"
+
+namespace Kross {
+
+namespace ChalkCore {
+
+ Image::Image(KisImageSP image, KisDoc* doc)
+ : Kross::Api::Class<Image>("ChalkImage"), m_image(image), m_doc(doc)
+{
+ addFunction("getActivePaintLayer", &Image::getActivePaintLayer);
+ addFunction("getWidth", &Image::getWidth);
+ addFunction("getHeight", &Image::getHeight);
+ addFunction("convertToColorspace", &Image::convertToColorspace);
+ addFunction("createPaintLayer", &Image::createPaintLayer);
+ addFunction("colorSpaceId", &Image::colorSpaceId);
+ addFunction("scale", &Image::scale);
+ addFunction("resize", &Image::resize);
+}
+
+
+Image::~Image()
+{
+}
+
+const TQString Image::getClassName() const {
+ return "Kross::ChalkCore::Image";
+}
+
+Kross::Api::Object::Ptr Image::getActivePaintLayer(Kross::Api::List::Ptr)
+{
+ KisPaintLayer* activePaintLayer = dynamic_cast<KisPaintLayer*>(m_image->activeLayer().data());
+ if(activePaintLayer )
+ {
+ return new PaintLayer(activePaintLayer, m_doc);
+ } else {
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception("The active layer is not paintable.") );
+ return 0;
+ }
+}
+Kross::Api::Object::Ptr Image::getWidth(Kross::Api::List::Ptr)
+{
+ return new Kross::Api::Variant(m_image->width());
+}
+Kross::Api::Object::Ptr Image::getHeight(Kross::Api::List::Ptr)
+{
+ return new Kross::Api::Variant(m_image->height());
+}
+Kross::Api::Object::Ptr Image::convertToColorspace(Kross::Api::List::Ptr args)
+{
+ KisColorSpace * dstCS = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID(Kross::Api::Variant::toString(args->item(0)), ""), "");
+ if(!dstCS)
+ {
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("Colorspace %0 is not available, please check your installation.").tqarg(Kross::Api::Variant::toString(args->item(0))) ) );
+ return 0;
+ }
+ m_image->convertTo(dstCS);
+ return 0;
+}
+
+Kross::Api::Object::Ptr Image::colorSpaceId(Kross::Api::List::Ptr )
+{
+ return new Kross::Api::Variant( m_image->colorSpace()->id().id() );
+}
+
+
+Kross::Api::Object::Ptr Image::createPaintLayer(Kross::Api::List::Ptr args)
+{
+ TQString name = Kross::Api::Variant::toString(args->item(0));
+ int opacity = Kross::Api::Variant::toInt(args->item(1));
+ opacity = CLAMP(opacity, 0, 255);
+ TQString csname;
+ if(args->count() > 2)
+ {
+ csname = Kross::Api::Variant::toString(args->item(2));
+ } else {
+ csname = m_image->colorSpace()->id().id();
+ }
+ KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID(csname, ""), "");
+ KisPaintLayer* layer;
+ if(cs)
+ {
+ layer = new KisPaintLayer(m_image, name, opacity, cs);
+ } else {
+ layer = new KisPaintLayer(m_image, name, opacity);
+ }
+ layer->setVisible(true);
+
+ m_image->addLayer(layer, m_image->rootLayer(), 0);
+ return new PaintLayer(layer);
+
+}
+
+Kross::Api::Object::Ptr Image::scale(Kross::Api::List::Ptr args)
+{
+ double cw = Kross::Api::Variant::toDouble(args->item(0));
+ double ch = Kross::Api::Variant::toDouble(args->item(1));
+ m_image->scale( cw, ch, 0, KisFilterStrategyRegistry::instance()->get( "Mitchell") );
+ return 0;
+}
+Kross::Api::Object::Ptr Image::resize(Kross::Api::List::Ptr args)
+{
+ int nw = Kross::Api::Variant::toInt(args->item(0));
+ int nh = Kross::Api::Variant::toInt(args->item(1));
+ int x = 0;
+ int y = 0;
+ if(args->count() > 2)
+ {
+ x = Kross::Api::Variant::toInt(args->item(2));
+ y = Kross::Api::Variant::toInt(args->item(3));
+ }
+ m_image->resize( nw, nh, x, y );
+ return 0;
+}
+
+
+}
+
+}
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_image.h b/chalk/plugins/viewplugins/scripting/chalkcore/krs_image.h
new file mode 100644
index 00000000..91314f3f
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_image.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 KROSS_KRITACOREKRSIMAGE_H
+#define KROSS_KRITACOREKRSIMAGE_H
+
+#include <api/class.h>
+
+#include <kis_types.h>
+
+class KisDoc;
+
+namespace Kross {
+
+namespace ChalkCore {
+
+class Image : public Kross::Api::Class<Image>
+{
+ public:
+ Image(KisImageSP image, KisDoc* doc = 0);
+ ~Image();
+ virtual const TQString getClassName() const;
+ private:
+ /**
+ * Return the active PaintLayer, if any.
+ */
+ Kross::Api::Object::Ptr getActivePaintLayer(Kross::Api::List::Ptr);
+ /**
+ * Return the width of the image.
+ */
+ Kross::Api::Object::Ptr getWidth(Kross::Api::List::Ptr);
+ /**
+ * Return the height of the image.
+ */
+ Kross::Api::Object::Ptr getHeight(Kross::Api::List::Ptr);
+ /**
+ * Resize an image
+ */
+ Kross::Api::Object::Ptr resize(Kross::Api::List::Ptr);
+ /**
+ * Scale an image
+ */
+ Kross::Api::Object::Ptr scale(Kross::Api::List::Ptr);
+ /**
+ * Convert the image to a colorspace.
+ * This function takes one argument :
+ * - the name of the destination colorspace
+ *
+ * For example (in Ruby) :
+ * @code
+ * image.convertToColorspace("CMYK")
+ * @endcode
+ */
+ Kross::Api::Object::Ptr convertToColorspace(Kross::Api::List::Ptr args);
+ /**
+ * Return the id of the colorspace of this image.
+ */
+ Kross::Api::Object::Ptr colorSpaceId(Kross::Api::List::Ptr );
+ /**
+ * Create a new PaintLayer for this image, and return it.
+ * This function takes at least two arguments :
+ * - the name of the layer
+ * - the opacity of the layer (between 0 and 255)
+ *
+ * This function can take one optional argument :
+ * - the id of the colorSpace (if this is not specified, the new PaintLayer
+ * will have the same colorspace as the image)
+ */
+ Kross::Api::Object::Ptr createPaintLayer(Kross::Api::List::Ptr args);
+ private:
+ KisImageSP m_image;
+ KisDoc* m_doc;
+};
+
+}
+
+}
+
+#endif
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_iterator.h b/chalk/plugins/viewplugins/scripting/chalkcore/krs_iterator.h
new file mode 100644
index 00000000..2e17ed98
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_iterator.h
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 KROSS_KRITACOREKRS_ITERATOR_H
+#define KROSS_KRITACOREKRS_ITERATOR_H
+
+#include <tqobject.h>
+#include <api/class.h>
+//#include <api/proxy.h>
+//#include <api/variant.h>
+
+#include <klocale.h>
+
+#include <kis_paint_layer.h>
+#include <kis_paint_device.h>
+#include <kis_types.h>
+
+#include <kis_script_monitor.h>
+
+namespace Kross {
+
+namespace ChalkCore {
+
+//<beurk> stupid TQt which doesn't support templated TQObject
+class IteratorMemoryManaged {
+ public:
+ virtual void tqinvalidateIterator() = 0;
+};
+
+class IteratorMemoryManager : public TQObject {
+ Q_OBJECT
+ TQ_OBJECT
+ public:
+ IteratorMemoryManager(IteratorMemoryManaged* it) : m_it(it)
+ {
+ // Connect the Monitor to know when the invalidating of iterator is needed
+ connect(KisScriptMonitor::instance(), TQT_SIGNAL(executionFinished(const Kross::Api::ScriptAction* )), this, TQT_SLOT(tqinvalidateIterator()));
+
+ }
+ public slots:
+ void tqinvalidateIterator()
+ {
+ m_it->tqinvalidateIterator();
+ }
+ private:
+ IteratorMemoryManaged* m_it;
+};
+//</beurk>
+/**
+ * This object allow to change the value of pixel one by one.
+ * The name of some function depends of the colorspace, for instance, if
+ * the colorspace of the layer is RGB, you will have setR, setG, setB... and for CMYK,
+ * setC, setM, setY, setK. In the doc bellow we will consider the colorspace is called ABC with
+ * three channels : A, B and C.
+ *
+ * Function: setA setB setC
+ * Those functions take one argument:
+ * - the new value of one of the channel of this pixel
+ *
+ * Function: setABC
+ * Set the value of all channels.
+ * This function take one argument:
+ * - an array with the new value for all channels
+ */
+template<class _T_It>
+class Iterator : public Kross::Api::Class<Iterator<_T_It> >, private IteratorMemoryManaged
+{
+ public:
+ Iterator(_T_It it, KisPaintLayerSP layer) : Kross::Api::Class<Iterator<_T_It> >("ChalkIterator"), m_itmm (new IteratorMemoryManager(this)), m_it(new _T_It(it)), nchannels(layer->paintDevice()->nChannels()), m_layer(layer)
+ {
+ // navigate in the iterator
+ this->addFunction("next",
+ new Kross::Api::ProxyFunction<
+ Iterator<_T_It>, // instance
+ bool (Iterator<_T_It>::*)(), // method
+ Kross::Api::Variant // return-value
+ >(this, &Iterator<_T_It>::next));
+ this->addFunction("isDone",
+ new Kross::Api::ProxyFunction<
+ Iterator<_T_It>, // instance
+ bool (Iterator<_T_It>::*)(), // method
+ Kross::Api::Variant // return-value
+ >(this, &Iterator<_T_It>::isDone));
+
+ // get/set value
+ TQValueVector<KisChannelInfo *> channels = layer->paintDevice()->colorSpace()->channels();
+ TQString initiales = "";
+ for(TQValueVector<KisChannelInfo *>::iterator itC = channels.begin(); itC != channels.end(); itC++)
+ {
+ KisChannelInfo * ci = *itC;
+ initiales += ci->name().left(1);
+ switch(ci->channelValueType())
+ {
+ case KisChannelInfo::UINT8:
+ this->addFunction("get"+ci->name(),
+ new Kross::Api::Function1< Iterator<_T_It> , uint >(
+ this, &Iterator<_T_It>::getChannelUINT8, ci->pos() ) );
+ this->addFunction("set"+ci->name(),
+ new Kross::Api::Function1< Iterator<_T_It> , uint >(
+ this, &Iterator<_T_It>::setChannelUINT8, ci->pos() ) );
+ break;
+ case KisChannelInfo::UINT16:
+ this->addFunction("get"+ci->name(),
+ new Kross::Api::Function1< Iterator<_T_It> , uint >(
+ this, &Iterator<_T_It>::getChannelUINT16, ci->pos() ) );
+ this->addFunction("set"+ci->name(),
+ new Kross::Api::Function1< Iterator<_T_It> , uint >(
+ this, &Iterator<_T_It>::setChannelUINT16, ci->pos() ) );
+ break;
+ case KisChannelInfo::FLOAT32:
+ this->addFunction("get"+ci->name(),
+ new Kross::Api::Function1< Iterator<_T_It> , uint >(
+ this, &Iterator<_T_It>::getChannelFLOAT, ci->pos() ) );
+ this->addFunction("set"+ci->name(),
+ new Kross::Api::Function1< Iterator<_T_It> , uint >(
+ this, &Iterator<_T_It>::setChannelFLOAT, ci->pos() ) );
+ break;
+ default:
+ kdDebug(41011) << "unsupported data format in scripts" << endl;
+ break;
+ }
+ }
+ initiales = initiales.upper();
+ // set/get general
+ addFunction("set" + initiales, &Iterator::setPixel);
+ addFunction("get" + initiales, &Iterator::getPixel);
+ kdDebug(41011) << ( "get" + initiales ) << endl;
+ // Various colorSpace
+ addFunction("invertColor", &Iterator::invertColor);
+ addFunction("darken", &Iterator::darken);
+ }
+
+ ~Iterator()
+ {
+ tqinvalidateIterator();
+ delete m_itmm;
+ }
+ virtual const TQString getClassName() const {
+ return "Kross::ChalkCore::KrsDoc";
+ };
+ private:
+ /**
+ * Darken a pixel.
+ * This functions at least one argument:
+ * - shade amount use to darken all color channels
+ *
+ * This function can take the following optional argument:
+ * - compensation to limit the darkening
+ */
+ Kross::Api::Object::Ptr darken(Kross::Api::List::Ptr args)
+ {
+ TQ_INT32 shade = Kross::Api::Variant::toUInt( args->item(0) );
+ bool compensate = (args->count() == 2);
+ double compensation = compensate ? Kross::Api::Variant::toDouble( args->item(2) ) : 0.;
+ m_layer->paintDevice()->colorSpace()->darken(m_it->rawData(), m_it->rawData(), shade, compensate, compensation, 1);
+ return 0;
+ }
+ /**
+ * Invert the color of a pixel.
+ */
+ Kross::Api::Object::Ptr invertColor(Kross::Api::List::Ptr )
+ {
+ m_layer->paintDevice()->colorSpace()->invertColor(m_it->rawData(), 1);
+ return 0;
+ }
+ /**
+ * Increment the positon, and go to the next pixel.
+ */
+ bool next()
+ {
+ ++(*m_it);
+ return m_it->isDone();
+ }
+ /**
+ * Return true if the iterator is at the end, and that no more pixels are available.
+ */
+ bool isDone()
+ {
+ return m_it->isDone();
+ }
+ Kross::Api::Object::Ptr getChannelUINT8(Kross::Api::List::Ptr, uint channelpos)
+ {
+ TQ_UINT8* data = (TQ_UINT8*)(m_it->rawData() + channelpos);
+ return new Kross::Api::Variant( * data);
+ }
+ Kross::Api::Object::Ptr setChannelUINT8(Kross::Api::List::Ptr args, uint channelpos)
+ {
+ TQ_UINT8* data = (TQ_UINT8*)(m_it->rawData() + channelpos); //*(uint*)channelpos);
+ *data = Kross::Api::Variant::toUInt( args->item(0) );
+ return 0;
+ }
+ Kross::Api::Object::Ptr getChannelUINT16(Kross::Api::List::Ptr, uint channelpos)
+ {
+ TQ_UINT16* data = (TQ_UINT16*)(m_it->rawData() + channelpos);
+ return new Kross::Api::Variant( * data);
+ }
+ Kross::Api::Object::Ptr setChannelUINT16(Kross::Api::List::Ptr args, uint channelpos)
+ {
+ TQ_UINT16* data = (TQ_UINT16*)(m_it->rawData() + channelpos);
+ *data = Kross::Api::Variant::toUInt( args->item(0) );
+ return 0;
+ }
+ Kross::Api::Object::Ptr getChannelFLOAT(Kross::Api::List::Ptr, uint channelpos)
+ {
+ float* data = (float*)(m_it->rawData() + channelpos);
+ return new Kross::Api::Variant( * data);
+ }
+ Kross::Api::Object::Ptr setChannelFLOAT(Kross::Api::List::Ptr args, uint channelpos)
+ {
+ float* data = (float*)(m_it->rawData() + channelpos);
+ *data = Kross::Api::Variant::toUInt( args->item(0) );
+ return 0;
+ }
+ Kross::Api::Object::Ptr getPixel(Kross::Api::List::Ptr)
+ {
+ TQValueVector<KisChannelInfo *> channels = m_layer->paintDevice()->colorSpace()->channels();
+ TQValueList<TQVariant> pixel;
+ for(TQValueVector<KisChannelInfo *>::iterator itC = channels.begin(); itC != channels.end(); itC++)
+ {
+ KisChannelInfo * ci = *itC;
+ TQ_UINT8* data = (TQ_UINT8*)(m_it->rawData() + ci->pos());
+ switch(ci->channelValueType())
+ {
+ case KisChannelInfo::UINT8:
+ pixel.push_back( *data);
+ break;
+ case KisChannelInfo::UINT16:
+ pixel.push_back( *((TQ_UINT16*) data) );
+ break;
+ case KisChannelInfo::FLOAT32:
+ pixel.push_back( *((float*) data) );
+ break;
+ default:
+ kdDebug(41011) << i18n("An error has occurred in %1").tqarg("getPixel") << endl;
+ kdDebug(41011) << i18n("unsupported data format in scripts") << endl;
+ break;
+ }
+ }
+ return new Kross::Api::Variant( pixel);
+ }
+ Kross::Api::Object::Ptr setPixel(Kross::Api::List::Ptr args)
+ {
+ TQValueList<TQVariant> pixel = Kross::Api::Variant::toList( args->item(0) );
+ TQValueVector<KisChannelInfo *> channels = m_layer->paintDevice()->colorSpace()->channels();
+ uint i = 0;
+ for(TQValueVector<KisChannelInfo *>::iterator itC = channels.begin(); itC != channels.end(); itC++, i++)
+ {
+ KisChannelInfo * ci = *itC;
+ TQ_UINT8* data = (TQ_UINT8*)(m_it->rawData() + ci->pos());
+ switch(ci->channelValueType())
+ {
+ case KisChannelInfo::UINT8:
+ *data = pixel[i].toUInt();
+ break;
+ case KisChannelInfo::UINT16:
+ *((TQ_UINT16*) data) = pixel[i].toUInt();
+ break;
+ case KisChannelInfo::FLOAT32:
+ *((float*) data) = pixel[i].toDouble();
+ break;
+ default:
+ kdDebug(41011) << i18n("An error has occurred in %1").tqarg("setPixel") << endl;
+ kdDebug(41011) << i18n("unsupported data format in scripts") << endl;
+ break;
+ }
+ }
+ return 0;
+ }
+ private:
+ virtual void tqinvalidateIterator()
+ {
+ kdDebug(41011) << "invalidating iterator" << endl;
+ if(m_it)
+ {
+ kdDebug(41011) << "deleting iterator" << endl;
+ delete m_it;
+ }
+ m_it = 0;
+ kdDebug() << " Iterator = " << m_it << endl;
+ }
+ private:
+ IteratorMemoryManager* m_itmm;
+ _T_It* m_it;
+ int nchannels;
+ KisPaintLayerSP m_layer;
+};
+
+}
+
+}
+
+#endif
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_paint_layer.cpp b/chalk/plugins/viewplugins/scripting/chalkcore/krs_paint_layer.cpp
new file mode 100644
index 00000000..5f800f6a
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_paint_layer.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 "krs_paint_layer.h"
+
+#include <klocale.h>
+
+#include <kis_colorspace_factory_registry.h>
+#include <kis_doc.h>
+#include <kis_layer.h>
+#include <kis_meta_registry.h>
+#include <kis_iterators_pixel.h>
+#include <kis_transaction.h>
+#include <kis_math_toolbox.h>
+
+#include "krs_iterator.h"
+#include "krs_histogram.h"
+#include "krs_painter.h"
+#include "krs_wavelet.h"
+
+namespace Kross {
+
+namespace ChalkCore {
+
+PaintLayer::PaintLayer(KisPaintLayerSP layer, KisDoc* doc)
+ : Kross::Api::Class<PaintLayer>("ChalkLayer"), m_layer(layer), m_doc(doc), m_cmd(0)
+{
+ addFunction("createRectIterator", &PaintLayer::createRectIterator);
+ addFunction("createHLineIterator", &PaintLayer::createHLineIterator);
+ addFunction("createVLineIterator", &PaintLayer::createVLineIterator);
+ addFunction("getWidth", &PaintLayer::getWidth);
+ addFunction("getHeight", &PaintLayer::getHeight);
+ addFunction("createHistogram", &PaintLayer::createHistogram);
+ addFunction("createPainter", &PaintLayer::createPainter);
+ addFunction("beginPainting", &PaintLayer::beginPainting);
+ addFunction("endPainting", &PaintLayer::endPainting);
+ addFunction("convertToColorspace", &PaintLayer::convertToColorspace);
+ addFunction("fastWaveletTransformation", &PaintLayer::fastWaveletTransformation);
+ addFunction("fastWaveletUntransformation", &PaintLayer::fastWaveletUntransformation);
+ addFunction("colorSpaceId", &PaintLayer::colorSpaceId);
+}
+
+
+PaintLayer::~PaintLayer()
+{
+}
+
+const TQString PaintLayer::getClassName() const {
+ return "Kross::ChalkCore::PaintLayer";
+}
+
+Kross::Api::Object::Ptr PaintLayer::createRectIterator(Kross::Api::List::Ptr args)
+{
+ return new Iterator<KisRectIteratorPixel>(
+ paintLayer()->paintDevice()->createRectIterator(Kross::Api::Variant::toUInt(args->item(0)),
+ Kross::Api::Variant::toUInt(args->item(1)),
+ Kross::Api::Variant::toUInt(args->item(2)),
+ Kross::Api::Variant::toUInt(args->item(3)), true),
+ paintLayer());
+}
+Kross::Api::Object::Ptr PaintLayer::createHLineIterator(Kross::Api::List::Ptr args)
+{
+ return new Iterator<KisHLineIteratorPixel>(
+ paintLayer()->paintDevice()->createHLineIterator(Kross::Api::Variant::toUInt(args->item(0)),
+ Kross::Api::Variant::toUInt(args->item(1)),
+ Kross::Api::Variant::toUInt(args->item(2)), true),
+ paintLayer());
+}
+Kross::Api::Object::Ptr PaintLayer::createVLineIterator(Kross::Api::List::Ptr args)
+{
+ return new Iterator<KisVLineIteratorPixel>(
+ paintLayer()->paintDevice()->createVLineIterator(Kross::Api::Variant::toUInt(args->item(0)),
+ Kross::Api::Variant::toUInt(args->item(1)),
+ Kross::Api::Variant::toUInt(args->item(2)), true),
+ paintLayer());
+}
+Kross::Api::Object::Ptr PaintLayer::getWidth(Kross::Api::List::Ptr)
+{
+ TQRect r1 = paintLayer()->extent();
+ TQRect r2 = paintLayer()->image()->bounds();
+ TQRect rect = r1.intersect(r2);
+ return new Kross::Api::Variant(rect.width());
+}
+Kross::Api::Object::Ptr PaintLayer::getHeight(Kross::Api::List::Ptr)
+{
+ TQRect r1 = paintLayer()->extent();
+ TQRect r2 = paintLayer()->image()->bounds();
+ TQRect rect = r1.intersect(r2);
+ return new Kross::Api::Variant(rect.height());
+}
+
+Kross::Api::Object::Ptr PaintLayer::createHistogram(Kross::Api::List::Ptr args)
+{
+ TQString histoname = Kross::Api::Variant::toString(args->item(0));
+ KisHistogramProducerFactory* factory = KisHistogramProducerFactoryRegistry::instance()->get(histoname);
+
+/* KisIDList listID = KisHistogramProducerFactoryRegistry::instance()->listKeys();
+ for(KisIDList::iterator it = listID.begin(); it != listID.end(); it++)
+ {
+ kdDebug(41011) << (*it).name() << " " << (*it).id() << endl;
+ }*/
+
+ enumHistogramType type ;
+ switch( Kross::Api::Variant::toUInt(args->item(1)) )
+ {
+ case 1:
+ type = LOGARITHMIC;
+ break;
+ case 0:
+ default:
+ type = LINEAR;
+ break;
+ }
+ if(factory && factory->isCompatibleWith( paintLayer()->paintDevice()->colorSpace() ))
+ {
+ return new Histogram( paintLayer().data(), factory->generate() , type);
+ } else {
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("An error has occured in %1").tqarg("createHistogram") + "\n" + i18n("The histogram %1 is not available").tqarg(histoname) ) );
+ }
+ return 0;
+}
+
+Kross::Api::Object::Ptr PaintLayer::createPainter(Kross::Api::List::Ptr )
+{
+ return new Painter(paintLayer());
+}
+
+Kross::Api::Object::Ptr PaintLayer::beginPainting(Kross::Api::List::Ptr args)
+{
+ TQString name = Kross::Api::Variant::toString(args->item(0));
+ if(m_cmd != 0)
+ {
+ delete m_cmd;
+ }
+ m_cmd = new KisTransaction(name, paintLayer()->paintDevice());
+ Q_CHECK_PTR(m_cmd);
+ return 0;
+}
+
+Kross::Api::Object::Ptr PaintLayer::endPainting(Kross::Api::List::Ptr)
+{
+ if(doc() !=0)
+ {
+ doc()->setModified(true);
+ doc()->currentImage()->activeLayer()->setDirty();
+ }
+ if(m_cmd != 0)
+ {
+ paintLayer()->image()->undoAdapter()->addCommand(m_cmd);
+ }
+ return 0;
+}
+
+Kross::Api::Object::Ptr PaintLayer::convertToColorspace(Kross::Api::List::Ptr args)
+{
+ KisColorSpace * dstCS = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID(Kross::Api::Variant::toString(args->item(0)), ""), "");
+ if(!dstCS)
+ {
+ // FIXME: inform user
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("An error has occured in %1").tqarg("convertToColorspace") + "\n" + i18n("Colorspace %1 is not available, please check your installation.").tqarg(Kross::Api::Variant::toString(args->item(0))) ) );
+ return 0;
+ }
+ paintLayer()->paintDevice()->convertTo(dstCS);
+ return 0;
+}
+
+Kross::Api::Object::Ptr PaintLayer::colorSpaceId(Kross::Api::List::Ptr )
+{
+ return new Kross::Api::Variant( paintLayer()->paintDevice()->colorSpace()->id().id() );
+}
+
+
+Kross::Api::Object::Ptr PaintLayer::fastWaveletTransformation(Kross::Api::List::Ptr )
+{
+ KisMathToolbox* mathToolbox = KisMetaRegistry::instance()->mtRegistry()->get( paintLayer()->paintDevice()->colorSpace()->mathToolboxID() );
+ TQRect rect = paintLayer()->exactBounds();
+ KisMathToolbox::KisWavelet* wav = mathToolbox->fastWaveletTransformation(paintLayer()->paintDevice(), rect);
+ return new Wavelet(wav);
+}
+Kross::Api::Object::Ptr PaintLayer::fastWaveletUntransformation(Kross::Api::List::Ptr args)
+{
+ Wavelet* wav = (Wavelet*)args->item(0).data();
+ KisMathToolbox* mathToolbox = KisMetaRegistry::instance()->mtRegistry()->get( paintLayer()->paintDevice()->colorSpace()->mathToolboxID() );
+ TQRect rect = paintLayer()->exactBounds();
+ mathToolbox->fastWaveletUntransformation( paintLayer()->paintDevice(), rect, wav->wavelet() );
+ return 0;
+}
+
+
+}
+
+}
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_paint_layer.h b/chalk/plugins/viewplugins/scripting/chalkcore/krs_paint_layer.h
new file mode 100644
index 00000000..18ac5088
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_paint_layer.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 KROSS_KRITACOREKRSLAYER_H
+#define KROSS_KRITACOREKRSLAYER_H
+
+#include <api/class.h>
+
+#include <kis_types.h>
+#include <kis_paint_layer.h>
+
+class KisDoc;
+class KisTransaction;
+
+namespace Kross {
+
+namespace ChalkCore {
+
+/**
+@author Cyrille Berger
+*/
+class PaintLayer : public Kross::Api::Class<PaintLayer>
+{
+ public:
+ explicit PaintLayer(KisPaintLayerSP layer, KisDoc* doc = 0);
+ virtual ~PaintLayer();
+ virtual const TQString getClassName() const;
+ private:
+ /**
+ * Create an iterator over a layer, it will iterate on a rectangle area.
+ * This function takes four arguments :
+ * - x
+ * - y
+ * - width of the rectangle
+ * - height of the rectangle
+ */
+ Kross::Api::Object::Ptr createRectIterator(Kross::Api::List::Ptr);
+ /**
+ * Create an iterator over a layer, it will iterate on a row.
+ * This function takes three arguments :
+ * - x start in the row
+ * - y vertical position of the row
+ * - width of the row
+ */
+ Kross::Api::Object::Ptr createHLineIterator(Kross::Api::List::Ptr);
+ /**
+ * Create an iterator over a layer, it will iterate on a column.
+ * This function takes three arguments :
+ * - x horizontal position of the column
+ * - y start in the column
+ * - height of the column
+ */
+ Kross::Api::Object::Ptr createVLineIterator(Kross::Api::List::Ptr);
+ /**
+ * Return the width of the layer
+ */
+ Kross::Api::Object::Ptr getWidth(Kross::Api::List::Ptr);
+ /**
+ * Return the height of the layer
+ */
+ Kross::Api::Object::Ptr getHeight(Kross::Api::List::Ptr);
+ /**
+ * This function creates an Histogram for this layer.
+ * It takes two arguments :
+ * - the type of the histogram ("RGB8HISTO")
+ * - 0 if the histogram is linear, or 1 if it is logarithmic
+ */
+ Kross::Api::Object::Ptr createHistogram(Kross::Api::List::Ptr);
+ /**
+ * This function create a Painter which will allow you to some painting on the layer.
+ */
+ Kross::Api::Object::Ptr createPainter(Kross::Api::List::Ptr);
+ /**
+ * Uses this function to create a new undo entry.
+ */
+ Kross::Api::Object::Ptr beginPainting(Kross::Api::List::Ptr args);
+ /**
+ * Uses this function to close the current undo entry and add it to the history.
+ */
+ Kross::Api::Object::Ptr endPainting(Kross::Api::List::Ptr args);
+ /**
+ * Convert the image to a colorspace.
+ * This function takes one argument :
+ * - the name of the destination colorspace
+ *
+ * For example (in Ruby) :
+ * @code
+ * image.convertToColorspace("CMYK")
+ * @endcode
+ */
+ Kross::Api::Object::Ptr convertToColorspace(Kross::Api::List::Ptr args);
+ /**
+ * Return the id of the colorspace of this paint layer.
+ */
+ Kross::Api::Object::Ptr colorSpaceId(Kross::Api::List::Ptr );
+ /**
+ * Return the fast wavelet transformed of the layer
+ */
+ Kross::Api::Object::Ptr fastWaveletTransformation(Kross::Api::List::Ptr args);
+ /**
+ * Untransform a fast wavelet into this layer
+ * It takes one argument :
+ * - a wavelet object
+ *
+ * For example (in Ruby) :
+ * @code
+ * wavelet = layer.fastWaveletTransformation()
+ * layer.fastWaveletUntransformation(wavelet)
+ * @endcode
+ */
+ Kross::Api::Object::Ptr fastWaveletUntransformation(Kross::Api::List::Ptr args);
+ public:
+ inline KisPaintLayerSP paintLayer() { return m_layer; }
+ inline KisDoc* doc() { return m_doc; }
+ private:
+ KisPaintLayerSP m_layer;
+ KisDoc* m_doc;
+ KisTransaction* m_cmd;
+};
+
+}
+
+}
+
+#endif
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_painter.cpp b/chalk/plugins/viewplugins/scripting/chalkcore/krs_painter.cpp
new file mode 100644
index 00000000..44991303
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_painter.cpp
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 "krs_painter.h"
+
+#include <kis_convolution_painter.h>
+#include <kis_fill_painter.h>
+#include <kis_paint_layer.h>
+#include <kis_paintop_registry.h>
+#include <kis_painter.h>
+
+#include "krs_brush.h"
+#include "krs_color.h"
+#include "krs_pattern.h"
+
+namespace Kross {
+
+namespace ChalkCore {
+
+Painter::Painter(KisPaintLayerSP layer)
+ : Kross::Api::Class<Painter>("ChalkPainter"), m_layer(layer),m_painter(new KisPainter(layer->paintDevice())),m_threshold(1)
+{
+ // convolution
+ addFunction("convolve", &Painter::convolve);
+ // Fill specific
+ addFunction("setFillThreshold", &Painter::setFillThreshold);
+ addFunction("fillColor", &Painter::fillColor);
+ addFunction("fillPattern", &Painter::fillPattern);
+
+ // Painting operations
+ addFunction("paintPolyline", &Painter::paintPolyline);
+ addFunction("paintLine", &Painter::paintLine);
+ addFunction("paintBezierCurve", &Painter::paintBezierCurve);
+ addFunction("paintEllipse", &Painter::paintEllipse);
+ addFunction("paintPolygon", &Painter::paintPolygon);
+ addFunction("paintRect", &Painter::paintRect);
+ addFunction("paintAt", &Painter::paintAt);
+ addFunction("setBackgroundColor", &Painter::setBackgroundColor);
+ addFunction("setPaintColor", &Painter::setPaintColor);
+
+ // Color operations
+ addFunction("setPattern", &Painter::setPattern);
+ addFunction("setBrush", &Painter::setBrush);
+
+ // How is painting done operations
+ addFunction("setPaintOp", &Painter::setPaintOp);
+ // Special settings
+ addFunction("setDuplicateOffset", &Painter::setDuplicateOffset);
+
+ // Style operation
+ addFunction("setOpacity", &Painter::setOpacity);
+ addFunction("setStrokeStyle", &Painter::setStrokeStyle);
+ addFunction("setFillStyle", &Painter::setFillStyle);
+}
+
+
+Painter::~Painter()
+{
+ delete m_painter;
+}
+
+Kross::Api::Object::Ptr Painter::convolve(Kross::Api::List::Ptr args)
+{
+ KisConvolutionPainter* cp = new KisConvolutionPainter(m_painter->device());
+ TQRect rect;
+ KisKernel kernel;
+ kernel.factor = Kross::Api::Variant::toInt(args->item(1));
+ kernel.offset = Kross::Api::Variant::toInt(args->item(2));
+
+ uint borderop = 3;
+ if( args.count() > 3 )
+ {
+ borderop = Kross::Api::Variant::toUInt(args->item(3));
+ }
+ uint channelsFlag = KisChannelInfo::FLAG_COLOR;
+ if( args.count() > 4 )
+ {
+ channelsFlag = Kross::Api::Variant::toUInt(args->item(4));
+ }
+ if( args.count() > 5)
+ {
+ uint x = Kross::Api::Variant::toUInt(args->item(5));
+ uint y = Kross::Api::Variant::toUInt(args->item(6));
+ uint w = Kross::Api::Variant::toUInt(args->item(7));
+ uint h = Kross::Api::Variant::toUInt(args->item(8));
+ rect = TQRect(x,y,w,h);
+ } else {
+ TQRect r1 = paintLayer()->paintDevice()->extent();
+ TQRect r2 = paintLayer()->image()->bounds();
+ rect = r1.intersect(r2);
+ }
+
+ TQValueList<TQVariant> kernelH = Kross::Api::Variant::toList( args->item(0) );
+
+ TQVariant firstlineVariant = *kernelH.begin();
+ if(firstlineVariant.type() != TQVariant::List)
+ {
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception(i18n("An error has occured in %1").tqarg("applyConvolution")) );
+ }
+
+ TQValueList<TQVariant> firstline = firstlineVariant.toList();
+
+ kernel.height = kernelH.size();
+ kernel.width = firstline.size();
+
+ kernel.data = new TQ_INT32[kernel.height * kernel.width];
+
+ uint i = 0;
+ for(TQValueList<TQVariant>::iterator itK = kernelH.begin(); itK != kernelH.end(); itK++, i ++ )
+ {
+ TQVariant lineVariant = *kernelH.begin();
+ if(lineVariant.type() != TQVariant::List)
+ {
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception(i18n("An error has occured in %1").tqarg("applyConvolution")) );
+ }
+ TQValueList<TQVariant> line = firstlineVariant.toList();
+ if(line.size() != kernel.width)
+ {
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception(i18n("An error has occured in %1").tqarg("applyConvolution")) );
+ }
+ uint j = 0;
+ for(TQValueList<TQVariant>::iterator itLine = line.begin(); itLine != line.end(); itLine++, j ++ )
+ {
+ kernel.data[ j + i * kernel.width ] = (*itLine).toInt();
+ }
+ }
+ cp->applyMatrix(&kernel, rect.x(), rect.y(), rect.width(), rect.height(), (KisConvolutionBorderOp)borderop, (KisChannelInfo::enumChannelFlags) channelsFlag);
+
+ delete[] kernel.data;
+ return 0;
+}
+
+
+KisFillPainter* Painter::createFillPainter()
+{
+ KisFillPainter* fp = new KisFillPainter(m_painter->device());
+ fp->setBrush( m_painter->brush() );
+ fp->setFillColor( m_painter->fillColor() );
+ fp->setPaintColor( m_painter->paintColor() );
+ fp->setFillStyle( m_painter->fillStyle() );
+ fp->setOpacity( m_painter->opacity() );
+ fp->setPattern( m_painter->pattern() );
+ return fp;
+}
+
+Kross::Api::Object::Ptr Painter::setFillThreshold(Kross::Api::List::Ptr args)
+{
+ m_threshold = Kross::Api::Variant::toInt(args->item(0));
+ return 0;
+}
+Kross::Api::Object::Ptr Painter::fillColor(Kross::Api::List::Ptr args)
+{
+ KisFillPainter* fp = createFillPainter();
+ uint x = Kross::Api::Variant::toUInt(args->item(0));
+ uint y = Kross::Api::Variant::toUInt(args->item(1));
+
+ fp->fillColor( x, y );
+ return 0;
+}
+Kross::Api::Object::Ptr Painter::fillPattern(Kross::Api::List::Ptr args)
+{
+ KisFillPainter* fp = createFillPainter();
+ uint x = Kross::Api::Variant::toUInt(args->item(0));
+ uint y = Kross::Api::Variant::toUInt(args->item(1));
+ fp->fillPattern(x, y);
+ return 0;
+}
+
+Kross::Api::Object::Ptr Painter::setStrokeStyle(Kross::Api::List::Ptr args)
+{
+ uint style = Kross::Api::Variant::toVariant(args->item(0)).toUInt();
+ KisPainter::StrokeStyle strokestyle;
+ switch(style)
+ {
+ case 1:
+ strokestyle = KisPainter::StrokeStyleBrush;
+ break;
+ default:
+ strokestyle = KisPainter::StrokeStyleNone;
+ }
+ m_painter->setStrokeStyle(strokestyle);
+ return 0;
+}
+
+Kross::Api::Object::Ptr Painter::setFillStyle(Kross::Api::List::Ptr args)
+{
+ uint style = Kross::Api::Variant::toVariant(args->item(0)).toUInt();
+ KisPainter::FillStyle fillstyle;
+ switch(style)
+ {
+ case 1:
+ fillstyle = KisPainter::FillStyleForegroundColor;
+ break;
+ case 2:
+ fillstyle = KisPainter::FillStyleBackgroundColor;
+ break;
+ case 3:
+ fillstyle = KisPainter::FillStylePattern;
+ break;
+ default:
+ fillstyle = KisPainter::FillStyleNone;
+ }
+ m_painter->setFillStyle(fillstyle);
+ return 0;
+}
+
+Kross::Api::Object::Ptr Painter::setOpacity(Kross::Api::List::Ptr args)
+{
+ TQ_UINT8 opacity = Kross::Api::Variant::toVariant(args->item(0)).toUInt();
+ m_painter->setOpacity(opacity);
+ return 0;
+}
+
+Kross::Api::Object::Ptr Painter::setDuplicateOffset(Kross::Api::List::Ptr args)
+{
+ double x1 = Kross::Api::Variant::toVariant(args->item(0)).toDouble();
+ double y1 = Kross::Api::Variant::toVariant(args->item(1)).toDouble();
+ m_painter->setDuplicateOffset(KisPoint(x1,y1));
+ return 0;
+}
+
+Kross::Api::Object::Ptr Painter::paintPolyline(Kross::Api::List::Ptr args)
+{
+ TQValueList<TQVariant> pointsX = Kross::Api::Variant::toList( args->item(0) );
+ TQValueList<TQVariant> pointsY = Kross::Api::Variant::toList( args->item(1) );
+ if(pointsX.size() != pointsY.size())
+ {
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception("the two lists should have the same size.") );
+ }
+ m_painter->paintPolyline( createPointsVector( pointsX, pointsY));
+ return 0;
+}
+
+Kross::Api::Object::Ptr Painter::paintLine(Kross::Api::List::Ptr args)
+{
+ double x1 = Kross::Api::Variant::toVariant(args->item(0)).toDouble();
+ double y1 = Kross::Api::Variant::toVariant(args->item(1)).toDouble();
+ double p1 = Kross::Api::Variant::toVariant(args->item(2)).toDouble();
+ double x2 = Kross::Api::Variant::toVariant(args->item(3)).toDouble();
+ double y2 = Kross::Api::Variant::toVariant(args->item(4)).toDouble();
+ double p2 = Kross::Api::Variant::toVariant(args->item(5)).toDouble();
+ m_painter->paintLine(KisPoint( x1, y1), p1, 0.0, 0.0, KisPoint( x2, y2 ), p2, 0.0, 0.0 );
+ return 0;
+}
+
+Kross::Api::Object::Ptr Painter::paintBezierCurve(Kross::Api::List::Ptr args)
+{
+ double x1 = Kross::Api::Variant::toVariant(args->item(0)).toDouble();
+ double y1 = Kross::Api::Variant::toVariant(args->item(1)).toDouble();
+ double p1 = Kross::Api::Variant::toVariant(args->item(2)).toDouble();
+ double cx1 = Kross::Api::Variant::toVariant(args->item(3)).toDouble();
+ double cy1 = Kross::Api::Variant::toVariant(args->item(4)).toDouble();
+ double cx2 = Kross::Api::Variant::toVariant(args->item(5)).toDouble();
+ double cy2 = Kross::Api::Variant::toVariant(args->item(6)).toDouble();
+ double x2 = Kross::Api::Variant::toVariant(args->item(7)).toDouble();
+ double y2 = Kross::Api::Variant::toVariant(args->item(8)).toDouble();
+ double p2 = Kross::Api::Variant::toVariant(args->item(9)).toDouble();
+ m_painter->paintBezierCurve( KisPoint(x1,y1), p1, 0.0, 0.0, KisPoint(cx1,cy1), KisPoint(cx2,cy2), KisPoint(x2,y2), p2, 0.0, 0.0);
+ return 0;
+}
+
+Kross::Api::Object::Ptr Painter::paintEllipse(Kross::Api::List::Ptr args)
+{
+ double x1 = Kross::Api::Variant::toVariant(args->item(0)).toDouble();
+ double y1 = Kross::Api::Variant::toVariant(args->item(1)).toDouble();
+ double x2 = Kross::Api::Variant::toVariant(args->item(2)).toDouble();
+ double y2 = Kross::Api::Variant::toVariant(args->item(3)).toDouble();
+ double p1 = Kross::Api::Variant::toVariant(args->item(4)).toDouble();
+ m_painter->paintEllipse( KisPoint(x1,y1), KisPoint(x2,y2), p1, 0.0, 0.0 );
+ return 0;
+}
+
+Kross::Api::Object::Ptr Painter::paintPolygon(Kross::Api::List::Ptr args)
+{
+ TQValueList<TQVariant> pointsX = Kross::Api::Variant::toList( args->item(0) );
+ TQValueList<TQVariant> pointsY = Kross::Api::Variant::toList( args->item(1) );
+ if(pointsX.size() != pointsY.size())
+ {
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception("the two lists should have the same size.") );
+ }
+ m_painter->paintPolygon( createPointsVector(pointsX, pointsY));
+ return 0;
+}
+
+Kross::Api::Object::Ptr Painter::paintRect(Kross::Api::List::Ptr args)
+{
+ double x1 = Kross::Api::Variant::toVariant(args->item(0)).toDouble();
+ double y1 = Kross::Api::Variant::toVariant(args->item(1)).toDouble();
+ double x2 = Kross::Api::Variant::toVariant(args->item(2)).toDouble();
+ double y2 = Kross::Api::Variant::toVariant(args->item(3)).toDouble();
+ double p1 = Kross::Api::Variant::toVariant(args->item(4)).toDouble();
+ m_painter->paintRect( KisPoint(x1, y1), KisPoint(x2,y2), p1, 0, 0);
+ return 0;
+}
+
+Kross::Api::Object::Ptr Painter::paintAt(Kross::Api::List::Ptr args)
+{
+ double x1 = Kross::Api::Variant::toVariant(args->item(0)).toDouble();
+ double y1 = Kross::Api::Variant::toVariant(args->item(1)).toDouble();
+ double p1 = Kross::Api::Variant::toVariant(args->item(2)).toDouble();
+ m_painter->paintAt( KisPoint( x1, y1 ), p1, 0.0, 0.0);
+ return 0;
+}
+
+Kross::Api::Object::Ptr Painter::setBackgroundColor(Kross::Api::List::Ptr args)
+{
+ Color* c = (Color*)args->item(0).data();
+ m_painter->setBackgroundColor( KisColor(c->toTQColor(), paintLayer()->paintDevice()->colorSpace() ));
+ return 0;
+}
+
+Kross::Api::Object::Ptr Painter::setPaintColor(Kross::Api::List::Ptr args)
+{
+ Color* c = (Color*)args->item(0).data();
+ m_painter->setPaintColor( KisColor(c->toTQColor(), paintLayer()->paintDevice()->colorSpace() ));
+ return 0;
+}
+
+Kross::Api::Object::Ptr Painter::setPattern(Kross::Api::List::Ptr args)
+{
+ Pattern* p = (Pattern*)args->item(0).data();
+ m_painter->setPattern( p->getPattern());
+ return 0;
+}
+
+
+Kross::Api::Object::Ptr Painter::setBrush(Kross::Api::List::Ptr args)
+{
+ Brush* b = (Brush*)args->item(0).data();
+ m_painter->setBrush( b->getBrush());
+ return 0;
+}
+Kross::Api::Object::Ptr Painter::setPaintOp(Kross::Api::List::Ptr args)
+{
+ TQString id = Kross::Api::Variant::toString(args->item(0));
+ KisPaintOp* op = KisPaintOpRegistry::instance()->paintOp( id, 0, m_painter );
+ m_painter->setPaintOp( op );
+ return 0;
+}
+
+}
+
+}
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_painter.h b/chalk/plugins/viewplugins/scripting/chalkcore/krs_painter.h
new file mode 100644
index 00000000..f4e2c06a
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_painter.h
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 KROSS_KRITACOREKRS_PAINTER_H
+#define KROSS_KRITACOREKRS_PAINTER_H
+
+#include <api/class.h>
+
+#include <kis_point.h>
+#include <kis_types.h>
+#include <kis_paint_layer.h>
+
+class KisPainter;
+class KisFillPainter;
+
+namespace Kross {
+
+namespace ChalkCore {
+
+class Painter : public Kross::Api::Class<Painter>
+{
+ public:
+ explicit Painter(KisPaintLayerSP layer);
+ ~Painter();
+ private:
+ // Convolution
+ /**
+ * This function apply a convolution kernel to an image.
+ * It takes at least three arguments :
+ * - a list of a list with the kernel (all lists need to have the same size)
+ * - factor
+ * - offset
+ *
+ * The value of a pixel will be given by the following function K*P/factor + offset,
+ * where K is the kernel and P is the neighbourhood.
+ *
+ * It can takes the following optional arguments :
+ * - borderOp control how to convolve the pixels on the border of an image ( 0 use the default color
+ * 1 use the pixel on the opposite side of the image 2 use the border pixel 3 avoid border pixels)
+ * - channel ( 1 for color 2 for alpha 3 for both)
+ * - x
+ * - y
+ * - width
+ * - height
+ */
+ Kross::Api::Object::Ptr convolve(Kross::Api::List::Ptr args);
+ // Fill specific
+ /**
+ * Set the threshold the fill threshold.
+ * It takes one argument :
+ * - threshold
+ */
+ Kross::Api::Object::Ptr setFillThreshold(Kross::Api::List::Ptr args);
+ /**
+ * Start filling color.
+ * It takes two argument :
+ * - x
+ * - y
+ */
+ Kross::Api::Object::Ptr fillColor(Kross::Api::List::Ptr args);
+ /**
+ * start filling a pattern
+ * It takes two argument :
+ * - x
+ * - y
+ */
+ Kross::Api::Object::Ptr fillPattern(Kross::Api::List::Ptr args);
+ // Painting operations
+ /**
+ * This function will paint a polyline.
+ * It takes two arguments :
+ * - a list of x position
+ * - a list of y position
+ */
+ Kross::Api::Object::Ptr paintPolyline(Kross::Api::List::Ptr args);
+ /**
+ * This function will paint a line.
+ * It takes five arguments :
+ * - x1
+ * - y1
+ * - x2
+ * - y2
+ * - pressure
+ */
+ Kross::Api::Object::Ptr paintLine(Kross::Api::List::Ptr args);
+ /**
+ * This function will paint a Bezier curve.
+ * It takes ten arguments :
+ * - x1
+ * - y1
+ * - p1
+ * - cx1
+ * - cy1
+ * - cx2
+ * - cx2
+ * - x2
+ * - y2
+ * - p2
+ *
+ * Where (x1,y1) is the start position, p1 is the pressure at the start,
+ * (x2,y2) is the ending position, p2 is the pressure at the end. (cx1,cy1) and (cx2,cy2)
+ * are the position of the control points.
+ */
+ Kross::Api::Object::Ptr paintBezierCurve(Kross::Api::List::Ptr args);
+ /**
+ * This function will paint an ellipse.
+ * It takes five arguments :
+ * - x1
+ * - y1
+ * - x2
+ * - y2
+ * - pressure
+ *
+ * Where (x1,y1) and (x2,y2) are the position of the two centers.
+ */
+ Kross::Api::Object::Ptr paintEllipse(Kross::Api::List::Ptr args);
+ /**
+ * This function will paint a polygon.
+ * It takes two arguments :
+ * - a list of x position
+ * - a list of y position
+ */
+ Kross::Api::Object::Ptr paintPolygon(Kross::Api::List::Ptr args);
+ /**
+ * This function will paint a rectangle.
+ * It takes five arguments :
+ * - x
+ * - y
+ * - width
+ * - height
+ * - pressure
+ */
+ Kross::Api::Object::Ptr paintRect(Kross::Api::List::Ptr args);
+ /**
+ * This function will paint at a given position.
+ * It takes three arguments :
+ * - x
+ * - y
+ * - pressure
+ */
+ Kross::Api::Object::Ptr paintAt(Kross::Api::List::Ptr args);
+ // Color operations
+ /**
+ * This functions set the paint color (also called foreground color).
+ * It takes one argument :
+ * - a Color
+ */
+ Kross::Api::Object::Ptr setPaintColor(Kross::Api::List::Ptr args);
+ /**
+ * This functions set the background color.
+ * It takes one argument :
+ * - a Color
+ */
+ Kross::Api::Object::Ptr setBackgroundColor(Kross::Api::List::Ptr args);
+ // How is painting done operations
+ /**
+ * This functions set the pattern used for filling.
+ * It takes one argument :
+ * - a Pattern object
+ */
+ Kross::Api::Object::Ptr setPattern(Kross::Api::List::Ptr args);
+ /**
+ * This functions set the brush used for painting.
+ * It takes one argument :
+ * - a Brush object
+ */
+ Kross::Api::Object::Ptr setBrush(Kross::Api::List::Ptr args);
+ /**
+ * This function define the paint operation.
+ * It takes one argument :
+ * - the name of the paint operation
+ */
+ Kross::Api::Object::Ptr setPaintOp(Kross::Api::List::Ptr args);
+ // Special settings
+ /**
+ * This function define the duplicate offset.
+ * It takes two arguments :
+ * - horizontal offset
+ * - vertical offset
+ */
+ Kross::Api::Object::Ptr setDuplicateOffset(Kross::Api::List::Ptr args);
+ // Style operation
+ /**
+ * This function set the opacity of the painting
+ * It takes one argument :
+ * - opacity in the range 0 to 255
+ */
+ Kross::Api::Object::Ptr setOpacity(Kross::Api::List::Ptr args);
+ /**
+ * This function set the style of the stroke.
+ * It takes one argument :
+ * - 0 for none 1 for brush
+ */
+ Kross::Api::Object::Ptr setStrokeStyle(Kross::Api::List::Ptr args);
+ /**
+ * This function set the fill style of the Painter.
+ * It takes one argument :
+ * - 0 for none 1 for fill with foreground color 2 for fill with background color
+ * 3 for fill with a pattern
+ */
+ Kross::Api::Object::Ptr setFillStyle(Kross::Api::List::Ptr args);
+ protected:
+ inline KisPaintLayerSP paintLayer() { return m_layer; }
+ private:
+ inline vKisPoint createPointsVector( TQValueList<TQVariant> xs, TQValueList<TQVariant> ys)
+ {
+ vKisPoint a;
+ TQValueList<TQVariant>::iterator itx = xs.begin();
+ TQValueList<TQVariant>::iterator ity = ys.begin();
+ for(; itx != xs.end(); ++itx, ++ity)
+ {
+ a.push_back(KisPoint( (*itx).toDouble(), (*ity).toDouble()));
+ }
+ return a;
+ }
+ inline KisFillPainter* createFillPainter();
+ private:
+ KisPaintLayerSP m_layer;
+ KisPainter* m_painter;
+ int m_threshold;
+};
+
+}
+
+}
+
+#endif
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_pattern.cpp b/chalk/plugins/viewplugins/scripting/chalkcore/krs_pattern.cpp
new file mode 100644
index 00000000..8ee4f909
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_pattern.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 "krs_pattern.h"
+
+#include <kis_pattern.h>
+
+namespace Kross {
+
+namespace ChalkCore {
+
+Pattern::Pattern(KisPattern* pattern, bool sharedPattern) : Kross::Api::Class<Pattern>("ChalkPattern"), m_pattern(pattern), m_sharedPattern(sharedPattern)
+{
+}
+
+Pattern::~Pattern()
+{
+ if(!m_sharedPattern)
+ delete m_pattern;
+}
+
+}
+
+}
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_pattern.h b/chalk/plugins/viewplugins/scripting/chalkcore/krs_pattern.h
new file mode 100644
index 00000000..be39cf31
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_pattern.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 KROSS_KRITACOREKRS_PATTERN_H
+#define KROSS_KRITACOREKRS_PATTERN_H
+
+#include <api/class.h>
+
+class KisPattern;
+
+namespace Kross {
+
+namespace ChalkCore {
+
+class Pattern : public Kross::Api::Class<Pattern>{
+ public:
+ /**
+ * @param sharedPattern tell if the pattern should be deleted or not when this object is deleted
+ */
+ Pattern(KisPattern*, bool sharedPattern);
+ ~Pattern();
+ public:
+ inline KisPattern* getPattern() { return m_pattern; }
+ private:
+ KisPattern* m_pattern;
+ bool m_sharedPattern;
+};
+
+}
+
+}
+
+#endif
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_script_progress.cpp b/chalk/plugins/viewplugins/scripting/chalkcore/krs_script_progress.cpp
new file mode 100644
index 00000000..b36076c4
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_script_progress.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 "krs_script_progress.h"
+
+#include "kis_script_progress.h"
+
+namespace Kross {
+
+namespace ChalkCore {
+
+ScriptProgress::ScriptProgress(KisScriptProgress* script): Kross::Api::Class<ScriptProgress>("ChalkScript"), m_script(script)
+{
+ addFunction("setProgressTotalSteps", &ScriptProgress::setProgressTotalSteps);
+ addFunction("setProgressTotalSteps", &ScriptProgress::setProgressTotalSteps);
+ addFunction("setProgress", &ScriptProgress::setProgress);
+ addFunction("incProgress", &ScriptProgress::incProgress);
+ addFunction("setProgressStage", &ScriptProgress::setProgressStage);
+}
+
+
+ScriptProgress::~ScriptProgress()
+{
+}
+
+Kross::Api::Object::Ptr ScriptProgress::setProgressTotalSteps(Kross::Api::List::Ptr args)
+{
+ m_script->setProgressTotalSteps( Kross::Api::Variant::toUInt(args->item(0)) );
+ return 0;
+}
+
+Kross::Api::Object::Ptr ScriptProgress::setProgress(Kross::Api::List::Ptr args)
+{
+ m_script->setProgress( Kross::Api::Variant::toUInt(args->item(0)) );
+ return 0;
+}
+
+Kross::Api::Object::Ptr ScriptProgress::incProgress(Kross::Api::List::Ptr)
+{
+ m_script->incProgress();
+ return 0;
+}
+
+Kross::Api::Object::Ptr ScriptProgress::setProgressStage(Kross::Api::List::Ptr args)
+{
+ m_script->setProgressStage( Kross::Api::Variant::toString(args->item(0)), Kross::Api::Variant::toUInt(args->item(1)) );
+ return 0;
+}
+
+}
+
+}
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_script_progress.h b/chalk/plugins/viewplugins/scripting/chalkcore/krs_script_progress.h
new file mode 100644
index 00000000..b2ae7e44
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_script_progress.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 KROSS_KRITACOREKRS_SCRIPTPROGRESS_H
+#define KROSS_KRITACOREKRS_SCRIPTPROGRESS_H
+
+#include <api/class.h>
+
+class KisScriptProgress;
+
+namespace Kross {
+
+namespace ChalkCore {
+
+/**
+ * ScriptProgress is used to manage the progress bar of the status bar in chalk
+ *
+ * For example (in ruby) :
+ * @code
+ * script = Krosschalkcore::get("ChalkScript")
+ * script.setProgressTotalSteps(1000)
+ * script.setProgressStage("progressive", 0)
+ * for i in 1..900
+ * script.incProgress()
+ * end
+ * script.setProgressStage("brutal", 1000)
+ * @endcode
+ */
+class ScriptProgress : public Kross::Api::Class<ScriptProgress> {
+ public:
+ ScriptProgress(KisScriptProgress* Script);
+ ~ScriptProgress();
+ private:
+ /**
+ * This function set the number of steps that the script will require.
+ * It takes one argument :
+ * - maximum value of the progress
+ */
+ Kross::Api::Object::Ptr setProgressTotalSteps(Kross::Api::List::Ptr);
+ /**
+ * This function set the value of progress.
+ * It takes one argument :
+ * - value of the progress
+ */
+ Kross::Api::Object::Ptr setProgress(Kross::Api::List::Ptr);
+ /**
+ * This function increment of one step the position of the progress.
+ */
+ Kross::Api::Object::Ptr incProgress(Kross::Api::List::Ptr);
+ /**
+ * This function set the value of the progress and display the text
+ */
+ Kross::Api::Object::Ptr setProgressStage(Kross::Api::List::Ptr);
+ private:
+ KisScriptProgress* m_script;
+};
+
+}
+
+}
+
+#endif
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_wavelet.cpp b/chalk/plugins/viewplugins/scripting/chalkcore/krs_wavelet.cpp
new file mode 100644
index 00000000..e166de7c
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_wavelet.cpp
@@ -0,0 +1,114 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 "krs_wavelet.h"
+
+#include <klocale.h>
+
+#include <kis_math_toolbox.h>
+
+namespace Kross {
+
+namespace ChalkCore {
+
+Wavelet::Wavelet(KisMathToolbox::KisWavelet* kwl)
+ : Kross::Api::Class<Wavelet>("ChalkWavelet"), m_wavelet(kwl)
+{
+ addFunction("getNCoeff", &Wavelet::getNCoeff);
+ addFunction("setNCoeff", &Wavelet::setNCoeff);
+ addFunction("getXYCoeff", &Wavelet::getXYCoeff);
+ addFunction("setXYCoeff", &Wavelet::setXYCoeff);
+ addFunction("getDepth", &Wavelet::getDepth);
+ addFunction("getSize", &Wavelet::getSize);
+ addFunction("getNumCoeffs", &Wavelet::getNumCoeffs);
+ m_numCoeff = m_wavelet->size*m_wavelet->size*m_wavelet->depth;
+}
+
+
+Wavelet::~Wavelet()
+{
+}
+
+
+Kross::Api::Object::Ptr Wavelet::getNCoeff(Kross::Api::List::Ptr args)
+{
+ TQ_UINT32 n = Kross::Api::Variant::toUInt(args->item(0));
+ if( n > m_numCoeff)
+ {
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("An error has occured in %1").tqarg("getNCoeff") + "\n" + i18n("Index out of bound") ) );
+ }
+ return new Kross::Api::Variant(*(m_wavelet->coeffs + n ));
+}
+
+Kross::Api::Object::Ptr Wavelet::setNCoeff(Kross::Api::List::Ptr args)
+{
+ TQ_UINT32 n = Kross::Api::Variant::toUInt(args->item(0));
+ double v = Kross::Api::Variant::toDouble(args->item(1));
+ if( n > m_numCoeff)
+ {
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("An error has occured in %1").tqarg("setNCoeff") + "\n" + i18n("Index out of bound") ) );
+ }
+ *(m_wavelet->coeffs + n ) = v;
+ return 0;
+}
+
+Kross::Api::Object::Ptr Wavelet::getXYCoeff(Kross::Api::List::Ptr args)
+{
+ TQ_UINT32 x = Kross::Api::Variant::toUInt(args->item(0));
+ TQ_UINT32 y = Kross::Api::Variant::toUInt(args->item(1));
+ if( x > m_wavelet->size && y > m_wavelet->size)
+ {
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("An error has occured in %1").tqarg("getXYCoeff") + "\n" + i18n("Index out of bound") ) );
+ }
+ return new Kross::Api::Variant(*(m_wavelet->coeffs + (x + y * m_wavelet->size ) * m_wavelet->depth ));
+}
+
+Kross::Api::Object::Ptr Wavelet::setXYCoeff(Kross::Api::List::Ptr args)
+{
+ TQ_UINT32 x = Kross::Api::Variant::toUInt(args->item(0));
+ TQ_UINT32 y = Kross::Api::Variant::toUInt(args->item(1));
+ double v = Kross::Api::Variant::toDouble(args->item(2));
+ if( x > m_wavelet->size && y > m_wavelet->size)
+ {
+ throw Kross::Api::Exception::Ptr( new Kross::Api::Exception( i18n("An error has occured in %1").tqarg("setXYCoeff") + "\n" + i18n("Index out of bound") ));
+ }
+ *(m_wavelet->coeffs + (x + y * m_wavelet->size ) * m_wavelet->depth ) = v;
+ return 0;
+}
+
+Kross::Api::Object::Ptr Wavelet::getDepth(Kross::Api::List::Ptr /*args*/)
+{
+ return new Kross::Api::Variant(m_wavelet->depth);
+}
+
+Kross::Api::Object::Ptr Wavelet::getSize(Kross::Api::List::Ptr)
+{
+ return new Kross::Api::Variant(m_wavelet->size);
+}
+
+Kross::Api::Object::Ptr Wavelet::getNumCoeffs(Kross::Api::List::Ptr)
+{
+ return new Kross::Api::Variant(m_numCoeff);
+}
+
+
+}
+
+}
diff --git a/chalk/plugins/viewplugins/scripting/chalkcore/krs_wavelet.h b/chalk/plugins/viewplugins/scripting/chalkcore/krs_wavelet.h
new file mode 100644
index 00000000..8a9a0889
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkcore/krs_wavelet.h
@@ -0,0 +1,92 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 KROSS_KRITACOREKRS_WAVELET_H
+#define KROSS_KRITACOREKRS_WAVELET_H
+
+#include <api/class.h>
+
+#include <kis_math_toolbox.h>
+
+namespace Kross {
+
+namespace ChalkCore {
+
+/**
+ @author Cyrille Berger <cberger@cberger.net>
+*/
+class Wavelet : public Kross::Api::Class<Wavelet>
+{
+ public:
+ Wavelet(KisMathToolbox::KisWavelet* wavelet);
+ ~Wavelet();
+ private:
+ /**
+ * Return the value of the Nth coefficient
+ * The function takes one argument :
+ * - the index of the coefficient
+ */
+ Kross::Api::Object::Ptr getNCoeff(Kross::Api::List::Ptr);
+ /**
+ * Set the value of the Nth coefficient
+ * The function takes two arguments :
+ * - the index of the coefficient
+ * - the new value of the coefficient
+ */
+ Kross::Api::Object::Ptr setNCoeff(Kross::Api::List::Ptr);
+ /**
+ * Return the value of a coefficient
+ * The function takes two arguments :
+ * - x
+ * - y
+ */
+ Kross::Api::Object::Ptr getXYCoeff(Kross::Api::List::Ptr);
+ /**
+ * Set the value of a coefficient
+ * The function takes three arguments :
+ * - x
+ * - y
+ * - the new value of the coefficient
+ */
+ Kross::Api::Object::Ptr setXYCoeff(Kross::Api::List::Ptr);
+ /**
+ * Return the depth of the layer
+ */
+ Kross::Api::Object::Ptr getDepth(Kross::Api::List::Ptr);
+ /**
+ * Return the size of the wavelet (size = width = height)
+ */
+ Kross::Api::Object::Ptr getSize(Kross::Api::List::Ptr);
+ /**
+ * Return the number of coefficients in this wavelet (= size * size * depth)
+ */
+ Kross::Api::Object::Ptr getNumCoeffs(Kross::Api::List::Ptr);
+ public:
+ KisMathToolbox::KisWavelet* wavelet() { return m_wavelet; }
+ private:
+ KisMathToolbox::KisWavelet* m_wavelet;
+ uint m_numCoeff;
+};
+
+}
+
+}
+
+#endif
diff --git a/chalk/plugins/viewplugins/scripting/chalkscripting.desktop b/chalk/plugins/viewplugins/scripting/chalkscripting.desktop
new file mode 100644
index 00000000..511e76a0
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkscripting.desktop
@@ -0,0 +1,81 @@
+[Desktop Entry]
+Name=Scripting plugin
+Name[bg]=Приставка за скриптове
+Name[ca]=Connector de seqüenciació
+Name[da]=Scriptplugin
+Name[de]=Skripting-Modul
+Name[el]=Πρόσθετο γραφής σεναρίων
+Name[eo]=Skriptad-kromaĵo
+Name[es]=Complemento para guiones
+Name[et]=Skriptiplugin
+Name[fa]=وصلۀ دست‌نوشته
+Name[fr]=Module de scriptage
+Name[fy]=Skriptplugin
+Name[ga]=Breiseán scriptithe
+Name[gl]=Plugin de programación
+Name[he]=תוסף לתסריטים
+Name[hu]=Szkript modul
+Name[is]=Skriftu íforrit
+Name[it]=Plugin di scripting
+Name[ja]=スクリプトプラグイン
+Name[km]=កម្មវិធី​ជំនួយ​សម្រាប់​ស្គ្រីប
+Name[nb]=Programtillegg for skripting
+Name[nds]=Skriptmoduul
+Name[ne]=प्लगइन स्क्रिप्ट गर्दै
+Name[nl]=Scriptplugin
+Name[pl]=Wtyczka obsługi języków skryptowych
+Name[pt]='Plugin' de programação
+Name[pt_BR]=Plugin de programação
+Name[ru]=Модуль поддержки сценариев
+Name[sk]=Modul pre skripty
+Name[sl]=Vstavek za skripte
+Name[sr]=Прикључак за скриптовање
+Name[sr@Latn]=Priključak za skriptovanje
+Name[sv]=Skriptinsticksprogram
+Name[uk]=Втулок для скриптів
+Name[uz]=Skriptlash plagini
+Name[uz@cyrillic]=Скриптлаш плагини
+Name[zh_CN]=脚本插件
+Name[zh_TW]=命令稿外掛程式
+Comment=Allow execution of scripts
+Comment[bg]=Изпълнение на скриптове
+Comment[ca]=Permet l'execució de seqüències
+Comment[da]=Tillad kørsel af script
+Comment[de]=Ermöglicht das Ausführen von Skripten
+Comment[el]=Επιτρέπει την εκτέλεση σεναρίων
+Comment[eo]=Permesi ruligon de skriptoj
+Comment[es]=Permite la ejecución de guiones
+Comment[et]=Võimaldab skriptide käivitamist
+Comment[fa]=اجازۀ اجرای دست‌نوشته‌ها
+Comment[fr]=Permet d'exécuter des scripts
+Comment[fy]=Hjirmei kinne skripts útfierd wurde
+Comment[gl]=Permite executar guións
+Comment[he]=אפשרות להרצת תסריטים
+Comment[hu]=Lehetővé teszi szkriptek végrehajtását
+Comment[is]=Leyfa að skriftur séu keyrðar
+Comment[it]=Permette di eseguire script
+Comment[ja]=スクリプトの実行を可能にします
+Comment[km]=អនុញ្ញាត​ឲ្យ​ប្រតិបត្តិ​ស្គ្រីប
+Comment[lv]=Atļaut skriptu izpildi
+Comment[nb]=Tillater skriptkjøring
+Comment[nds]=Skripten utföhren
+Comment[ne]=स्क्रिप्टको कार्यान्वयनलाई अनुमति दिनुहोस्
+Comment[nl]=Hiermee kunnen scripts uitgevoerd worden
+Comment[pl]=Zezwala na wykonywanie skryptów
+Comment[pt]=Permitir executar programas ou 'scripts'
+Comment[pt_BR]=Permitir executar programas ou 'scripts'
+Comment[ru]=Возможность выполнения сценариев
+Comment[sk]=Povoliť vykonávanie skriptov
+Comment[sl]=Dovoli izvedbo skriptov
+Comment[sr]=Омогући извршавање скрипти
+Comment[sr@Latn]=Omogući izvršavanje skripti
+Comment[sv]=Tillåt körning av skript
+Comment[uk]=Дає змогу виконувати скрипти
+Comment[uz]=Skriptlarni ishga tushirishga ruxsat berish
+Comment[uz@cyrillic]=Скриптларни ишга туширишга рухсат бериш
+Comment[zh_CN]=允许执行脚本
+Comment[zh_TW]=允許執行命令稿
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalkscripting
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/scripting/chalkscripting/Makefile.am b/chalk/plugins/viewplugins/scripting/chalkscripting/Makefile.am
new file mode 100644
index 00000000..b805ef18
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkscripting/Makefile.am
@@ -0,0 +1,19 @@
+INCLUDES = -I$(top_srcdir)/chalk/sdk \
+ -I$(top_srcdir)/chalk/core \
+ -I$(top_srcdir)/chalk/chalkcolor/ \
+ -I$(top_srcdir)/chalk/ui \
+ $(KROSS_INCLUDES) \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+
+lib_LTLIBRARIES = libchalkscripting.la
+libchalkscripting_la_SOURCES = kis_script_progress.cpp kis_script_monitor.cpp
+noinst_HEADERS = kis_script_progress.h
+
+libchalkscripting_la_LDFLAGS = -no-undefined $(all_libraries)
+libchalkscripting_la_LIBADD = $(top_builddir)/chalk/libchalkcommon.la $(top_builddir)/lib/kross/main/libkrossmain.la
+
+KDE_CXXFLAGS = $(USE_EXCEPTIONS)
+
+libchalkscripting_la_METASOURCES = AUTO
diff --git a/chalk/plugins/viewplugins/scripting/chalkscripting/kis_script_monitor.cpp b/chalk/plugins/viewplugins/scripting/chalkscripting/kis_script_monitor.cpp
new file mode 100644
index 00000000..3967ffe7
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkscripting/kis_script_monitor.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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_script_monitor.h"
+
+#include <main/scriptaction.h>
+#include <main/scriptguiclient.h>
+
+
+KisScriptMonitor::KisScriptMonitor()
+{
+}
+
+
+KisScriptMonitor::~KisScriptMonitor()
+{
+ s_instance = 0;
+}
+
+void KisScriptMonitor::monitor(Kross::Api::ScriptGUIClient* guiClient)
+{
+ connect(guiClient, TQT_SIGNAL(executionFinished( const Kross::Api::ScriptAction* )), TQT_SIGNAL(executionFinished( const Kross::Api::ScriptAction* )));
+ connect(guiClient, TQT_SIGNAL(executionStarted( const Kross::Api::ScriptAction* )), TQT_SIGNAL(executionStarted( const Kross::Api::ScriptAction* )));
+}
+
+KisScriptMonitor* KisScriptMonitor::s_instance = 0;
+
+KisScriptMonitor* KisScriptMonitor::instance()
+{
+ if(s_instance == 0)
+ s_instance = new KisScriptMonitor();
+ return s_instance;
+}
+
+#include "kis_script_monitor.moc"
+
diff --git a/chalk/plugins/viewplugins/scripting/chalkscripting/kis_script_monitor.h b/chalk/plugins/viewplugins/scripting/chalkscripting/kis_script_monitor.h
new file mode 100644
index 00000000..c1ee64c0
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkscripting/kis_script_monitor.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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_SCRIPT_MONITOR_H
+#define KIS_SCRIPT_MONITOR_H
+
+#include <tqobject.h>
+
+namespace Kross {
+ namespace Api {
+ class ScriptGUIClient;
+ class ScriptAction;
+ }
+}
+
+/**
+ @author Cyrille Berger <cberger@cberger.net>
+*/
+class KisScriptMonitor : public TQObject {
+ Q_OBJECT
+ TQ_OBJECT
+ private:
+ KisScriptMonitor();
+ ~KisScriptMonitor();
+ public:
+ static KisScriptMonitor* instance();
+ void monitor(Kross::Api::ScriptGUIClient* guiClient);
+ signals:
+ void executionFinished(const Kross::Api::ScriptAction* );
+ void executionStarted(const Kross::Api::ScriptAction* );
+ private:
+ static KisScriptMonitor* s_instance;
+
+};
+
+#endif
diff --git a/chalk/plugins/viewplugins/scripting/chalkscripting/kis_script_progress.cpp b/chalk/plugins/viewplugins/scripting/chalkscripting/kis_script_progress.cpp
new file mode 100644
index 00000000..d7af4eb4
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkscripting/kis_script_progress.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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_script_progress.h"
+
+#include <kis_progress_display_interface.h>
+#include <kis_view.h>
+
+void KisScriptProgress::activateAsSubject()
+{
+ m_view->canvasSubject()->progressDisplay()->setSubject( this, true, false /* TODO: how to cancel a script ? */ );
+}
+
+void KisScriptProgress::setProgressTotalSteps(TQ_INT32 totalSteps)
+{
+ m_progressTotalSteps = totalSteps;
+ m_progressSteps = 0;
+ m_lastProgressPerCent = 0;
+ emit notifyProgress(0);
+}
+
+void KisScriptProgress::setProgress(TQ_INT32 progress)
+{
+ m_progressSteps = progress;
+ TQ_INT32 progressPerCent = (m_progressSteps * 100) / (m_progressTotalSteps > 0 ? m_progressTotalSteps : 1);
+
+ if (progressPerCent != m_lastProgressPerCent) {
+
+ m_lastProgressPerCent = progressPerCent;
+ emit notifyProgress(progressPerCent);
+ }
+}
+
+void KisScriptProgress::incProgress()
+{
+ setProgress( ++m_progressSteps );
+}
+
+void KisScriptProgress::setProgressStage(const TQString& stage, TQ_INT32 progress)
+{
+ TQ_INT32 progressPerCent = (progress * 100) / (m_progressTotalSteps > 0 ? m_progressTotalSteps : 1);
+ m_lastProgressPerCent = progress;
+ emit notifyProgressStage( stage, progressPerCent);
+}
+
+void KisScriptProgress::progressDone()
+{
+ emit notifyProgressDone();
+}
diff --git a/chalk/plugins/viewplugins/scripting/chalkscripting/kis_script_progress.h b/chalk/plugins/viewplugins/scripting/chalkscripting/kis_script_progress.h
new file mode 100644
index 00000000..48af433c
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/chalkscripting/kis_script_progress.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * This program 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 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 Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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_SCRIPT_PROGRESS_H_
+#define _KIS_SCRIPT_PROGRESS_H_
+
+#include <kis_progress_subject.h>
+
+class KisView;
+
+/**
+ * TODO: clarify the situation, while, in the future, multiple scripts could be running at a same time,
+ * some of the functions are global to all script and some aren't.
+ */
+class KisScriptProgress : public KisProgressSubject
+{
+ public:
+ KisScriptProgress(KisView* view) : m_view(view) {};
+ public:
+ /**
+ * This function will set this class as the KisProgressSubject in view
+ */
+ void activateAsSubject();
+ virtual void cancel() {};
+ public:
+ void setProgressTotalSteps(TQ_INT32 totalSteps);
+ void setProgress(TQ_INT32 progress);
+ void incProgress();
+ void setProgressStage(const TQString& stage, TQ_INT32 progress);
+ void progressDone();
+ inline void setPackagePath(TQString path) { m_packagePath = path; };
+ inline TQString packagePath() { return m_packagePath; }
+ private:
+ TQ_INT32 m_progressSteps, m_progressTotalSteps, m_lastProgressPerCent;
+ KisView * m_view;
+ TQString m_packagePath;
+};
+
+#endif
diff --git a/chalk/plugins/viewplugins/scripting/samples/Makefile.am b/chalk/plugins/viewplugins/scripting/samples/Makefile.am
new file mode 100644
index 00000000..0f0c383d
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/Makefile.am
@@ -0,0 +1,3 @@
+INCLUDES = -I$(srcdir)/../../../sdk -I$(srcdir)/../../../core -I$(srcdir)/../../../chalkcolor/ -I$(srcdir)/../../../ui -I$(top_srcdir)/kexi/scriptingcore/main $(KOFFICE_INCLUDES) $(all_includes)
+METASOURCES = AUTO
+SUBDIRS = python ruby
diff --git a/chalk/plugins/viewplugins/scripting/samples/python/Makefile.am b/chalk/plugins/viewplugins/scripting/samples/python/Makefile.am
new file mode 100644
index 00000000..c15a3b3b
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/python/Makefile.am
@@ -0,0 +1,5 @@
+scriptinvertdir = $(kde_datadir)/chalk/scripts/invertpython
+scriptinvert_SCRIPTS = invert.py invertpython.rc
+
+scriptreshapedir = $(kde_datadir)/chalk/scripts/reshapehisto
+scriptreshape_SCRIPTS = reshapehisto.py reshapehisto.rc
diff --git a/chalk/plugins/viewplugins/scripting/samples/python/invert.py b/chalk/plugins/viewplugins/scripting/samples/python/invert.py
new file mode 100644
index 00000000..7a642760
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/python/invert.py
@@ -0,0 +1,48 @@
+# This file is part of Chalk
+#
+# Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net>
+#
+# 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.
+
+class Inverter:
+ def __init__(self):
+ try:
+ import krosschalkcore
+ except:
+ raise "Import of the ChalkCore module failed."
+ doc = krosschalkcore.get("ChalkDocument")
+ script = krosschalkcore.get("ChalkScript")
+ image = doc.getImage()
+ layer = image.getActivePaintLayer()
+ if(layer.colorSpaceId() != "RGBA" ):
+ raise("This script works only for 8bit RGBA layers")
+ width = layer.getWidth()
+ height = layer.getHeight()
+ script.setProgressTotalSteps(width * height)
+ layer.beginPainting("invert")
+ it = layer.createRectIterator( 0, 0, width, height )
+ print "kikoo\n"
+ finesh = it.isDone()
+ while (not finesh) :
+ p = it.getRGBA()
+ p[0] = 255 - p[0]
+ p[1] = 255 - p[1]
+ p[2] = 255 - p[2]
+ it.setRGBA(p)
+ script.incProgress()
+ finesh = it.next()
+ layer.endPainting()
+
+Inverter()
diff --git a/chalk/plugins/viewplugins/scripting/samples/python/invertpython.rc b/chalk/plugins/viewplugins/scripting/samples/python/invertpython.rc
new file mode 100644
index 00000000..d2224311
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/python/invertpython.rc
@@ -0,0 +1,9 @@
+<KrossScripting>
+ <ScriptAction
+ name="InvertPython"
+ text="Invert (python)"
+ description="Invert the pixel of an image (python)"
+ icon=""
+ interpreter="python"
+ file="invert.py" />
+</KrossScripting>
diff --git a/chalk/plugins/viewplugins/scripting/samples/python/reshapehisto.py b/chalk/plugins/viewplugins/scripting/samples/python/reshapehisto.py
new file mode 100644
index 00000000..4ef66965
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/python/reshapehisto.py
@@ -0,0 +1,300 @@
+# This file is part of Chalk
+#
+# Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+#
+# 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.
+
+import math
+
+# it's an experimental script to try to reshape.histogram, while the results are far to be convincing yet
+# it is still an example on how to use histogram in a script
+
+def sign(a):
+ if a < 0:
+ return -1
+ else:
+ return 1
+#def abs(a):
+ #if a <
+
+def computeDiff(histo, histoTarget):
+ diff = [ ]
+ histoMax = histo.getHighest()
+ count = 0
+ while( count < 256 ) :
+ v = histo.getValue(count)
+ diff.append( v / histoMax - histoTarget[count])
+ count += 1
+ derivdiff = [ ]
+ derivdiff.append(diff[1] - diff[0] )
+ count = 1
+ while( count < 255 ) :
+ derivdiff.append((diff[count+1] - diff[count - 1])/2.0)
+ print count
+ print " "
+ print derivdiff[count]
+ print " "
+ count += 1
+ derivdiff.append(diff[255] - diff[254] )
+ return diff
+
+try:
+ import krosschalkcore
+except:
+ raise "Import of the ChalkCore module failed."
+
+#histoTarget = [ 0.0, 0.01226531745085, 0.024528789662323, 0.0367885716726463, 0.049042819075215, 0.0612896882960706, 0.0735273368712555, 0.0857539237239997, 0.0979676094416996, 0.110166556552646, 0.122348929802458, 0.13451289643019, 0.146656626444054, 0.158778292896733, 0.170876072160234, 0.18294814420024, 0.194992692849922, 0.207007906083172, 0.218991976287209, 0.230943100534525, 0.242859480854121, 0.254739324502003, 0.266580844230888, 0.278382258559083, 0.290141792038499, 0.301857675521758, 0.313528146428344, 0.325151449009778, 0.336725834613756, 0.348249561947225, 0.359720897338346, 0.371138114997318, 0.38249949727601, 0.393803334926368, 0.405047927357568, 0.416231582891849, 0.427352619019025, 0.4384093626496, 0.449400150366478, 0.460323328675215, 0.471177254252771, 0.481960294194744, 0.492670826261026, 0.50330723911986, 0.513867932590253, 0.524351317882718, 0.534755817838293, 0.545079867165813, 0.555321912677404, 0.565480413522147, 0.575553841417885, 0.585540680881154, 0.595439429455167, 0.605248597935856, 0.614966710595909, 0.624592305406788, 0.634123934258679, 0.643560163178352, 0.652899572544893, 0.662140757303275, 0.671282327175744, 0.680322906870975, 0.689261136290974, 0.698095670735701, 0.706825181105366, 0.715448354100387, 0.723963892418968, 0.732370514952268, 0.740666956977137, 0.748851970346384, 0.756924323676554, 0.764882802533185, 0.772726209613504, 0.780453364926561, 0.788063105970749, 0.795554287908693, 0.802925783739486, 0.810176484468239, 0.817305299272921, 0.824311155668464, 0.83119299966812, 0.837949795942015, 0.84458052797292, 0.851084198209167, 0.857459828214736, 0.863706458816447, 0.869823150248263, 0.875808982292675, 0.881663054419139, 0.887384485919556, 0.892972416040772, 0.898426004114068, 0.903744429681637, 0.908926892620016, 0.913972613260457, 0.918880832506229, 0.923650811946811, 0.928281833968988, 0.93277320186481, 0.937124239936404, 0.941334293597632, 0.945402729472569, 0.949328935490789, 0.953112320979447, 0.956752316752142, 0.960248375194552, 0.963599970346811, 0.966806597982642, 0.969867775685214, 0.972783042919718, 0.97555196110265, 0.978174113667795, 0.980649106128898, 0.982976566139007, 0.985156143546496, 0.987187510447739, 0.989070361236445, 0.990804412649628, 0.99238940381023, 0.993825096266363, 0.995111274027184, 0.99624774359539, 0.997234333996328, 0.998070896803715, 0.998757306161974, 0.99929345880516, 0.999679274072503, 0.999914693920536, 0.999999682931835, 0.99993422832034, 0.999718339933283, 0.999352050249705, 0.998835414375572, 0.998168510035481, 0.997351437560967, 0.996384319875413, 0.995267302475555, 0.994000553409588, 0.992584263251893, 0.991018645074359, 0.989303934414332, 0.987440389239176, 0.985428289907469, 0.983267939126818, 0.980959661908326, 0.978503805517689, 0.975900739422957, 0.973150855238948, 0.970254566668332, 0.967212309439392, 0.964024541240472, 0.960691741651122, 0.957214412069943, 0.953593075639162, 0.949828277165924, 0.945920583040329, 0.941870581150226, 0.937678880792763, 0.933346112582728, 0.928872928357675, 0.924260001079857, 0.919508024734984, 0.914617714227821, 0.909589805274631, 0.90442505429249, 0.899124238285494, 0.89368815472786, 0.888117621443952, 0.882413476485242, 0.876576578004235, 0.870607804125365, 0.86450805281288, 0.858278241735758, 0.851919308129644, 0.845432208655849, 0.83881791925743, 0.832077435012361, 0.825211769983833, 0.818221957067693, 0.811109047837053, 0.803874112384084, 0.796518239159033, 0.789042534806467, 0.781448123998789, 0.773736149267035, 0.76590777082899, 0.757964166414642, 0.749906531088995, 0.741736077072283, 0.733454033557598, 0.725061646525966, 0.716560178558895, 0.707950908648432, 0.699235132004742, 0.690414159861254, 0.681489319277395, 0.672461952938941, 0.663333418956019, 0.654105090658787, 0.644778356390828, 0.635354619300277, 0.625835297128734, 0.616221821997965, 0.606515640194456, 0.596718211951823, 0.586831011231134, 0.576855525499155, 0.566793255504575, 0.556645715052225, 0.546414430775338, 0.536100941905873, 0.525706800042952, 0.515233568919429, 0.504682824166636, 0.49405615307734, 0.483355154366944, 0.472581437932973, 0.461736624612871, 0.450822345940161, 0.439840243898986, 0.428791970677089, 0.417679188417244, 0.406503568967204, 0.39526679362818, 0.383970552901897, 0.372616546236274, 0.361206481769749, 0.349742076074299, 0.338225053897198, 0.326657147901536, 0.315040098405551, 0.303375653120808, 0.291665566889271, 0.279911601419294, 0.268115525020586, 0.256279112338177, 0.244404144085436, 0.232492406776176, 0.220545692455878, 0.208565798432095, 0.196554527004056, 0.184513685191523, 0.172445084462932, 0.160350540462877, 0.148231872738948, 0.136090904468, 0.123929462181863, 0.111749375492553, 0.0995524768170189, 0.0873406011014653, 0.0751155855452987, 0.0628792693247314, 0.0506334933160884, 0.0383800998188613, 0.0261209322785436, 0.0138578350092972 ]
+
+histoTarget = [ 0.0, 0.00392156862745098, 0.00784313725490196, 0.0117647058823529, 0.0156862745098039, 0.0196078431372549, 0.0235294117647059, 0.0274509803921569, 0.0313725490196078, 0.0352941176470588, 0.0392156862745098, 0.0431372549019608, 0.0470588235294118, 0.0509803921568627, 0.0549019607843137, 0.0588235294117647, 0.0627450980392157, 0.0666666666666667, 0.0705882352941176, 0.0745098039215686, 0.0784313725490196, 0.0823529411764706, 0.0862745098039216, 0.0901960784313725, 0.0941176470588235, 0.0980392156862745, 0.101960784313725, 0.105882352941176, 0.109803921568627, 0.113725490196078, 0.117647058823529, 0.12156862745098, 0.125490196078431, 0.129411764705882, 0.133333333333333, 0.137254901960784, 0.141176470588235, 0.145098039215686, 0.149019607843137, 0.152941176470588, 0.156862745098039, 0.16078431372549, 0.164705882352941, 0.168627450980392, 0.172549019607843, 0.176470588235294, 0.180392156862745, 0.184313725490196, 0.188235294117647, 0.192156862745098, 0.196078431372549, 0.2, 0.203921568627451, 0.207843137254902, 0.211764705882353, 0.215686274509804, 0.219607843137255, 0.223529411764706, 0.227450980392157, 0.231372549019608, 0.235294117647059, 0.23921568627451, 0.243137254901961, 0.247058823529412, 0.250980392156863, 0.254901960784314, 0.258823529411765, 0.262745098039216, 0.266666666666667, 0.270588235294118, 0.274509803921569, 0.27843137254902, 0.282352941176471, 0.286274509803922, 0.290196078431373, 0.294117647058824, 0.298039215686275, 0.301960784313725, 0.305882352941176, 0.309803921568627, 0.313725490196078, 0.317647058823529, 0.32156862745098, 0.325490196078431, 0.329411764705882, 0.333333333333333, 0.337254901960784, 0.341176470588235, 0.345098039215686, 0.349019607843137, 0.352941176470588, 0.356862745098039, 0.36078431372549, 0.364705882352941, 0.368627450980392, 0.372549019607843, 0.376470588235294, 0.380392156862745, 0.384313725490196, 0.388235294117647, 0.392156862745098, 0.396078431372549, 0.4, 0.403921568627451, 0.407843137254902, 0.411764705882353, 0.415686274509804, 0.419607843137255, 0.423529411764706, 0.427450980392157, 0.431372549019608, 0.435294117647059, 0.43921568627451, 0.443137254901961, 0.447058823529412, 0.450980392156863, 0.454901960784314, 0.458823529411765, 0.462745098039216, 0.466666666666667, 0.470588235294118, 0.474509803921569, 0.47843137254902, 0.482352941176471, 0.486274509803922, 0.490196078431373, 0.494117647058824, 0.498039215686275, 0.501960784313725, 0.505882352941176, 0.509803921568627, 0.513725490196078, 0.517647058823529, 0.52156862745098, 0.525490196078431, 0.529411764705882, 0.533333333333333, 0.537254901960784, 0.541176470588235, 0.545098039215686, 0.549019607843137, 0.552941176470588, 0.556862745098039, 0.56078431372549, 0.564705882352941, 0.568627450980392, 0.572549019607843, 0.576470588235294, 0.580392156862745, 0.584313725490196, 0.588235294117647, 0.592156862745098, 0.596078431372549, 0.6, 0.603921568627451, 0.607843137254902, 0.611764705882353, 0.615686274509804, 0.619607843137255, 0.623529411764706, 0.627450980392157, 0.631372549019608, 0.635294117647059, 0.63921568627451, 0.643137254901961, 0.647058823529412, 0.650980392156863, 0.654901960784314, 0.658823529411765, 0.662745098039216, 0.666666666666667, 0.670588235294118, 0.674509803921569, 0.67843137254902, 0.682352941176471, 0.686274509803922, 0.690196078431373, 0.694117647058824, 0.698039215686274, 0.701960784313725, 0.705882352941177, 0.709803921568627, 0.713725490196078, 0.717647058823529, 0.72156862745098, 0.725490196078431, 0.729411764705882, 0.733333333333333, 0.737254901960784, 0.741176470588235, 0.745098039215686, 0.749019607843137, 0.752941176470588, 0.756862745098039, 0.76078431372549, 0.764705882352941, 0.768627450980392, 0.772549019607843, 0.776470588235294, 0.780392156862745, 0.784313725490196, 0.788235294117647, 0.792156862745098, 0.796078431372549, 0.8, 0.803921568627451, 0.807843137254902, 0.811764705882353, 0.815686274509804, 0.819607843137255, 0.823529411764706, 0.827450980392157, 0.831372549019608, 0.835294117647059, 0.83921568627451, 0.843137254901961, 0.847058823529412, 0.850980392156863, 0.854901960784314, 0.858823529411765, 0.862745098039216, 0.866666666666667, 0.870588235294118, 0.874509803921569, 0.87843137254902, 0.882352941176471, 0.886274509803922, 0.890196078431372, 0.894117647058824, 0.898039215686275, 0.901960784313726, 0.905882352941176, 0.909803921568627, 0.913725490196078, 0.917647058823529, 0.92156862745098, 0.925490196078431, 0.929411764705882, 0.933333333333333, 0.937254901960784, 0.941176470588235, 0.945098039215686, 0.949019607843137, 0.952941176470588, 0.956862745098039, 0.96078431372549, 0.964705882352941, 0.968627450980392, 0.972549019607843, 0.976470588235294, 0.980392156862745, 0.984313725490196, 0.988235294117647, 0.992156862745098, 0.996078431372549, 1.0 ]
+
+doc = krosschalkcore.get("ChalkDocument")
+image = doc.getImage()
+layer = image.getActivePaintLayer()
+if (layer.colorSpaceId() != "RGBA" ):
+ raise("This script works only for 8bit RGBA layers")
+
+width = layer.getWidth()
+height = layer.getHeight()
+
+countreshaping = 0
+while countreshaping < 1:
+ histo = layer.createHistogram("RGB8HISTO",0)
+ print "################################### histogram reshaping ##################################################"
+ if histo == 0:
+ raise "Uncompatible histogram\n"
+ print "Max : " + str( histo.getMax() ) + " Min : " + str( histo.getMin() )
+
+ #Compute the area of the target histogram
+ aireHistoTarget = 0.0
+ count = 0
+ while( count < 256 ) :
+ aireHistoTarget += histoTarget[count]
+ count += 1
+
+ #compute the table for the blue channel
+ histo.setChannel(0)
+ tableb = [ ]
+ histoMax = histo.getHighest()
+ aireHisto = width * height
+ coeff = aireHistoTarget / aireHisto
+ count = 0
+ position = 0
+ residu = 0.
+ while( count < 256 ) :
+ residu += histo.getValue(count) * coeff
+ while residu > 0.0:
+ residu -= histoTarget[position]
+ position += 1
+ tableb.append( position )
+ count += 1
+ #compute the table for the green channel
+ histo.setChannel(1)
+ tableg = [ ]
+ histoMax = histo.getHighest()
+ aireHisto = width * height
+ coeff = aireHistoTarget / aireHisto
+ count = 0
+ position = 0
+ residu = 0.
+ while( count < 256 ) :
+ residu += histo.getValue(count) * coeff
+ while residu > 0.0:
+ residu -= histoTarget[position]
+ position += 1
+ tableg.append( position )
+ count += 1
+ #compute the table for the red channel
+ histo.setChannel(2)
+ tabler = [ ]
+ histoMax = histo.getHighest()
+ aireHisto = width * height
+ coeff = aireHistoTarget / aireHisto
+ count = 0
+ position = 0
+ residu = 0.
+ while( count < 256 ) :
+ residu += histo.getValue(count) * coeff
+ while residu > 0.0:
+ residu -= histoTarget[position]
+ position += 1
+ tabler.append( position )
+ count += 1
+
+ it = layer.createRectIterator( 0, 0, width, height )
+ print "kikoo : " + str(countreshaping)
+ while (not it.isDone()) :
+ r = it.getRed()
+ g = it.getGreen()
+ b = it.getBlue()
+ #var = ( tabler[r] - r + tableg[g] - g + tableb[b] - b ) / 3
+ #ng = g + var
+ #nr = r + var
+ #nb = b + var
+ it.setRed(tabler[r])
+ it.setGreen(tableg[g])
+ it.setBlue(tableb[b])
+ it.next()
+
+ #histo.setChannel(0)
+ #diff = [ ]
+ #histoMax = histo.getHighest()
+ #count = 0
+ #while( count < 256 ) :
+ #v = histo.getValue(count)
+ #diff.append( v / histoMax - histoTarget[count])
+ #count += 1
+ #diffb = [ ]
+ #diffb.append(diff[1] - diff[0] )
+ #count = 1
+ #while( count < 255 ) :
+ #diffb.append((diff[count+1] - diff[count - 1])/2.0)
+ #count += 1
+ #diffb.append(diff[255] - diff[254] )
+
+ #histo.setChannel(1)
+ #diff = [ ]
+ #histoMax = histo.getHighest()
+ #count = 0
+ #while( count < 256 ) :
+ #v = histo.getValue(count)
+ #diff.append( v / histoMax - histoTarget[count])
+ #count += 1
+ #diffg = [ ]
+ #diffg.append(diff[1] - diff[0] )
+ #count = 1
+ #while( count < 255 ) :
+ #diffg.append((diff[count+1] - diff[count - 1])/2.0)
+ #count += 1
+ #diffg.append(diff[255] - diff[254] )
+
+ #histo.setChannel(2)
+ #diff = [ ]
+ #histoMax = histo.getHighest()
+ #count = 0
+ #while( count < 256 ) :
+ #v = histo.getValue(count)
+ #diff.append( v / histoMax - histoTarget[count])
+ #count += 1
+ #diffr = [ ]
+ #diffr.append(diff[1] - diff[0] )
+ #count = 1
+ #while( count < 255 ) :
+ #diffr.append((diff[count+1] - diff[count - 1])/2.0)
+ #count += 1
+ #diffr.append(diff[255] - diff[254] )
+
+
+ #histo.setChannel(0)
+ #diff = [ ]
+ #histoMax = histo.getHighest()
+ #count = 0
+ #while( count < 256 ) :
+ #v = histo.getValue(count)
+ #diff.append( v / histoMax - histoTarget[count])
+ #count += 1
+ #diffb = [ ]
+ #diffb.append( sign(diff[1] - diff[0] ) * abs(diff[0]) )
+ #count = 1
+ #while( count < 255 ) :
+ #diffb.append( sign(diff[count+1] - diff[count - 1]) * abs(diff[count]) )
+ #count += 1
+ #diffb.append( sign(diff[255] - diff[254] ) * abs(diff[255]) )
+
+ #histo.setChannel(1)
+ #diff = [ ]
+ #histoMax = histo.getHighest()
+ #count = 0
+ #while( count < 256 ) :
+ #v = histo.getValue(count)
+ #diff.append( v / histoMax - histoTarget[count])
+ #count += 1
+ #diffg = [ ]
+ #diffg.append( sign(diff[1] - diff[0] ) * abs(diff[0]) )
+ #count = 1
+ #while( count < 255 ) :
+ #diffg.append( sign(diff[count+1] - diff[count - 1]) * abs(diff[count]) )
+ #count += 1
+ #diffg.append( sign(diff[255] - diff[254] ) * abs(diff[255]) )
+
+ #histo.setChannel(2)
+ #diff = [ ]
+ #histoMax = histo.getHighest()
+ #count = 0
+ #while( count < 256 ) :
+ #v = histo.getValue(count)
+ #diff.append( v / histoMax - histoTarget[count])
+ #count += 1
+ #diffr = [ ]
+ #diffr.append( sign(diff[1] - diff[0] ) * abs(diff[0]) )
+ #count = 1
+ #while( count < 255 ) :
+ #diffr.append( sign(diff[count+1] - diff[count - 1]) * abs(diff[count]) )
+ #count += 1
+ #diffr.append( sign(diff[255] - diff[254] ) * abs(diff[255]) )
+
+
+ #print str(diffr) + " " + str(diff[count+1]) + " " + str(diff[count-1])
+
+ #histo.setChannel(0)
+ #diffb = computeDiff(histo, histoTarget)
+ #print "##########################"
+ #count = 0
+ #while( count < 256 ) :
+ #print count
+ #print " "
+ #print diffb[count]
+ #print "\n"
+ #count += 1
+
+ #histo.setChannel(1)
+ #diffg = computeDiff(histo, histoTarget)
+ #print "##########################"
+ #count = 0
+ #while( count < 256 ) :
+ #print count
+ #print " "
+ #print diffg[count]
+ #print "\n"
+ #count += 1
+
+ #histo.setChannel(2)
+ #diffr = computeDiff(histo, histoTarget)
+ #print "##########################"
+ #count = 0
+ #while( count < 256 ) :
+ #print count
+ #print " "
+ #print diffr[count]
+ #print "\n"
+ #count += 1
+
+ #it = layer.createRectIterator( 0, 0, width, height )
+ #print "kikoo : " + str(countreshaping)
+ #while (not it.isDone()) :
+ #r = it.getRed()
+ #g = it.getGreen()
+ #b = it.getBlue()
+ #coeff = 1.0 - ( diffr[r] + diffg[g] + diffb[b] ) / 3.0
+ ##print str(r) + " = " + str(diffr[r]) + " " + str(g) + " = " + str(diffg[g]) + " " + str(b) + " = " + str(diffb[b]) + " coeff = " + str(coeff)
+ #ng = g * coeff
+ #nr = r * coeff
+ #nb = b * coeff
+ #it.setRed(nr)
+ #it.setGreen(ng)
+ #it.setBlue(nb)
+ #it.next()
+ countreshaping += 1
+
+doc.notifyModification()
diff --git a/chalk/plugins/viewplugins/scripting/samples/python/reshapehisto.rc b/chalk/plugins/viewplugins/scripting/samples/python/reshapehisto.rc
new file mode 100644
index 00000000..481f5764
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/python/reshapehisto.rc
@@ -0,0 +1,9 @@
+<KrossScripting>
+ <ScriptAction
+ name="ReshapeHistogramPython"
+ text="Reshape Histogram (python)"
+ description="It's an experimental approach to improve color of image, it doesn't work as it, but it show how to use an histogram in a script :)"
+ icon=""
+ interpreter="python"
+ file="reshapehisto.py" />
+</KrossScripting>
diff --git a/chalk/plugins/viewplugins/scripting/samples/ruby/Makefile.am b/chalk/plugins/viewplugins/scripting/samples/ruby/Makefile.am
new file mode 100644
index 00000000..bebd4a71
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/ruby/Makefile.am
@@ -0,0 +1,18 @@
+scriptsinvertdir = $(kde_datadir)/chalk/scripts/invertruby
+scriptsinvert_SCRIPTS = invert.rb invertruby.rc
+
+scriptschangecsdir = $(kde_datadir)/chalk/scripts/changecs
+scriptschangecs_SCRIPTS = changecs.rb changecs.rc
+
+scriptsrandompaintdir = $(kde_datadir)/chalk/scripts/randompaint
+scriptsrandompaint_SCRIPTS = randompaint.rb randompaint.rc
+
+scriptsfilterstestdir = $(kde_datadir)/chalk/scripts/filterstest
+scriptsfilterstest_SCRIPTS = filterstest.rb filterstest.rc
+
+scriptstorturefiltersdir = $(kde_datadir)/chalk/scripts/torturefilters
+scriptstorturefilters_SCRIPTS = torture-filters.rb torture-filters.rc
+
+scriptstorturepaintingdir = $(kde_datadir)/chalk/scripts/torturepainting
+scriptstorturepainting_SCRIPTS = torture-painting.rb torture-painting.rc
+
diff --git a/chalk/plugins/viewplugins/scripting/samples/ruby/changecs.rb b/chalk/plugins/viewplugins/scripting/samples/ruby/changecs.rb
new file mode 100644
index 00000000..be7c0d89
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/ruby/changecs.rb
@@ -0,0 +1,5 @@
+require "krosschalkcore"
+
+doc = Krosschalkcore::get("ChalkDocument")
+image = doc.getImage()
+image.convertToColorspace("LABA")
diff --git a/chalk/plugins/viewplugins/scripting/samples/ruby/changecs.rc b/chalk/plugins/viewplugins/scripting/samples/ruby/changecs.rc
new file mode 100644
index 00000000..4121693d
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/ruby/changecs.rc
@@ -0,0 +1,9 @@
+<KrossScripting>
+ <ScriptAction
+ name="ChangeColorspaceRuby"
+ text="Change Colorspace"
+ description="Demonstrate how to change the colorspace in a script"
+ icon=""
+ interpreter="ruby"
+ file="changecs.rb" />
+</KrossScripting>
diff --git a/chalk/plugins/viewplugins/scripting/samples/ruby/filterstest.rb b/chalk/plugins/viewplugins/scripting/samples/ruby/filterstest.rb
new file mode 100644
index 00000000..bf76b018
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/ruby/filterstest.rb
@@ -0,0 +1,31 @@
+# This file is part of Chalk
+#
+# Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net>
+#
+# 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.
+
+require "krosschalkcore"
+
+doc = Krosschalkcore::get("ChalkDocument")
+
+image = doc.getImage()
+layer = image.getActivePaintLayer()
+width = layer.getWidth()
+height = layer.getHeight()
+
+filter = Krosschalkcore::getFilter("invert")
+
+filter.process(layer )
+filter.process(layer, 10, 10, 20, 20 )
diff --git a/chalk/plugins/viewplugins/scripting/samples/ruby/filterstest.rc b/chalk/plugins/viewplugins/scripting/samples/ruby/filterstest.rc
new file mode 100644
index 00000000..2f8dfb98
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/ruby/filterstest.rc
@@ -0,0 +1,9 @@
+<KrossScripting>
+ <ScriptAction
+ name="FiltersTestRuby"
+ text="Filters Test"
+ description="Test of filters in scripting (ruby)"
+ icon=""
+ interpreter="ruby"
+ file="filterstest.rb" />
+</KrossScripting>
diff --git a/chalk/plugins/viewplugins/scripting/samples/ruby/invert.rb b/chalk/plugins/viewplugins/scripting/samples/ruby/invert.rb
new file mode 100644
index 00000000..d9ad32f7
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/ruby/invert.rb
@@ -0,0 +1,45 @@
+# This file is part of Chalk
+#
+# Copyright (c) 2005-2006 Cyrille Berger <cberger@cberger.net>
+#
+# 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.
+
+require "krosschalkcore"
+
+doc = Krosschalkcore::get("ChalkDocument")
+script = Krosschalkcore::get("ChalkScript")
+image = doc.getImage()
+layer = image.getActivePaintLayer()
+
+if(layer.colorSpaceId() != "RGBA" )
+ raise("This script works only for 8bit RGBA layers")
+end
+
+width = layer.getWidth()
+height = layer.getHeight()
+script.setProgressTotalSteps(width * height)
+layer.beginPainting("invert")
+it = layer.createRectIterator( 0, 0, width, height )
+while (it.isDone() == 0)
+ p = it.getRGBA()
+ p[0] = 255 - p[0]
+ p[1] = 255 - p[1]
+ p[2] = 255 - p[2]
+ it.setRGBA(p)
+ script.incProgress()
+ it.next()
+end
+
+layer.endPainting()
diff --git a/chalk/plugins/viewplugins/scripting/samples/ruby/invertruby.rc b/chalk/plugins/viewplugins/scripting/samples/ruby/invertruby.rc
new file mode 100644
index 00000000..9cc7bd6a
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/ruby/invertruby.rc
@@ -0,0 +1,9 @@
+<KrossScripting>
+ <ScriptAction
+ name="InvertRuby"
+ text="Invert (ruby)"
+ description="Invert the pixel of an image (ruby)"
+ icon=""
+ interpreter="ruby"
+ file="invert.rb" />
+</KrossScripting>
diff --git a/chalk/plugins/viewplugins/scripting/samples/ruby/randompaint.rb b/chalk/plugins/viewplugins/scripting/samples/ruby/randompaint.rb
new file mode 100644
index 00000000..1ec25dcd
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/ruby/randompaint.rb
@@ -0,0 +1,98 @@
+def randomizeStyle(painter)
+ painter.setFillStyle(4 *rand)
+ painter.setStrokeStyle(2 *rand)
+end
+
+require "krosschalkcore"
+
+doc = Krosschalkcore::get("ChalkDocument")
+script = Krosschalkcore::get("ChalkScript")
+
+image = doc.getImage()
+layer = image.getActivePaintLayer()
+width = layer.getWidth()
+height = layer.getHeight()
+
+script.setProgressTotalSteps(110)
+layer.beginPainting("random paint")
+
+painter = layer.createPainter()
+
+# create painting color
+blackcolor = Krosschalkcore::newRGBColor(0,0,0)
+
+# set painting color
+painter.setPaintColor( blackcolor )
+
+# get the brush
+brush = Krosschalkcore::getBrush("Circle (05)")
+
+# define the brush
+painter.setBrush(brush)
+
+# get the pattern
+pattern = Krosschalkcore::getPattern("Bricks")
+
+# set the pattern
+painter.setPattern(pattern)
+
+# define the paint operation
+painter.setPaintOp("paintbrush")
+
+# randomly paint
+for i in 1..10
+ # set painting color
+ painter.setPaintColor( Krosschalkcore::newRGBColor(rand*255,rand*255,rand*255) )
+ painter.paintAt(rand * width , rand * height,1.1)
+ script.incProgress()
+end
+
+# randomly rect or circle paint
+for i in 1..100
+ # set painting color
+ painter.setPaintColor( Krosschalkcore::newRGBColor(rand*255,rand*255,rand*255) )
+ painter.setBackgroundColor( Krosschalkcore::newRGBColor(rand*255,rand*255,rand*255) )
+ painter.setOpacity( rand*255 )
+# set the brush
+ if(rand < 0.5)
+ painter.setBrush( Krosschalkcore::newRectBrush(rand*20,rand*20,rand*10,rand*10) )
+ else
+ painter.setBrush( Krosschalkcore::newCircleBrush(rand*20,rand*20,rand*10,rand*10) )
+ end
+ # paint a point
+ tqshape = rand * 7
+ painter.setStrokeStyle(1)
+ if( tqshape < 1 )
+ painter.paintAt(rand * width , rand * height,1.1)
+ elsif(tqshape < 2 )
+ xs = Array.new
+ ys = Array.new
+ for i in 0..6
+ xs[i] = rand*width
+ ys[i] = rand*height
+ end
+ painter.paintPolyline(xs,ys)
+ elsif(tqshape < 3)
+ painter.paintLine(rand * width, rand * height, 1.1, rand * width, rand * height,1.1)
+ elsif(tqshape < 4)
+ painter.paintBezierCurve(rand * width, rand * height, 1.1, rand * width, rand * height, rand * width , rand * height, rand * width, rand * height, 1.1)
+ elsif(tqshape < 5)
+ randomizeStyle(painter)
+ painter.paintEllipse(rand * width, rand * height, rand * width, rand * height, 1.1)
+ elsif(tqshape < 6)
+ xs = Array.new
+ ys = Array.new
+ for i in 0..6
+ xs[i] = rand*width
+ ys[i] = rand*height
+ end
+ randomizeStyle(painter)
+ painter.paintPolygon(xs, ys)
+ elsif(tqshape < 7)
+ randomizeStyle(painter)
+ painter.paintRect(rand * width, rand * height, rand * width, rand * height, 1.1)
+ end
+ script.incProgress()
+end
+
+layer.endPainting()
diff --git a/chalk/plugins/viewplugins/scripting/samples/ruby/randompaint.rc b/chalk/plugins/viewplugins/scripting/samples/ruby/randompaint.rc
new file mode 100644
index 00000000..3697f700
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/ruby/randompaint.rc
@@ -0,0 +1,9 @@
+<KrossScripting>
+ <ScriptAction
+ name="RandomPaintRuby"
+ text="Random Paint"
+ description="Demonstrate how to use the Painter script API and paint random shape on screen"
+ icon=""
+ interpreter="ruby"
+ file="randompaint.rb" />
+</KrossScripting>
diff --git a/chalk/plugins/viewplugins/scripting/samples/ruby/torture-filters.rb b/chalk/plugins/viewplugins/scripting/samples/ruby/torture-filters.rb
new file mode 100644
index 00000000..b92a67e0
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/ruby/torture-filters.rb
@@ -0,0 +1,70 @@
+# This file is part of Chalk
+#
+# Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+#
+# 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.
+
+require "krosschalkcore"
+
+doc = Krosschalkcore::get("ChalkDocument")
+
+image = doc.getImage()
+layer = image.getActivePaintLayer()
+
+def testFilter(layer, filterid)
+ print " applying filter ", filterid, "\n"
+ begin
+ filter = Krosschalkcore::getFilter(filterid)
+ filter.process(layer)
+ rescue
+ print " WARNING: this filter is incompatible with this colorspace\n"
+ end
+end
+
+
+def testColorspace(layer, colorspaceid)
+ print "Testing for ", colorspaceid, "\n"
+ if (layer.colorSpaceId() != colorspaceid)
+ layer.convertToColorspace(colorspaceid)
+ end
+ testFilter(layer, "invert")
+ testFilter(layer, "bumpmap")
+ testFilter(layer, "cimg")
+ testFilter(layer, "desaturate")
+ testFilter(layer, "autocontrast")
+ testFilter(layer, "brightnesscontrast")
+ testFilter(layer, "gaussian blur")
+ testFilter(layer, "cubism")
+ testFilter(layer, "emboss")
+ testFilter(layer, "simplenoisereducer")
+ testFilter(layer, "waveletnoisereducer")
+ testFilter(layer, "oilpaint")
+ testFilter(layer, "pixelize")
+ testFilter(layer, "raindrops")
+ testFilter(layer, "roundcorners")
+ testFilter(layer, "smalltiles")
+ testFilter(layer, "sobel")
+end
+
+testColorspace(layer, "RGBA")
+testColorspace(layer, "RGBA16")
+testColorspace(layer, "RGBAF16HALF")
+testColorspace(layer, "RGBAF32")
+testColorspace(layer, "CMYK")
+testColorspace(layer, "CMYKA16")
+testColorspace(layer, "CMYK")
+testColorspace(layer, "CMYKA16")
+testColorspace(layer, "LABA")
+testColorspace(layer, "LMSAF32")
diff --git a/chalk/plugins/viewplugins/scripting/samples/ruby/torture-filters.rc b/chalk/plugins/viewplugins/scripting/samples/ruby/torture-filters.rc
new file mode 100644
index 00000000..b3abde5b
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/ruby/torture-filters.rc
@@ -0,0 +1,9 @@
+<KrossScripting>
+ <ScriptAction
+ name="TortureFiltersRuby"
+ text="Torture Chalk with Filters"
+ description="Test all filters with all colorspaces (ruby)"
+ icon=""
+ interpreter="ruby"
+ file="torture-filters.rb" />
+</KrossScripting>
diff --git a/chalk/plugins/viewplugins/scripting/samples/ruby/torture-painting.rb b/chalk/plugins/viewplugins/scripting/samples/ruby/torture-painting.rb
new file mode 100644
index 00000000..b7c784fc
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/ruby/torture-painting.rb
@@ -0,0 +1,133 @@
+# This file is part of Chalk
+#
+# Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
+#
+# 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.
+
+require "krosschalkcore"
+
+class TorturePainting
+
+ def initialize()
+
+ doc = Krosschalkcore::get("ChalkDocument")
+ @script = Krosschalkcore::get("ChalkScript")
+
+ @image = doc.getImage()
+ @width = @image.getWidth()
+ @height = @image.getHeight()
+
+ @script.setProgressTotalSteps(30 * 10)
+
+ testColorspace("RGBA")
+ testColorspace("RGBA16")
+ testColorspace("RGBAF16HALF")
+ testColorspace("RGBAF32")
+ testColorspace("CMYK")
+ testColorspace("CMYKA16")
+ testColorspace("CMYK")
+ testColorspace("CMYKA16")
+ testColorspace("LABA")
+ testColorspace("LMSAF32")
+
+
+ end
+
+ def randomizeStyle(painter)
+ painter.setFillStyle(4 *rand)
+ painter.setStrokeStyle(2 *rand)
+ end
+
+
+ def testColorspace(cs)
+ print "Torturing for ", cs, "\n"
+ layer = @image.createPaintLayer("torture", 255 * rand, "RGBA" );
+ torture(layer)
+ end
+
+
+ def torture(layer)
+ layer.beginPainting("torture painting")
+
+ painter = layer.createPainter()
+
+ # create painting color
+ blackcolor = Krosschalkcore::newRGBColor(0,0,0)
+
+ # set painting color
+ painter.setPaintColor( blackcolor )
+
+ # get the pattern
+ pattern = Krosschalkcore::getPattern("Bricks")
+
+ # set the pattern
+ painter.setPattern(pattern)
+
+ # define the paint operation
+ painter.setPaintOp("paintbrush")
+
+ # randomly rect or circle paint
+ for i in 1..30
+ # set painting color
+ painter.setPaintColor( Krosschalkcore::newRGBColor(rand*255,rand*255,rand*255) )
+ painter.setBackgroundColor( Krosschalkcore::newRGBColor(rand*255,rand*255,rand*255) )
+ painter.setOpacity( rand*255 )
+ # set the brush
+ if(rand < 0.5)
+ painter.setBrush( Krosschalkcore::newRectBrush(rand*20,rand*20,rand*10,rand*10) )
+ else
+ painter.setBrush( Krosschalkcore::newCircleBrush(rand*20,rand*20,rand*10,rand*10) )
+ end
+ # paint a point
+ tqshape = rand * 7
+ painter.setStrokeStyle(1)
+ if( tqshape < 1 )
+ painter.paintAt(rand * @width , rand * @height,1.1)
+ elsif(tqshape < 2 )
+ xs = Array.new
+ ys = Array.new
+ for i in 0..6
+ xs[i] = rand*@width
+ ys[i] = rand*@height
+ end
+ painter.paintPolyline(xs,ys)
+ elsif(tqshape < 3)
+ painter.paintLine(rand * @width, rand * @height, 1.1, rand * @width, rand * @height,1.1)
+ elsif(tqshape < 4)
+ painter.paintBezierCurve(rand * @width, rand * @height, 1.1, rand * @width, rand * @height, rand * @width , rand * @height, rand * @width, rand * @height, 1.1)
+ elsif(tqshape < 5)
+ randomizeStyle(painter)
+ painter.paintEllipse(rand * @width, rand * @height, rand * @width, rand * @height, 1.1)
+ elsif(tqshape < 6)
+ xs = Array.new
+ ys = Array.new
+ for i in 0..6
+ xs[i] = rand*@width
+ ys[i] = rand*@height
+ end
+ randomizeStyle(painter)
+ painter.paintPolygon(xs, ys)
+ elsif(tqshape < 7)
+ randomizeStyle(painter)
+ painter.paintRect(rand * @width, rand * @height, rand * @width, rand * @height, 1.1)
+ end
+ @script.incProgress()
+ end
+ layer.endPainting()
+ end
+
+end
+
+TorturePainting.new() \ No newline at end of file
diff --git a/chalk/plugins/viewplugins/scripting/samples/ruby/torture-painting.rc b/chalk/plugins/viewplugins/scripting/samples/ruby/torture-painting.rc
new file mode 100644
index 00000000..51f2eee4
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/samples/ruby/torture-painting.rc
@@ -0,0 +1,9 @@
+<KrossScripting>
+ <ScriptAction
+ name="TorturePainting"
+ text="Torture Chalk with Painting"
+ description="Paint on an image and create multiple layers"
+ icon=""
+ interpreter="ruby"
+ file="torture-painting.rb" />
+</KrossScripting>
diff --git a/chalk/plugins/viewplugins/scripting/scripting.cc b/chalk/plugins/viewplugins/scripting/scripting.cc
new file mode 100644
index 00000000..34b4d1d8
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/scripting.cc
@@ -0,0 +1,111 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ * 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 "scripting.h"
+
+#include <stdlib.h>
+#include <vector>
+
+#include <tqapplication.h>
+#include <tqpoint.h>
+
+#include <kdebug.h>
+#include <kfiledialog.h>
+#include <kgenericfactory.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+
+#define KROSS_MAIN_EXPORT KDE_EXPORT
+#include <main/manager.h>
+#include <main/scriptguiclient.h>
+#include <main/wdgscriptsmanager.h>
+
+#include <kopalettemanager.h>
+
+#include <kis_doc.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_view.h>
+#include <kis_image.h>
+#include <kis_layer.h>
+
+#include "chalkscripting/kis_script_progress.h"
+#include "chalkscripting/kis_script_monitor.h"
+
+typedef KGenericFactory<Scripting> ChalkScriptingFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkscripting, ChalkScriptingFactory( "chalk" ) )
+
+Scripting::Scripting(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ setInstance(ChalkScriptingFactory::instance());
+
+
+ if ( tqparent->inherits("KisView") )
+ {
+ setInstance(Scripting::instance());
+ m_view = (KisView*) tqparent;
+ m_scriptguiclient = new Kross::Api::ScriptGUIClient( m_view, m_view );
+// m_scriptguiclient ->setXMLFile(locate("data","chalkplugins/scripting.rc"), true);
+ //BEGIN TODO: understand why the ScriptGUIClient doesn't "link" its actions to the menu
+ setXMLFile(locate("data","chalkplugins/scripting.rc"), true);
+ new KAction(i18n("Execute Script File..."), 0, 0, m_scriptguiclient, TQT_SLOT(executeScriptFile()), actionCollection(), "executescriptfile");
+ new KAction(i18n("Script Manager..."), 0, 0, m_scriptguiclient, TQT_SLOT(showScriptManager()), actionCollection(), "configurescripts");
+ //END TODO
+
+ TQWidget * w = new Kross::Api::WdgScriptsManager(m_scriptguiclient, m_view);
+
+ m_view->canvasSubject()->paletteManager()->addWidget(w, "Scripts Manager", chalk::LAYERBOX, 10, PALETTE_DOCKER, false);
+
+ connect(m_scriptguiclient, TQT_SIGNAL(executionFinished( const Kross::Api::ScriptAction* )), this, TQT_SLOT(executionFinished(const Kross::Api::ScriptAction*)));
+ connect(m_scriptguiclient, TQT_SIGNAL(executionStarted( const Kross::Api::ScriptAction* )), this, TQT_SLOT(executionStarted(const Kross::Api::ScriptAction*)));
+ KisScriptMonitor::instance()->monitor( m_scriptguiclient );
+
+ Kross::Api::Manager::scriptManager()->addTQObject(m_view->canvasSubject()->document(), "ChalkDocument");
+ Kross::Api::Manager::scriptManager()->addTQObject(TQT_TQOBJECT(m_view), "ChalkView");
+ m_scriptProgress = new KisScriptProgress(m_view);
+ Kross::Api::Manager::scriptManager()->addTQObject(m_scriptProgress, "ChalkScriptProgress");
+
+ }
+
+}
+
+Scripting::~Scripting()
+{
+}
+
+void Scripting::executionFinished(const Kross::Api::ScriptAction*)
+{
+ m_view->canvasSubject()->document()->setModified(true);
+ m_view->canvasSubject()->document()->currentImage()->activeLayer()->setDirty();
+ m_scriptProgress->progressDone();
+ TQApplication::restoreOverrideCursor();
+}
+
+void Scripting::executionStarted(const Kross::Api::ScriptAction* act)
+{
+ kdDebug(41011) << act->getPackagePath() << endl;
+ m_scriptProgress->setPackagePath( act->getPackagePath() );
+}
+
+
+#include "scripting.moc"
diff --git a/chalk/plugins/viewplugins/scripting/scripting.h b/chalk/plugins/viewplugins/scripting/scripting.h
new file mode 100644
index 00000000..a981175d
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/scripting.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net>
+ *
+ * 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 SCRIPTING_H
+#define SCRIPTING_H
+
+#include <kparts/plugin.h>
+
+class KisView;
+class KisScript;
+class KisScriptProgress;
+
+namespace Kross {
+ namespace Api {
+ class ScriptGUIClient;
+ class ScriptAction;
+ }
+}
+
+class Scripting : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+ public:
+ Scripting(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~Scripting();
+ private slots:
+ void executionFinished(const Kross::Api::ScriptAction*);
+ void executionStarted(const Kross::Api::ScriptAction*);
+ private:
+ KisView * m_view;
+ Kross::Api::ScriptGUIClient* m_scriptguiclient;
+ KisScriptProgress* m_scriptProgress;
+};
+
+
+#endif
diff --git a/chalk/plugins/viewplugins/scripting/scripting.rc b/chalk/plugins/viewplugins/scripting/scripting.rc
new file mode 100644
index 00000000..1b4999df
--- /dev/null
+++ b/chalk/plugins/viewplugins/scripting/scripting.rc
@@ -0,0 +1,10 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkscripting" version="3">
+ <MenuBar>
+ <Menu name="Scripts"><text>S&amp;cripts</text>
+ <Separator/>
+ <Action name="executescriptfile"/>
+ <Action name="configurescripts"/>
+ </Menu>
+ </MenuBar>
+</kpartgui>
diff --git a/chalk/plugins/viewplugins/selectopaque/Makefile.am b/chalk/plugins/viewplugins/selectopaque/Makefile.am
new file mode 100644
index 00000000..7f83e3c6
--- /dev/null
+++ b/chalk/plugins/viewplugins/selectopaque/Makefile.am
@@ -0,0 +1,25 @@
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalkselectopaque.la
+
+chalkselectopaque_la_SOURCES = selectopaque.cc
+noinst_HEADERS = selectopaque.h
+
+chalkselectopaque_la_LIBADD = ../../../libchalkcommon.la
+chalkselectopaque_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) chalkblurfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui
+
+chalkrcdir = $(kde_datadir)/chalkplugins
+chalkrc_DATA = selectopaque.rc
+EXTRA_DIST = $(chalkrc_DATA)
+
+kde_services_DATA = chalkselectopaque.desktop
+
+chalkselectopaque_la_METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
diff --git a/chalk/plugins/viewplugins/selectopaque/chalkselectopaque.desktop b/chalk/plugins/viewplugins/selectopaque/chalkselectopaque.desktop
new file mode 100644
index 00000000..049c6a40
--- /dev/null
+++ b/chalk/plugins/viewplugins/selectopaque/chalkselectopaque.desktop
@@ -0,0 +1,26 @@
+[Desktop Entry]
+Name=SelectOpaque
+Name[bg]=Негатив
+Name[da]=Markér ugennemsigtig
+Name[de]=UndurchsichtigeAuswählen
+Name[et]=Läbipaistmatute pikslite valik
+Name[fy]=Untrochsichtige selektearje
+Name[it]=Seleziona i pixel opachi
+Name[km]=ជ្រើស​ស្រអាប់
+Name[nds]=Decken utsöken
+Name[ne]=अपारदर्शी चयन
+Name[nl]=Ondoorzichtige selecteren
+Name[pl]=Zaznaczanie nieprzezroczystości
+Name[pt]=Selecção Opaca
+Name[pt_BR]=Seleção Opaca
+Name[ru]=Выделение непрозрачных областей
+Name[sk]=Invertovať Výber
+Name[sr]=Избор непрозирног
+Name[sr@Latn]=Izbor neprozirnog
+Name[sv]=Markera ogenomskinliga
+Name[uk]=Виділення непрозорих ділянок
+Name[zh_TW]=選擇不透明
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalkselectopaque
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/selectopaque/selectopaque.cc b/chalk/plugins/viewplugins/selectopaque/selectopaque.cc
new file mode 100644
index 00000000..a5717a97
--- /dev/null
+++ b/chalk/plugins/viewplugins/selectopaque/selectopaque.cc
@@ -0,0 +1,116 @@
+/*
+ * selectopague.h -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 <math.h>
+
+#include <stdlib.h>
+
+#include <tqcursor.h>
+#include <tqapplication.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_selected_transaction.h>
+#include <kis_cursor.h>
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_layer.h>
+#include <kis_paint_device.h>
+#include <kis_iterator.h>
+#include <kis_iterators_pixel.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_view.h>
+#include <kis_selection.h>
+#include <kis_selection_manager.h>
+#include "selectopaque.h"
+
+typedef KGenericFactory<SelectOpaque> SelectOpaqueFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkselectopaque, SelectOpaqueFactory( "chalk" ) )
+
+SelectOpaque::SelectOpaque(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+
+ if (tqparent->inherits("KisView")) {
+ setInstance(SelectOpaqueFactory::instance());
+ setXMLFile(locate("data","chalkplugins/selectopaque.rc"), true);
+ m_view = dynamic_cast<KisView*>(tqparent);
+ m_view->canvasSubject()->selectionManager()->addSelectionAction( new KAction(i18n("&Select All Opaque Pixels..."), 0, 0, this, TQT_SLOT(slotActivated()), actionCollection(), "selectopaque") );
+
+ }
+}
+
+SelectOpaque::~SelectOpaque()
+{
+}
+
+void SelectOpaque::slotActivated()
+{
+ KisSelectedTransaction *transaction;
+
+ KisPaintDeviceSP layer = m_view->canvasSubject()->currentImg()->activeDevice();
+ if (!layer) return;
+ TQApplication::setOverrideCursor(KisCursor::waitCursor());
+
+ if (layer->image()->undo()) transaction = new KisSelectedTransaction(i18n("Select Opaque Pixels"), layer);
+ // XXX: Multithread this!
+ TQ_INT32 x, y, w, h;
+ layer->exactBounds(x, y, w, h);
+
+ KisColorSpace * cs = layer->colorSpace();
+
+ if(! layer->hasSelection())
+ layer->selection()->clear();
+ KisSelectionSP selection = layer->selection();
+
+ KisHLineIterator hiter = layer->createHLineIterator(x, y, w, false);
+ KisHLineIterator selIter = selection ->createHLineIterator(x, y, w, true);
+
+ for (int row = 0; row < h; ++row) {
+ while (!hiter.isDone()) {
+ // Don't try to select transparent pixels.
+ if (cs->getAlpha( hiter.rawData() ) > OPACITY_TRANSPARENT) {
+ *(selIter.rawData()) = MAX_SELECTED;
+ }
+ ++hiter;
+ ++selIter;
+ }
+ hiter.nextRow();
+ selIter.nextRow();
+ }
+ TQApplication::restoreOverrideCursor();
+ layer->setDirty();
+ layer->emitSelectionChanged();
+
+ if (layer->image()->undo()) m_view->canvasSubject()->undoAdapter()->addCommand(transaction);
+
+}
+
+#include "selectopaque.moc"
+
diff --git a/chalk/plugins/viewplugins/selectopaque/selectopaque.h b/chalk/plugins/viewplugins/selectopaque/selectopaque.h
new file mode 100644
index 00000000..47614e30
--- /dev/null
+++ b/chalk/plugins/viewplugins/selectopaque/selectopaque.h
@@ -0,0 +1,45 @@
+/*
+ * selectopaque.h -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 SELECTOPAQUE_H
+#define SELECTOPAQUE_H
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+class SelectOpaque : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+ public:
+ SelectOpaque(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~SelectOpaque();
+
+ private slots:
+ void slotActivated();
+
+ private:
+ KisView * m_view;
+ KisPainter * m_painter;
+
+};
+
+#endif // SELECTOPAQUE_H
diff --git a/chalk/plugins/viewplugins/selectopaque/selectopaque.rc b/chalk/plugins/viewplugins/selectopaque/selectopaque.rc
new file mode 100644
index 00000000..a4809d59
--- /dev/null
+++ b/chalk/plugins/viewplugins/selectopaque/selectopaque.rc
@@ -0,0 +1,10 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkselectopaque" version="1">
+<MenuBar>
+ <Menu name="Select"><text>Select</text>
+ <Separator/>
+ <Action name="selectopaque"/>
+ <Separator/>
+ </Menu>
+</MenuBar>
+</kpartgui>
diff --git a/chalk/plugins/viewplugins/separate_channels/Makefile.am b/chalk/plugins/viewplugins/separate_channels/Makefile.am
new file mode 100644
index 00000000..9b28a89d
--- /dev/null
+++ b/chalk/plugins/viewplugins/separate_channels/Makefile.am
@@ -0,0 +1,27 @@
+chalkrcdir = $(kde_datadir)/chalkplugins
+chalkrc_DATA = imageseparate.rc
+EXTRA_DIST = $(chalkrc_DATA)
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalkseparatechannels.la
+
+chalkseparatechannels_la_SOURCES = wdg_separations.ui \
+ kis_channel_separator.cc dlg_separate.cc \
+ kis_separate_channels_plugin.cc
+
+noinst_HEADERS = wdg_separations.h kis_separate_channels_plugin.h \
+ kis_channel_separator.h dlg_separate.h
+
+kde_services_DATA = chalkseparatechannels.desktop
+
+chalkseparatechannels_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui -L../../../../lib/kofficecore/.libs -lkofficecore
+chalkseparatechannels_la_LIBADD = ../../../libchalkcommon.la
+
+chalkseparatechannels_la_METASOURCES = AUTO
diff --git a/chalk/plugins/viewplugins/separate_channels/chalkseparatechannels.desktop b/chalk/plugins/viewplugins/separate_channels/chalkseparatechannels.desktop
new file mode 100644
index 00000000..efb596b8
--- /dev/null
+++ b/chalk/plugins/viewplugins/separate_channels/chalkseparatechannels.desktop
@@ -0,0 +1,42 @@
+[Desktop Entry]
+Name=Separate Channels Plugin
+Name[bg]=Приставка за отделен канал
+Name[ca]=Connector de canals separats
+Name[da]=Plugin for separate kanaler
+Name[de]="Kanäle trennen"-Modul
+Name[el]=Πρόσθετο διαχωρισμού καναλιών
+Name[eo]=Apartkanal-kromaĵo
+Name[es]=Complemento para canales separados
+Name[et]=Kanalite lahutamise plugin
+Name[fa]=جدا کردن وصلۀ مجراها
+Name[fr]=Module de séparation des canaux
+Name[fy]=Plugin foar aparte kanalen
+Name[gl]=Plugin de Separación de Canais
+Name[he]=תוסף לריבוי ערוצים
+Name[hu]=Csatornaszétválasztó modul
+Name[is]=Aðgreindar rásir íforrit
+Name[it]=Plugin per la separazione dei canali
+Name[ja]=チャンネル分離プラグイン
+Name[km]=កម្មវិធី​ជំនួយ​ដើម្បី​បំបែក​ឆានែល
+Name[nb]=Programtillegg for atskilte kanaler
+Name[nds]=Kanaaltrenn-Moduul
+Name[ne]=च्यानल प्लगइन छुट्याउनुहोस्
+Name[nl]=Plugin voor aparte kanalen
+Name[pl]=Wtyczka oddzielania kanałów
+Name[pt]='Plugin' de Separação de Canais
+Name[pt_BR]=Plugin de Separação de Canais
+Name[ru]=Разбор изображения по каналам
+Name[sk]=Modul oddelenie kanálov
+Name[sl]=Vstavek za ločevanje kanalov
+Name[sr]=Прикључак за раздвајање канала
+Name[sr@Latn]=Priključak za razdvajanje kanala
+Name[sv]=Insticksprogram för separata kanaler
+Name[uk]=Втулок розділення каналів
+Name[uz]=Kanallarni ajratish uchun plagin
+Name[uz@cyrillic]=Каналларни ажратиш учун плагин
+Name[zh_CN]=独立通道插件
+Name[zh_TW]=分離色頻外掛程式
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalkseparatechannels
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/separate_channels/dlg_separate.cc b/chalk/plugins/viewplugins/separate_channels/dlg_separate.cc
new file mode 100644
index 00000000..e6124046
--- /dev/null
+++ b/chalk/plugins/viewplugins/separate_channels/dlg_separate.cc
@@ -0,0 +1,110 @@
+/*
+ * dlg_separate.cc - part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <tqradiobutton.h>
+#include <tqcheckbox.h>
+#include <tqbuttongroup.h>
+#include <tqlabel.h>
+#include <tqcombobox.h>
+#include <tqbutton.h>
+
+#include <klocale.h>
+#include <knuminput.h>
+#include <kdebug.h>
+
+#include "dlg_separate.h"
+#include "wdg_separations.h"
+
+DlgSeparate::DlgSeparate( const TQString & imageCS,
+ const TQString & layerCS,
+ TQWidget * tqparent,
+ const char * name)
+ : super (tqparent, name, true, i18n("Separate Image"), Ok | Cancel, Ok),
+ m_imageCS(imageCS),
+ m_layerCS(layerCS)
+{
+ m_page = new WdgSeparations(this, "separate_image");
+ Q_CHECK_PTR(m_page);
+ setMainWidget(m_page);
+ resize(m_page->tqsizeHint());
+
+ m_page->lblColormodel->setText(layerCS);
+ m_page->grpOutput->hide();
+ connect(m_page->grpSource, TQT_SIGNAL(clicked(int)), this, TQT_SLOT(slotSetColorSpaceLabel(int)));
+ connect(m_page->chkColors, TQT_SIGNAL(toggled(bool)), m_page->chkDownscale, TQT_SLOT(setDisabled(bool)));
+
+ connect(this, TQT_SIGNAL(okClicked()),
+ this, TQT_SLOT(okClicked()));
+}
+
+DlgSeparate::~DlgSeparate()
+{
+ delete m_page;
+}
+
+
+
+enumSepAlphaOptions DlgSeparate::getAlphaOptions()
+{
+ return (enumSepAlphaOptions)m_page->grpAlpha->selectedId();
+}
+
+enumSepSource DlgSeparate::getSource()
+{
+ return (enumSepSource)m_page->grpSource->selectedId();
+}
+
+enumSepOutput DlgSeparate::getOutput()
+{
+ return (enumSepOutput)m_page->grpOutput->selectedId();
+}
+
+
+bool DlgSeparate::getDownscale()
+{
+ return m_page->chkDownscale->isChecked();
+}
+
+bool DlgSeparate::getToColor()
+{
+ return m_page->chkColors->isChecked();
+}
+
+// SLOTS
+
+void DlgSeparate::okClicked()
+{
+ accept();
+}
+
+void DlgSeparate::slotSetColorSpaceLabel(int buttonid)
+{
+ if (buttonid == 0) {
+ m_page->lblColormodel->setText(m_layerCS);
+ }
+ else {
+ m_page->lblColormodel->setText(m_imageCS);
+ }
+}
+void DlgSeparate::enableDownscale(bool enable) {
+ m_page->chkDownscale->setEnabled(enable);
+}
+
+#include "dlg_separate.moc"
diff --git a/chalk/plugins/viewplugins/separate_channels/dlg_separate.h b/chalk/plugins/viewplugins/separate_channels/dlg_separate.h
new file mode 100644
index 00000000..d3536dda
--- /dev/null
+++ b/chalk/plugins/viewplugins/separate_channels/dlg_separate.h
@@ -0,0 +1,68 @@
+/*
+ * dlg_imagesize.h -- part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 DLG_SEPARATE
+#define DLG_SEPARATE
+
+#include <kdialogbase.h>
+#include <kis_channel_separator.h>
+
+class WdgSeparations;
+
+/**
+ * This dialog allows the user to configure the decomposition of an image
+ * into layers: one layer for each color channel.
+ */
+class DlgSeparate: public KDialogBase {
+ typedef KDialogBase super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ DlgSeparate(const TQString & imageCS, const TQString & layerCS, TQWidget * tqparent = 0,
+ const char* name = 0);
+ ~DlgSeparate();
+
+public:
+
+ enumSepAlphaOptions getAlphaOptions();
+ enumSepSource getSource();
+ enumSepOutput getOutput();
+
+ bool getDownscale();
+ void enableDownscale(bool enable);
+
+ bool getToColor();
+
+
+private slots:
+
+ void slotSetColorSpaceLabel(int buttonid);
+ void okClicked();
+
+private:
+
+ WdgSeparations * m_page;
+ TQString m_imageCS;
+ TQString m_layerCS;
+
+};
+
+#endif // DLG_SEPARATE
diff --git a/chalk/plugins/viewplugins/separate_channels/imageseparate.rc b/chalk/plugins/viewplugins/separate_channels/imageseparate.rc
new file mode 100644
index 00000000..b0518510
--- /dev/null
+++ b/chalk/plugins/viewplugins/separate_channels/imageseparate.rc
@@ -0,0 +1,9 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkseparatechannels" version="6">
+<MenuBar>
+ <Menu name="Image"><text>Image</text>
+ <Separator/>
+ <Action name="separate"/>
+ </Menu>
+</MenuBar>
+</kpartgui>
diff --git a/chalk/plugins/viewplugins/separate_channels/kis_channel_separator.cc b/chalk/plugins/viewplugins/separate_channels/kis_channel_separator.cc
new file mode 100644
index 00000000..3315177c
--- /dev/null
+++ b/chalk/plugins/viewplugins/separate_channels/kis_channel_separator.cc
@@ -0,0 +1,301 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * ported from Gimp, Copyright (C) 1997 Eiichi Takamori <taka@ma1.seikyou.ne.jp>
+ * 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 <limits.h>
+
+#include <stdlib.h>
+#include <vector>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+#include <knuminput.h>
+#include <kfiledialog.h>
+
+
+#include <KoFilterManager.h>
+
+#include <kis_doc.h>
+#include <kis_image.h>
+#include "kis_meta_registry.h"
+#include <kis_iterators_pixel.h>
+#include <kis_layer.h>
+#include <kis_paint_layer.h>
+#include <kis_group_layer.h>
+#include <kis_transaction.h>
+#include <kis_undo_adapter.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_progress_subject.h>
+#include <kis_progress_display_interface.h>
+#include <kis_colorspace.h>
+#include <kis_colorspace_factory_registry.h>
+#include <kis_view.h>
+#include <kis_paint_device.h>
+#include <kis_channelinfo.h>
+
+#include "kis_channel_separator.h"
+
+KisChannelSeparator::KisChannelSeparator(KisView * view)
+ : m_view(view)
+{
+}
+
+void KisChannelSeparator::separate(KisProgressDisplayInterface * progress, enumSepAlphaOptions alphaOps, enumSepSource sourceOps, enumSepOutput outputOps, bool downscale, bool toColor)
+{
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+ if (!image) return;
+
+ KisLayerSP layer = image->activeLayer();
+ if (!layer) return;
+
+ KisPaintDeviceSP src = image->activeDevice();
+ if (!src) return;
+
+ m_cancelRequested = false;
+ if ( progress )
+ progress->setSubject(this, true, true);
+ emit notifyProgressStage(i18n("Separating image..."), 0);
+
+ KisColorSpace * dstCs = 0;
+
+ TQ_UINT32 numberOfChannels = src->nChannels();
+ KisColorSpace * srcCs = src->colorSpace();
+ TQValueVector<KisChannelInfo *> channels = srcCs->channels();
+
+ // Use the flattened image, if required
+ switch(sourceOps) {
+
+ case(ALL_LAYERS):
+ src = image->mergedImage();
+ break;
+ default:
+ break;
+ }
+
+ vKisPaintDeviceSP layers;
+
+ TQValueVector<KisChannelInfo *>::const_iterator begin = channels.begin();
+ TQValueVector<KisChannelInfo *>::const_iterator end = channels.end();
+
+
+ TQRect rect = src->exactBounds();
+
+ int i = 0;
+ TQ_UINT32 channelIndex = 0;
+ for (TQValueVector<KisChannelInfo *>::const_iterator it = begin; it != end; ++it, ++channelIndex)
+ {
+
+ KisChannelInfo * ch = (*it);
+
+ if (ch->channelType() == KisChannelInfo::ALPHA && alphaOps != CREATE_ALPHA_SEPARATION) {
+ continue;
+ }
+
+ TQ_INT32 channelSize = ch->size();
+ TQ_INT32 channelPos = ch->pos();
+ TQ_INT32 destSize = 1;
+
+ KisPaintDeviceSP dev;
+ if (toColor) {
+ // We don't downscale if we separate to color channels
+ dev = new KisPaintDevice(srcCs, "color separations");
+ }
+ else {
+ if (channelSize == 1 || downscale) {
+ dev = new KisPaintDevice( KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("GRAYA",""),"" ), "8 bit grayscale sep");
+ }
+ else {
+ dev = new KisPaintDevice( KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("GRAYA16",""),"" ), "16 bit grayscale sep");
+ destSize = 2;
+ }
+ }
+
+ dstCs = dev->colorSpace();
+
+ layers.push_back(dev);
+
+ for (TQ_INT32 row = 0; row < rect.height(); ++row) {
+
+ KisHLineIteratorPixel srcIt = src->createHLineIterator(rect.x(), rect.y() + row, rect.width(), false);
+ KisHLineIteratorPixel dstIt = dev->createHLineIterator(rect.x(), rect.y() + row, rect.width(), true);
+
+ while( ! srcIt.isDone() )
+ {
+ if (srcIt.isSelected())
+ {
+ if (toColor) {
+ dstCs->getSingleChannelPixel(dstIt.rawData(), srcIt.rawData(), channelIndex);
+
+ if (alphaOps == COPY_ALPHA_TO_SEPARATIONS) {
+ //dstCs->setAlpha(dstIt.rawData(), srcIt.rawData()[srcAlphaPos], 1);
+ dstCs->setAlpha(dstIt.rawData(), srcCs->getAlpha(srcIt.rawData()), 1);
+ }
+ else {
+ dstCs->setAlpha(dstIt.rawData(), OPACITY_OPAQUE, 1);
+ }
+ }
+ else {
+
+ // To grayscale
+
+ // Decide wether we need downscaling
+ if (channelSize == 1 && destSize == 1) {
+
+ // Both 8-bit channels
+ dstIt.rawData()[0] = srcIt.rawData()[channelPos];
+
+ if (alphaOps == COPY_ALPHA_TO_SEPARATIONS) {
+ dstCs->setAlpha(dstIt.rawData(), srcCs->getAlpha(srcIt.rawData()), 1);
+ }
+ else {
+ dstCs->setAlpha(dstIt.rawData(), OPACITY_OPAQUE, 1);
+ }
+ }
+ else if (channelSize == 2 && destSize == 2) {
+
+ // Both 16-bit
+ dstIt.rawData()[0] = srcIt.rawData()[channelPos];
+ dstIt.rawData()[1] = srcIt.rawData()[channelPos + 1];
+
+ if (alphaOps == COPY_ALPHA_TO_SEPARATIONS) {
+ dstCs->setAlpha(dstIt.rawData(), srcCs->getAlpha(srcIt.rawData()), 1);
+ }
+ else {
+ dstCs->setAlpha(dstIt.rawData(), OPACITY_OPAQUE, 1);
+ }
+ }
+ else if (channelSize != 1 && destSize == 1) {
+ // Downscale
+ memset(dstIt.rawData(), srcCs->scaleToU8(srcIt.rawData(), channelPos), 1);
+
+ // XXX: Do alpha
+ dstCs->setAlpha(dstIt.rawData(), OPACITY_OPAQUE, 1);
+ }
+ else if (channelSize != 2 && destSize == 2) {
+ // Upscale
+ dstIt.rawData()[0] = srcCs->scaleToU8(srcIt.rawData(), channelPos);
+
+ // XXX: Do alpha
+ dstCs->setAlpha(dstIt.rawData(), OPACITY_OPAQUE, 1);
+
+ }
+ }
+ }
+ ++dstIt;
+ ++srcIt;
+ }
+ }
+ ++i;
+
+ emit notifyProgress((i * 100) / numberOfChannels);
+ if (m_cancelRequested) {
+ break;
+ }
+ }
+
+ vKisPaintDeviceSP_it deviceIt = layers.begin();
+
+ emit notifyProgressDone();
+
+ if (!m_cancelRequested) {
+
+ KisUndoAdapter * undo = 0;
+ if ((undo = image->undoAdapter()) && undo->undo()) {
+ undo->beginMacro(i18n("Separate Image"));
+ }
+
+ // Flatten the image if required
+ switch(sourceOps) {
+ case(ALL_LAYERS):
+ image->flatten();
+ break;
+ default:
+ break;
+ }
+
+ for (TQValueVector<KisChannelInfo *>::const_iterator it = begin; it != end; ++it)
+ {
+
+ KisChannelInfo * ch = (*it);
+
+ if (ch->channelType() == KisChannelInfo::ALPHA && alphaOps != CREATE_ALPHA_SEPARATION) {
+ // Don't make an separate separation of the alpha channel if the user didn't ask for it.
+ continue;
+ }
+
+ if (outputOps == TO_LAYERS) {
+ KisPaintLayerSP l = new KisPaintLayer( image, ch->name(), OPACITY_OPAQUE, *deviceIt);
+ image->addLayer( dynamic_cast<KisLayer*>(l.data()), image->rootLayer(), 0);
+ }
+ else {
+ TQStringList listMimeFilter = KoFilterManager::mimeFilter("application/x-chalk", KoFilterManager::Export);
+ TQString mimelist = listMimeFilter.join(" ");
+
+ KFileDialog fd (TQString(), mimelist, m_view, "Export Layer", true);
+ fd.setCaption(i18n("Export Layer") + "(" + ch->name() + ")");
+ fd.setMimeFilter(listMimeFilter);
+ fd.setOperationMode(KFileDialog::Saving);
+ fd.setURL(KURL(ch->name()));
+ if (!fd.exec()) return;
+
+ KURL url = fd.selectedURL();
+ TQString mimefilter = fd.currentMimeFilter();
+
+ if (url.isEmpty())
+ return;
+
+ KisPaintLayerSP l = new KisPaintLayer( image, ch->name(), OPACITY_OPAQUE, *deviceIt);
+ TQRect r = l->exactBounds();
+
+ KisDoc d;
+ d.prepareForImport();
+
+ KisImageSP dst = new KisImage(d.undoAdapter(), r.width(), r.height(), (*deviceIt)->colorSpace(), l->name());
+ d.setCurrentImage( dst );
+ dst->addLayer(l->clone(), dst->rootLayer(), 0);
+
+ d.setOutputMimeType(mimefilter.latin1());
+ d.exp0rt(url);
+
+ }
+
+ ++deviceIt;
+ }
+
+ if (undo && undo->undo()) {
+ undo->endMacro();
+ }
+
+ m_view->canvasSubject()->document()->setModified(true);
+ }
+}
+
+
+
+
+#include "kis_channel_separator.moc"
diff --git a/chalk/plugins/viewplugins/separate_channels/kis_channel_separator.h b/chalk/plugins/viewplugins/separate_channels/kis_channel_separator.h
new file mode 100644
index 00000000..d8bf777e
--- /dev/null
+++ b/chalk/plugins/viewplugins/separate_channels/kis_channel_separator.h
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_CHANNEL_SEPARATOR_H_
+#define _KIS_CHANNEL_SEPARATOR_H_
+
+#include <kis_progress_subject.h>
+
+class KisView;
+class KisProgressDisplayInterface;
+
+
+enum enumSepAlphaOptions {
+ COPY_ALPHA_TO_SEPARATIONS = 0,
+ DISCARD_ALPHA = 1,
+ CREATE_ALPHA_SEPARATION = 2
+};
+
+
+enum enumSepSource {
+ CURRENT_LAYER = 0,
+ ALL_LAYERS = 1,
+ VISIBLE_LAYERS = 2
+};
+
+enum enumSepOutput {
+ TO_LAYERS = 0,
+ TO_IMAGES = 1
+};
+
+class KisChannelSeparator : public KisProgressSubject {
+
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ KisChannelSeparator(KisView * view);
+ virtual ~KisChannelSeparator() {};
+
+ void separate(KisProgressDisplayInterface * progress, enumSepAlphaOptions alphaOps, enumSepSource sourceOps, enumSepOutput outputOps, bool downscale, bool toColor);
+
+public: // Implement KisProgressSubject
+ virtual void cancel() { m_cancelRequested = true; }
+
+
+private:
+ KisView * m_view;
+ bool m_cancelRequested;
+
+};
+
+#endif
diff --git a/chalk/plugins/viewplugins/separate_channels/kis_separate_channels_plugin.cc b/chalk/plugins/viewplugins/separate_channels/kis_separate_channels_plugin.cc
new file mode 100644
index 00000000..64a83db5
--- /dev/null
+++ b/chalk/plugins/viewplugins/separate_channels/kis_separate_channels_plugin.cc
@@ -0,0 +1,96 @@
+/*
+ * This file is part of the KDE project
+ *
+ * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_view.h>
+#include <kis_types.h>
+#include <kis_image.h>
+#include <kis_paint_device.h>
+#include <kis_layer.h>
+
+#include "kis_separate_channels_plugin.h"
+#include "kis_channel_separator.h"
+#include "dlg_separate.h"
+
+K_EXPORT_COMPONENT_FACTORY( chalkseparatechannels, KGenericFactory<KisSeparateChannelsPlugin>( "chalk" ) )
+
+KisSeparateChannelsPlugin::KisSeparateChannelsPlugin(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+
+ if ( tqparent->inherits("KisView") ) {
+ setInstance(KGenericFactory<KisSeparateChannelsPlugin>::instance());
+ setXMLFile(locate("data","chalkplugins/imageseparate.rc"), true);
+ m_view = (KisView*) tqparent;
+ (void) new KAction(i18n("Separate Image..."), 0, 0, this, TQT_SLOT(slotSeparate()), actionCollection(), "separate");
+ }
+}
+
+KisSeparateChannelsPlugin::~KisSeparateChannelsPlugin()
+{
+}
+
+void KisSeparateChannelsPlugin::slotSeparate()
+{
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+ if (!image) return;
+
+ KisLayerSP l = image->activeLayer();
+ if (!l) return;
+
+ KisPaintDeviceSP dev = image->activeDevice();
+ if (!dev) return;
+
+ DlgSeparate * dlgSeparate = new DlgSeparate(dev->colorSpace()->id().name(),
+ image->colorSpace()->id().name(), m_view, "Separate");
+ Q_CHECK_PTR(dlgSeparate);
+
+ dlgSeparate->setCaption(i18n("Separate Image"));
+
+ // If we're 8-bits, disable the downscale option
+ if (dev->pixelSize() == dev->nChannels()) {
+ dlgSeparate->enableDownscale(false);
+ }
+
+ if (dlgSeparate->exec() == TQDialog::Accepted) {
+
+ KisChannelSeparator separator(m_view);
+ separator.separate(m_view->canvasSubject()->progressDisplay(),
+ dlgSeparate->getAlphaOptions(),
+ dlgSeparate->getSource(),
+ dlgSeparate->getOutput(),
+ dlgSeparate->getDownscale(),
+ dlgSeparate->getToColor());
+
+ }
+
+ delete dlgSeparate;
+
+}
+
+#include "kis_separate_channels_plugin.moc"
diff --git a/chalk/plugins/viewplugins/separate_channels/kis_separate_channels_plugin.h b/chalk/plugins/viewplugins/separate_channels/kis_separate_channels_plugin.h
new file mode 100644
index 00000000..ce3aa731
--- /dev/null
+++ b/chalk/plugins/viewplugins/separate_channels/kis_separate_channels_plugin.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of Chalk
+ *
+ * Copyright (c) Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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_SEPARATE_CHANNELS_PLUGIN_H_
+#define _KIS_SEPARATE_CHANNELS_PLUGIN_H_
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+
+
+class KisSeparateChannelsPlugin : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ KisSeparateChannelsPlugin(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~KisSeparateChannelsPlugin();
+
+private slots:
+
+ void slotSeparate();
+
+private:
+
+ KisView * m_view;
+};
+
+#endif
diff --git a/chalk/plugins/viewplugins/separate_channels/wdg_separations.ui b/chalk/plugins/viewplugins/separate_channels/wdg_separations.ui
new file mode 100644
index 00000000..0593258b
--- /dev/null
+++ b/chalk/plugins/viewplugins/separate_channels/wdg_separations.ui
@@ -0,0 +1,182 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgSeparations</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgSeparations</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>570</width>
+ <height>350</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQCheckBox" row="4" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>chkColors</cstring>
+ </property>
+ <property name="text">
+ <string>Output to color, not grayscale</string>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="3" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>chkDownscale</cstring>
+ </property>
+ <property name="text">
+ <string>Downscale to 8-bit before separating</string>
+ </property>
+ </widget>
+ <widget class="TQButtonGroup" row="2" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>grpAlpha</cstring>
+ </property>
+ <property name="title">
+ <string>Alpha Options</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQRadioButton">
+ <property name="name">
+ <cstring>radioCopyAlpha</cstring>
+ </property>
+ <property name="text">
+ <string>Copy alpha channel to each separated channel as an alpha channel</string>
+ </property>
+ </widget>
+ <widget class="TQRadioButton">
+ <property name="name">
+ <cstring>radioDiscardAlpha</cstring>
+ </property>
+ <property name="text">
+ <string>Discard alpha channel</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQRadioButton">
+ <property name="name">
+ <cstring>radioSeparateAlpha</cstring>
+ </property>
+ <property name="text">
+ <string>Create separate separation from alpha channel</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer row="5" column="1">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQButtonGroup" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>grpSource</cstring>
+ </property>
+ <property name="title">
+ <string>Source</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>radioCurrentLayer</cstring>
+ </property>
+ <property name="text">
+ <string>Current layer</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>radioAllLayers</cstring>
+ </property>
+ <property name="text">
+ <string>Flatten all layers before separation</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQButtonGroup" row="1" column="2">
+ <property name="name">
+ <cstring>grpOutput</cstring>
+ </property>
+ <property name="title">
+ <string>Output</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQRadioButton">
+ <property name="name">
+ <cstring>radioLayers</cstring>
+ </property>
+ <property name="text">
+ <string>To layers</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQRadioButton">
+ <property name="name">
+ <cstring>radioImages</cstring>
+ </property>
+ <property name="text">
+ <string>To images</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQLabel" row="0" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>lblColormodel</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Current color model:</string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>radioCurrentLayer</tabstop>
+ <tabstop>radioLayers</tabstop>
+ <tabstop>radioDiscardAlpha</tabstop>
+ <tabstop>chkDownscale</tabstop>
+ <tabstop>chkColors</tabstop>
+</tabstops>
+<tqlayoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/chalk/plugins/viewplugins/shearimage/Makefile.am b/chalk/plugins/viewplugins/shearimage/Makefile.am
new file mode 100644
index 00000000..5f8efe55
--- /dev/null
+++ b/chalk/plugins/viewplugins/shearimage/Makefile.am
@@ -0,0 +1,25 @@
+chalkrcdir = $(kde_datadir)/chalkplugins
+chalkrc_DATA = shearimage.rc
+
+EXTRA_DIST = $(chalkrc_DATA)
+
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalkshearimage.la
+
+kde_services_DATA = chalkshearimage.desktop
+
+chalkshearimage_la_SOURCES = wdg_shearimage.ui shearimage.cc dlg_shearimage.cc
+noinst_HEADERS = wdg_shearimage.h dlg_shearimage.h shearimage.h
+
+chalkshearimage_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) chalkblurfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui
+chalkshearimage_la_LIBADD = ../../../libchalkcommon.la
+
+chalkshearimage_la_METASOURCES = AUTO
diff --git a/chalk/plugins/viewplugins/shearimage/chalkshearimage.desktop b/chalk/plugins/viewplugins/shearimage/chalkshearimage.desktop
new file mode 100644
index 00000000..6f3ac5ae
--- /dev/null
+++ b/chalk/plugins/viewplugins/shearimage/chalkshearimage.desktop
@@ -0,0 +1,37 @@
+[Desktop Entry]
+Name=Shear Image Plugin
+Name[bg]=Приставка за отрязване на изображение
+Name[ca]=Connector de tall d'imatge
+Name[da]=Plugin for skævvrid billede
+Name[de]="Bild scheren"-Modul
+Name[el]=Πρόσθετο στρέβλωσης εικόνας
+Name[es]=Complemento para cortar la imagen
+Name[et]=Pildinihke plugin
+Name[fa]=اشتراک وصلۀ تصویر
+Name[fr]=Module de rognage d'images
+Name[fy]=Ofbylding skeanlûke plugin
+Name[gl]=Plugin de Inclinación da Imaxe
+Name[hu]=Képnyíró modul
+Name[is]=Klippa mynd íforrit
+Name[it]=Plugin di distorsione delle immagini
+Name[ja]=画像剪断変形プラグイン
+Name[km]=កម្មវិធី​ជំនួយ​ដើម្បី​កាត់​រូបភាព
+Name[nb]=Programtillegg for bildeskjæring
+Name[nds]=Bildscheer-Moduul
+Name[ne]=छवि प्लगइन अपूर्ण गर्नुहोस्
+Name[nl]=Afbeelding schuintrekken
+Name[pl]=Wtyczka obcinania obrazków
+Name[pt]='Plugin' de Inclinação da Imagem
+Name[pt_BR]=Plugin de Inclinação da Imagem
+Name[ru]=Сдвиг
+Name[sk]=Modul roztrhnutie obrázku
+Name[sl]=Vstavek Ostriži sliko
+Name[sr]=Прикључак за смицање слике
+Name[sr@Latn]=Priključak za smicanje slike
+Name[sv]=Insticksprogram för skjuva bild
+Name[uk]=Втулок перекошення зображення
+Name[zh_TW]=修剪圖片外掛程式
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalkshearimage
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/shearimage/dlg_shearimage.cc b/chalk/plugins/viewplugins/shearimage/dlg_shearimage.cc
new file mode 100644
index 00000000..ff6dadde
--- /dev/null
+++ b/chalk/plugins/viewplugins/shearimage/dlg_shearimage.cc
@@ -0,0 +1,96 @@
+/*
+ * dlg_shearimage.cc - part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 <config.h>
+
+#include <math.h>
+
+#include <iostream>
+
+using namespace std;
+
+#include <tqradiobutton.h>
+#include <tqcheckbox.h>
+#include <tqlabel.h>
+#include <tqlayout.h>
+
+#include <klocale.h>
+#include <knuminput.h>
+#include <kdebug.h>
+
+#include "dlg_shearimage.h"
+#include "wdg_shearimage.h"
+
+
+DlgShearImage::DlgShearImage( TQWidget * tqparent,
+ const char * name)
+ : super (tqparent, name, true, i18n("Shear Image"), Ok | Cancel, Ok)
+{
+ m_lock = false;
+
+ m_page = new WdgShearImage(this, "shear_image");
+ m_page->tqlayout()->setMargin(0);
+ Q_CHECK_PTR(m_page);
+
+ setMainWidget(m_page);
+ resize(m_page->tqsizeHint());
+
+ connect(this, TQT_SIGNAL(okClicked()),
+ this, TQT_SLOT(okClicked()));
+
+}
+
+DlgShearImage::~DlgShearImage()
+{
+ delete m_page;
+}
+
+void DlgShearImage::setAngleX(TQ_UINT32 angle)
+{
+ m_page->shearAngleX->setValue(angle);
+ m_oldAngle = angle;
+
+}
+
+void DlgShearImage::setAngleY(TQ_UINT32 angle)
+{
+ m_page->shearAngleY->setValue(angle);
+ m_oldAngle = angle;
+
+}
+
+TQ_INT32 DlgShearImage::angleX()
+{
+ return (TQ_INT32)tqRound(m_page->shearAngleX->value());
+}
+
+TQ_INT32 DlgShearImage::angleY()
+{
+ return (TQ_INT32)tqRound(m_page->shearAngleY->value());
+}
+
+// SLOTS
+
+void DlgShearImage::okClicked()
+{
+ accept();
+}
+
+#include "dlg_shearimage.moc"
diff --git a/chalk/plugins/viewplugins/shearimage/dlg_shearimage.h b/chalk/plugins/viewplugins/shearimage/dlg_shearimage.h
new file mode 100644
index 00000000..5c82abc7
--- /dev/null
+++ b/chalk/plugins/viewplugins/shearimage/dlg_shearimage.h
@@ -0,0 +1,55 @@
+/*
+ * dlg_shearimage.h -- part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Michael Thaler <michael.thaler@physik.tu-muenchen.de>
+ *
+ * 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 DLG_SHEARIMAGE
+#define DLG_SHEARIMAGE
+
+#include <kdialogbase.h>
+
+class WdgShearImage;
+
+class DlgShearImage: public KDialogBase {
+ typedef KDialogBase super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ DlgShearImage(TQWidget * tqparent = 0,
+ const char* name = 0);
+ ~DlgShearImage();
+
+ void setAngleX(TQ_UINT32 w);
+ void setAngleY(TQ_UINT32 w);
+ TQ_INT32 angleX();
+ TQ_INT32 angleY();
+
+private slots:
+
+ void okClicked();
+
+private:
+
+ WdgShearImage * m_page;
+ double m_oldAngle;
+ bool m_lock;
+
+};
+
+#endif // DLG_SHEARIMAGE
diff --git a/chalk/plugins/viewplugins/shearimage/shearimage.cc b/chalk/plugins/viewplugins/shearimage/shearimage.cc
new file mode 100644
index 00000000..4e7e61d6
--- /dev/null
+++ b/chalk/plugins/viewplugins/shearimage/shearimage.cc
@@ -0,0 +1,113 @@
+/*
+ * shearimage.cc -- Part of Chalk
+ *
+ * Copyright (c) 2004 Michael Thaler
+ *
+ * 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 <math.h>
+
+#include <stdlib.h>
+
+#include <tqslider.h>
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_doc.h>
+#include <kis_config.h>
+#include <kis_image.h>
+#include <kis_layer.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_view.h>
+#include <kis_selection.h>
+
+#include "shearimage.h"
+#include "dlg_shearimage.h"
+
+typedef KGenericFactory<ShearImage> ShearImageFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkshearimage, ShearImageFactory( "chalk" ) )
+
+// XXX: this plugin could also provide layer scaling/resizing
+ShearImage::ShearImage(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+ if ( tqparent->inherits("KisView") )
+ {
+ setInstance(ShearImageFactory::instance());
+ setXMLFile(locate("data","chalkplugins/shearimage.rc"), true);
+
+ (void) new KAction(i18n("&Shear Image..."), 0, 0, this, TQT_SLOT(slotShearImage()), actionCollection(), "shearimage");
+ (void) new KAction(i18n("&Shear Layer..."), 0, 0, this, TQT_SLOT(slotShearLayer()), actionCollection(), "shearlayer");
+
+ m_view = (KisView*) tqparent;
+ }
+}
+
+ShearImage::~ShearImage()
+{
+ m_view = 0;
+}
+
+void ShearImage::slotShearImage()
+{
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+
+ if (!image) return;
+
+ DlgShearImage * dlgShearImage = new DlgShearImage(m_view, "ShearImage");
+ Q_CHECK_PTR(dlgShearImage);
+
+ dlgShearImage->setCaption(i18n("Shear Image"));
+
+ if (dlgShearImage->exec() == TQDialog::Accepted) {
+ TQ_INT32 angleX = dlgShearImage->angleX();
+ TQ_INT32 angleY = dlgShearImage->angleY();
+ m_view->shearCurrentImage(angleX, angleY);
+ }
+ delete dlgShearImage;
+}
+
+void ShearImage::slotShearLayer()
+{
+ KisImageSP image = m_view->canvasSubject()->currentImg();
+
+ if (!image) return;
+
+ DlgShearImage * dlgShearImage = new DlgShearImage(m_view, "ShearLayer");
+ Q_CHECK_PTR(dlgShearImage);
+
+ dlgShearImage->setCaption(i18n("Shear Layer"));
+
+ if (dlgShearImage->exec() == TQDialog::Accepted) {
+ TQ_INT32 angleX = dlgShearImage->angleX();
+ TQ_INT32 angleY = dlgShearImage->angleY();
+ m_view->shearLayer(angleX, angleY);
+
+ }
+ delete dlgShearImage;
+}
+
+#include "shearimage.moc"
diff --git a/chalk/plugins/viewplugins/shearimage/shearimage.h b/chalk/plugins/viewplugins/shearimage/shearimage.h
new file mode 100644
index 00000000..c824fb51
--- /dev/null
+++ b/chalk/plugins/viewplugins/shearimage/shearimage.h
@@ -0,0 +1,47 @@
+/*
+ * shearimage.h -- Part of Chalk
+ *
+ * Copyright (c) 2004 Michael Thaler (michael.thaler@physik.tu-muenchen.de)
+ *
+ * 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 SHEARIMAGE_H
+#define SHEARIMAGE_H
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+class ShearImage : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ ShearImage(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~ShearImage();
+
+private slots:
+
+ void slotShearImage();
+ void slotShearLayer();
+
+private:
+
+ KisView * m_view;
+ KisPainter * m_painter;
+
+};
+
+#endif // SHEARIMAGE_H
diff --git a/chalk/plugins/viewplugins/shearimage/shearimage.rc b/chalk/plugins/viewplugins/shearimage/shearimage.rc
new file mode 100644
index 00000000..8b6cbf1a
--- /dev/null
+++ b/chalk/plugins/viewplugins/shearimage/shearimage.rc
@@ -0,0 +1,13 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkshearimage" version="6">
+<MenuBar>
+ <Menu name="Image"><text>&amp;Image</text>
+ <Separator/>
+ <Action name="shearimage"/>
+ </Menu>
+ <Menu name="Layer"><text>La&amp;yer</text>
+ <Separator/>
+ <Action name="shearlayer"/>
+ </Menu>
+</MenuBar>
+</kpartgui>
diff --git a/chalk/plugins/viewplugins/shearimage/wdg_shearimage.ui b/chalk/plugins/viewplugins/shearimage/wdg_shearimage.ui
new file mode 100644
index 00000000..d63b58f5
--- /dev/null
+++ b/chalk/plugins/viewplugins/shearimage/wdg_shearimage.ui
@@ -0,0 +1,102 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgShearImage</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgShearImage</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>323</width>
+ <height>114</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Shear Image</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>grpPixelDimensions</cstring>
+ </property>
+ <property name="title">
+ <string>&amp;Shear Image</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KIntNumInput" row="0" column="1">
+ <property name="name">
+ <cstring>shearAngleX</cstring>
+ </property>
+ <property name="minValue">
+ <number>-45</number>
+ </property>
+ <property name="maxValue">
+ <number>45</number>
+ </property>
+ <property name="suffix">
+ <string>°</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>lblShearAngelY</cstring>
+ </property>
+ <property name="text">
+ <string>Shear angle Y:</string>
+ </property>
+ </widget>
+ <widget class="KIntNumInput" row="1" column="1">
+ <property name="name">
+ <cstring>shearAngleY</cstring>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>32767</width>
+ <height>100</height>
+ </size>
+ </property>
+ <property name="minValue">
+ <number>-45</number>
+ </property>
+ <property name="maxValue">
+ <number>45</number>
+ </property>
+ <property name="suffix">
+ <string>°</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lblShearAngleX</cstring>
+ </property>
+ <property name="text">
+ <string>Shear angle X:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>intWidth</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>shearAngleX</tabstop>
+</tabstops>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>knuminput.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/viewplugins/substrate/Makefile.am b/chalk/plugins/viewplugins/substrate/Makefile.am
new file mode 100644
index 00000000..5331a04e
--- /dev/null
+++ b/chalk/plugins/viewplugins/substrate/Makefile.am
@@ -0,0 +1,26 @@
+chalkrcdir = $(kde_datadir)/chalkplugins
+chalkrc_DATA = substrate.rc
+
+EXTRA_DIST = $(chalkrc_DATA)
+
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalksubstrate.la
+
+chalksubstrate_la_SOURCES = substrate.cc dlg_substrate.cc wdgsubstrate.ui kis_repeating_substrate.cc
+noinst_HEADERS = wdgsubstrate.h dlg_substrate.h kis_repeating_substrate.h substrate.h
+
+chalksubstrate_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) chalkblurfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui
+chalksubstrate_la_LIBADD = ../../../libchalkcommon.la
+
+kde_services_DATA = chalksubstrate.desktop
+
+METASOURCES = AUTO
diff --git a/chalk/plugins/viewplugins/substrate/chalksubstrate.desktop b/chalk/plugins/viewplugins/substrate/chalksubstrate.desktop
new file mode 100644
index 00000000..8d8a7f7b
--- /dev/null
+++ b/chalk/plugins/viewplugins/substrate/chalksubstrate.desktop
@@ -0,0 +1,35 @@
+[Desktop Entry]
+Name=Substrate
+Name[bg]=Основа
+Name[ca]=Substrat
+Name[da]=Substrat
+Name[de]=Träger
+Name[el]=Υπόστρωμα
+Name[es]=Sustrato
+Name[et]=Substraat
+Name[fa]=زیربنا
+Name[fy]=Substraat
+Name[ga]=Foshraith
+Name[gl]=Substrato
+Name[hu]=Szubsztrát
+Name[it]=Substrato
+Name[ja]=下地
+Name[nb]=Substrat
+Name[nds]=Wassboden
+Name[ne]=जीवाधार
+Name[nl]=Substraat
+Name[pl]=Wycięcie
+Name[pt]=Substrato
+Name[pt_BR]=Substrato
+Name[ru]=Подложка
+Name[sk]=Substrát
+Name[sl]=Substrat
+Name[sr]=Супстрат
+Name[sr@Latn]=Supstrat
+Name[sv]=Substrat
+Name[uk]=Підложка
+Name[zh_TW]=基底
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalksubstrate
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/substrate/dlg_substrate.cc b/chalk/plugins/viewplugins/substrate/dlg_substrate.cc
new file mode 100644
index 00000000..dcecce48
--- /dev/null
+++ b/chalk/plugins/viewplugins/substrate/dlg_substrate.cc
@@ -0,0 +1,59 @@
+/*
+ * dlg_substrate.cc - part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <klocale.h>
+
+#include "dlg_substrate.h"
+#include "wdgsubstrate.h"
+
+
+DlgSubstrate::DlgSubstrate( TQWidget * tqparent,
+ const char * name)
+ : super (tqparent, name, true, i18n("Color Range"), Ok | Cancel, Ok)
+{
+ m_previewPix = TQPixmap();
+ m_page = new WdgSubstrate(this, "substrate");
+ Q_CHECK_PTR(m_page);
+ setCaption(i18n("Substrate"));
+ setMainWidget(m_page);
+ resize(m_page -> size());
+
+ connect(this, TQT_SIGNAL(okClicked()),
+ this, TQT_SLOT(okClicked()));
+}
+
+DlgSubstrate::~DlgSubstrate()
+{
+ delete m_page;
+}
+
+void DlgSubstrate::setPixmap(TQPixmap pix)
+{
+ m_previewPix = pix;
+ m_previewPix.detach();
+}
+
+void DlgSubstrate::okClicked()
+{
+ accept();
+}
+
+#include "dlg_substrate.moc"
+
diff --git a/chalk/plugins/viewplugins/substrate/dlg_substrate.h b/chalk/plugins/viewplugins/substrate/dlg_substrate.h
new file mode 100644
index 00000000..82051ad3
--- /dev/null
+++ b/chalk/plugins/viewplugins/substrate/dlg_substrate.h
@@ -0,0 +1,62 @@
+/*
+ * dlg_substrate.h -- part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 DLG_SUBSTRATE
+#define DLG_SUBSTRATE
+
+#include <tqpixmap.h>
+
+#include <kdialogbase.h>
+
+#include "wdgsubstrate.h"
+
+
+/**
+ * This dialog allows the user to modify a layer or a selection
+ * by adding more colour in a particular channel or lighten or
+ * darken an image.
+ */
+class DlgSubstrate: public KDialogBase {
+
+ typedef KDialogBase super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ DlgSubstrate(TQWidget * tqparent = 0,
+ const char* name = 0);
+ ~DlgSubstrate();
+
+ /**
+ * Set the initial preview pixmap
+ */
+ void setPixmap(TQPixmap pix);
+
+private slots:
+
+ void okClicked();
+
+private:
+
+ WdgSubstrate * m_page;
+ TQPixmap m_previewPix;
+};
+
+#endif // DLG_SUBSTRATE
diff --git a/chalk/plugins/viewplugins/substrate/kis_repeating_substrate.cc b/chalk/plugins/viewplugins/substrate/kis_repeating_substrate.cc
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/chalk/plugins/viewplugins/substrate/kis_repeating_substrate.cc
diff --git a/chalk/plugins/viewplugins/substrate/kis_repeating_substrate.h b/chalk/plugins/viewplugins/substrate/kis_repeating_substrate.h
new file mode 100644
index 00000000..1a229dc1
--- /dev/null
+++ b/chalk/plugins/viewplugins/substrate/kis_repeating_substrate.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2006 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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_SUBSTRATE_H
+#define KIS_SUBSTRATE_H
+
+#include <tqrect.h>
+#include <ksharedptr.h>
+
+class KisImage;
+
+/// All values are normalized to a range between 0 and 1.
+/// XXX: Do we need more?
+struct KisSubstratePixel {
+ float height; // absolute height of the current position
+ float smoothness; // determines how easily the painting tool "slips" over the surface
+ float absorbency; // determines how much wetness the substrate can absorb. XXX: How about speed of absorbing?
+ float r; //.Red component of reflectivity
+ float g; // Green component of reflectivity
+ float b; // Blue component of reflectivity
+ float transmittance; // Similar to alpha. XXX: Ask Leonardo about this.
+};
+
+/**
+ * This abstract class defines the properties of a substrate -- that is, the simulation
+ * of the paper or canvas for natural media.
+ *
+ * Subclass this interface to define a specific type of substrate: repeating,
+ * or full-size, with specific and cool ways of generating the surface, or
+ * maybe based on scans of real substrates.
+ */
+class KisSubstrate : public KShared {
+
+public:
+
+ KisSubstrate(KisImage * /*img*/) : KShared() {};
+ virtual ~KisSubstrate() {};
+
+
+ /**
+ * Copy the pixel values in the specified rect into an array of Substrate.
+ * Make sure the array is big enough!
+ */
+ virtual void getPixels(KisSubstratePixel * /*substrate*/, const TQRect & /*rc*/) = 0;
+
+ /**
+ * Return a pointer to the substrate at the specified position. Note that
+ * you cannot do pointe arithmetic with this value: the position of the
+ * neighbouring pixels cannot be determined from this value
+ */
+ virtual KisSubstratePixel * getPixel(uint x, uint y) = 0;
+
+};
+
+#endif
diff --git a/chalk/plugins/viewplugins/substrate/substrate.cc b/chalk/plugins/viewplugins/substrate/substrate.cc
new file mode 100644
index 00000000..8aa4d32e
--- /dev/null
+++ b/chalk/plugins/viewplugins/substrate/substrate.cc
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2006 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 <math.h>
+
+#include <stdlib.h>
+
+#include <tqslider.h>
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_layer.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_view.h>
+
+#include "substrate.h"
+#include "dlg_substrate.h"
+
+typedef KGenericFactory<SubstratePlugin> SubstrateFactory;
+K_EXPORT_COMPONENT_FACTORY( chalksubstrate, SubstrateFactory( "chalk" ) )
+
+SubstratePlugin::SubstratePlugin(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+
+ if ( tqparent->inherits("KisView") )
+ {
+ setInstance(SubstrateFactory::instance());
+ setXMLFile(locate("data","chalkplugins/substrate.rc"), true);
+
+ (void) new KAction(i18n("&Substrate..."), 0, 0, this, TQT_SLOT(slotSubstrateActivated()), actionCollection(), "substrate");
+
+ m_view = (KisView*) tqparent;
+ }
+}
+
+SubstratePlugin::~SubstratePlugin()
+{
+}
+
+void SubstratePlugin::slotSubstrateActivated()
+{
+ DlgSubstrate * dlgSubstrate = new DlgSubstrate(m_view, "Substrate");
+ Q_CHECK_PTR(dlgSubstrate);
+ if (dlgSubstrate -> exec() == TQDialog::Accepted) {
+ // Retrieve changes made by dialog
+ // Apply changes to layer (selection)
+ }
+ delete dlgSubstrate;
+}
+
+#include "substrate.moc"
+
diff --git a/chalk/plugins/viewplugins/substrate/substrate.h b/chalk/plugins/viewplugins/substrate/substrate.h
new file mode 100644
index 00000000..409a00f3
--- /dev/null
+++ b/chalk/plugins/viewplugins/substrate/substrate.h
@@ -0,0 +1,45 @@
+/*
+ * substrate.h -- Part of Chalk
+ *
+ * Copyright (c) 2006 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 SUBSTATE_H
+#define SUBSTATE_H
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+class SubstratePlugin : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ SubstratePlugin(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~SubstratePlugin();
+
+private slots:
+ void slotSubstrateActivated();
+
+private:
+ KisView * m_view;
+ KisPainter * m_painter;
+
+};
+
+#endif // SUBSTATE_H
diff --git a/chalk/plugins/viewplugins/substrate/substrate.rc b/chalk/plugins/viewplugins/substrate/substrate.rc
new file mode 100644
index 00000000..cf8b8537
--- /dev/null
+++ b/chalk/plugins/viewplugins/substrate/substrate.rc
@@ -0,0 +1,8 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalksubstrate" version="1">
+<MenuBar>
+ <Menu name="Image"><text>Image</text>
+ <Action name="substrate"/>
+ </Menu>
+</MenuBar>
+</kpartgui>
diff --git a/chalk/plugins/viewplugins/substrate/wdgsubstrate.ui b/chalk/plugins/viewplugins/substrate/wdgsubstrate.ui
new file mode 100644
index 00000000..be0713ed
--- /dev/null
+++ b/chalk/plugins/viewplugins/substrate/wdgsubstrate.ui
@@ -0,0 +1,221 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgSubstrate</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>Form1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>478</width>
+ <height>358</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>grpCustom</cstring>
+ </property>
+ <property name="title">
+ <string>Custom Canvas Definition</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout3</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQComboBox" row="0" column="1" rowspan="1" colspan="2">
+ <item>
+ <property name="text">
+ <string>Custom</string>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>cmbPredefinedCanvases</cstring>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="2" column="2">
+ <property name="name">
+ <cstring>bnBackground</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Save custom substrate as:</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lblPredefined</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Pre-defined canvas types:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>cmbPredefinedCanvases</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>lblColor</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Basic color:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>bnBackground</cstring>
+ </property>
+ </widget>
+ <widget class="TQLineEdit" row="1" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>lineEdit1</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout2</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQSlider" row="3" column="1">
+ <property name="name">
+ <cstring>slAbsorbency</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="TQSlider" row="2" column="1">
+ <property name="name">
+ <cstring>slFiber</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="2">
+ <property name="name">
+ <cstring>textLabel9</cstring>
+ </property>
+ <property name="text">
+ <string>Grainy</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lblSmoothness</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Smooth:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>slSlippery</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>lblAbsorbency</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Water repellant:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>slAbsorbency</cstring>
+ </property>
+ </widget>
+ <widget class="TQSlider" row="0" column="1">
+ <property name="name">
+ <cstring>slSlippery</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>lblHeight</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Flat:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>slHeight</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>lblFiber</cstring>
+ </property>
+ <property name="text">
+ <string>Fine &amp;fiber:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>slFiber</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="2">
+ <property name="name">
+ <cstring>lblRough</cstring>
+ </property>
+ <property name="text">
+ <string>Rough</string>
+ </property>
+ </widget>
+ <widget class="TQSlider" row="1" column="1">
+ <property name="name">
+ <cstring>slHeight</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="2">
+ <property name="name">
+ <cstring>textLabel11</cstring>
+ </property>
+ <property name="text">
+ <string>Absorbent</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="2">
+ <property name="name">
+ <cstring>textLabel10</cstring>
+ </property>
+ <property name="text">
+ <string>Coarse</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tqlayoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcolorbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/chalk/plugins/viewplugins/variations/Makefile.am b/chalk/plugins/viewplugins/variations/Makefile.am
new file mode 100644
index 00000000..5a3fafc9
--- /dev/null
+++ b/chalk/plugins/viewplugins/variations/Makefile.am
@@ -0,0 +1,26 @@
+chalkrcdir = $(kde_datadir)/chalkplugins
+chalkrc_DATA = variations.rc
+
+EXTRA_DIST = $(chalkrc_DATA)
+
+
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../chalkcolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+kde_module_LTLIBRARIES = chalkvariations.la
+
+chalkvariations_la_SOURCES = variations.cc dlg_variations.cc wdg_variations.ui
+noinst_HEADERS = wdg_variations.h
+
+chalkvariations_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) chalkblurfilter_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \
+ -L../../../../chalk/ui/.libs -lchalkui -L../../../../lib/kofficeui/.libs -lkofficeui
+chalkvariations_la_LIBADD = ../../../libchalkcommon.la
+
+kde_services_DATA = chalkvariations.desktop
+
+chalkvariations_la_METASOURCES = AUTO
diff --git a/chalk/plugins/viewplugins/variations/chalkvariations.desktop b/chalk/plugins/viewplugins/variations/chalkvariations.desktop
new file mode 100644
index 00000000..32b873d1
--- /dev/null
+++ b/chalk/plugins/viewplugins/variations/chalkvariations.desktop
@@ -0,0 +1,40 @@
+[Desktop Entry]
+Name=Variations Plugin
+Name[bg]=Приставка за вариации
+Name[ca]=Connector de variacions
+Name[da]=Plugin med variationer
+Name[de]=Variationen-Modul
+Name[el]=Πρόσθετο παραλλαγών
+Name[eo]=Variaĵ-kromprogramo
+Name[es]=Complemento para variaciones
+Name[et]=Variatsioonide plugin
+Name[fa]=وصلۀ تغییرات
+Name[fr]=Module de variations
+Name[fy]=Fariaasjeplugin
+Name[gl]=Extensión de Variacións
+Name[hu]=Variációk modul
+Name[is]=Breytileika íforrit
+Name[it]=Plugin delle variazioni
+Name[ja]=バリエーションプラグイン
+Name[km]=កម្មវិធី​ជំនួយ​ភាព​ប្រែប្រួល
+Name[nb]=Programtillegg for variasjoner
+Name[nds]=Varianten-Moduul
+Name[ne]=भिन्नता प्लगइन
+Name[nl]=Variatieplugin
+Name[pl]=Wtyczka wariacji
+Name[pt]='Plugin' de Variações
+Name[pt_BR]=Plugin de Variações
+Name[ru]=Вариации
+Name[sk]=Modul variácie
+Name[sl]=Vstavek Variacije
+Name[sr]=Прикључак за варијације
+Name[sr@Latn]=Priključak za varijacije
+Name[sv]=Insticksprogram med variationer
+Name[uk]=Варіації
+Name[uz]=Variatsiya plagini
+Name[uz@cyrillic]=Вариация плагини
+Name[zh_TW]=變動外掛程式
+ServiceTypes=Chalk/ViewPlugin
+Type=Service
+X-KDE-Library=chalkvariations
+X-Chalk-Version=2
diff --git a/chalk/plugins/viewplugins/variations/dlg_variations.cc b/chalk/plugins/viewplugins/variations/dlg_variations.cc
new file mode 100644
index 00000000..13324623
--- /dev/null
+++ b/chalk/plugins/viewplugins/variations/dlg_variations.cc
@@ -0,0 +1,58 @@
+/*
+ * dlg_variations.cc - part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 <klocale.h>
+
+#include "dlg_variations.h"
+#include "wdg_variations.h"
+
+
+DlgVariations::DlgVariations( TQWidget * tqparent,
+ const char * name)
+ : super (tqparent, name, true, i18n("Color Range"), Ok | Cancel, Ok)
+{
+ m_previewPix = TQPixmap();
+ m_page = new WdgVariations(this, "variations");
+ Q_CHECK_PTR(m_page);
+ setCaption(i18n("Variations"));
+ setMainWidget(m_page);
+ resize(m_page -> size());
+
+ connect(this, TQT_SIGNAL(okClicked()),
+ this, TQT_SLOT(okClicked()));
+}
+
+DlgVariations::~DlgVariations()
+{
+ delete m_page;
+}
+
+void DlgVariations::setPixmap(TQPixmap pix)
+{
+ m_previewPix = pix;
+ m_previewPix.detach();
+}
+
+void DlgVariations::okClicked()
+{
+ accept();
+}
+
+#include "dlg_variations.moc"
diff --git a/chalk/plugins/viewplugins/variations/dlg_variations.h b/chalk/plugins/viewplugins/variations/dlg_variations.h
new file mode 100644
index 00000000..e160e6aa
--- /dev/null
+++ b/chalk/plugins/viewplugins/variations/dlg_variations.h
@@ -0,0 +1,62 @@
+/*
+ * dlg_variations.h -- part of KimageShop^WKrayon^WChalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ *
+ * 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 DLG_VARIATIONS
+#define DLG_VARIATIONS
+
+#include <tqpixmap.h>
+
+#include <kdialogbase.h>
+
+#include "wdg_variations.h"
+
+
+/**
+ * This dialog allows the user to modify a layer or a selection
+ * by adding more colour in a particular channel or lighten or
+ * darken an image.
+ */
+class DlgVariations: public KDialogBase {
+
+ typedef KDialogBase super;
+ Q_OBJECT
+ TQ_OBJECT
+
+public:
+
+ DlgVariations(TQWidget * tqparent = 0,
+ const char* name = 0);
+ ~DlgVariations();
+
+ /**
+ * Set the initial preview pixmap
+ */
+ void setPixmap(TQPixmap pix);
+
+private slots:
+
+ void okClicked();
+
+private:
+
+ WdgVariations * m_page;
+ TQPixmap m_previewPix;
+};
+
+#endif // DLG_VARIATIONS
diff --git a/chalk/plugins/viewplugins/variations/variations.cc b/chalk/plugins/viewplugins/variations/variations.cc
new file mode 100644
index 00000000..40e8fcf8
--- /dev/null
+++ b/chalk/plugins/viewplugins/variations/variations.cc
@@ -0,0 +1,88 @@
+/*
+ * variation.h -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 <math.h>
+
+#include <stdlib.h>
+
+#include <tqslider.h>
+#include <tqpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <ktempfile.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_doc.h>
+#include <kis_image.h>
+#include <kis_layer.h>
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_view.h>
+
+#include "variations.h"
+#include "dlg_variations.h"
+
+typedef KGenericFactory<Variations> VariationsFactory;
+K_EXPORT_COMPONENT_FACTORY( chalkvariations, VariationsFactory( "chalk" ) )
+
+Variations::Variations(TQObject *tqparent, const char *name, const TQStringList &)
+ : KParts::Plugin(tqparent, name)
+{
+
+ if ( tqparent->inherits("KisView") )
+ {
+ setInstance(VariationsFactory::instance());
+ setXMLFile(locate("data","chalkplugins/variations.rc"), true);
+
+ (void) new KAction(i18n("&Variations..."), 0, 0, this, TQT_SLOT(slotVariationsActivated()), actionCollection(), "variations");
+
+ m_view = (KisView*) tqparent;
+ }
+}
+
+Variations::~Variations()
+{
+}
+
+void Variations::slotVariationsActivated()
+{
+ DlgVariations * dlgVariations = new DlgVariations(m_view, "Variations");
+ Q_CHECK_PTR(dlgVariations);
+ // Render layer to a TQIMage -- keep in mind possibility of selection
+
+ // Scale TQImage
+
+ // Set original TQImage in dialog
+
+ if (dlgVariations -> exec() == TQDialog::Accepted) {
+ // Retrieve changes made by dialog
+ // Apply changes to layer (selection)
+ }
+ delete dlgVariations;
+}
+
+#include "variations.moc"
+
diff --git a/chalk/plugins/viewplugins/variations/variations.h b/chalk/plugins/viewplugins/variations/variations.h
new file mode 100644
index 00000000..d8680ba7
--- /dev/null
+++ b/chalk/plugins/viewplugins/variations/variations.h
@@ -0,0 +1,45 @@
+/*
+ * variation.h -- Part of Chalk
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * 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 VARIATIONS_H
+#define VARIATIONS_H
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+class Variations : public KParts::Plugin
+{
+ Q_OBJECT
+ TQ_OBJECT
+public:
+ Variations(TQObject *tqparent, const char *name, const TQStringList &);
+ virtual ~Variations();
+
+private slots:
+ void slotVariationsActivated();
+
+private:
+ KisView * m_view;
+ KisPainter * m_painter;
+
+};
+
+#endif // VARIATIONS_H
diff --git a/chalk/plugins/viewplugins/variations/variations.rc b/chalk/plugins/viewplugins/variations/variations.rc
new file mode 100644
index 00000000..d5db6590
--- /dev/null
+++ b/chalk/plugins/viewplugins/variations/variations.rc
@@ -0,0 +1,8 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
+<kpartgui library="chalkvariations" version="6">
+<MenuBar>
+ <Menu name="Image"><text>Image</text>
+ <Action name="variations"/>
+ </Menu>
+</MenuBar>
+</kpartgui>
diff --git a/chalk/plugins/viewplugins/variations/wdg_variations.ui b/chalk/plugins/viewplugins/variations/wdg_variations.ui
new file mode 100644
index 00000000..191b84bb
--- /dev/null
+++ b/chalk/plugins/viewplugins/variations/wdg_variations.ui
@@ -0,0 +1,897 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>WdgVariations</class>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>WdgVariations</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>763</width>
+ <height>852</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>Variations</string>
+ </property>
+ <widget class="TQFrame">
+ <property name="name">
+ <cstring>framePreview</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>11</x>
+ <y>11</y>
+ <width>328</width>
+ <height>255</height>
+ </rect>
+ </property>
+ <property name="paletteBackgroundColor">
+ <color>
+ <red>166</red>
+ <green>188</green>
+ <blue>153</blue>
+ </color>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lblOriginal</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="0" column="1">
+ <property name="name">
+ <cstring>lblCurrentPick</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="1">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Current Pick</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Original</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQGroupBox">
+ <property name="name">
+ <cstring>grpOptions</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>345</x>
+ <y>11</y>
+ <width>210</width>
+ <height>250</height>
+ </rect>
+ </property>
+ <property name="title">
+ <string>Options</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQRadioButton" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>radioShadows</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Shadows</string>
+ </property>
+ </widget>
+ <widget class="TQRadioButton" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>radioMidtones</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Midtones</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQRadioButton" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>radioHighlights</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Highlights</string>
+ </property>
+ </widget>
+ <widget class="TQRadioButton" row="3" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>radioSaturation</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Saturation</string>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="6" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>chkClipping</cstring>
+ </property>
+ <property name="text">
+ <string>Show &amp;clipping</string>
+ </property>
+ </widget>
+ <widget class="TQSlider" row="5" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>slider1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="4" column="0">
+ <property name="name">
+ <cstring>lblFine</cstring>
+ </property>
+ <property name="text">
+ <string>Fine</string>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="4" column="1">
+ <property name="name">
+ <cstring>lblCoars</cstring>
+ </property>
+ <property name="text">
+ <string>Coarse</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="TQLayoutWidget">
+ <property name="name">
+ <cstring>tqlayout5</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>570</x>
+ <y>10</y>
+ <width>174</width>
+ <height>819</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>bnLoad</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Load...</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton">
+ <property name="name">
+ <cstring>bnSave</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Save As...</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="tqsizeHint">
+ <size>
+ <width>20</width>
+ <height>187</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQFrame">
+ <property name="name">
+ <cstring>frameLight</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>32767</width>
+ <height>556</height>
+ </size>
+ </property>
+ <property name="paletteBackgroundColor">
+ <color>
+ <red>166</red>
+ <green>188</green>
+ <blue>153</blue>
+ </color>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lblLighter</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel12</cstring>
+ </property>
+ <property name="text">
+ <string>Lighter</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>lblCurrentPick3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel13</cstring>
+ </property>
+ <property name="text">
+ <string>Current Pick</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="4" column="0">
+ <property name="name">
+ <cstring>lblDarker</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="5" column="0">
+ <property name="name">
+ <cstring>textLabel14</cstring>
+ </property>
+ <property name="text">
+ <string>Darker</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQFrame">
+ <property name="name">
+ <cstring>frameColor</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>270</y>
+ <width>540</width>
+ <height>556</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>540</width>
+ <height>556</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>540</width>
+ <height>556</height>
+ </size>
+ </property>
+ <property name="paletteBackgroundColor">
+ <color>
+ <red>166</red>
+ <green>188</green>
+ <blue>153</blue>
+ </color>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>lblMoreCyan</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>30</x>
+ <y>190</y>
+ <width>150</width>
+ <height>150</height>
+ </rect>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel9</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>390</x>
+ <y>350</y>
+ <width>110</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>More Red</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel7</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>50</x>
+ <y>350</y>
+ <width>120</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>More Cyan</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>lblMoreBlue</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>110</x>
+ <y>380</y>
+ <width>150</width>
+ <height>150</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel5</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>140</x>
+ <y>170</y>
+ <width>91</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>More Green</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>lblMoreRed</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>370</x>
+ <y>190</y>
+ <width>150</width>
+ <height>150</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>lblMoreYellow</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>10</y>
+ <width>150</width>
+ <height>150</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>lblMoreMagenta</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>280</x>
+ <y>380</y>
+ <width>150</width>
+ <height>150</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel8</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>210</x>
+ <y>350</y>
+ <width>128</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>Current Pick</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel6</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>310</x>
+ <y>170</y>
+ <width>93</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>More Yellow</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>lblCurrentPick2</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>200</x>
+ <y>190</y>
+ <width>150</width>
+ <height>150</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>Box</enum>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>lblMoreGreen</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>110</x>
+ <y>10</y>
+ <width>150</width>
+ <height>150</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="tqminimumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="tqmaximumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="pixmap">
+ <pixmap>image0</pixmap>
+ </property>
+ <property name="scaledContents">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel11</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>290</x>
+ <y>540</y>
+ <width>128</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>More Magenta</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel10</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>140</x>
+ <y>540</y>
+ <width>77</width>
+ <height>20</height>
+ </rect>
+ </property>
+ <property name="text">
+ <string>More Blue</string>
+ </property>
+ <property name="tqalignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ </widget>
+</widget>
+<images>
+ <image name="image0">
+ <data format="XPM.GZ" length="55092">789cccbd47b7eb38b2ef397f9fa2d6e5ecae5e7cf266d0035266cb6da7ed77af1ed07b2f1aa9bf7c83883f704c56d5cd7c75bb5f95d6c9ca5f8a22114044202200f0fccffffcdbe7d3fddffef37ffe8fea625c02eb6f966f947ffb4fbb4e92ebfff57fff9fffcffff88fe160f0b7fecf68389bfe6df41fffc7fff80febf96fd6df9401ff5fcff64232ffde36244f7a762ac953fefd56f29cf35cf2a267f3072ff9f733c906e7836493f35eb2c59fd74ab6797b1f243bfcfb46b2cb7fef0a1e72799c5af2907f7f94cce5732cc963fefd483297cf3a8387d43f992999ffde0c25f3dfb79a64de5f662099dfcfe924cf386f24f3fe4a44ff0fd17e5b327f9e772799dfcfb8078fa87d662499cbebbb9249de6fc9bcbd9d2f99dab795ccc7b31a48e6e3b71a4ae6e315ed25f3f1b04f82a93f0dc1636a9ff32999daf32599f757a54ae6fde17e48e6fae23892b97e78a2bd63ea1f438cef849e97e892f9f7652b99b76f3d91cce53763f0947e6f08fd9c1137b664de5e43c83fc7f53bf0022cf475499c8be719c4f113d824de5cc01671fd0eb6895dbaff50d8ab174ae6f2ad3ac9a47f63c924df4832d73f732a99f777f324998fb73993ccfb5f7f96ccc7df3a49e6e3514592b9bd3aa664ae1fd6bd646eaf9a2b98f4ddf52573fdb58e60d89f6d49e6df9b13c97c3c1d45326fbf634826ffb2934cfee40086fdf88164de7ff65232d9eb9b646e1fa607867e9bbe641a8f816092cf14f2423f4d070c7d8b9f25f3e7bbaf60e89fb791ccfb3b15df43ffe22f30f42f13f240ffea1b18fab716bf877ee967b043dc92bf1f0ea16fdd9af3a8f740bc3dbe64f2f70bc9bcbfcd2fc9bcbfbd4432f90b4730f5cff55e3297bfc9c0187f732899f4772099c6e35b321f7f6b0fc6f8daa6649aff7692f9f3724d32d7f7cb4932ef6ffb4e32e9b302c6f86723c9dcdefc50326f9ff32e99f7975382a10fd75c32d7e795906742fdd3bd49e6df67a2bdd09ff20886beb89164fefcd54932ef9ffa2c98fca72bda0b7d6a9f25f3feb0c4f842bf9a07b0d02fd13fd0afe2090cffd6c660e85b24ae87be05a40f63e1df8277c9bc7debab643e5e575732efef6e2799cb1bfcf89ecbdbed2573fd5cfd781e1fcf952d98fa3b91cf277f74cd24f3fe0f3ec08807ba8d64ae9fc54232e98f27993faff9f13df787ae680ff4d57995cce57103c95c7fac3bc97c7c7c5f308d67b8028bf9f72299cbd3dc49e6f2981f92797fd69664de5f7e2499dbb33b92ccdb6f2dc1d067772099fca72e99b7ff6a49a6f946f437f4b9bd48267934b0d0ef77c9bc7dad68df9cee9fee25f3fe69447fcc31df88f1843eaf6e92f9f3da89649a0fee25f3f1cb85be41ff0331bed07f5f8ca7f0a7d43f13a1df9d2a99f777f32899dfffea80111faeae92b93cee41f090f7effa0c463ce77f48a6f9ee51321fafeb4930f547bb01433fecb164fe7cff5b321f2f2f92ccfb3f93d793bd745b30f421ae2593bfd94be6fd1b2692b93cde4e32b79fda164ced8ddec1d017e74332f9dbb564de5e772899e299140c7dcaa692b93db8df92797fe61d18fe3117e303fd59b792e979b164de3f8918ff05f5cf46f40ff4c715e301fdb9bd80e13f57f792797fad4a30fce906bf17f3f51ae331c4fc19a13d43f89780e693a9f0a7ed028cebfd4e321fafe6198c7cc00b2473f9bc77c95cdf4a4ff0908fc75a5c8f78bfb52553fcf02999ebbfdf08a6f10e5ec1c2bfdc49a6f97c2b99e6ff27c9642f3fbee7fab416f2407fc299643efe912f99ec692099cbd3b492b9bc9ab8ff94c63711fd0bfdb2a792c93e2ac9140f689229df5125f3feed5660e85ffd2a99fce34432efdfee00867e5e14c9941f8ec0d0bfcc904cf9572a99b7a76e25f3fe73c760a1afaa646ebf99e85fe86f2ec61bfaea0b79e11f0ba12f2eda8bfb4b7d267b98897c64dd81a1cfeb503297afbd934cf1d45e30fc93f81ef363b896ccefbf3a4a26793dc1149fae7d30f247ff2a99ea1d3fbee7fed68b05a31eb1924cf9c2083ca5f6076bc9542fd948e6fa900e2473fdbbbc09463d630246be1a6692f9f84481643edef95532b73f5df01cfd7993ccdb7be92453beb5924cf3c14432efbf5cfc7e01fffa2999e6bfb1646e5f9b022ce2cba364de3e37114cfec132c0d047f74d32f9e37b30f26b2f05431f5763c9bc7f42c1d04797e6cf99d0c71be41fc21fa52a18fe24207d9f0bfd5a1d04d3f8570fe009d573dca3642e7fbb054f697ca237c1246f3a944cf53a5b32c5a72f60f81bd796ccaf4f2bc994af2d2593be6f2453bea682e7345eed4e32d5ff14c9bcbf2f57c95cff7dd15ef8a35097ccdb93cd25537e2bfa6b3124fffd055ec2bfcc24537c548045fe518331decda7647ebd2eda6ba37fc478c01f6d44ffb8d43e1ded17e3af3960cc97f5022cf481e257a6dd149fd96bf08cc6ffe64aa6f92604c35eec4032b7efab2799e2375b30e94b2aae5f50ff58aa642e6fe148a67ce1065e927fb80d2553bd2494cc9fdf3e49a6fc45c863c07e1dc97cfcd3a3606a5f7d05633e887682497faf4bb08df8e2030cfb2bc9de17a2ff4bf49f886762f4cf10f666bd80618f3e8dff92f5177f5e914be6ed2f36e005c91b5f24533cf22598ecafeec04be467ae64f28757b041bfaf5f040f29fe68c0268d9726da63917e14a2bdd0c7f424998f5f44fdb314fd91bf83a18f8105467fdc4660e86783e789fee94a30e215e3118c78a3a0f9dc60fd45fa34072f491fc329d8a0f685a964aae7dfc0265d5f2f05537f568f60d86bb091ccfbe36248e6fad988dfbba85f8e24533e48f66f88fe892b30fa67634ba6f97508467f6d1cb0a827435ed11f35fa6388f9c9a7f8c814f157fd065e92fe5f6e6083e42f5cb0897ac417d8227dca3fc036f55fb305431fba77c1747f3b02bba4df3ad9ab29e42f669229df46fb647fe460d8d3aa0243fecd2758d4bbefc0a21eb403a33f2a8a772c263f6fff35055ba827d1f85aa2bf2f1a58f4f70a8cfb252a18febdf1c0f02701f58f2dda7f5d48a6fe9b8071fff21d2cfc83603caf51c1b87fb106433f4b1a1f87fd17eebf1b17ec903efbd43e46b0f71a0c79cb2d58c4e72d18cf2f1bb078be0dc6f3339abf5cd11f8906c6f5de1a8cf846e3f6c1cbe724df068cf6548964ae3f1b130c7f9096608c7f7603a3bde90e8ce7bb2f60b4d77e00c39f075c9f98f639e47fa34832d7e7f84c2c9eb7ba80216ffb08c6f3cc042cd64f1a30e42f9760d88fe382d19e1ced19c11e42aebf0cf17cd306435ecb04a33d610e16f20b16f1470a16ed3981457cf9443c82bdae2660e19f79bc341c8be7d70e18cfd71ec022df8ac178feaa05e379d72bf108e3df70ff369cc8fe1d8345bc9c81d1fe60452cfaeb7a03c3be74ba7e2adbd382f1fbcb3b18e3910dc1689f4df24e657fd4603cafb2c168bffb0cc6f32b1ebf0c67e2fe01e9d34cdcef1283e12faa6f30ee67f860e1ffe660a1efdc7f0ee7e2fed58c58b6e70cc6ef8d002cd6173db0a83f2dc0d0b78edbf77021e5bd078bf6aec1f87d41fabd14f2155bb0f8fd108cdfeb2330da93de83f1fc8ac6d310f2ac1a309ed772ff3734c5fdb48d64ee0fb72e58d4e75ec0f87d7202a33f0d713df4a5237bb7e4782a60b11ee681d15eed112cee1782a1cf158f4f86b6b8bf6581c5fa2af5a733823f762d30eed7d2efdd11f2efcd1d18d76bdc5e468311f2a3c007e379f5082cea75f760e8fbfa8d782cf49dfba3d150fcbebc030b7bdc83a17f099faf472371ffe64c2ceed73460e883cefb6b3416f7ab4fc463e10f2c30e46b8927e279b94b2cee6f6cc1d087ec092cec4930c6f342f24f85fc46442caef75660e8cf85fb93d18cfd9ec783f1162ceaa37cfe19cdc5fd3ceabfb990d79d80d13eeb152cd64fe9fa85f8de7c05a33df9188cf66cbec0d0c7f50d0c7df3b8ff1f2d85bcce002ce227078ceb1d0f2cfca54e3c41fb6f74bd21ef5780f17c5d058bf53beeaf46e618ebd77a2299c77f5bba9f25c6b7f4c1c2bfbd80d19eeb07f104fda1933cb678de2603e37eba01c6ef6f57b0a8ff71ff3d72c6a8b7e8d47faee88fb507c6effd188cdf3bdc1ec67d38c739e2e3c5a63393e21723269e60fde4f22c99d677b93e307577285eb7b8fd8f27ecfe9cf50e0c7d8a79ff8ca7ec7bfefb6b412cc627db81c57e823730ead9eb1158d43fb8bce399b8fe7a0716eb5d7330c663c3fb733c67eda1fa484d2cc6c39a83a11fed193ca57a651282b13e16f3f96ebc9860bdc8d880c5fe810c2cf21bae8fe3e544d4cb23c93c5ed30a30ea071b170cff92d0f81813d443d71730eaed9a07c6f53eb7b7b1c9bee7fa117c49a6f5024b30c5b3760cb6b19ec9e3adb13331e8face93ccfbaf3883f13c23013ba8a72e05d3fd0d1b8c7c734df23b53d8df86facf9da03e7e1b80f1fc82f7e76430813e6d63e229fa3be5e333194e4cd40b52b04ded31b8fe4e4653110ff2fa0a73a736f28d9a788afd67fa180cfd6a1db0588fe3fe7f32610accfb77c3f59721f2c77c493cc5fe0aaf00e37eb731788afa4e059ed1f8361f60d48f6dde1f93d914ebc7460a46bd2fe4fd37994fc7940f6cbec1e89f98cf5f93a578def5013c433d86da6f4c51bf09b9bd4dcce982f2b39cebcbc49a22fff6b83e4dec29ea15d95932adb704c433acffebf43c776ad1fd039d7886f5d315bf3f5356f09acf77d3d1d4a5fa65734f3cc3fe035d134cf7372c30ec355b824dc413dc3fb0e9906574dcdf79c4e2f74501c6fa5b74104cdfb73c3e9d4ea6d6887f7fdb10b3e791bef1f9940ddf1ceb078fe005f5b7c5e7e3e96c86f58f8d0246fd3a76c1f311f9b377b043e31bf07c693a9fa1de19df816dec07f804bb584fa3fe5accc47a86069e517b82002cd6f775b043f39bc6e3dde9923d8eeb7332035bd47f3705ec60ff824d3cc7fecf84ebefd498c19e2faf609bfa2be6f9f0d49c2d51cff5c016e5fb2b176c8f78fb8b15d8a5fa99c9e7d7a93543fdab1b831dfafde6287844f5d10e8cf1af49bfac39c63bff024f499e98ee6fb3fb937f7d023bd4fed407bb435aafb124d37e2d5d30b53f03cf87d43eeb0d8cf5dd7803c67cb7e1f63d75587f707df1e9fece7c30a2fd5d7b30f6b3469f9269fdc792cce5594dc1587fba52ffb84c1edebecd5e326f7f41faebceb19f2cda8271bfa6133ca2e727e0118d4fb2164cfa9c2892f978af4c30eca1f1c19321d7bf2bff7e3660e34ff5e53bb043cfaf5dc174bf6c0076a97fdb929805acfcfb6d0446bdbee4ed9f0d857eddd660f89b6e2298da5f05c4ac3f687e6bc0c311ad87e07a263f9f0fda77f094da537f8067245fc5f569369a1963d29f2b31eb5fdabfe20ba6e7a777e0d188ff3eb9815906c29fa78227d04f053ca3f6b65c3f6663260fd553a93d2cfca4fec91bc95cfeea041e517f5fb8fece2662fcdd023c86ff33c1d31167cd06cf21cf5c308d679d8017d41f0df72fb3e9cc1ef3ebab14ec8c69bfc05432ed47d38885fe5d4cc9b4fe37028fc8fecb37c9649f25784cf6ebbf82e7f47dbc042fe87e05f5cf4ce8936b82e7f4fb36113ca6f17a002fe8f986b8de80fe8bef4dd28fc292cce52fa68269fc4d1effb0db2f49decd0c0c7fdc92fe2ce6131a3f6d2d98fcb7bf02cf49bf370330d68fea5a30fdde38831dfabea3fe59b2fea178b0009bd41e4f03db23aeff37713decb5f00593fc2df5a7c1ee47eb6f2330eadd17156c8ea87ff7609bfc45590b267f78d5c02e714bfa6ab2f1207ff80136c87ef22918f34dfe06c67cd186c48b018dafcee3cd99c5ee47faa48217647f99609bf4c7a0f1b2160392afa3f6da6cfc68bcd69279ff949f6093daef4ec1f067f5817831a4e76de8f70ebb9ece177c806d6abfb3235ec0dfba2bc9b4df9bc6d7ed1376ae5f5c3fe703263f6f4f520a1e53fc99102f66d4be8cf7cf7cc8e4e3d7673e784c7cdd82a7d4de5a03c3fe751e9f3265c2fca09be009d94fc2e397394b87c99f186bf08cfa4fe3fd3b9fb0e7717dacc792e97c0b8f5f58f8bb20d6793d613e5f2cc7b49fc5005bd49e35b56fb1c4fcecf1fe9e2fd9f7743dfdde582ca83f8267b049ed59f3f9686eb2eb69fd782699d62fa83de67244f67de1fa3eb79643b237ef2698f4ab9e8347d4feb0008fc99e1c6a8fbd70d05f4762261e6f9f46e3e730a6f3160618fdbbe6f9c6dc5d0ea8bd0df5bf6b88f89aebdfa25f00a5f8ff4e32edd749c0636aff66019ee17939780e7de2f92a73f643e8bb031e537b7c133c237bf5dec073ba7f44f71f1a225ea3e78f447f79dfe011ddcfe3f22dc68c29feff06e379ba0e9ed2ef0b1effb1747d44f3b1fd0d5ed2f78d0236c65cdf367c7e5fb0009858bf07cfd15f7bf082f4a3492473f96f19d8257b6df8f82e66cb05f55fbe223630ff6f797cbc98b3f67079527afe82319d17e1f6b7581a03fafdc693ccc7d7a0fb194b97da7bbb111b63f2af1bae9f0bd31810eb7cbd61612d1dd2bf94da671943c8cfe7af856d8c69be6e0563be594f2573fdd7b8bd2c1c763ded0f53c01392c7bb4ae6fdd3717d5db8c684fa4bbb134cdfa767f094e28180fba3e5c080fff15fc0b309f5ef9764d24ff13dfc43cae7a3e5d0807d6cf8782d47acbdfcfeed0b783ea1fad50ebca0ef6f3ed82079a32f30f2c5644f6c627f5acce7df655fd0e1e3930460a662dc3f1cc14beaaf40133ca178a8069bf47cdf90ccc74ff3c10e8de78dfa676c8afd09b564daff5982b1ff36a6f64c58ffd2fed40b7836a1fac504bc9c50fd6101c6fc97abc426e2b3700fc67911f3018cf33ac99d643e1edd198cf3176e07463da4fa0063bf8826be47bd53e7fe773965e345fded806db217eb1d8c78f29612b3f6923ea9603cbffb0663bf4949d7b38083c663b3022f68fceb7bb043f6118682a9ff8c02ec92bfcbe9fe7dba49f5c30d18fb636c9e2f2ce7ecf7144f2a6097e4bbe5c4ecf7140fcdc0b0b734018bfde03a784af3c53504cfb15f47dc0ffb0bbb8160ecbffc002fa95e58edc1d8bf1a4dc1163d2f36c1a8575495609c5f1a4aa6f3a134febd83e2ed2f376093faafa3e72fcc01f1f50b3c217ddd5660ac37ad63f00cfe5407cf69beef5230ea35c6026c60bfe55532e55b39d8a4eb6f73b0d8df20ee6f637fe04a32cdff03b043fd757b904cf9d9168c7ae7ed2299ce7b3692697fc898d8c2f99ddb128cf3b317f49f85fa6348f75f1a06d9afb604c37ff817b04dfa1c0ec10ee9bb4ef22ecd015d7fdd8047345eb5079e907e598e60d2d7b40363ffe3762598e2d5750e16e703d692297ffc128cf35768af897afb36108cfaee5c32d56b0f9269fe2e24f3f61731d880ff5125d37ed80558ac974c25d37ec09d64de7fe64132f73fea27d8a2f15732c9b4bea008a6f655a23fb1dfb28c24d3fe470d8c7ae1ed5132e95b2099cf8fa6e82fd4e3c32fc9b4bee3125b38ef7723ff641816d99b7d03dbe48fc22bd8a1f9f95a825d9adf4af28706eb1ede5eaf060fe97aaf133ca1fc5605237e6d8ee009e5bbd5198cf58b4efc1efb6fb71730f67bae66e025c5df8a09c6fecae020998fafd248a6f3ba909fd93b6f4f71025bb0af52329ddf9849e6cf533fc036e993924ba6f96726993f2fcec00ef57ff12e99e2c34a32ed7f0cc1f017d5bb649aef7cc9bc3f22f13c97fa4fc3f859388f5a6d25f3f69443c1d86f3b06e37c4be54ae6edd354c9bc7dd791643aefdc4aa67acf2b18e7f134f13dced325a4ef26d3379affc95f9826e2cb952a99c6f7153ca57835fd0463ff691108267fb579028b78c2001b34dee14532bf7f62814df88b4832d52f2ab085f59d0118eba3752899ecff2699eae307c9b43fb405431f9454329d2fbb97ccdb938cc02ee95b2adaebd2f8b590dfc279e448974ce3f12998e67b4d30ce074713c934ff403e0be72d2dba9fc5e607defeca014fc85f5413f094e2313b954cfea0114cfe467901233fd41792a99e6a49a6f527c198afd71bc9549fb9822dea8fba944cf9502799dad782b17e6d7592c9be6782495fea42321fdff8c7f77cbcb477b043fa1deb9229ff4904e37cc697641a7f0decd27828aa647abfc45032ade7b982495f13b25fcbc2fb0c944032d9cb93606abf5949a6f314cf60bc4fc00a24f3f6b79960d29f5a914cf11dfa53d87bf82999d6df303e16ceb755a4cf369b3fc8ff7660ec3f57de04933ff0f760ac5f665bc114df2b67c1a44f57156c507f5f1cc9b49ff3198cfdc69bab60aac7ac4f601be7fd22c1781fc95132ddaf95ccdbabd492b93e794f60e883229e87fd9ef959326fbf3a964cf9e00318fe5d9d4be6fda192fed916ce83a92f92a93dbe64ca8fd11f229e4c6f92f9f3938164ca1f4f82b1fe994ae6df871f60acf79a6bc9bc7f62f49785f3b1b75230d95775914cf30bfacfc279b22df90f47c413a621995f9f7be011f99b6d2b98e2136d021e4f683d63059e4cb83e7ae2fa19dd4f3b83e734df943118f581f22099cba33c8397549f592dc026d69b8f9279fb6f9f60e453d6156c537f5a63c9644f8160aa47695330fc8dee0aa6e7c5b964f28791648a6fe692297e580aa6fa6628da8bf8c3bc974cf9642118fa38954cf58f89649acf1692e93c27e9936361ffbdd149e6df2b9e609c1f7d96ccf549ad24d37974e887d0676721998f8fba924cf1fa9364b247713df687754f92e9fc672399ea45a23d581f35af92f9f7b9f81eef13885ac1181f4b32d5dfa10f16f6a3044bc974dee9158cfd3f892399fcbb2d993fff26fa6786fd3ba23f711ef146d7bbcc7e283f7b944ce7995ec0639aafab25784af671db0a9e52feb200cfc9fe320f2cec650f5e52beae7d49a6f319e2fe4bd457766083f453bf80b11fa878154cf6b2adc1585f37c4fde0af235530f251717fc45b9e90d7c17ca848a67add5530ad1f74a160aa8f76e279c8e7c34630f97f3b174cf2379a645abf247fe35a781f90ff2818f3c1443297571d49a67cfd4930cd87da1b58e8ff5630ece74b32cd1fa564aaef7982697dc87900633f73694ae6faa0be4aa6fd789a648aa724637fd25a32ed3f79924ceb3d3330f6f325ad64de1fd98364927f2598facbd42553fd3594ccafcf311e16cecbdf22c95c5e652a99de7f267e8ff3c9e1bb641a6f4732bf3efb008bfd812f92297eb32473794b31bec87fa30a2ccea3ee0493ff30f79269bfe23718f53e6b2099ea0377609c7f34be2453fc7b914cf91c1f2f63c0e6478a0fb6e019d58be207c1538aff8fe039e503712b99e6eb5c3297a750c04b1afff22618fb1922c1347fc73bc9b47f4630f2f9eda360b2efab2e98fcd1ea158cfd83452598f47f6b48e6cf8feec1a8b7a40bc1f05f3bc9bcffb61918f596f85d32d5e3447fbaa48ff94030f6ffdc24737bf267c416f6a7ac3f2453fe580bc67e99122cceeb9c24533d6b2299f4ad108cfce30773fd500cc9341f7792a9fe6b0ba6f5da6b2399ce372ec1d85f1d9d25f3efd59b60f89f3bc9bc3fd4a364f22f6f60ec97543792797fa8a960d8c74d32f9932918f61ed49269ff832d99e44d24f3f61a23c1d43f96fc1ef1fe1c8cf763448e645a3f16cfc3fe3d632899e2955832cdafd01f0be7d5ad4a32ad9f3792b9fcc64030ced3d792b93e9723c9b41feb02c6fe67732b99f68b7c4aa6faa3180f9c17f6499ffa032dc46bf098ec5d8f24d3fe08133ca1f530ed049e527eb7f50593ffb83c48a6fd570a7846f7d36b30e6fff25b32d5ab73c1145f28ef82299ed1e660d473b64f92a9def92698fcdd5a3cdf46fd24914cfbcd74c9b43e21e445fda611f7437cb1fe124cf65edcc02edd3f7225d3fb001e05d3fc5ebd108b7879bb93ccfbc72f05937e66a9605abf538e92493f56e021d99f6249a6fa5b2b98fc9f72914cedc3785a789f52f12698e42943c964ef17c9e40fe792697e1849e6f2648e60ac470660bc9f243b4aa6fd3fa1647ebda20826f9d24c32ef0ff55e32d5d7447f60fe2f9f25933f5a4aa6f8e62c18f9502299f40ffa61e1fd4b4a2899f6279492495ed19e29e297028cf795048d64dedef05530e29137c9e47fe4efb19f740cc6fed152134ced0f55c9fcfb488c17dedf74b9934cf64dfa3c326754ffab0cc1643f510ac67a78ba04633e77466083ecb309c026cdffa921998f476582b19fa7ba0aa6f93e5e0ba6fca6188051bf4b447bb1bf4aff00237ff60f92e9fd41f792e9bc7d2599e6f717c1d8cf247e8f7a5d160ba6fecf23c1b4bf21a0f86264e13c72f82499f2fd57c1f06727c954bfcec098df755b30d9ef7a2e98ecdf78974cf54cb447d47b3d5330e2cb0fc9b4df47dc0ffbd12ea9647a9fec1e2cde07f92e99f60b1c05239e3e4ba6f9df974cf9d74932ed9ffff17b2e5f70014f90ef288261df8664b25f5332bd6f0ae36be1fc4ef92499f22d4b3297ff593c0fefb7525dc9e4df3c30de5fa53a9229feb12553bc2ec66f46f2565f92c97f37609ca7b4df25d37e825a32adff89fba39eaafb92293fea24f3ebb7627cb13ebbfd944cfbadbf2453fe37154cf287a664d257d15e715e80fa6fcce673f2af117846f94076075e503d2188c1d88f9a9b82c91f2457c954cf38832df2279ba9647adfe70a8cfaecf62098e2ef6e2699ce27ed04533cb2d5c0d8efaa3c09a6fa46f12199ec5d3c0feba51dcd9f63517f5dbd0886bd3f4be6d76f7f30d59b62c164afde5432d5271f2453bdf0118c7abd77124ced4f1ac914afae2553bd5edc0ff3b9f32498ec6d1308a6f66c55c9341fdd83313f9ba23da8ef46a564dabf664aa6fd21f27b8a37e291643abfe249a6f9ce174cfb13a2028cf78b25b9647a1fd4a364f20fdf92c97f0c25d37a512599d607a03f22bf375ac994ffa49229ff78944cf94a2618fe48fe1ef59e4632bd3f270163becf2ac994bf8beb71fe4b0d2453bd27964cf552d13fa807da2f9269ff612499e627d13ed40f424330b55f13d763bfc6ed4332c50f37c1f0f78a64daff3d964cfb43c578637daf7a138cfd39429f719e6745fa30314df21f590ec6fedd32134cfbb10c5d30f98bcb8b64da2f3c01dbd87fbc174cf5c92001e37c4d25eee760fff1b7605a0fc8b792e9fc81b8bf43f149740263ff68fe2a989eb722fb9c8878201849a6f75f9e25d3f37cc974fee15532bdaf752898ecdd0904d37a475080512faf7e30e9432e18e7f56e82914f5482c91e0bf13ce4ff7e2698c627fb924cebcfe2f7d8ff1b3e80719eaa934cfaee3992491e717ff80f6f2699f22ff13dcecfa753c9e4bf0e92293f394aa6fd139660b2cfc8904cf9df4230e68b4a32add78bf1c0feda740ec6fbebcab3648a8f2792c95fd492299e1848a67ccd164cf25b2d58f887ab64f2379d64de3fea4132bd6f4efc7e8e7827944cfb7f1e2553bd4f134cfa6c799269ffb6781eea8df14432b57f2718ebe591645a2f8b05231f15bfc77e0f652699e229f13cbc7faa9a4ba6f361427fb03f5013fa8cf5e2c495ccbfd73dc924af180fec0fd33e24737922f17c9c6f6cc91ea626f69b5e13f082fccfe64d32d547bfc0385f565ec0886fba1cecd07a663394ccfb237b05633d627b144cf6779949a6f75fd682c93f06349f4dc5fa433d154cfaace982697d721b4aa6f3c11918f585742299fce5bd64aa67958229be5ac560ac27ac12c178bfd79b64da0ff1e37b7adf95fc3dcef70592a95ebb174cfe3a10cf47fda01c08c67e1b5f32bdcfb0134cfde12a92493ed17f585fc81f25d378dc49a6f8e253308d57249e3f417c7a904cfbcd7e30c5d382b11e982592797f24df82b1de954ba67aa6907f4af69baec138af6c8d24533d692f99ea733bc1e4ff3c0b2cde37be944cfe712499f2b1b964b2675732c52bd0670bfb45d54832e58fba64da0fb301e3fd8d4a2499d67f857ee0fc72f82d99be5f81713e3e194aa6fd49e27e588fb89ec1884fae13c9d4ffa27fb0bff0229e67537fae481f66e612fb2d776083ec3debc026eaa53618f18a3b0323fe580f04d3f5c98b64da7f63825df217852e99ce77907c33113f6c4dc134df6f1f24d37c9982b17ee04f05537b9a77c9148f88dfa3deb07a92ccfb7f73168cf365778229be48bf25537d19f28bf501e55e309d4fc94f92c97fcec158cf2b12c1e41fbb4fc9b43e3d104cf3f7f6158cf87ebb170cffe448267942c1e47fba05187f1f455049a6f5614330f4ff0d8cf3b88ab83fde3770d94ba6fafc12bca0f6a557c1c80f6dc9644fb964aa7f1492a99eb1934cf3f718bc44fd632199f2ab67c914bfd782518f16e389f78346a23dd8bfa58c25d379ba4030c95b5f2453fc5c824deacfec2299f6eb6c25d37ae74630e2b94632ad170bf9b13fb87b964cf514713df61bd4aa643a9f0f7bb31cecbf10fa28f6e3f89269bd83e2adb9399f52bd33032fa6fcfef9086cd07e8d95f81eeb1b97a964b2bf0dd8a2f958ff02dbb41fbbbb825d9a3f2eb5608a3fe28560caafb6141fcd45fdb11a83b11e180f05d37e5c5f114cfe669d8051ef6f3dc1a40fab108cf3d9e55a30ce3b1a60d4d78bab649a5fe5f7645f978364dededbb360f247452899ea616730d6e7d6779269fdfb4330f9bbd4148cf8e7058cf5b8e44932bdffe25e30f6835c24d3f9d1b964b27f713decdd16ed9b937fd2f792a99ed2082679a247b0380f33964cf3ab18af05c52f57d1df381f5baf2453bcff0046fcacfe60daaf6a4aa6f9ed4b30ce7fce25d3fedd1918f65f8af1c37e6d4f954cf9cf5a32c927fa17fbede254326faf22aec77c1bd582a9fd971d58ecef3524d3fe5ea1bfd84f97d1f82ec47a83be124cf5c8ca07dba4efbab8de9df2dffba44f0b51afeb5cc1747d32154cf61eecc043ccf74f9269ffd3098cf7495c1e25d3f9c14a30ad9f281f92693de2001ee3bcf34430e94f71114cfe259883f17ef6b52599de2f36144cfaa23c4aa6fafd188cfa79d60a267de832c1345f1786649a3f7e30cd97a2bdc86ff55232c54fb9648a6fc4f367e44fbaa1649a5f669269ffb7f87e4ef6915f2453beaf4ba6f9443c1feb655a2c99e47b944cfb532493ff6bef25d3f86ec1e2bc532318ef1712fa82f3cdc55e32b5ff1b0c7b5acd25d3df9fa04ba67ac25e32bd0f44b4cfc0f95ad13f787f759c08c6fb8f34c9141f6e2453fee80b46fe22fac7c2fbafef24933f17fa8efdf9590dc6fb8d4a8a079626ceb3d513b04bfa5a527cb664f645eb65067848f359fd8369bfec063cc27ae45532d5e31f25f3f15c3d83315f5d12c9544f740553fe1e6592a93f3dc158bfb88127145ffb9560b2873a96cce5d75f25537ce90ba6fa62f283a95e2ae49bd2f82b0f82c93ef385645a6f17ed453d39984aa6fac04c32fdfd5607c1a42ff14a30cdb7b74232e5a76f60e483fe5132cdafb960c4fb5f60c4aba52218ebaf7b30d69fb6e27b9c1f0ceec1d82f962b92c95f1d24537da7148cf93d05239f534f92e9bc8bb81fcefb1547c9544fabc1383fe68af1c67e92f807d3fe43213ff6af7662fcb19fdaa37cc410f5ebfc5e30cd1f6b07ecd2f85a347e06332faa8f1cc0d0efdb17784cf6e91a82499ff44ff004eb318f92693fdebd649adf5f05937efa67c1347fe91618e7bb6e7782112faa60ac8736a1601a8fac00a31ee98c05e37d155bc1347ff8aa647a1fc009bca0f1f21682c99f9ae2fe0b6acf360763fd62bb168cfcb0148cf7790879f1be9ad4954cf53cd17fd8bfe49f24533db1164cfdbd7d07e33cd346fc1efb17b789643a4f300423bf303760bcdfec42f669b27885ee47f38169e1bc977e124cf18d3706e3fd11fa163c22fdda9482a7b43e7805c3ff058660ba9f2b9e87f364d14632d5fb4792e9ef37fe02e33cd926028bf364efe039c9b712f747fdd9ad24d3f58231fee58b601affdb9b648a6f7230dedfe12d25d3fa760a467d3817f218145fd99f9269bda1924cefdf93df23fe7e009b349f98623c2c1a5ffb2298ee97d8609c3f32e6609c3f8b2cc9646f0bc914cf3f4aa6786607c6fe958ee20f8bcdafb43f81e20b165e93fe5c3e25d37e30f13dea3ddd093cc27ede2d18f5983804e3fd1d9a25989ed7168269ff61fa089e223f9e8167d47f862699d6f39e25d3fe68152ce2b70318e7c9ec67c9f4fe12138cf70f252918f1932b9e67507caf08f9f1be9938069b648fc15e308dbf32108cf7df88e7637f627c150cff7a0163ff42f000c6f99c88ec9b4d37a867d1fc62b3f1a3fd3c743f5b8c5ff102463cb2da82117fb4df9269bde12498ec510f25d3fef01c8cfcb8b425d37eaa5232bd5f2506235ed85a9269bda4154ce31d89f6cef17ea8037841f76b447b17d84fb6012fa9fd6b211fea49978b608a4f0c156c423f3bc9b49f3602c31e6f7bc1d0bf4a32c50fe44f6c1bfb3be22918e7e93a6287d907adb70ec063eacfd51b784afdb3d1c0c85f8a5232cd97afe0398ddf652d99fcf75130e5879d09c67c961482c97eae7bb049f74b3ac9349e86649a4f2692b93cb978be8df749b88229be509660eca7f39f24d3f922713dd6afaedf8269bcd690c7c6f9d755001e52bc5b533ceb5a63d29fab2199ce63edc1139a9f82083c25f9f5068cf745dd2cf082c6238d25d3fb1d378229bf503ec178dfce6a0946fce9bd0aa6fe5ccf04e37d0af27aca77ac1bd8a2e747df9229fe2dc136f98ffc4530e9f34a934cf9f10fa6e78be739387f48fde9daa8f7273c3e310716f67b260f9269ffde1318efefb91e24537dcd06e3fd79f6156ca0deb1904cf6a080d1fe6a2199e67b5f303d4fbb801dd8fb0a8cf8f9a611db78ff5dac8211df745f60d413133e7e2c389be17ccc183c27ff97459279ffac4b30de27947e0826f94c4532bd7f5d032fa9fd6d2a784af58e21d8a0f9e1aa48a6f53f5b30d58ffd6730de5f94ad89ed01d9ef86eb2b0b2eb0feac6fc04b92af7525d3fbcd8f6093fccde64532d9cb4d30c57fe1128cfd33eb77c1a41feb028cf7355a1f82e9f9ee1cec62ffea9b60f227892918e785f0bd8dfdafe9b3601a4f270463fda81980f17ea59adbbf3966fd41ef472dc14bf2075b1b6c60fdec4132d50f0bc9944f1cc126c693dad7bf5e9ff2075c6f63bd6b45fd33b1e6549fb8adc0580fdc7682c97fdd5ab035a5f74309c67961e50bec523c1de2f736eaf7f11c3ca4feaba8bfa6d664467fffdc080c7f53b492a97e6f08a6f686776013fab4964cf69982717ed224ff30b5b15fe81608c6fbd3ce60c48b2d8dd78cdd8ff2eb5430c5839b5730f2dff60086be74a4af33d6ff148fdd8391ff6a74bf390b30693de808b6917f64c436ce8fdf1230f6bfb7345e0b6b3a27fbe9c0f319bdaf8bfcc782a5f7e43f0f60cc4705f99f256b3fedf71c826d92ef3625b627349f68dcdf9b2c9f9b927f237d3458ffd1fc5b8327f007241f530f1aaf6b00467cad51ffb2f8674efd41fed5b6711ed0e4fac192cf39b57733022fe97ecf977feda32abf7d8c9f3e26ffa7827fa74fcf0afb9da5daaac3fe58ff6a0be8f3df21cb2f72b9ecf3bb5c0afe9b90afff77f7df5116d62247f5d81ffad87ddba87590cbfd87bfb3f1f9779605f20899fa6be8cfffb79fff167b71e9f393743ffadc1663f4e33aa96fbdedf8eccf3f18b9ffff65e16dfbc90e6009240d1fa9bf2b3bc9439ee0df4d1661eb3f64f9313a3f24f3e4e717cbfa7791e5379fecfefa91d758f05a8e94457a8a7f2b590235542335561335553335570b364ea55aa917b5669f86e951ab76ec7365b2de544dd5d99f15ff9dc67eb1fe379365a3aed827652391a85bf6b963d2ecd43dfbec982c07464726dd91fdfb4e3da9f74cce7bf5817d0c76e53ff4daff5b6479e43dfdc446e699fddb597d515fb94ebda9efea87faa906ec9a9449f8c524f85607ea501da96375a24ed5993a67d2fc1bc9c25a7a5637ec9f91ba607f02d8fd92c9f2cafe6929aafaa4284cc7be15431d2ba662b18fad380af31a8aa7f8ff3d92fcf7cc954aa0844aa4c44aa2a44aa6e44ccf5ca63d2dfbf4b6622a059b45064aa954ca45a9954669954eb92a3745537465a5acffe8b5ff37cab251b6ca9db253cf8aa2ec95036bf1513929f7ca83f2a83c29cfca5979515e9537e55df9503e952ff6dfbf9581325446ca589928d37f23596c65a6cc9505d3b393b26413cd83f261288661b044c0b00dc7700dcff08dc0088dc8888dc4488dccc88dc2288dcab8a87746fddf23c99f9345b58ca6ff23a390df6677a3353ae36adc0ccdd08d95b13636c6d6b83376c69efd391847e364dcb3cf897d8e8c1fd8e7d178329e8db3f162bc1a6fc6bbf1c1b4b0cf02685e757f9b797f9aadfe999ff8af6561527c1a5feccfb7313086c6c818315fd4186363624c8d194b9916c6b2370ad3304dd3326de3683aa68b8fc73ebe19b04f684666c465eaa53a9a31936a6726666a66666e16666956e6c5accdc66ccdcebc9a375333757365aecdcd2f33b1f2eb1cfcd764311a736bde3169becd9db9e7b21ccc8379344fe6bdf9603e9a4fe6b379365fcc57f3cd7c373fcc4ff38b7dbecd8139c467648ed967c23e63736aceccb9b960992a3334e3de322cd3b22cdb722cd7f22cdf0aacd08aacd84aacd4caacdc2aac12b9dc2f91c5ffaa2c56655dac4b3f2e566d0cad5a3d5b8dd55a9d75b56e9666e9d6ca5a5b1bd6d3f7ccd96ead3bd6522689b5b3f61677bfd6019f2393666a9dac7beb817d1ead27ebd93ab351da592fd6abf566bd5b1fd6274b98bf5884b0601e3d61b3e9c0faeea3cf1fd1d1bfa2634cb31a8bfe82f001fff74a89aca135b2c6d6c49a5a336b6e2d7acdb196cc74fa4a9ed18f85b5b34d48f2439643bf4c614e6ddb766cd77ab03ddbb7033bb42326cfc178b4633bb1533bb37336abda766197ea935dd997de92fecce74fc932307756cdc6646055aa67d77663b776675fed9badd9ba71303fec95bdb6376c249ef9676fed9924625414662bcc5e602bf766681bf6d6beb377f6de3eb0cfde3eda27fb9e8debde7eb01fed27fbd93eb319d7b35fec57656fbfb1d1b07efffcafc9f27cb16a66274cb78cc6f8b4df992c1ff6a7fd657fdb037bc8faf3c47a7864bbe6dc1edb137b6a2db924bb7e64fab161ff9cb1f6ce85fd9b91bdb0972c485698ddcc1dc3311d662c8eed384cd2bde33a9ee33b8113b218f5dd89545df17fcdecfe155954d7183ab113333bb1edda499cd4c9ec2f27778a5e0ea7640ff0ed3d6b55653d3b17361acf4cc706cc6216dc6ed8ff3b356b6be3b44ca6b9d3998173756e8e66f7938feeac9cb5b3b1b7ecf78eb365d21c8d9d73e7ec9cbd73708ecec9b9771e7ec9107ecb7a7eb6a03f234b2f09f3c683fe7ecea3f3e43c3b67e7c58cadb33db1ced6b33d6656cc3ece2b6b5dc5dab5c0a7f765ec63cfe9e374f8bc39efbd24f6d20e9d0f66fd47e7d3f9ea7fe954ce379366dffff5f6cec8e9ff5acca933b3eb9fe4f8576599ab9db3b05f9c25fba1e21a6ce2b08c23f34accd3bab6ebb8aebd702a73e17ab66b1f5d9ff9a8931b981fccdacfaca5f76ec86c2ae673e6d18ddcd84d98bde0e3746e6a7acc73b02b594fbcd93336be67377373b7704bb7722f6e6d176e63356e6b358ae67656f3afe8987a70afaaeddeecd6d55cdd5db96b3626cfeec6dd9a43f7ceddb97b3622dbde86dd837bb4576e6031ed331df7e4debb0feea3fbe43e1b817b765fdc472195fbeabeb9efec5707f7c3f9703fdd2ff7db1db84377c474f1c0fe7dec4edca93b73e7eec25daabd2f6091b8a7aa81f70fbdda9f91c533d8f46d79b6e778ae937b9e71b2179eef055ec8e4601fdbf0222ff612e6030eb6d1eb8c977a99977b85577a9577f16aaff15aaff3aedecdd33cdd5b796b36e7c7c6c9db785befce7a70471ebb0b1b5d9dfd3ff36fde8e59cec1db7b07efe89dbc7bb5f01e58467af31ebcc71f5af5bb1ff853b23c79cfded97bf15ebd37a730637362dbde3bd32f2e099368cbe6f229b39ae7de76bd0fefd3fbf2bebd8137f446ded89b78536fe6cdbd85b76441d7a3aff8866ffa966ffb8e71f45ddfb31e7c9ff9e8ad6df8811ff663e547ee8069e4831ffb899ffa198bd6be51bffd523c9189fe75599e2f7eee177ee957fec5af0d6603e6d46f7a49fc967d3aff6acead27ffd6cf77bee6ebfeca5ffb1b7febdff93b7fef1ffca37f62f966a2bef8f78aea3ff88ffe93ffec9ffd17ffd57ff3df8da3bdf03ffc4fff8bf9f485bd30c74ee57ffb037fe88f8cbd3ff627fed49ff9737fa1382c27fd6679f70f597ea97dfc99d8d25f066aa004060b112da65f6aff97c0f7fae5b7811d38fe3570cd0fe31478811f04411844411c24411a64411e14411954c14509839a7d1afb3d68838ee59af3e06a3f07b7400bf460c5fc48ef0d9560ddeb99ad30d906f6c27a0e36ecaedbe02ed8057ba50e0e4a191c8353708f0af54f35ab3f2d8b1d3c048fc153f01c9ccdd829ad73f012bcf6da15bc05ef81137c049fccf38c83afe03b1804c360148c8309fb330d66c19c49b47016c1325443253442d3188416fbc39c71e8865ee88741188651c86cc73a8709f3cb4698f29881c50f61d6fbfc300f8bb00cabf012d661e32fd421d3b41fb2387f94e5e77af6cf63d25f1db661175ec39b19875aa8b3bbafac636f27e13a5c33795e8c7b2f0d37e136bc0b77e13e3c84c7f014de870fe163f8143e8767f52d7c095fc337ab08dfc38ff033fc62d2982c22f6d97ff90e07e1301c8563e3184ed82cb40dd6e1943d63e6ee99fd7c9b53f6dfe7e1225c466aa428456444e68fcacdaf5a46b288ff862c28f1d4c8525fd5d7c88e1c7f19b9e673e41987c8376751c02375a61351c8e2f7cf88e524511c25511a65c62dca8347ab65f369cafe3c4645f01895aa1255d125aaa3266a5910d345d7e8166966678ccc75d4467ab48ad6d126da4677c629da452c82f0039ef778d68ecdb40bf6bc7d74888ed129ba77d2e8217aecefcdabed866af4d1eeaff6f2932c068fb043b77516ca2e7a8a9ea373f4629ea357f6a437e6750d16a79ca37773c2e6e8aad7eae823fa8cbea2ef68a0ce153f1a2aea8f2a2c7f9e1b8da27134096d2b8ca6d1cc8aa379b48896b11a2b56111b319bac629b85166eccbc3d9f73962c7f93b29843e33ef6e3200ea3fb388ae3f081f554cadbcafc5a1f25fe2c0b7ff68f7131d4f8f9e22cd4f73889d3388bf3b888cbb86277bcb0f87111d7d6dedd5b4f7c2639b959dcc46ddcc557ff515dfdb4f662cb3bbaca5875e25bacc5ba3f8b57f13adec4dbf82edec57ba5890fea323ec6a7f83e7e881fe327e3143fb3d866c9bc7380b86e689de373fc120ce2d76011bfc5effd88736b3055a38fdeff992c0ad34726cb6b9cb8adba8a3f4c23fe649db7641ec6b09ee3da665ed3fc0c33f6dcaff83b1ec4c378a456eaca7e51ee94713c862c3c1eecff9dfdb7493c55f57816cfe345bc4c54e3c17e4894c448ccc44aecc449dcc44bfc24484263efde9b3e8bd8d887e7a42c3b65f3d6d17c4da2244e92244db2a84872b1baf07765b1c886f8155b36bbb2fe65914fa2b8499194e69b71f26fd69e8dc9d9b998dff6c13ad953e39054c925a99326d6d5f7beea9db4ccca52f40d55c1d97d95bb385332bb4abae49adc12cd38252ceb4956c93ad924dbe42eba26bb641f1c9243724cd82c657a8ec272014364d94c9b4b2f4dee9387e4d158264f09b34ab146d2e722ff4c96e499f5e198e50e2bf6efe7e4257935dfad3e3f3f276f56ff8afa7df26ece8dfb709c7c249fc957f29d0c143d192a8b64c4abe3bdc7b4fbac8dc9c264b2df93713231de9269324be6c63159d8c76469c6a99a2aa9919aa995daa9e3dfa76eeaa5bef1603a2cbfe1b2f45910cb54b769601cd3308dd2384dd294cbc2d76dfa7cc4180aaff6932c96b0fe3453466e6b97cc8e9d344f8bb4343fd22a4c98f75a5afdfe8687f4621becee75daa46ddaa5d7d451f4a04b6fa996ea91c9fd3f978549c3644957e93adda4dbf42eddb15fedd3837d4c8fe9c9d8a7f7e943fa18fae953642b7a344c9fd373fa92bed2c8902c2ca7db4681719fbea5efe947fa997ef5feb197a56f7f9f5bfd2acb8f91e17a78607dbb5412ff2139a7dfce9069eb673ae86da5f7c54ee5fa696f8f553a4ac7e9249da6b3a4b50b65c3f42c5177fe23ef31361a7d0edad724d379ba4897999a29c63163f971b4efb3e3ccecb3e2649559999d39ea57ea0475e6665ee66781e9fa81a3a06ab0eb675096e1c5599845599c25ce23b3172e8b6af5b9d52fb2889a9add3f99d14efd4a064ccf952c553eb2cc74cc2fe61b077dcecbf477613d982316e37efaeb2ccf8aaccc2a61e7e45b98b34db24b56678d5dc763f53b6bb32ebb662c62f343d6df6ff6c2fd66de9c652c99661ce3a74ccf56d93adb306bd3b36d76e74efa5999c53363a603cf76bfcd8445369691edb23d93e5901db313d31d85db7491ddff268bf28b2ca67a973d3032b24743c99eb82ccc37f67d642ebcc4661146f69c9db397ec357bcbde852c1855577d4bdaec23fb8c9e93419a655fd97736c8d8e866a36cec8eb24936355da7cc66d9bcf7ebacbf17d93257734509552b377233b7723b77d8377d3d6dc29edad74398b7cedddccbfdec900779a828ff4496be024a7dabf8bd36f63edacc23c330ee982cbd97efed70c024619219f7799c27fe364ff32c3c30597eac4172bf95e779919779a556f925aff3266f8d63dee5d75eb7dc613f1ef9cdfdeeb3e25cb316f153aee7ab7cad9eed32dfe4dbfcced67396c1b09879c8729a4bafd9feb7719f29f93e3fe4c73cc88e4c9b1392c52afe812cbd0f559209d332db2ed5263f1926f32baed05ca6678eed5877ecbfbce6f7fe5dfe104cf347a3fd690d92d97afe943f671725cecff94bfe9abfe5ef7dd4937ff49909af719cddaf6cca73628dcd8871fe997fe5dff9404d9cc833f3613ecac7f1579ff1997dbc4c51b4cfee30c9a7f92cc9988e1d59a699f47e377c0bdffe200bb75792259fab7b854d65ea77be302c63cfd2fb1dd5bc481673943bf9b2500b8545f5b3e8814547b6dcabc0575793b1fa919f0ba33059b7d9ac557d2cbfe8f312ebaeb7e4c2e96b1785cb62ad53e1157e111461112923d52ee22229d22233f67d5ec365611ac6aecdd98cb92f8aa22caa3c2459faf6b398f5f597f9e5375958c6b34f6fcc62be8b0b7be4ce74a97227646177ae8ba6688b2e288a6b714bf25f7684303d53fc645268855eac8ab5710835e7b597a5d8b06cabaf6a7ef4d5be60cd243916dbe2aed815fbe2a0d8c5317b284ec57df1503c16cc3efa1a279764614e0b268f7128cec54bf15abcfd248b1aaa7f57164fcab22bde59fe742a3ed894b5efa33c5420875c9645f1597c15dfc5a01806398ba2c90bffd8555114a3625c4c8a692f4931ebd72c989ea8c5bc8f467b5b6677e03163b12cd5ecbb544287c540d7d250c2d22cadd22e9dd2354ebc22c2ae36c7f6a1f498cdc6a55f06e1ae64290dd731f7efc822d654c40cf3adb665c472b053191b2ecbef852cfb5e16f3cb3a9749999659996749745f163f564a7824669465599597b22e9b5e92b2cd34661b565f3b6371dc985bb4e10ffaaca7ecca6b79b3be4acd0a4a9d8d67c4a45995eb72536e992cbabdeda326368e5bebbecf64cabb7257ee7b591425cd7a6d28b552fb45961fd13ef773ea8dcd103b75c56439183e1bebc81c5b7d3d2cb0674e63cfcb63792aefcb87f2b17c6271ce86e527a398c594ca9d5d97cfe5b97c295fcbb7f29d79d12eef32adafee9bb3bebec13f337b5f7eb079bc2c3fcbaff2bb1c985d392c47e5b89c94d3c42d67e5bc5c944be3c45c7d156a7c4c0f665f1939564a655466d06746a7e0d4ef2ab2aadf62fedefb3059d8b7663f36c8d834bbaa2c26cbbd19b2deec97483a264b6b06c6a1b22bc79bc5e3a00996e5c4dc562e538ba86236cfa29545e5574115329fca66bb3ea736471513d73a313946fd9a4515dbdb2aa9d22aabf2aaa84a2bacaaea52d55553b5556745c1b1ba062b362e5ba7a355b57ebda3aff254b74aabf42467b21c83a36ad9f51f641151a5cf6571d488e9e246bd315559556b264bc4662c268b193269f64c96a37bf65a6fae2e2387e9eb5bb5a9b6d55db5abf6cab53a54c7ea54f575e17be6c717d681c5d5233e26a3fe2ebd3d570f4c96c7eaa97af646d5b97ab1aaead5dc556fd57bf5517d565ff128afabef5e966ac07ac2e5f5cf678bddb11a56a36a9ce4ce23c6c5339adf627e4bca6270efba60d1ee539ac5a36a524db98e912c51af654c965335f33a8f656bca3c34ccae9a87af9eaac6ac3f17d5f2a26637f7f5a25cb81fb615f38349d17f26b406c3ee7570377d7e75312fd6c5be38e1cbc5bd78179f8d897f092e6134b8449798c9d2b91fccbadefb159cde673059946a7449823e47f6d9c7fea32ca859283c96225912f549bdbfa4ec9e593fc6fdfa9c6df523d4af3d18a774e75d2fb9925e8ad0c8eefbbcfd525eaacbe5525f9a4b6b9c2edde56a6fcdd1e5165f98bd93244764f10773e445d68e5da55df4cbeab2b6c2cbe6b2bddc5d7655a7b697fde57039ba2fbd2c173633b1d8cde27fd5d684fde2fef27079e4b2a0adfd5add3f95256071f24d29c2faf27479eeb585d61bfb95a07ecd81e9d8a377f35545b3df7975c88ca6feec72bebc5c5ecdc4383afae58daf136d8235f75dbd7e8db92c7c3d96f5f196c5dd5333bebc5f3e2e9f97afcb777cbcf06a13d388e16578195dc66c869ddb6c66cd466c967db5ee7adbbf4c2ed3cb8ccba2f0bcc2fe5d16392f4096545373b5cdcf97f9657159f6eb90bdcdb2d8b85fd50accc08d8c83a7298f8a1fb4c620fca8d55a49b6b5519bc98ac9f9565bb56def1cc38bfaf99ecd8d336ef74cc7b8341e9b3146e6dcdef82cdeac9ddaadbddaaf83484b46e9ad0eeba88eeb84e5ca9fcce3796c6e9db008f4c9dd32590e755a67756e325990875bfd0aeaeff9cbcfb2287eaa2b6e5dd4a5f25557c68149c0bc0fb3dfa8978569716cc69eee2b6aa9cc422bfc8caa9a4590ec7f0d6b5beb7eb84347cdaf2c63af9cd73063f67faa22f6ebdeaff7d27875c746f9cbfc626d5cd6d7fa566bb55eafea35d36ca77c8af27a536fcdd8b9b23cdceb6318d6239bdec2eabb7a57efcb3d932515759e3fe695d8112074cc55efd44370523ae5b13e184cb3597e7f6fdbbc12cfda581f599b4ff57dfde0b6a1556d13b77eac9fea67e3549feb17a65b8bfab59f159cd728b02d1691ceeb37bfb1b7fe376fd994b220ca89acbdfb5abfd71ff56738a8bfeaef7a500fcba01e992ed3c27db17077aec3f29881cb324b63578feb493de5b2507ef20f7264f6a797a59ffb13f6ff0d9bfda7f5ac9ed70b9657b2fc8bc52e5b7b592f9d779bcdc98dda288de13f5a35f3ca1f8dd958c64363db47f6d9374e3f438693be6ed3fbb2c665ff34a2d0def09a9af1cb1ae0d074eb5be3357e1334a1f3d4444ddc244dcafae291e54977eeaec9ac2dfb158b429bbc299ab2a9b8bdd09ca8f42b763fcb42732397c5e4b364aa8cd2cc99c77a7369eaa6316377c3eefb7039352d0b8359d6e186c6aee99a6b738badd0b48a466b74fbc18c9b557aecc7c57c6fd64cdfc76c2c3efa5cbdd9345bebdcdcb9dbbe8283d53fac9c9b5ebfb3a4d935fbe6604d9a63736aee9b0726c363f3d43c3799bbeb6be64c2fe3e6dcbc34afcd9b948559c51f65a1d95ecaa2f1959bb5faa138cd7bf3c1a22ac7ff609e89d973bfa6686f9b4fe3e0dbcd57f31dbae167ad3483669828d60b7bde283359ae356bc66c961b46611f41369366dacc9ab971b296eeb6e1e3815566167d9b9ed3354b63efad5bb5555aa3355bcbe8ebd581396efb15c45d9f2b87ba71689dd66dbdd6ef63181e7719aadfaf09ff365752a5cfa4bdc2fdfa937a8bc76de03dc65d1b1afd4afdb658703fbbed6dba8d8c531bb7499b865ef5de666d9e9fdaa22ddbcad8370fed85595585fce4beaddba66ddbaebd5e5876dfded8bcf3ddd70ee4eabfefed5aaddf1de36baddeaeda755bb35f6dda6df0dede056f5ec89eb7734a63d7eedb437b6c4f52163f38fd41161bd97abff39945bc2c951e313ddbe5b9a2b7f7ed43fbc8b4f7686ffa9d05b5d53ef55adf326fdf9edb97f6d518861f4e5c44ed5bb269df59ccb3cf3b7bc9645ef5f949fbd17eb65fed773b6887eda865b3068b697aed123b19f67e906bf6b69db0acf8d44edb593b6751cb397875ed76d12e3bb59fdbeace38754a67746667c571922779af472c8e39fe4116e75759d84c99a94967770e93e6dab99d67192cd770d89cb063be56ef7c7b5b9f7d3753baa00bbba8da767197746997b1b0b8e8ca7e6dc8db75157bfea5abbbc6df756dd775d7eed6699ddeadfaac8e723b5ec95b326b687b8fe2fb4e65dce75db7ee36eeaedb76776c02d875fbe6397aef0eddb13b75f7dd43f7f8ab2cbfc563b40fdae2fbb87b59fabdb76ef7d43de7cfddb97be95e6bc738b9ae7de8ff1a4166c38eb3eddeba77964f9cba8feeb3fbeabe9d85fad80dba6137eac6d19d195b0b33f6b56ed24dbb5937ef16ddf2aa5e95ab71358d9dfbca7763f9bd1ce6d00ffa99fd6ad97bc7bada4cbe73b7bb322bb18ee1cadd5d5deffdea3109dfaffe35b886d7280fa302b66ffe1d1d13eb0b72bf196a7fdcef5de36b52b2d65d53ebe19ab119ef6c9dddcf7eb5f79ab3ff5a5ccb6bc5e29897ebe55a5bfeb5b9b6d7ee7acd27d7db55bb321d5533b30bdf8da69c5c57d7f57573dde6937efe655aa8f4750ce623a2be06c6f7638dd87c74ecfd38d515ade7de5aaa8171bcde5d77d7bdda3847b5edab2c5993353c07367f9c07f8afd7f89ca7ebe17a8cd953afa7eb3d3dddbf998b6641d1eef5e1fa787dba3e5fcfd797eb6bad3069deaeefd78febe7f5ebfa5d75d74139bc0eafa3eb987d26d7e975769d7b6bd60b8bcccccceb92dba2f5f327f2dd7d73c7fc1c27ebcc52c3a79b7263f955348c4c36f3b9aa6dbf33591cbebef31764b99937eb66df1cd6379ecb66877edf8bad140b2fb9b139d0b8f7b51b0b346f8152ddc25b748bd5db2db9a5b7ec96df8a68d025e15755df4a7377ab6e97f0e3c626c65b5bac6e9db1ef772df0fd16d6af1f5eafb0d86cc4246aee7236b3dcaeb7db4d4bc6d133cb2d44fefb87ddf3ffb52ce6e34dbfad6eeb86c5860d1b0d663515f3f8ecff6d8fc5eecc9fe593dbe6b6bdddd5a5fa62d7cae2b65386b7fdeda0d4ea58dd869f55773bde4eb7fbcbddede1f6787bba3ddfce51623f180fb71733643e7af24759983454afa4fbbfdede54f7f67efb48068a226ac97f7d7d3f2a6e9fb7afdbf76dc02b565f2cb35c58776c86d89a73162f6d6e43e3741bddc6b7c96d9abab759eadce6f1241ef77bf56f8bc80a5fa2eab6d4d4a8d394a85202f5ac199aa9599aadb1b16e5acdedade4e78fbbef3396c82759cc58f3345f0bb4508bf242d1d20ce3f287d3597fc25e1eb5584bb454cbfad981dd7b617e7a119385f624cdedad96f733a75668a5566917ad564325615ed0b65fe289b25322add15aadd3aedacdf84c1dd573979aa6e9da4a5b6b1b7ba16da99af0ebc8b03f2a8bb1ad7667dada9db653bba0b9bddbef2c7f37642dcfa1f8f22fc8926a7beda01db59376af3db008efce9cfa1f2c3bda71eb6451633568f92e43ed517bd29eb5b3f6a2bd46b935d2de8c85f61e4fb40f36269f2c216e94246ccb2767e999da97f6ad0d3436a6edeeefd98bf5dcee2c35f2b59136d6260a8bd955d72eed525db37111f562ef2fcbf2a84db59936d716da52578d7da8318f79673d9993b86e6fecb363518056b6bac26c79a71bbad92a9dab5bc64db77527327457c97596ee844e7fe622ce597e32d4033dd4233dd6133dedc7e0d74f98f5b2447e2f95bbd7333dcfebb2d20bf6fbfe0c84266b797c86ff2b3a16157aa957fa45aff5466ff5aedf11c3f2de39af8f322fa45ffb798faffbfaa6ebbe66817ed3355dd757fa5adfe85bfdcef850bff59dbe77c6d5413fe847fda4dfeb0ffaa3fe14bd07aece722db28dde4ef86e0bf3e78fe9e8e764adbfe8af4aa36ead86cdca34abf4f6eff075c43fbd8724c9f537fdbdb8ea1ffaa7fea57febcc07588affed6ed3ca56a3f7beea637afd3a561f4733895c33d687fa888dd0589fe8537da6cff585be5ca92b6565accc95e5eddd3c7ded778d38d5ca5e39b6e1eec90f0b0ff68b2cae7170dc95bbf2567e3c535f56415f310a4e2cdeea57df6a5a7bfb73b2048fab701505b355bc4a56e92a5be5ed78555807166b6efa5ccb3afe248bc9b28265dee5ceed8565b4b755b9aa5697555dcd568d3e5ab5b1c7f7c23129dcddaaeb76abab395e752c5bbbe3f66e626ef955166f7533e3b261f9d270a5b1f178e335567efeafaf2afd9571311f57fa6ab55a6bb362b8daacb6abbbcbc76ad75767d2a05f79b0b67d0ecf64796372ec983c0adfc570cff7819ef85efea3d8cf6bdcbbdf76e87ff8cd6abf3aac8ead1d7cb84edffa7e9e679aa6b63b6627bfcae2af4eab7b9643ad570fcdfbea919fce727f3a052c4f69fca971795a3dafceab176db67ad5ebd5dbea7df5b1fa8cbff26ef595f615a31fbbddf98749f7c177bc0f9d57f6795b7daf06d17e35147b2cfbbdbccd9339ee7739b58bd5a8d72e173b9358e3acdf65b1ceab717d67ec5693d574355bcd51c3b7708ec1fdf3314c92af16abe55a5d2b6b439badcdb5b5b6d7ceda5d7bc69e45cffb1f7bdefb489eaffb32097a7b62b3105fc7e3fba9f9beea7e36627e6318266b7f1dacc3c0091cbecb91452c6431bd17f85d967e7473dbd8d7efeb681dab77e20c2d9745f9b16be9cff8b1f03198af933c5d5bc1789daeb375be2ed6e5ba5a5fd6b5b5b437741601fbf7fbd5b30fbe57a25f6bb15a16fc34ceba757416dfb3e83e9ce9d77ecd807df6ebceefd6cc62bc50c8d2eeb411f366bfd90bd7d26374b7beadb53573e4b2fee5fed5793f628aba5eaf37ebedfa6ebd5befd787f5717d5adfaf1fd68feba790c5fdd69eef5ac1b8b04fbf9ef76a7e704b3e584bbedb9f5950bffba8f7e2eb7e97fcb1df83b63eaf5f02d736cc28effa73246c8e1feb193f73d2e7373edfafe4b23c69bb7e5dbf35cafa7dfdc1e617c8f2f7f78ffdf38ff3283f69566595d196e7f5e7fa6bfdbd1eac87eb11d335bea38c568b980e4db0afbf8fa6c6acc7cffc04c6b2dfadd7cbe90f7a7bea77569a43967505d5e0a69a713e6171d79d36d1f3f5b8f776eb49bfa3b61f93cb389f38de7aba9eade7eabdd8d32b674be7afc8f2d3d9621ecf798f6a11dcaf179774bdcc5f36ea46d9181bb37faead164ebf368979c230a77db5439cb4602336661ab91436d3dc39174ba1fd0a2caa7f6511e4ae0f0b36569fdfacc6cce59f8ce3c6c9271b77e36dfc4d607da94f56f35b9bfed2b8fc7eb6381a2a9ee2da55972acd26dc449b78936cd24db6c9f9aa0bcb6eac27ffdbf68bbc782effdf76ae6549552488eee733a6f615fdba7dbb6356a899203e5a6db51f3b4444f0c14b1489987f9faa8202a4bd37b457331113b9d010943a661645669d93b6d9e37b5a6207f5ce54d90a7b630ee6244ed8f3c2d4532060d9afca32ad349d280e4d481246103617866ae8b10a11c3b2b36c86248e1fe983506f36cb7bd7f59cde1344592e9dd23decc91c0e90c0115250a0014d680104cf80a691efb672cf7c667bc1191af13a6a6c8d2ed758790ea8a041fba8a546ca6681e23a2c67047dffd9b4a1130fb9e20cbad0833e2ce34747a706bc2c0e85fef98baee722bfd4f4404187dc51957668dcd0c2d0b660004318c12b8c61025378f3347fb13bb0acbe5df0f8ab3a31cdd0e01d3ee0136ee036e9c2ddb1ed7437f7e95459c13d7169c0bcfd003fe0117eb2bb700a4ff08c94def1b9eef5e9337dca1557dfc052a8ea8aefae6ed98c216b9d45ef4ffa485524aebeeaa181333471eeaa5edbb7f71bff47100423b4421517519a70a1686ff7106f632dbe471b97ebe0a027b3a4874ec8a276354cdffc603e255ca59dee228325a4b8c2354b719e8d29bbca113774bcb961e319c8f15c1f6327bd3884873ca043ee1bdcda7dce35430f7d0c30740718e10e636fed2f7ddd7f0cc2861b3aa1161991827b3cecfa8d66ec6112bce2115354f693204dfadb96d559cd6ccab25f967cd21655d61b3627a2d61336b0892d72a03dc20e53978ef868d8fa229f5faee75a7fe935c07eb745b764495b08ec7d0311d5f514356ca3bffd70224ff774bfb3f1822818bb5ad8461d3bd8c5de6e837df6fe0507fb088787258ef015c7d68bd0fa1a7cc79ef3f0a8623d21573237714a0f6bb636061dba66de58d0211dac1b76bfe293ef6039b59ad281736c393795d713791dceebf80ee712f96e3009ddd07544a5d179e13613e6e4967d435ca3ec245389a0cad56bfd58aad7bf7aee9fc122ff178e852391e3f3ba9c7d9399eff23a234758aeb7d96b869def6fe7fb0f468e60216ac18678a2378b9890bd31a42ee18c42f1d27b720dcf09969c1fb0909d7904e76ec356026184f0baafc89d66956e3da5fecbf6f6f369d67545d6b5c5d924df135a7ec542cb5e26e49a7cbfc201afa191da8093df3604f79408ae9ab0ad576031ca9ca3caca1635c83935653d22cfb448ce3bcf6adc752c32e62a9eb9443352aa19aaaae7e288acea1ab4729f2cb50e052bf5d4871cf952b02732ae47d9db635ea9689b453c57bc2062244752ad5f5e84c592fcc3e1ee4c949995795bc152fdbea830d827ffc84c20e9088f91d2fb395e4b665b520152c3422492ebf27dce3a1163b10a2cc60916c11710bad85b6ed69a7320cdc09db863ceee0a1533e20c1ccef6c814cd995eb334f9fc9ecf4b7ebda988b5c23b67b1108e04dff03d63da7fc32f8b9a5f4caeec2fc7c9c7e6f5bc5e154b795ce2e596e3679fca7dd222b624e3bc58134fe3a1e0bbcd199677fcb81c4b3d6a7ea7d6aeb0fb7e71ceb9a3f5738b7cbeda2ba7de3ba79caf57e52fff15fb1fcbbfd3fefcfbaf3ffe0193cc32fd</data>
+ </image>
+</images>
+<tqlayoutdefaults spacing="6" margin="11"/>
+</UI>